3fffd135bc0d52732305710c99fa3aa2b99c5101
[fw/sdcc] / src / pic / gen.c
1 /*-------------------------------------------------------------------------
2   SDCCgen51.c - source file for code generation for 8051
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   
9   This program is free software; you can redistribute it and/or modify it
10   under the terms of the GNU General Public License as published by the
11   Free Software Foundation; either version 2, or (at your option) any
12   later version.
13   
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License for more details.
18   
19   You should have received a copy of the GNU General Public License
20   along with this program; if not, write to the Free Software
21   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22   
23   In other words, you are welcome to use, share and improve this program.
24   You are forbidden to forbid anyone else to use, share and improve
25   what you give them.   Help stamp out software-hoarding!
26   
27   Notes:
28   000123 mlh    Moved aopLiteral to SDCCglue.c to help the split
29                 Made everything static
30 -------------------------------------------------------------------------*/
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <ctype.h>
36 #include "SDCCglobl.h"
37 #include "newalloc.h"
38
39 #ifdef HAVE_SYS_ISA_DEFS_H
40 #include <sys/isa_defs.h>
41 #else
42 #ifdef HAVE_MACHINE_ENDIAN_H
43 #include <machine/endian.h>
44 #else
45 #ifdef HAVE_ENDIAN_H
46 #include <endian.h>
47 #else
48 #if !defined(__BORLANDC__) && !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__CYGWIN__)
49 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
50 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
51 #endif
52 #endif
53 #endif
54 #endif
55
56 #include "common.h"
57 #include "SDCCpeeph.h"
58 #include "ralloc.h"
59 #include "pcode.h"
60 #include "gen.h"
61
62
63 static int labelOffset=0;
64 static int debug_verbose=1;
65 static int optimized_for_speed = 0;
66
67 /* max_key keeps track of the largest label number used in 
68    a function. This is then used to adjust the label offset
69    for the next function.
70 */
71 static int max_key=0;
72 static int GpsuedoStkPtr=0;
73
74 unsigned int pic14aopLiteral (value *val, int offset);
75 const char *AopType(short type);
76 static iCode *ifxForOp ( operand *op, iCode *ic );
77
78 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
79
80 /* this is the down and dirty file with all kinds of 
81    kludgy & hacky stuff. This is what it is all about
82    CODE GENERATION for a specific MCU . some of the
83    routines may be reusable, will have to see */
84
85 static char *zero = "#0x00";
86 static char *one  = "#0x01";
87 static char *spname = "sp";
88
89 char *fReturnpic14[] = {"FSR","dph","b","a" };
90 //char *fReturn390[] = {"dpl","dph","dpx", "b","a" };
91 unsigned fReturnSizePic = 4; /* shared with ralloc.c */
92 static char **fReturn = fReturnpic14;
93
94 static char *accUse[] = {"a","b"};
95
96 //static short rbank = -1;
97
98 static struct {
99     short r0Pushed;
100     short r1Pushed;
101     short accInUse;
102     short inLine;
103     short debugLine;
104     short nRegsSaved;
105     set *sendSet;
106 } _G;
107
108 /* Resolved ifx structure. This structure stores information
109    about an iCode ifx that makes it easier to generate code.
110 */
111 typedef struct resolvedIfx {
112   symbol *lbl;     /* pointer to a label */
113   int condition;   /* true or false ifx */
114   int generated;   /* set true when the code associated with the ifx
115                     * is generated */
116 } resolvedIfx;
117
118 extern int pic14_ptrRegReq ;
119 extern int pic14_nRegs;
120 extern FILE *codeOutFile;
121 static void saverbank (int, iCode *,bool);
122
123 static lineNode *lineHead = NULL;
124 static lineNode *lineCurr = NULL;
125
126 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
127 0xE0, 0xC0, 0x80, 0x00};
128 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
129 0x07, 0x03, 0x01, 0x00};
130
131 static  pBlock *pb;
132
133 /*-----------------------------------------------------------------*/
134 /*  my_powof2(n) - If `n' is an integaer power of 2, then the      */
135 /*                 exponent of 2 is returned, otherwise -1 is      */
136 /*                 returned.                                       */
137 /* note that this is similar to the function `powof2' in SDCCsymt  */
138 /* if(n == 2^y)                                                    */
139 /*   return y;                                                     */
140 /* return -1;                                                      */
141 /*-----------------------------------------------------------------*/
142 static int my_powof2 (unsigned long num)
143 {
144   if(num) {
145     if( (num & (num-1)) == 0) {
146       int nshifts = -1;
147       while(num) {
148         num>>=1;
149         nshifts++;
150       }
151       return nshifts;
152     }
153   }
154
155   return -1;
156 }
157
158 void DEBUGpic14_AopType(int line_no, operand *left, operand *right, operand *result)
159 {
160
161   DEBUGpic14_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
162                        line_no,
163                        ((result) ? AopType(AOP_TYPE(result)) : "-"),
164                        ((result) ? aopGet(AOP(result),0,TRUE,FALSE) : "-"),
165                        ((left)   ? AopType(AOP_TYPE(left)) : "-"),
166                        ((left)   ? aopGet(AOP(left),0,TRUE,FALSE) : "-"),
167                        ((right)  ? AopType(AOP_TYPE(right)) : "-"),
168                        ((right)  ? aopGet(AOP(right),0,FALSE,FALSE) : "-"),
169                        ((result) ? AOP_SIZE(result) : 0));
170
171 }
172
173 void DEBUGpic14_emitcode (char *inst,char *fmt, ...)
174 {
175     va_list ap;
176     char lb[INITIAL_INLINEASM];  
177     char *lbp = lb;
178
179     if(!debug_verbose)
180       return;
181
182     va_start(ap,fmt);   
183
184     if (inst && *inst) {
185         if (fmt && *fmt)
186             sprintf(lb,"%s\t",inst);
187         else
188             sprintf(lb,"%s",inst);
189         vsprintf(lb+(strlen(lb)),fmt,ap);
190     }  else
191         vsprintf(lb,fmt,ap);
192
193     while (isspace(*lbp)) lbp++;
194
195     if (lbp && *lbp) 
196         lineCurr = (lineCurr ?
197                     connectLine(lineCurr,newLineNode(lb)) :
198                     (lineHead = newLineNode(lb)));
199     lineCurr->isInline = _G.inLine;
200     lineCurr->isDebug  = _G.debugLine;
201
202     addpCode2pBlock(pb,newpCodeCharP(lb));
203
204     va_end(ap);
205 }
206
207
208 static void emitpLabel(int key)
209 {
210   addpCode2pBlock(pb,newpCodeLabel(key+100+labelOffset));
211 }
212
213 void emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
214 {
215
216   if(pcop)
217     addpCode2pBlock(pb,newpCode(poc,pcop));
218   else
219     DEBUGpic14_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
220 }
221
222 void emitpcodeNULLop(PIC_OPCODE poc)
223 {
224
225   addpCode2pBlock(pb,newpCode(poc,NULL));
226
227 }
228
229 /*-----------------------------------------------------------------*/
230 /* pic14_emitcode - writes the code into a file : for now it is simple    */
231 /*-----------------------------------------------------------------*/
232 void pic14_emitcode (char *inst,char *fmt, ...)
233 {
234     va_list ap;
235     char lb[INITIAL_INLINEASM];  
236     char *lbp = lb;
237
238     va_start(ap,fmt);   
239
240     if (inst && *inst) {
241         if (fmt && *fmt)
242             sprintf(lb,"%s\t",inst);
243         else
244             sprintf(lb,"%s",inst);
245         vsprintf(lb+(strlen(lb)),fmt,ap);
246     }  else
247         vsprintf(lb,fmt,ap);
248
249     while (isspace(*lbp)) lbp++;
250
251     if (lbp && *lbp) 
252         lineCurr = (lineCurr ?
253                     connectLine(lineCurr,newLineNode(lb)) :
254                     (lineHead = newLineNode(lb)));
255     lineCurr->isInline = _G.inLine;
256     lineCurr->isDebug  = _G.debugLine;
257
258     if(debug_verbose)
259       addpCode2pBlock(pb,newpCodeCharP(lb));
260
261     va_end(ap);
262 }
263
264
265 /*-----------------------------------------------------------------*/
266 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
267 /*-----------------------------------------------------------------*/
268 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
269 {
270     bool r0iu = FALSE , r1iu = FALSE;
271     bool r0ou = FALSE , r1ou = FALSE;
272
273     /* the logic: if r0 & r1 used in the instruction
274     then we are in trouble otherwise */
275
276     /* first check if r0 & r1 are used by this
277     instruction, in which case we are in trouble */
278     if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
279         (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
280     {
281         goto endOfWorld;      
282     }
283
284     r0ou = bitVectBitValue(ic->rMask,R0_IDX);
285     r1ou = bitVectBitValue(ic->rMask,R1_IDX);
286
287     /* if no usage of r0 then return it */
288     if (!r0iu && !r0ou) {
289         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
290         (*aopp)->type = AOP_R0;
291         
292         return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
293     }
294
295     /* if no usage of r1 then return it */
296     if (!r1iu && !r1ou) {
297         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
298         (*aopp)->type = AOP_R1;
299
300         return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R1_IDX);
301     }    
302
303     /* now we know they both have usage */
304     /* if r0 not used in this instruction */
305     if (!r0iu) {
306         /* push it if not already pushed */
307         if (!_G.r0Pushed) {
308             pic14_emitcode ("push","%s",
309                       pic14_regWithIdx(R0_IDX)->dname);
310             _G.r0Pushed++ ;
311         }
312         
313         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
314         (*aopp)->type = AOP_R0;
315
316         return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
317     }
318
319     /* if r1 not used then */
320
321     if (!r1iu) {
322         /* push it if not already pushed */
323         if (!_G.r1Pushed) {
324             pic14_emitcode ("push","%s",
325                       pic14_regWithIdx(R1_IDX)->dname);
326             _G.r1Pushed++ ;
327         }
328         
329         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
330         (*aopp)->type = AOP_R1;
331         return pic14_regWithIdx(R1_IDX);
332     }
333
334 endOfWorld :
335     /* I said end of world but not quite end of world yet */
336     /* if this is a result then we can push it on the stack*/
337     if (result) {
338         (*aopp)->type = AOP_STK;    
339         return NULL;
340     }
341
342     /* other wise this is true end of the world */
343     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
344            "getFreePtr should never reach here");
345     exit(0);
346 }
347
348 /*-----------------------------------------------------------------*/
349 /* newAsmop - creates a new asmOp                                  */
350 /*-----------------------------------------------------------------*/
351 asmop *newAsmop (short type)
352 {
353     asmop *aop;
354
355     aop = Safe_calloc(1,sizeof(asmop));
356     aop->type = type;
357     return aop;
358 }
359
360 static void genSetDPTR(int n)
361 {
362     if (!n)
363     {
364         pic14_emitcode(";", "Select standard DPTR");
365         pic14_emitcode("mov", "dps, #0x00");
366     }
367     else
368     {
369         pic14_emitcode(";", "Select alternate DPTR");
370         pic14_emitcode("mov", "dps, #0x01");
371     }
372 }
373
374 /*-----------------------------------------------------------------*/
375 /* resolveIfx - converts an iCode ifx into a form more useful for  */
376 /*              generating code                                    */
377 /*-----------------------------------------------------------------*/
378 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
379 {
380   if(!resIfx) 
381     return;
382
383   DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
384
385   resIfx->condition = 1;    /* assume that the ifx is true */
386   resIfx->generated = 0;    /* indicate that the ifx has not been used */
387
388   if(!ifx) {
389     resIfx->lbl = newiTempLabel(NULL);  /* oops, there is no ifx. so create a label */
390     DEBUGpic14_emitcode("; ***","%s %d null ifx creating new label key =%d",
391                         __FUNCTION__,__LINE__,resIfx->lbl->key);
392   } else {
393     if(IC_TRUE(ifx)) {
394       resIfx->lbl = IC_TRUE(ifx);
395     } else {
396       resIfx->lbl = IC_FALSE(ifx);
397       resIfx->condition = 0;
398     }
399     if(IC_TRUE(ifx)) 
400       DEBUGpic14_emitcode("; ***","ifx true is non-null");
401     if(IC_FALSE(ifx)) 
402       DEBUGpic14_emitcode("; ***","ifx false is non-null");
403   }
404
405   DEBUGpic14_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,labelOffset);
406
407 }
408 /*-----------------------------------------------------------------*/
409 /* pointerCode - returns the code for a pointer type               */
410 /*-----------------------------------------------------------------*/
411 static int pointerCode (sym_link *etype)
412 {
413
414     return PTR_TYPE(SPEC_OCLS(etype));
415
416 }
417
418 /*-----------------------------------------------------------------*/
419 /* aopForSym - for a true symbol                                   */
420 /*-----------------------------------------------------------------*/
421 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
422 {
423     asmop *aop;
424     memmap *space= SPEC_OCLS(sym->etype);
425
426     DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
427     /* if already has one */
428     if (sym->aop)
429         return sym->aop;
430
431     /* assign depending on the storage class */
432     /* if it is on the stack or indirectly addressable */
433     /* space we need to assign either r0 or r1 to it   */    
434     if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
435         sym->aop = aop = newAsmop(0);
436         aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
437         aop->size = getSize(sym->type);
438
439         /* now assign the address of the variable to 
440         the pointer register */
441         if (aop->type != AOP_STK) {
442
443             if (sym->onStack) {
444                     if ( _G.accInUse )
445                         pic14_emitcode("push","acc");
446
447                     pic14_emitcode("mov","a,_bp");
448                     pic14_emitcode("add","a,#0x%02x",
449                              ((sym->stack < 0) ?
450                               ((char)(sym->stack - _G.nRegsSaved )) :
451                               ((char)sym->stack)) & 0xff);
452                     pic14_emitcode("mov","%s,a",
453                              aop->aopu.aop_ptr->name);
454
455                     if ( _G.accInUse )
456                         pic14_emitcode("pop","acc");
457             } else
458                 pic14_emitcode("mov","%s,#%s",
459                          aop->aopu.aop_ptr->name,
460                          sym->rname);
461             aop->paged = space->paged;
462         } else
463             aop->aopu.aop_stk = sym->stack;
464         return aop;
465     }
466     
467     if (sym->onStack && options.stack10bit)
468     {
469         /* It's on the 10 bit stack, which is located in
470          * far data space.
471          */
472          
473       //DEBUGpic14_emitcode(";","%d",__LINE__);
474
475         if ( _G.accInUse )
476                 pic14_emitcode("push","acc");
477
478         pic14_emitcode("mov","a,_bp");
479         pic14_emitcode("add","a,#0x%02x",
480                  ((sym->stack < 0) ?
481                    ((char)(sym->stack - _G.nRegsSaved )) :
482                    ((char)sym->stack)) & 0xff);
483         
484         genSetDPTR(1);
485         pic14_emitcode ("mov","dpx1,#0x40");
486         pic14_emitcode ("mov","dph1,#0x00");
487         pic14_emitcode ("mov","dpl1, a");
488         genSetDPTR(0);
489         
490         if ( _G.accInUse )
491             pic14_emitcode("pop","acc");
492             
493         sym->aop = aop = newAsmop(AOP_DPTR2);
494         aop->size = getSize(sym->type); 
495         return aop;
496     }
497
498     //DEBUGpic14_emitcode(";","%d",__LINE__);
499     /* if in bit space */
500     if (IN_BITSPACE(space)) {
501         sym->aop = aop = newAsmop (AOP_CRY);
502         aop->aopu.aop_dir = sym->rname ;
503         aop->size = getSize(sym->type);
504         //DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
505         return aop;
506     }
507     /* if it is in direct space */
508     if (IN_DIRSPACE(space)) {
509         sym->aop = aop = newAsmop (AOP_DIR);
510         aop->aopu.aop_dir = sym->rname ;
511         aop->size = getSize(sym->type);
512         DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
513         return aop;
514     }
515
516     /* special case for a function */
517     if (IS_FUNC(sym->type)) {   
518         sym->aop = aop = newAsmop(AOP_IMMD);    
519         //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
520         aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
521         strcpy(aop->aopu.aop_immd,sym->rname);
522         aop->size = FPTRSIZE; 
523         return aop;
524     }
525
526
527     /* only remaining is far space */
528     /* in which case DPTR gets the address */
529     sym->aop = aop = newAsmop(AOP_DPTR);
530     pic14_emitcode ("mov","dptr,#%s", sym->rname);
531     aop->size = getSize(sym->type);
532
533     DEBUGpic14_emitcode(";","%d size = %d",__LINE__,aop->size);
534     /* if it is in code space */
535     if (IN_CODESPACE(space))
536         aop->code = 1;
537
538     return aop;     
539 }
540
541 /*-----------------------------------------------------------------*/
542 /* aopForRemat - rematerialzes an object                           */
543 /*-----------------------------------------------------------------*/
544 static asmop *aopForRemat (symbol *sym)
545 {
546     iCode *ic = sym->rematiCode;
547     asmop *aop = newAsmop(AOP_IMMD);
548     int val = 0;
549     DEBUGpic14_emitcode(";","%s %d",__FUNCTION__,__LINE__);
550     for (;;) {
551         if (ic->op == '+')
552             val += (int) operandLitValue(IC_RIGHT(ic));
553         else if (ic->op == '-')
554             val -= (int) operandLitValue(IC_RIGHT(ic));
555         else
556             break;
557         
558         ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
559     }
560
561     if (val)
562         sprintf(buffer,"(%s %c 0x%04x)",
563                 OP_SYMBOL(IC_LEFT(ic))->rname, 
564                 val >= 0 ? '+' : '-',
565                 abs(val) & 0xffff);
566     else
567         strcpy(buffer,OP_SYMBOL(IC_LEFT(ic))->rname);
568
569     //DEBUGpic14_emitcode(";","%s",buffer);
570     aop->aopu.aop_immd = Safe_calloc(1,strlen(buffer)+1);
571     strcpy(aop->aopu.aop_immd,buffer);    
572     return aop;        
573 }
574
575 int aopIdx (asmop *aop, int offset)
576 {
577   if(!aop)
578     return -1;
579
580   if(aop->type !=  AOP_REG)
581     return -2;
582         
583   return aop->aopu.aop_reg[offset]->rIdx;
584
585 }
586 /*-----------------------------------------------------------------*/
587 /* regsInCommon - two operands have some registers in common       */
588 /*-----------------------------------------------------------------*/
589 static bool regsInCommon (operand *op1, operand *op2)
590 {
591     symbol *sym1, *sym2;
592     int i;
593
594     /* if they have registers in common */
595     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
596         return FALSE ;
597
598     sym1 = OP_SYMBOL(op1);
599     sym2 = OP_SYMBOL(op2);
600
601     if (sym1->nRegs == 0 || sym2->nRegs == 0)
602         return FALSE ;
603
604     for (i = 0 ; i < sym1->nRegs ; i++) {
605         int j;
606         if (!sym1->regs[i])
607             continue ;
608
609         for (j = 0 ; j < sym2->nRegs ;j++ ) {
610             if (!sym2->regs[j])
611                 continue ;
612
613             if (sym2->regs[j] == sym1->regs[i])
614                 return TRUE ;
615         }
616     }
617
618     return FALSE ;
619 }
620
621 /*-----------------------------------------------------------------*/
622 /* operandsEqu - equivalent                                        */
623 /*-----------------------------------------------------------------*/
624 static bool operandsEqu ( operand *op1, operand *op2)
625 {
626     symbol *sym1, *sym2;
627
628     /* if they not symbols */
629     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
630         return FALSE;
631
632     sym1 = OP_SYMBOL(op1);
633     sym2 = OP_SYMBOL(op2);
634
635     /* if both are itemps & one is spilt
636        and the other is not then false */
637     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
638         sym1->isspilt != sym2->isspilt )
639         return FALSE ;
640
641     /* if they are the same */
642     if (sym1 == sym2)
643         return TRUE ;
644
645     if (strcmp(sym1->rname,sym2->rname) == 0)
646         return TRUE;
647
648
649     /* if left is a tmp & right is not */
650     if (IS_ITEMP(op1)  && 
651         !IS_ITEMP(op2) &&
652         sym1->isspilt  &&
653         (sym1->usl.spillLoc == sym2))
654         return TRUE;
655
656     if (IS_ITEMP(op2)  && 
657         !IS_ITEMP(op1) &&
658         sym2->isspilt  &&
659         sym1->level > 0 &&
660         (sym2->usl.spillLoc == sym1))
661         return TRUE ;
662
663     return FALSE ;
664 }
665
666 /*-----------------------------------------------------------------*/
667 /* pic14_sameRegs - two asmops have the same registers                   */
668 /*-----------------------------------------------------------------*/
669 bool pic14_sameRegs (asmop *aop1, asmop *aop2 )
670 {
671     int i;
672
673     if (aop1 == aop2)
674         return TRUE ;
675
676     if (aop1->type != AOP_REG ||
677         aop2->type != AOP_REG )
678         return FALSE ;
679
680     if (aop1->size != aop2->size )
681         return FALSE ;
682
683     for (i = 0 ; i < aop1->size ; i++ )
684         if (aop1->aopu.aop_reg[i] !=
685             aop2->aopu.aop_reg[i] )
686             return FALSE ;
687
688     return TRUE ;
689 }
690
691 /*-----------------------------------------------------------------*/
692 /* aopOp - allocates an asmop for an operand  :                    */
693 /*-----------------------------------------------------------------*/
694 void aopOp (operand *op, iCode *ic, bool result)
695 {
696     asmop *aop;
697     symbol *sym;
698     int i;
699
700     if (!op)
701         return ;
702
703     //    DEBUGpic14_emitcode(";","%d",__LINE__);
704     /* if this a literal */
705     if (IS_OP_LITERAL(op)) {
706         op->aop = aop = newAsmop(AOP_LIT);
707         aop->aopu.aop_lit = op->operand.valOperand;
708         aop->size = getSize(operandType(op));
709         return;
710     }
711
712     /* if already has a asmop then continue */
713     if (op->aop)
714         return ;
715
716     /* if the underlying symbol has a aop */
717     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
718       DEBUGpic14_emitcode(";","%d",__LINE__);
719         op->aop = OP_SYMBOL(op)->aop;
720         return;
721     }
722
723     /* if this is a true symbol */
724     if (IS_TRUE_SYMOP(op)) {    
725       //DEBUGpic14_emitcode(";","%d - true symop",__LINE__);
726       op->aop = aopForSym(ic,OP_SYMBOL(op),result);
727       return ;
728     }
729
730     /* this is a temporary : this has
731     only four choices :
732     a) register
733     b) spillocation
734     c) rematerialize 
735     d) conditional   
736     e) can be a return use only */
737
738     sym = OP_SYMBOL(op);
739
740
741     /* if the type is a conditional */
742     if (sym->regType == REG_CND) {
743         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
744         aop->size = 0;
745         return;
746     }
747
748     /* if it is spilt then two situations
749     a) is rematerialize 
750     b) has a spill location */
751     if (sym->isspilt || sym->nRegs == 0) {
752
753       DEBUGpic14_emitcode(";","%d",__LINE__);
754         /* rematerialize it NOW */
755         if (sym->remat) {
756             sym->aop = op->aop = aop =
757                                       aopForRemat (sym);
758             aop->size = getSize(sym->type);
759             return;
760         }
761
762         if (sym->accuse) {
763             int i;
764             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
765             aop->size = getSize(sym->type);
766             for ( i = 0 ; i < 2 ; i++ )
767                 aop->aopu.aop_str[i] = accUse[i];
768             DEBUGpic14_emitcode(";","%d",__LINE__);
769             return;  
770         }
771
772         if (sym->ruonly ) {
773             unsigned i;
774             aop = op->aop = sym->aop = newAsmop(AOP_STR);
775             aop->size = getSize(sym->type);
776             for ( i = 0 ; i < fReturnSizePic ; i++ )
777               aop->aopu.aop_str[i] = fReturn[i];
778             DEBUGpic14_emitcode(";","%d",__LINE__);
779             return;
780         }
781
782         /* else spill location  */
783         if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
784             /* force a new aop if sizes differ */
785             sym->usl.spillLoc->aop = NULL;
786         }
787         DEBUGpic14_emitcode(";","%s %d %s",__FUNCTION__,__LINE__,sym->usl.spillLoc->rname);
788         sym->aop = op->aop = aop = 
789                                   aopForSym(ic,sym->usl.spillLoc,result);
790         aop->size = getSize(sym->type);
791         return;
792     }
793
794     /* must be in a register */
795     sym->aop = op->aop = aop = newAsmop(AOP_REG);
796     aop->size = sym->nRegs;
797     for ( i = 0 ; i < sym->nRegs ;i++)
798         aop->aopu.aop_reg[i] = sym->regs[i];
799 }
800
801 /*-----------------------------------------------------------------*/
802 /* freeAsmop - free up the asmop given to an operand               */
803 /*----------------------------------------------------------------*/
804 void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
805 {   
806     asmop *aop ;
807
808     if (!op)
809         aop = aaop;
810     else 
811         aop = op->aop;
812
813     if (!aop)
814         return ;
815
816     if (aop->freed)
817         goto dealloc; 
818
819     aop->freed = 1;
820
821     /* depending on the asmop type only three cases need work AOP_RO
822        , AOP_R1 && AOP_STK */
823 #if 0
824     switch (aop->type) {
825         case AOP_R0 :
826             if (_G.r0Pushed ) {
827                 if (pop) {
828                     pic14_emitcode ("pop","ar0");     
829                     _G.r0Pushed--;
830                 }
831             }
832             bitVectUnSetBit(ic->rUsed,R0_IDX);
833             break;
834
835         case AOP_R1 :
836             if (_G.r1Pushed ) {
837                 if (pop) {
838                     pic14_emitcode ("pop","ar1");
839                     _G.r1Pushed--;
840                 }
841             }
842             bitVectUnSetBit(ic->rUsed,R1_IDX);          
843             break;
844
845         case AOP_STK :
846         {
847             int sz = aop->size;    
848             int stk = aop->aopu.aop_stk + aop->size;
849             bitVectUnSetBit(ic->rUsed,R0_IDX);
850             bitVectUnSetBit(ic->rUsed,R1_IDX);          
851
852             getFreePtr(ic,&aop,FALSE);
853             
854             if (options.stack10bit)
855             {
856                 /* I'm not sure what to do here yet... */
857                 /* #STUB */
858                 fprintf(stderr, 
859                         "*** Warning: probably generating bad code for "
860                         "10 bit stack mode.\n");
861             }
862             
863             if (stk) {
864                 pic14_emitcode ("mov","a,_bp");
865                 pic14_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
866                 pic14_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
867             } else {
868                 pic14_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
869             }
870
871             while (sz--) {
872                 pic14_emitcode("pop","acc");
873                 pic14_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
874                 if (!sz) break;
875                 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
876             }
877             op->aop = aop;
878             freeAsmop(op,NULL,ic,TRUE);
879             if (_G.r0Pushed) {
880                 pic14_emitcode("pop","ar0");
881                 _G.r0Pushed--;
882             }
883
884             if (_G.r1Pushed) {
885                 pic14_emitcode("pop","ar1");
886                 _G.r1Pushed--;
887             }       
888         }
889     }
890 #endif
891
892 dealloc:
893     /* all other cases just dealloc */
894     if (op ) {
895         op->aop = NULL;
896         if (IS_SYMOP(op)) {
897             OP_SYMBOL(op)->aop = NULL;    
898             /* if the symbol has a spill */
899             if (SPIL_LOC(op))
900                 SPIL_LOC(op)->aop = NULL;
901         }
902     }
903 }
904
905 /*-----------------------------------------------------------------*/
906 /* aopGet - for fetching value of the aop                          */
907 /*-----------------------------------------------------------------*/
908 char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
909 {
910     char *s = buffer ;
911     char *rs;
912
913     //DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
914     /* offset is greater than
915     size then zero */
916     if (offset > (aop->size - 1) &&
917         aop->type != AOP_LIT)
918         return zero;
919
920     /* depending on type */
921     switch (aop->type) {
922         
923     case AOP_R0:
924     case AOP_R1:
925         DEBUGpic14_emitcode(";","%d",__LINE__);
926         /* if we need to increment it */       
927         while (offset > aop->coff) {        
928             pic14_emitcode ("inc","%s",aop->aopu.aop_ptr->name);  
929             aop->coff++;
930         }
931         
932         while (offset < aop->coff) {
933             pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
934             aop->coff--;
935         }
936         
937         aop->coff = offset ;
938         if (aop->paged) {
939             pic14_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
940             return (dname ? "acc" : "a");
941         }       
942         sprintf(s,"@%s",aop->aopu.aop_ptr->name);
943         rs = Safe_calloc(1,strlen(s)+1);
944         strcpy(rs,s);   
945         return rs;
946         
947     case AOP_DPTR:
948     case AOP_DPTR2:
949         DEBUGpic14_emitcode(";","%d",__LINE__);
950     if (aop->type == AOP_DPTR2)
951     {
952         genSetDPTR(1);
953     }
954     
955         while (offset > aop->coff) {
956             pic14_emitcode ("inc","dptr");
957             aop->coff++;
958         }
959         
960         while (offset < aop->coff) {        
961             pic14_emitcode("lcall","__decdptr");
962             aop->coff--;
963         }
964         
965         aop->coff = offset;
966         if (aop->code) {
967             pic14_emitcode("clr","a");
968             pic14_emitcode("movc","a,@a+dptr");
969         }
970     else {
971             pic14_emitcode("movx","a,@dptr");
972     }
973             
974     if (aop->type == AOP_DPTR2)
975     {
976         genSetDPTR(0);
977     }
978             
979     return (dname ? "acc" : "a");
980         
981         
982     case AOP_IMMD:
983       DEBUGpic14_emitcode(";","%d",__LINE__);
984         if (bit16) 
985             sprintf (s,"%s",aop->aopu.aop_immd);
986         else
987             if (offset) 
988                 sprintf(s,"(%s >> %d)",
989                         aop->aopu.aop_immd,
990                         offset*8);
991             else
992                 sprintf(s,"%s",
993                         aop->aopu.aop_immd);
994         rs = Safe_calloc(1,strlen(s)+1);
995         strcpy(rs,s);   
996         return rs;
997         
998     case AOP_DIR:
999         if (offset)
1000             sprintf(s,"(%s + %d)",
1001                     aop->aopu.aop_dir,
1002                     offset);
1003         else
1004             sprintf(s,"%s",aop->aopu.aop_dir);
1005         rs = Safe_calloc(1,strlen(s)+1);
1006         strcpy(rs,s);   
1007         return rs;
1008         
1009     case AOP_REG:
1010         if (dname) 
1011             return aop->aopu.aop_reg[offset]->dname;
1012         else
1013             return aop->aopu.aop_reg[offset]->name;
1014         
1015     case AOP_CRY:
1016       //pic14_emitcode(";","%d",__LINE__);
1017       return aop->aopu.aop_dir;
1018         
1019     case AOP_ACC:
1020         DEBUGpic14_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1021         return "AOP_accumulator_bug";
1022
1023     case AOP_LIT:
1024         sprintf(s,"0x%02x", pic14aopLiteral (aop->aopu.aop_lit,offset));
1025         rs = Safe_calloc(1,strlen(s)+1);
1026         strcpy(rs,s);   
1027         return rs;
1028         
1029     case AOP_STR:
1030         DEBUGpic14_emitcode(";","%d",__LINE__);
1031         aop->coff = offset ;
1032         if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1033             dname)
1034             return "acc";
1035         
1036         return aop->aopu.aop_str[offset];
1037         
1038     }
1039
1040     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1041            "aopget got unsupported aop->type");
1042     exit(0);
1043 }
1044
1045 /*-----------------------------------------------------------------*/
1046 /* popGetLabel - create a new pCodeOp of type PO_LABEL             */
1047 /*-----------------------------------------------------------------*/
1048 pCodeOp *popGetLabel(unsigned int key)
1049 {
1050
1051   DEBUGpic14_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1052
1053   if(key>max_key)
1054     max_key = key;
1055
1056   return newpCodeOpLabel(key+100+labelOffset);
1057 }
1058
1059 /*-----------------------------------------------------------------*/
1060 /* popCopyReg - copy a pcode operator                              */
1061 /*-----------------------------------------------------------------*/
1062 pCodeOp *popCopyReg(pCodeOpReg *pc)
1063 {
1064   pCodeOpReg *pcor;
1065
1066   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1067   pcor->pcop.type = pc->pcop.type;
1068   if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1069     fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1070   pcor->r = pc->r;
1071   pcor->rIdx = pc->rIdx;
1072
1073   //DEBUGpic14_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1074
1075   return PCOP(pcor);
1076 }
1077
1078 /*-----------------------------------------------------------------*/
1079 /* popCopy - copy a pcode operator                                 */
1080 /*-----------------------------------------------------------------*/
1081 pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval)
1082 {
1083   pCodeOp *pcop;
1084
1085   pcop = Safe_calloc(1,sizeof(pCodeOpBit) );
1086   pcop->type = PO_BIT;
1087   if(!(pcop->name = Safe_strdup(pc->name)))
1088     fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1089   ((pCodeOpBit *)pcop)->bit = bitval;
1090
1091   ((pCodeOpBit *)pcop)->inBitSpace = 0; //(pc->type == PO_BIT) ? 1 : 0;
1092
1093   return pcop;
1094 }
1095
1096 /*-----------------------------------------------------------------*/
1097 /* popGet - asm operator to pcode operator conversion              */
1098 /*-----------------------------------------------------------------*/
1099 pCodeOp *popGetLit(unsigned int lit)
1100 {
1101
1102   return newpCodeOpLit(lit);
1103 }
1104
1105
1106 /*-----------------------------------------------------------------*/
1107 /* popGet - asm operator to pcode operator conversion              */
1108 /*-----------------------------------------------------------------*/
1109 pCodeOp *popGetWithString(char *str)
1110 {
1111   pCodeOp *pcop;
1112
1113
1114   if(!str) {
1115     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1116     exit (1);
1117   }
1118
1119   pcop = newpCodeOp(str,PO_STR);
1120
1121   return pcop;
1122 }
1123
1124 pCodeOp *popRegFromString(char *str)
1125 {
1126
1127   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1128   pcop->type = PO_GPR_REGISTER;
1129
1130   PCOR(pcop)->rIdx = -1;
1131   PCOR(pcop)->r = NULL;
1132
1133   DEBUGpic14_emitcode(";","%d",__LINE__);
1134   pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1135
1136   return pcop;
1137 }
1138
1139 pCodeOp *popRegFromIdx(int rIdx)
1140 {
1141   pCodeOp *pcop;
1142
1143   DEBUGpic14_emitcode ("; ***","%s,%d  , rIdx=0x%x",
1144                        __FUNCTION__,__LINE__,rIdx);
1145
1146   pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1147
1148   PCOR(pcop)->rIdx = rIdx;
1149   PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1150   PCOR(pcop)->r->isFree = 0;
1151   PCOR(pcop)->r->wasUsed = 1;
1152
1153   pcop->type = PCOR(pcop)->r->pc_type;
1154
1155
1156   return pcop;
1157 }
1158 /*-----------------------------------------------------------------*/
1159 /* popGet - asm operator to pcode operator conversion              */
1160 /*-----------------------------------------------------------------*/
1161 pCodeOp *popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1162 {
1163     char *s = buffer ;
1164     char *rs;
1165
1166     pCodeOp *pcop;
1167
1168     //DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1169     /* offset is greater than
1170     size then zero */
1171
1172     if (offset > (aop->size - 1) &&
1173         aop->type != AOP_LIT)
1174       return NULL;  //zero;
1175
1176     /* depending on type */
1177     switch (aop->type) {
1178         
1179     case AOP_R0:
1180     case AOP_R1:
1181     case AOP_DPTR:
1182     case AOP_DPTR2:
1183     case AOP_ACC:
1184         DEBUGpic14_emitcode(";8051 legacy","%d type = %s",__LINE__,AopType(aop->type));
1185         //pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1186         //pcop->type = PO_SFR_REGISTER;
1187
1188         //PCOR(pcop)->rIdx = -1;
1189         //PCOR(pcop)->r = NULL;
1190         // Really nasty hack to check for temporary registers
1191
1192         //pcop->name = Safe_strdup("BAD_REGISTER");
1193
1194         return NULL;
1195         
1196     case AOP_IMMD:
1197       DEBUGpic14_emitcode(";","%d",__LINE__);
1198         pcop = Safe_calloc(1,sizeof(pCodeOp) );
1199         pcop->type = PO_IMMEDIATE;
1200         //if (bit16) 
1201         //    sprintf (s,"%s",aop->aopu.aop_immd);
1202         //else
1203         if (offset) 
1204           sprintf(s,"(%s >> %d)",
1205                   aop->aopu.aop_immd,
1206                   offset*8);
1207         else
1208           sprintf(s,"%s",
1209                   aop->aopu.aop_immd);
1210         pcop->name = Safe_calloc(1,strlen(s)+1);
1211         strcpy(pcop->name,s);   
1212         return pcop;
1213         
1214     case AOP_DIR:
1215         pcop = Safe_calloc(1,sizeof(pCodeOp) );
1216         pcop->type = PO_DIR;
1217         if (offset)
1218             sprintf(s,"(%s + %d)",
1219                     aop->aopu.aop_dir,
1220                     offset);
1221         else
1222             sprintf(s,"%s",aop->aopu.aop_dir);
1223         pcop->name = Safe_calloc(1,strlen(s)+1);
1224         strcpy(pcop->name,s);   
1225         return pcop;
1226         
1227     case AOP_REG:
1228       {
1229         int rIdx = aop->aopu.aop_reg[offset]->rIdx;
1230
1231         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1232         PCOR(pcop)->rIdx = rIdx;
1233         PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1234         pcop->type = PCOR(pcop)->r->pc_type;
1235         rs = aop->aopu.aop_reg[offset]->name;
1236         //DEBUGpic14_emitcode(";","%d regiser idx = %d name =%s",__LINE__,rIdx,rs);
1237         return pcop;
1238       }
1239
1240     case AOP_CRY:
1241       pcop = newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1242       return pcop;
1243         
1244     case AOP_LIT:
1245       return newpCodeOpLit(pic14aopLiteral (aop->aopu.aop_lit,offset));
1246
1247     case AOP_STR:
1248       DEBUGpic14_emitcode(";","%d",__LINE__);
1249
1250       pcop = Safe_calloc(1,sizeof(pCodeOp) );
1251       pcop->type = PO_STR;
1252
1253       //aop->coff = offset ;
1254       //if (strcmp(aop->aopu.aop_str[offset],"a") == 0 && dname)
1255       //  sprintf(s,"%s","acc");
1256       //else
1257       sprintf(s,"%s",aop->aopu.aop_str[offset]);
1258       pcop->name = Safe_calloc(1,strlen(s)+1);
1259       strcpy(pcop->name,s);   
1260       return pcop;
1261         
1262     }
1263
1264     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1265            "popGet got unsupported aop->type");
1266     exit(0);
1267 }
1268 /*-----------------------------------------------------------------*/
1269 /* aopPut - puts a string for a aop                                */
1270 /*-----------------------------------------------------------------*/
1271 void aopPut (asmop *aop, char *s, int offset)
1272 {
1273     char *d = buffer ;
1274     symbol *lbl ;
1275
1276     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1277
1278     if (aop->size && offset > ( aop->size - 1)) {
1279         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1280                "aopPut got offset > aop->size");
1281         exit(0);
1282     }
1283
1284     /* will assign value to value */
1285     /* depending on where it is ofcourse */
1286     switch (aop->type) {
1287     case AOP_DIR:
1288         if (offset)
1289             sprintf(d,"(%s + %d)",
1290                     aop->aopu.aop_dir,offset);
1291         else
1292             sprintf(d,"%s",aop->aopu.aop_dir);
1293         
1294         if (strcmp(d,s)) {
1295           DEBUGpic14_emitcode(";","%d",__LINE__);
1296           if(strcmp(s,"W"))
1297             pic14_emitcode("movf","%s,w",s);
1298           pic14_emitcode("movwf","%s",d);
1299
1300           if(strcmp(s,"W"))
1301             pic14_emitcode(";BUG! should have this:movf","%s,w   %d",s,__LINE__);
1302           emitpcode(POC_MOVWF,popGet(aop,offset));
1303
1304
1305         }
1306         break;
1307         
1308     case AOP_REG:
1309         if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0 &&
1310             strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1311           /*
1312             if (*s == '@'           ||
1313                 strcmp(s,"r0") == 0 ||
1314                 strcmp(s,"r1") == 0 ||
1315                 strcmp(s,"r2") == 0 ||
1316                 strcmp(s,"r3") == 0 ||
1317                 strcmp(s,"r4") == 0 ||
1318                 strcmp(s,"r5") == 0 ||
1319                 strcmp(s,"r6") == 0 || 
1320                 strcmp(s,"r7") == 0 )
1321                 pic14_emitcode("mov","%s,%s  ; %d",
1322                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1323             else
1324           */
1325
1326           if(strcmp(s,"W"))
1327             pic14_emitcode("movf","%s,w  ; %d",s,__LINE__);
1328
1329           pic14_emitcode("movwf","%s",
1330                    aop->aopu.aop_reg[offset]->name);
1331
1332           if(strcmp(s,"W")) {
1333             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1334             pcop->type = PO_GPR_REGISTER;
1335
1336             PCOR(pcop)->rIdx = -1;
1337             PCOR(pcop)->r = NULL;
1338
1339             DEBUGpic14_emitcode(";","%d",__LINE__);
1340             pcop->name = Safe_strdup(s);
1341             emitpcode(POC_MOVFW,pcop);
1342           }
1343           emitpcode(POC_MOVWF,popGet(aop,offset));
1344
1345         }
1346         break;
1347         
1348     case AOP_DPTR:
1349     case AOP_DPTR2:
1350     
1351     if (aop->type == AOP_DPTR2)
1352     {
1353         genSetDPTR(1);
1354     }
1355     
1356         if (aop->code) {
1357             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1358                    "aopPut writting to code space");
1359             exit(0);
1360         }
1361         
1362         while (offset > aop->coff) {
1363             aop->coff++;
1364             pic14_emitcode ("inc","dptr");
1365         }
1366         
1367         while (offset < aop->coff) {
1368             aop->coff-- ;
1369             pic14_emitcode("lcall","__decdptr");
1370         }
1371         
1372         aop->coff = offset;
1373         
1374         /* if not in accumulater */
1375         MOVA(s);        
1376         
1377         pic14_emitcode ("movx","@dptr,a");
1378         
1379     if (aop->type == AOP_DPTR2)
1380     {
1381         genSetDPTR(0);
1382     }
1383         break;
1384         
1385     case AOP_R0:
1386     case AOP_R1:
1387         while (offset > aop->coff) {
1388             aop->coff++;
1389             pic14_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1390         }
1391         while (offset < aop->coff) {
1392             aop->coff-- ;
1393             pic14_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1394         }
1395         aop->coff = offset;
1396         
1397         if (aop->paged) {
1398             MOVA(s);           
1399             pic14_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1400             
1401         } else
1402             if (*s == '@') {
1403                 MOVA(s);
1404                 pic14_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1405             } else
1406                 if (strcmp(s,"r0") == 0 ||
1407                     strcmp(s,"r1") == 0 ||
1408                     strcmp(s,"r2") == 0 ||
1409                     strcmp(s,"r3") == 0 ||
1410                     strcmp(s,"r4") == 0 ||
1411                     strcmp(s,"r5") == 0 ||
1412                     strcmp(s,"r6") == 0 || 
1413                     strcmp(s,"r7") == 0 ) {
1414                     char buffer[10];
1415                     sprintf(buffer,"a%s",s);
1416                     pic14_emitcode("mov","@%s,%s",
1417                              aop->aopu.aop_ptr->name,buffer);
1418                 } else
1419                     pic14_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1420         
1421         break;
1422         
1423     case AOP_STK:
1424         if (strcmp(s,"a") == 0)
1425             pic14_emitcode("push","acc");
1426         else
1427             pic14_emitcode("push","%s",s);
1428         
1429         break;
1430         
1431     case AOP_CRY:
1432         /* if bit variable */
1433         if (!aop->aopu.aop_dir) {
1434             pic14_emitcode("clr","a");
1435             pic14_emitcode("rlc","a");
1436         } else {
1437             if (s == zero) 
1438                 pic14_emitcode("clr","%s",aop->aopu.aop_dir);
1439             else
1440                 if (s == one)
1441                     pic14_emitcode("setb","%s",aop->aopu.aop_dir);
1442                 else
1443                     if (!strcmp(s,"c"))
1444                         pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1445                     else {
1446                         lbl = newiTempLabel(NULL);
1447                         
1448                         if (strcmp(s,"a")) {
1449                             MOVA(s);
1450                         }
1451                         pic14_emitcode("clr","c");
1452                         pic14_emitcode("jz","%05d_DS_",lbl->key+100);
1453                         pic14_emitcode("cpl","c");
1454                         pic14_emitcode("","%05d_DS_:",lbl->key+100);
1455                         pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1456                     }
1457         }
1458         break;
1459         
1460     case AOP_STR:
1461         aop->coff = offset;
1462         if (strcmp(aop->aopu.aop_str[offset],s))
1463             pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1464         break;
1465         
1466     case AOP_ACC:
1467         aop->coff = offset;
1468         if (!offset && (strcmp(s,"acc") == 0))
1469             break;
1470         
1471         if (strcmp(aop->aopu.aop_str[offset],s))
1472             pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1473         break;
1474
1475     default :
1476         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1477                "aopPut got unsupported aop->type");
1478         exit(0);    
1479     }    
1480
1481 }
1482
1483 /*-----------------------------------------------------------------*/
1484 /* reAdjustPreg - points a register back to where it should        */
1485 /*-----------------------------------------------------------------*/
1486 static void reAdjustPreg (asmop *aop)
1487 {
1488     int size ;
1489
1490     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1491     aop->coff = 0;
1492     if ((size = aop->size) <= 1)
1493         return ;
1494     size-- ;
1495     switch (aop->type) {
1496         case AOP_R0 :
1497         case AOP_R1 :
1498             while (size--)
1499                 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1500             break;          
1501         case AOP_DPTR :
1502         case AOP_DPTR2:
1503             if (aop->type == AOP_DPTR2)
1504             {
1505                 genSetDPTR(1);
1506             } 
1507             while (size--)
1508             {
1509                 pic14_emitcode("lcall","__decdptr");
1510             }
1511                 
1512             if (aop->type == AOP_DPTR2)
1513             {
1514                 genSetDPTR(0);
1515             }                
1516             break;  
1517
1518     }   
1519
1520 }
1521
1522 /*-----------------------------------------------------------------*/
1523 /* genNotFloat - generates not for float operations              */
1524 /*-----------------------------------------------------------------*/
1525 static void genNotFloat (operand *op, operand *res)
1526 {
1527     int size, offset;
1528     char *l;
1529     symbol *tlbl ;
1530
1531     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1532     /* we will put 127 in the first byte of 
1533     the result */
1534     aopPut(AOP(res),"#127",0);
1535     size = AOP_SIZE(op) - 1;
1536     offset = 1;
1537
1538     l = aopGet(op->aop,offset++,FALSE,FALSE);
1539     MOVA(l);    
1540
1541     while(size--) {
1542         pic14_emitcode("orl","a,%s",
1543                  aopGet(op->aop,
1544                         offset++,FALSE,FALSE));
1545     }
1546     tlbl = newiTempLabel(NULL);
1547
1548     tlbl = newiTempLabel(NULL);
1549     aopPut(res->aop,one,1);
1550     pic14_emitcode("jz","%05d_DS_",(tlbl->key+100));
1551     aopPut(res->aop,zero,1);
1552     pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
1553
1554     size = res->aop->size - 2;
1555     offset = 2;    
1556     /* put zeros in the rest */
1557     while (size--) 
1558         aopPut(res->aop,zero,offset++);
1559 }
1560
1561 #if 0
1562 /*-----------------------------------------------------------------*/
1563 /* opIsGptr: returns non-zero if the passed operand is             */   
1564 /* a generic pointer type.                                         */
1565 /*-----------------------------------------------------------------*/ 
1566 static int opIsGptr(operand *op)
1567 {
1568     sym_link *type = operandType(op);
1569     
1570     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1571     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1572     {
1573         return 1;
1574     }
1575     return 0;        
1576 }
1577 #endif
1578
1579 /*-----------------------------------------------------------------*/
1580 /* pic14_getDataSize - get the operand data size                         */
1581 /*-----------------------------------------------------------------*/
1582 int pic14_getDataSize(operand *op)
1583 {
1584     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1585
1586
1587     return AOP_SIZE(op);
1588
1589     // tsd- in the pic port, the genptr size is 1, so this code here
1590     // fails. ( in the 8051 port, the size was 4).
1591 #if 0
1592     int size;
1593     size = AOP_SIZE(op);
1594     if (size == GPTRSIZE)
1595     {
1596         sym_link *type = operandType(op);
1597         if (IS_GENPTR(type))
1598         {
1599             /* generic pointer; arithmetic operations
1600              * should ignore the high byte (pointer type).
1601              */
1602             size--;
1603     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1604         }
1605     }
1606     return size;
1607 #endif
1608 }
1609
1610 /*-----------------------------------------------------------------*/
1611 /* pic14_outAcc - output Acc                                             */
1612 /*-----------------------------------------------------------------*/
1613 void pic14_outAcc(operand *result)
1614 {
1615   int size,offset;
1616   DEBUGpic14_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
1617   DEBUGpic14_AopType(__LINE__,NULL,NULL,result);
1618
1619
1620   size = pic14_getDataSize(result);
1621   if(size){
1622     emitpcode(POC_MOVWF,popGet(AOP(result),0));
1623     size--;
1624     offset = 1;
1625     /* unsigned or positive */
1626     while(size--)
1627       emitpcode(POC_CLRF,popGet(AOP(result),offset++));
1628   }
1629
1630 }
1631
1632 /*-----------------------------------------------------------------*/
1633 /* pic14_outBitC - output a bit C                                        */
1634 /*-----------------------------------------------------------------*/
1635 void pic14_outBitC(operand *result)
1636 {
1637
1638     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1639     /* if the result is bit */
1640     if (AOP_TYPE(result) == AOP_CRY) 
1641         aopPut(AOP(result),"c",0);
1642     else {
1643         pic14_emitcode("clr","a  ; %d", __LINE__);
1644         pic14_emitcode("rlc","a");
1645         pic14_outAcc(result);
1646     }
1647 }
1648
1649 /*-----------------------------------------------------------------*/
1650 /* pic14_toBoolean - emit code for orl a,operator(sizeop)                */
1651 /*-----------------------------------------------------------------*/
1652 void pic14_toBoolean(operand *oper)
1653 {
1654     int size = AOP_SIZE(oper) - 1;
1655     int offset = 1;
1656
1657     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1658
1659     if ( AOP_TYPE(oper) != AOP_ACC) {
1660       emitpcode(POC_MOVFW,popGet(AOP(oper),0));
1661     }
1662     while (size--) {
1663       emitpcode(POC_IORFW, popGet(AOP(oper),offset++));
1664     }
1665 }
1666
1667
1668 /*-----------------------------------------------------------------*/
1669 /* genNot - generate code for ! operation                          */
1670 /*-----------------------------------------------------------------*/
1671 static void genNot (iCode *ic)
1672 {
1673   symbol *tlbl;
1674   sym_link *optype = operandType(IC_LEFT(ic));
1675   int size;
1676
1677   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1678   /* assign asmOps to operand & result */
1679   aopOp (IC_LEFT(ic),ic,FALSE);
1680   aopOp (IC_RESULT(ic),ic,TRUE);
1681
1682   DEBUGpic14_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
1683   /* if in bit space then a special case */
1684   if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1685     pic14_emitcode("movlw","1<<%s");
1686     //pic14_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
1687     //pic14_emitcode("cpl","c"); 
1688     //pic14_outBitC(IC_RESULT(ic));
1689     goto release;
1690   }
1691
1692   /* if type float then do float */
1693   if (IS_FLOAT(optype)) {
1694     genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
1695     goto release;
1696   }
1697
1698   size = AOP_SIZE(IC_RESULT(ic));
1699   if(size == 1) {
1700     emitpcode(POC_COMFW,popGet(AOP(IC_LEFT(ic)),0));
1701     emitpcode(POC_ANDLW,popGetLit(1));
1702     emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0));
1703     goto release;
1704   }
1705   pic14_toBoolean(IC_LEFT(ic));
1706
1707   tlbl = newiTempLabel(NULL);
1708   pic14_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
1709   pic14_emitcode("","%05d_DS_:",tlbl->key+100);
1710   pic14_outBitC(IC_RESULT(ic));
1711
1712  release:    
1713   /* release the aops */
1714   freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1715   freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1716 }
1717
1718
1719 /*-----------------------------------------------------------------*/
1720 /* genCpl - generate code for complement                           */
1721 /*-----------------------------------------------------------------*/
1722 static void genCpl (iCode *ic)
1723 {
1724     int offset = 0;
1725     int size ;
1726
1727
1728     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1729     /* assign asmOps to operand & result */
1730     aopOp (IC_LEFT(ic),ic,FALSE);
1731     aopOp (IC_RESULT(ic),ic,TRUE);
1732
1733     /* if both are in bit space then 
1734     a special case */
1735     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1736         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
1737
1738         pic14_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
1739         pic14_emitcode("cpl","c"); 
1740         pic14_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
1741         goto release; 
1742     } 
1743
1744     size = AOP_SIZE(IC_RESULT(ic));
1745     while (size--) {
1746         char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1747         MOVA(l);       
1748         pic14_emitcode("cpl","a");
1749         aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1750     }
1751
1752
1753 release:
1754     /* release the aops */
1755     freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1756     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1757 }
1758
1759 /*-----------------------------------------------------------------*/
1760 /* genUminusFloat - unary minus for floating points                */
1761 /*-----------------------------------------------------------------*/
1762 static void genUminusFloat(operand *op,operand *result)
1763 {
1764     int size ,offset =0 ;
1765     char *l;
1766
1767     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1768     /* for this we just need to flip the 
1769     first it then copy the rest in place */
1770     size = AOP_SIZE(op) - 1;
1771     l = aopGet(AOP(op),3,FALSE,FALSE);
1772
1773     MOVA(l);    
1774
1775     pic14_emitcode("cpl","acc.7");
1776     aopPut(AOP(result),"a",3);    
1777
1778     while(size--) {
1779         aopPut(AOP(result),
1780                aopGet(AOP(op),offset,FALSE,FALSE),
1781                offset);
1782         offset++;
1783     }          
1784 }
1785
1786 /*-----------------------------------------------------------------*/
1787 /* genUminus - unary minus code generation                         */
1788 /*-----------------------------------------------------------------*/
1789 static void genUminus (iCode *ic)
1790 {
1791   int size, i;
1792   sym_link *optype, *rtype;
1793
1794
1795   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1796   /* assign asmops */
1797   aopOp(IC_LEFT(ic),ic,FALSE);
1798   aopOp(IC_RESULT(ic),ic,TRUE);
1799
1800   /* if both in bit space then special
1801      case */
1802   if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1803       AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
1804
1805     emitpcode(POC_BCF,   popGet(AOP(IC_RESULT(ic)),0));
1806     emitpcode(POC_BTFSS, popGet(AOP(IC_LEFT(ic)),0));
1807     emitpcode(POC_BSF,   popGet(AOP(IC_RESULT(ic)),0));
1808
1809     goto release; 
1810   } 
1811
1812   optype = operandType(IC_LEFT(ic));
1813   rtype = operandType(IC_RESULT(ic));
1814
1815   /* if float then do float stuff */
1816   if (IS_FLOAT(optype)) {
1817     genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1818     goto release;
1819   }
1820
1821   /* otherwise subtract from zero by taking the 2's complement */
1822   size = AOP_SIZE(IC_LEFT(ic));
1823
1824   for(i=0; i<size; i++) {
1825     if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
1826       emitpcode(POC_COMF,  popGet(AOP(IC_LEFT(ic)),i));
1827     else {
1828       emitpcode(POC_COMFW, popGet(AOP(IC_LEFT(ic)),i));
1829       emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),i));
1830     }
1831   }
1832
1833   emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),0));
1834   for(i=1; i<size; i++) {
1835     emitSKPNZ;
1836     emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),i));
1837   }
1838
1839  release:
1840   /* release the aops */
1841   freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1842   freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
1843 }
1844
1845 /*-----------------------------------------------------------------*/
1846 /* saveRegisters - will look for a call and save the registers     */
1847 /*-----------------------------------------------------------------*/
1848 static void saveRegisters(iCode *lic) 
1849 {
1850     int i;
1851     iCode *ic;
1852     bitVect *rsave;
1853     sym_link *dtype;
1854
1855     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1856     /* look for call */
1857     for (ic = lic ; ic ; ic = ic->next) 
1858         if (ic->op == CALL || ic->op == PCALL)
1859             break;
1860
1861     if (!ic) {
1862         fprintf(stderr,"found parameter push with no function call\n");
1863         return ;
1864     }
1865
1866     /* if the registers have been saved already then
1867     do nothing */
1868     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
1869         return ;
1870
1871     /* find the registers in use at this time 
1872     and push them away to safety */
1873     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1874                           ic->rUsed);
1875
1876     ic->regsSaved = 1;
1877     if (options.useXstack) {
1878         if (bitVectBitValue(rsave,R0_IDX))
1879             pic14_emitcode("mov","b,r0");
1880         pic14_emitcode("mov","r0,%s",spname);
1881         for (i = 0 ; i < pic14_nRegs ; i++) {
1882             if (bitVectBitValue(rsave,i)) {
1883                 if (i == R0_IDX)
1884                     pic14_emitcode("mov","a,b");
1885                 else
1886                     pic14_emitcode("mov","a,%s",pic14_regWithIdx(i)->name);
1887                 pic14_emitcode("movx","@r0,a");
1888                 pic14_emitcode("inc","r0");
1889             }
1890         }
1891         pic14_emitcode("mov","%s,r0",spname);
1892         if (bitVectBitValue(rsave,R0_IDX))
1893             pic14_emitcode("mov","r0,b");           
1894     } else
1895         for (i = 0 ; i < pic14_nRegs ; i++) {
1896             if (bitVectBitValue(rsave,i))
1897                 pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
1898         }
1899
1900     dtype = operandType(IC_LEFT(ic));
1901     if (currFunc && dtype && 
1902         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
1903         IFFUNC_ISISR(currFunc->type) &&
1904         !ic->bankSaved) 
1905
1906         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
1907
1908 }
1909 /*-----------------------------------------------------------------*/
1910 /* unsaveRegisters - pop the pushed registers                      */
1911 /*-----------------------------------------------------------------*/
1912 static void unsaveRegisters (iCode *ic)
1913 {
1914     int i;
1915     bitVect *rsave;
1916
1917     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1918     /* find the registers in use at this time 
1919     and push them away to safety */
1920     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1921                           ic->rUsed);
1922     
1923     if (options.useXstack) {
1924         pic14_emitcode("mov","r0,%s",spname);   
1925         for (i =  pic14_nRegs ; i >= 0 ; i--) {
1926             if (bitVectBitValue(rsave,i)) {
1927                 pic14_emitcode("dec","r0");
1928                 pic14_emitcode("movx","a,@r0");
1929                 if (i == R0_IDX)
1930                     pic14_emitcode("mov","b,a");
1931                 else
1932                     pic14_emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
1933             }       
1934
1935         }
1936         pic14_emitcode("mov","%s,r0",spname);
1937         if (bitVectBitValue(rsave,R0_IDX))
1938             pic14_emitcode("mov","r0,b");
1939     } else
1940         for (i =  pic14_nRegs ; i >= 0 ; i--) {
1941             if (bitVectBitValue(rsave,i))
1942                 pic14_emitcode("pop","%s",pic14_regWithIdx(i)->dname);
1943         }
1944
1945 }  
1946
1947
1948 /*-----------------------------------------------------------------*/
1949 /* pushSide -                                                      */
1950 /*-----------------------------------------------------------------*/
1951 static void pushSide(operand * oper, int size)
1952 {
1953 #if 0
1954         int offset = 0;
1955     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1956         while (size--) {
1957                 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
1958                 if (AOP_TYPE(oper) != AOP_REG &&
1959                     AOP_TYPE(oper) != AOP_DIR &&
1960                     strcmp(l,"a") ) {
1961                         pic14_emitcode("mov","a,%s",l);
1962                         pic14_emitcode("push","acc");
1963                 } else
1964                         pic14_emitcode("push","%s",l);
1965         }
1966 #endif
1967 }
1968
1969 /*-----------------------------------------------------------------*/
1970 /* assignResultValue -                                             */
1971 /*-----------------------------------------------------------------*/
1972 static void assignResultValue(operand * oper)
1973 {
1974   int size = AOP_SIZE(oper);
1975
1976   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1977
1978   if(!GpsuedoStkPtr) {
1979     /* The last byte in the assignment is in W */
1980     size--;
1981     emitpcode(POC_MOVWF, popGet(AOP(oper),size));
1982     GpsuedoStkPtr++;
1983   }
1984
1985   while (size--) {
1986     emitpcode(POC_MOVFW,popRegFromIdx(GpsuedoStkPtr-1 + Gstack_base_addr));
1987     GpsuedoStkPtr++;
1988     emitpcode(POC_MOVWF, popGet(AOP(oper),size));
1989   }
1990 }
1991
1992
1993 /*-----------------------------------------------------------------*/
1994 /* genIpush - genrate code for pushing this gets a little complex  */
1995 /*-----------------------------------------------------------------*/
1996 static void genIpush (iCode *ic)
1997 {
1998
1999   DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2000 #if 0
2001     int size, offset = 0 ;
2002     char *l;
2003
2004
2005     /* if this is not a parm push : ie. it is spill push 
2006     and spill push is always done on the local stack */
2007     if (!ic->parmPush) {
2008
2009         /* and the item is spilt then do nothing */
2010         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2011             return ;
2012
2013         aopOp(IC_LEFT(ic),ic,FALSE);
2014         size = AOP_SIZE(IC_LEFT(ic));
2015         /* push it on the stack */
2016         while(size--) {
2017             l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2018             if (*l == '#') {
2019                 MOVA(l);
2020                 l = "acc";
2021             }
2022             pic14_emitcode("push","%s",l);
2023         }
2024         return ;        
2025     }
2026
2027     /* this is a paramter push: in this case we call
2028     the routine to find the call and save those
2029     registers that need to be saved */   
2030     saveRegisters(ic);
2031
2032     /* then do the push */
2033     aopOp(IC_LEFT(ic),ic,FALSE);
2034
2035
2036         // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2037     size = AOP_SIZE(IC_LEFT(ic));
2038
2039     while (size--) {
2040         l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2041         if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && 
2042             AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2043             strcmp(l,"a") ) {
2044             pic14_emitcode("mov","a,%s",l);
2045             pic14_emitcode("push","acc");
2046         } else
2047             pic14_emitcode("push","%s",l);
2048     }       
2049
2050     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2051 #endif
2052 }
2053
2054 /*-----------------------------------------------------------------*/
2055 /* genIpop - recover the registers: can happen only for spilling   */
2056 /*-----------------------------------------------------------------*/
2057 static void genIpop (iCode *ic)
2058 {
2059   DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2060 #if 0
2061     int size,offset ;
2062
2063
2064     /* if the temp was not pushed then */
2065     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2066         return ;
2067
2068     aopOp(IC_LEFT(ic),ic,FALSE);
2069     size = AOP_SIZE(IC_LEFT(ic));
2070     offset = (size-1);
2071     while (size--) 
2072         pic14_emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
2073                                    FALSE,TRUE));
2074
2075     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2076 #endif
2077 }
2078
2079 /*-----------------------------------------------------------------*/
2080 /* unsaverbank - restores the resgister bank from stack            */
2081 /*-----------------------------------------------------------------*/
2082 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2083 {
2084   DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2085 #if 0
2086     int i;
2087     asmop *aop ;
2088     regs *r = NULL;
2089
2090     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2091     if (popPsw) {
2092         if (options.useXstack) {
2093             aop = newAsmop(0);
2094             r = getFreePtr(ic,&aop,FALSE);
2095             
2096             
2097             pic14_emitcode("mov","%s,_spx",r->name);
2098             pic14_emitcode("movx","a,@%s",r->name);
2099             pic14_emitcode("mov","psw,a");
2100             pic14_emitcode("dec","%s",r->name);
2101             
2102         }else
2103             pic14_emitcode ("pop","psw");
2104     }
2105
2106     for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
2107         if (options.useXstack) {       
2108             pic14_emitcode("movx","a,@%s",r->name);
2109             //pic14_emitcode("mov","(%s+%d),a",
2110             //       regspic14[i].base,8*bank+regspic14[i].offset);
2111             pic14_emitcode("dec","%s",r->name);
2112
2113         } else 
2114           pic14_emitcode("pop",""); //"(%s+%d)",
2115         //regspic14[i].base,8*bank); //+regspic14[i].offset);
2116     }
2117
2118     if (options.useXstack) {
2119
2120         pic14_emitcode("mov","_spx,%s",r->name);
2121         freeAsmop(NULL,aop,ic,TRUE);
2122
2123     }
2124 #endif 
2125 }
2126
2127 /*-----------------------------------------------------------------*/
2128 /* saverbank - saves an entire register bank on the stack          */
2129 /*-----------------------------------------------------------------*/
2130 static void saverbank (int bank, iCode *ic, bool pushPsw)
2131 {
2132   DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2133 #if 0
2134     int i;
2135     asmop *aop ;
2136     regs *r = NULL;
2137
2138     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2139     if (options.useXstack) {
2140
2141         aop = newAsmop(0);
2142         r = getFreePtr(ic,&aop,FALSE);  
2143         pic14_emitcode("mov","%s,_spx",r->name);
2144
2145     }
2146
2147     for (i = 0 ; i < pic14_nRegs ;i++) {
2148         if (options.useXstack) {
2149             pic14_emitcode("inc","%s",r->name);
2150             //pic14_emitcode("mov","a,(%s+%d)",
2151             //         regspic14[i].base,8*bank+regspic14[i].offset);
2152             pic14_emitcode("movx","@%s,a",r->name);           
2153         } else 
2154           pic14_emitcode("push","");// "(%s+%d)",
2155                      //regspic14[i].base,8*bank+regspic14[i].offset);
2156     }
2157     
2158     if (pushPsw) {
2159         if (options.useXstack) {
2160             pic14_emitcode("mov","a,psw");
2161             pic14_emitcode("movx","@%s,a",r->name);     
2162             pic14_emitcode("inc","%s",r->name);
2163             pic14_emitcode("mov","_spx,%s",r->name);       
2164             freeAsmop (NULL,aop,ic,TRUE);
2165             
2166         } else
2167             pic14_emitcode("push","psw");
2168         
2169         pic14_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2170     }
2171     ic->bankSaved = 1;
2172 #endif
2173 }
2174
2175 /*-----------------------------------------------------------------*/
2176 /* genCall - generates a call statement                            */
2177 /*-----------------------------------------------------------------*/
2178 static void genCall (iCode *ic)
2179 {
2180   sym_link *dtype;   
2181
2182   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2183
2184   /* if caller saves & we have not saved then */
2185   if (!ic->regsSaved)
2186     saveRegisters(ic);
2187
2188   /* if we are calling a function that is not using
2189      the same register bank then we need to save the
2190      destination registers on the stack */
2191   dtype = operandType(IC_LEFT(ic));
2192   if (currFunc && dtype && 
2193       (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2194       IFFUNC_ISISR(currFunc->type) &&
2195       !ic->bankSaved) 
2196
2197     saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2198
2199   /* if send set is not empty the assign */
2200   if (_G.sendSet) {
2201     iCode *sic;
2202     /* For the Pic port, there is no data stack.
2203      * So parameters passed to functions are stored
2204      * in registers. (The pCode optimizer will get
2205      * rid of most of these :).
2206      */
2207     int psuedoStkPtr=-1; 
2208     int firstTimeThruLoop = 1;
2209
2210     _G.sendSet = reverseSet(_G.sendSet);
2211
2212     /* First figure how many parameters are getting passed */
2213     for (sic = setFirstItem(_G.sendSet) ; sic ; 
2214          sic = setNextItem(_G.sendSet)) {
2215
2216       aopOp(IC_LEFT(sic),sic,FALSE);
2217       psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2218       freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2219     }
2220
2221     for (sic = setFirstItem(_G.sendSet) ; sic ; 
2222          sic = setNextItem(_G.sendSet)) {
2223       int size, offset = 0;
2224
2225       aopOp(IC_LEFT(sic),sic,FALSE);
2226       size = AOP_SIZE(IC_LEFT(sic));
2227
2228
2229       while (size--) {
2230         DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2231                              AopType(AOP_TYPE(IC_LEFT(sic))));
2232
2233         if(!firstTimeThruLoop) {
2234           /* If this is not the first time we've been through the loop
2235            * then we need to save the parameter in a temporary
2236            * register. The last byte of the last parameter is
2237            * passed in W. */
2238           emitpcode(POC_MOVWF,popRegFromIdx(--psuedoStkPtr + Gstack_base_addr));
2239
2240         }
2241         firstTimeThruLoop=0;
2242
2243         //if (strcmp(l,fReturn[offset])) {
2244
2245         if ( ((AOP(IC_LEFT(sic))->type) == AOP_IMMD) ||
2246              ((AOP(IC_LEFT(sic))->type) == AOP_LIT) )
2247           emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(sic)),offset));
2248         else
2249           emitpcode(POC_MOVFW,popGet(AOP(IC_LEFT(sic)),offset));
2250
2251         //}
2252         offset++;
2253       }
2254       freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2255     }
2256     _G.sendSet = NULL;
2257   }
2258   /* make the call */
2259   emitpcode(POC_CALL,popGetWithString(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2260                                       OP_SYMBOL(IC_LEFT(ic))->rname :
2261                                       OP_SYMBOL(IC_LEFT(ic))->name));
2262
2263   GpsuedoStkPtr=0;
2264   /* if we need assign a result value */
2265   if ((IS_ITEMP(IC_RESULT(ic)) && 
2266        (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2267         OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2268       IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2269
2270     _G.accInUse++;
2271     aopOp(IC_RESULT(ic),ic,FALSE);
2272     _G.accInUse--;
2273
2274     assignResultValue(IC_RESULT(ic));
2275
2276     DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2277                          AopType(AOP_TYPE(IC_RESULT(ic))));
2278                 
2279     freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2280   }
2281
2282   /* adjust the stack for parameters if 
2283      required */
2284   if (ic->parmBytes) {
2285     int i;
2286     if (ic->parmBytes > 3) {
2287       pic14_emitcode("mov","a,%s",spname);
2288       pic14_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2289       pic14_emitcode("mov","%s,a",spname);
2290     } else 
2291       for ( i = 0 ; i <  ic->parmBytes ;i++)
2292         pic14_emitcode("dec","%s",spname);
2293
2294   }
2295
2296   /* if register bank was saved then pop them */
2297   if (ic->bankSaved)
2298     unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2299
2300   /* if we hade saved some registers then unsave them */
2301   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2302     unsaveRegisters (ic);
2303
2304
2305 }
2306
2307 /*-----------------------------------------------------------------*/
2308 /* genPcall - generates a call by pointer statement                */
2309 /*-----------------------------------------------------------------*/
2310 static void genPcall (iCode *ic)
2311 {
2312     sym_link *dtype;
2313     symbol *rlbl = newiTempLabel(NULL);
2314
2315
2316     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2317     /* if caller saves & we have not saved then */
2318     if (!ic->regsSaved)
2319         saveRegisters(ic);
2320
2321     /* if we are calling a function that is not using
2322     the same register bank then we need to save the
2323     destination registers on the stack */
2324     dtype = operandType(IC_LEFT(ic));
2325     if (currFunc && dtype && 
2326         IFFUNC_ISISR(currFunc->type) &&
2327         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2328         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2329
2330
2331     /* push the return address on to the stack */
2332     pic14_emitcode("mov","a,#%05d_DS_",(rlbl->key+100));
2333     pic14_emitcode("push","acc");    
2334     pic14_emitcode("mov","a,#(%05d_DS_ >> 8)",(rlbl->key+100));
2335     pic14_emitcode("push","acc");
2336     
2337     if (options.model == MODEL_FLAT24)
2338     {
2339         pic14_emitcode("mov","a,#(%05d_DS_ >> 16)",(rlbl->key+100));
2340         pic14_emitcode("push","acc");    
2341     }
2342
2343     /* now push the calling address */
2344     aopOp(IC_LEFT(ic),ic,FALSE);
2345
2346     pushSide(IC_LEFT(ic), FPTRSIZE);
2347
2348     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
2349
2350     /* if send set is not empty the assign */
2351     if (_G.sendSet) {
2352         iCode *sic ;
2353
2354         for (sic = setFirstItem(_G.sendSet) ; sic ; 
2355              sic = setNextItem(_G.sendSet)) {
2356             int size, offset = 0;
2357             aopOp(IC_LEFT(sic),sic,FALSE);
2358             size = AOP_SIZE(IC_LEFT(sic));
2359             while (size--) {
2360                 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
2361                                 FALSE,FALSE);
2362                 if (strcmp(l,fReturn[offset]))
2363                     pic14_emitcode("mov","%s,%s",
2364                              fReturn[offset],
2365                              l);
2366                 offset++;
2367             }
2368             freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2369         }
2370         _G.sendSet = NULL;
2371     }
2372
2373     pic14_emitcode("ret","");
2374     pic14_emitcode("","%05d_DS_:",(rlbl->key+100));
2375
2376
2377     /* if we need assign a result value */
2378     if ((IS_ITEMP(IC_RESULT(ic)) &&
2379          (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2380           OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2381         IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2382
2383         _G.accInUse++;
2384         aopOp(IC_RESULT(ic),ic,FALSE);
2385         _G.accInUse--;
2386         
2387         assignResultValue(IC_RESULT(ic));
2388
2389         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2390     }
2391
2392     /* adjust the stack for parameters if 
2393     required */
2394     if (ic->parmBytes) {
2395         int i;
2396         if (ic->parmBytes > 3) {
2397             pic14_emitcode("mov","a,%s",spname);
2398             pic14_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2399             pic14_emitcode("mov","%s,a",spname);
2400         } else 
2401             for ( i = 0 ; i <  ic->parmBytes ;i++)
2402                 pic14_emitcode("dec","%s",spname);
2403
2404     }
2405
2406     /* if register bank was saved then unsave them */
2407     if (currFunc && dtype && 
2408         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2409         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2410
2411     /* if we hade saved some registers then
2412     unsave them */
2413     if (ic->regsSaved)
2414         unsaveRegisters (ic);
2415
2416 }
2417
2418 /*-----------------------------------------------------------------*/
2419 /* resultRemat - result  is rematerializable                       */
2420 /*-----------------------------------------------------------------*/
2421 static int resultRemat (iCode *ic)
2422 {
2423     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2424     if (SKIP_IC(ic) || ic->op == IFX)
2425         return 0;
2426
2427     if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2428         symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2429         if (sym->remat && !POINTER_SET(ic)) 
2430             return 1;
2431     }
2432
2433     return 0;
2434 }
2435
2436 #if defined(__BORLANDC__) || defined(_MSC_VER)
2437 #define STRCASECMP stricmp
2438 #else
2439 #define STRCASECMP strcasecmp
2440 #endif
2441
2442 /*-----------------------------------------------------------------*/
2443 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2444 /*-----------------------------------------------------------------*/
2445 static bool inExcludeList(char *s)
2446 {
2447   DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2448 #if 0
2449     int i =0;
2450     
2451     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2452     if (options.excludeRegs[i] &&
2453     STRCASECMP(options.excludeRegs[i],"none") == 0)
2454         return FALSE ;
2455
2456     for ( i = 0 ; options.excludeRegs[i]; i++) {
2457         if (options.excludeRegs[i] &&
2458         STRCASECMP(s,options.excludeRegs[i]) == 0)
2459             return TRUE;
2460     }
2461 #endif
2462     return FALSE ;
2463 }
2464
2465 /*-----------------------------------------------------------------*/
2466 /* genFunction - generated code for function entry                 */
2467 /*-----------------------------------------------------------------*/
2468 static void genFunction (iCode *ic)
2469 {
2470     symbol *sym;
2471     sym_link *ftype;
2472
2473     DEBUGpic14_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2474
2475     labelOffset += (max_key+4);
2476     max_key=0;
2477     GpsuedoStkPtr=0;
2478     _G.nRegsSaved = 0;
2479     /* create the function header */
2480     pic14_emitcode(";","-----------------------------------------");
2481     pic14_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2482     pic14_emitcode(";","-----------------------------------------");
2483
2484     pic14_emitcode("","%s:",sym->rname);
2485     addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname));
2486
2487     ftype = operandType(IC_LEFT(ic));
2488
2489     /* if critical function then turn interrupts off */
2490     if (IFFUNC_ISCRITICAL(ftype))
2491         pic14_emitcode("clr","ea");
2492
2493     /* here we need to generate the equates for the
2494        register bank if required */
2495 #if 0
2496     if (FUNC_REGBANK(ftype) != rbank) {
2497         int i ;
2498
2499         rbank = FUNC_REGBANK(ftype);
2500         for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2501             if (strcmp(regspic14[i].base,"0") == 0)
2502                 pic14_emitcode("","%s = 0x%02x",
2503                          regspic14[i].dname,
2504                          8*rbank+regspic14[i].offset);
2505             else
2506                 pic14_emitcode ("","%s = %s + 0x%02x",
2507                           regspic14[i].dname,
2508                           regspic14[i].base,
2509                           8*rbank+regspic14[i].offset);
2510         }
2511     }
2512 #endif
2513
2514     /* if this is an interrupt service routine then
2515     save acc, b, dpl, dph  */
2516     if (IFFUNC_ISISR(sym->type)) {
2517         
2518         if (!inExcludeList("acc"))          
2519             pic14_emitcode ("push","acc");      
2520         if (!inExcludeList("b"))
2521             pic14_emitcode ("push","b");
2522         if (!inExcludeList("dpl"))
2523             pic14_emitcode ("push","dpl");
2524         if (!inExcludeList("dph"))
2525             pic14_emitcode ("push","dph");
2526         if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2527         {
2528             pic14_emitcode ("push", "dpx");
2529             /* Make sure we're using standard DPTR */
2530             pic14_emitcode ("push", "dps");
2531             pic14_emitcode ("mov", "dps, #0x00");
2532             if (options.stack10bit)
2533             {   
2534                 /* This ISR could conceivably use DPTR2. Better save it. */
2535                 pic14_emitcode ("push", "dpl1");
2536                 pic14_emitcode ("push", "dph1");
2537                 pic14_emitcode ("push", "dpx1");
2538             }
2539         }
2540         /* if this isr has no bank i.e. is going to
2541            run with bank 0 , then we need to save more
2542            registers :-) */
2543         if (!FUNC_REGBANK(sym->type)) {
2544
2545             /* if this function does not call any other
2546                function then we can be economical and
2547                save only those registers that are used */
2548             if (! IFFUNC_HASFCALL(sym->type)) {
2549                 int i;
2550
2551                 /* if any registers used */
2552                 if (sym->regsUsed) {
2553                     /* save the registers used */
2554                     for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2555                         if (bitVectBitValue(sym->regsUsed,i) ||
2556                           (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2557                             pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);                         
2558                     }
2559                 }
2560                 
2561             } else {
2562                 /* this function has  a function call cannot
2563                    determines register usage so we will have the
2564                    entire bank */
2565                 saverbank(0,ic,FALSE);
2566             }       
2567         }
2568     } else {
2569         /* if callee-save to be used for this function
2570            then save the registers being used in this function */
2571         if (IFFUNC_CALLEESAVES(sym->type)) {
2572             int i;
2573             
2574             /* if any registers used */
2575             if (sym->regsUsed) {
2576                 /* save the registers used */
2577                 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2578                     if (bitVectBitValue(sym->regsUsed,i) ||
2579                       (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2580                         pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2581                         _G.nRegsSaved++;
2582                     }
2583                 }
2584             }
2585         }
2586     }
2587
2588     /* set the register bank to the desired value */
2589     if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type)) {
2590         pic14_emitcode("push","psw");
2591         pic14_emitcode("mov","psw,#0x%02x",(FUNC_REGBANK(sym->type) << 3)&0x00ff);   
2592     }
2593
2594     if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
2595
2596         if (options.useXstack) {
2597             pic14_emitcode("mov","r0,%s",spname);
2598             pic14_emitcode("mov","a,_bp");
2599             pic14_emitcode("movx","@r0,a");
2600             pic14_emitcode("inc","%s",spname);
2601         }
2602         else
2603         {
2604             /* set up the stack */
2605             pic14_emitcode ("push","_bp");     /* save the callers stack  */
2606         }
2607         pic14_emitcode ("mov","_bp,%s",spname);
2608     }
2609
2610     /* adjust the stack for the function */
2611     if (sym->stack) {
2612
2613         int i = sym->stack;
2614         if (i > 256 ) 
2615             werror(W_STACK_OVERFLOW,sym->name);
2616
2617         if (i > 3 && sym->recvSize < 4) {              
2618
2619             pic14_emitcode ("mov","a,sp");
2620             pic14_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2621             pic14_emitcode ("mov","sp,a");
2622            
2623         }
2624         else
2625             while(i--)
2626                 pic14_emitcode("inc","sp");
2627     }
2628
2629      if (sym->xstack) {
2630
2631         pic14_emitcode ("mov","a,_spx");
2632         pic14_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2633         pic14_emitcode ("mov","_spx,a");
2634     }    
2635
2636 }
2637
2638 /*-----------------------------------------------------------------*/
2639 /* genEndFunction - generates epilogue for functions               */
2640 /*-----------------------------------------------------------------*/
2641 static void genEndFunction (iCode *ic)
2642 {
2643     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2644
2645     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2646
2647     if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
2648     {
2649         pic14_emitcode ("mov","%s,_bp",spname);
2650     }
2651
2652     /* if use external stack but some variables were
2653     added to the local stack then decrement the
2654     local stack */
2655     if (options.useXstack && sym->stack) {      
2656         pic14_emitcode("mov","a,sp");
2657         pic14_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2658         pic14_emitcode("mov","sp,a");
2659     }
2660
2661
2662     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
2663         if (options.useXstack) {
2664             pic14_emitcode("mov","r0,%s",spname);
2665             pic14_emitcode("movx","a,@r0");
2666             pic14_emitcode("mov","_bp,a");
2667             pic14_emitcode("dec","%s",spname);
2668         }
2669         else
2670         {
2671             pic14_emitcode ("pop","_bp");
2672         }
2673     }
2674
2675     /* restore the register bank  */    
2676     if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
2677         pic14_emitcode ("pop","psw");
2678
2679     if (IFFUNC_ISISR(sym->type)) {
2680
2681         /* now we need to restore the registers */
2682         /* if this isr has no bank i.e. is going to
2683            run with bank 0 , then we need to save more
2684            registers :-) */
2685         if (!FUNC_REGBANK(sym->type)) {
2686             
2687             /* if this function does not call any other
2688                function then we can be economical and
2689                save only those registers that are used */
2690             if (! IFFUNC_HASFCALL(sym->type)) {
2691                 int i;
2692                 
2693                 /* if any registers used */
2694                 if (sym->regsUsed) {
2695                     /* save the registers used */
2696                     for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2697                         if (bitVectBitValue(sym->regsUsed,i) ||
2698                           (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2699                             pic14_emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2700                     }
2701                 }
2702                 
2703             } else {
2704                 /* this function has  a function call cannot
2705                    determines register usage so we will have the
2706                    entire bank */
2707                 unsaverbank(0,ic,FALSE);
2708             }       
2709         }
2710
2711         if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2712         {
2713             if (options.stack10bit)
2714             {
2715                 pic14_emitcode ("pop", "dpx1");
2716                 pic14_emitcode ("pop", "dph1");
2717                 pic14_emitcode ("pop", "dpl1");
2718             }   
2719             pic14_emitcode ("pop", "dps");
2720             pic14_emitcode ("pop", "dpx");
2721         }
2722         if (!inExcludeList("dph"))
2723             pic14_emitcode ("pop","dph");
2724         if (!inExcludeList("dpl"))
2725             pic14_emitcode ("pop","dpl");
2726         if (!inExcludeList("b"))
2727             pic14_emitcode ("pop","b");
2728         if (!inExcludeList("acc"))
2729             pic14_emitcode ("pop","acc");
2730
2731         if (IFFUNC_ISCRITICAL(sym->type))
2732             pic14_emitcode("setb","ea");
2733
2734         /* if debug then send end of function */
2735 /*      if (options.debug && currFunc) { */
2736         if (currFunc) {
2737             _G.debugLine = 1;
2738             pic14_emitcode(";","C$%s$%d$%d$%d ==.",
2739                      FileBaseName(ic->filename),currFunc->lastLine,
2740                      ic->level,ic->block); 
2741             if (IS_STATIC(currFunc->etype))         
2742                 pic14_emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
2743             else
2744                 pic14_emitcode(";","XG$%s$0$0 ==.",currFunc->name);
2745             _G.debugLine = 0;
2746         }
2747         
2748         pic14_emitcode ("reti","");
2749     }
2750     else {
2751         if (IFFUNC_ISCRITICAL(sym->type))
2752             pic14_emitcode("setb","ea");
2753         
2754         if (IFFUNC_CALLEESAVES(sym->type)) {
2755             int i;
2756             
2757             /* if any registers used */
2758             if (sym->regsUsed) {
2759                 /* save the registers used */
2760                 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2761                     if (bitVectBitValue(sym->regsUsed,i) ||
2762                       (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2763                         pic14_emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2764                 }
2765             }
2766             
2767         }
2768
2769         /* if debug then send end of function */
2770         if (currFunc) {
2771             _G.debugLine = 1;
2772             pic14_emitcode(";","C$%s$%d$%d$%d ==.",
2773                      FileBaseName(ic->filename),currFunc->lastLine,
2774                      ic->level,ic->block); 
2775             if (IS_STATIC(currFunc->etype))         
2776                 pic14_emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
2777             else
2778                 pic14_emitcode(";","XG$%s$0$0 ==.",currFunc->name);
2779             _G.debugLine = 0;
2780         }
2781
2782         pic14_emitcode ("return","");
2783         emitpcodeNULLop(POC_RETURN);
2784
2785         /* Mark the end of a function */
2786         addpCode2pBlock(pb,newpCodeFunction(NULL,NULL));
2787     }
2788
2789 }
2790
2791 /*-----------------------------------------------------------------*/
2792 /* genRet - generate code for return statement                     */
2793 /*-----------------------------------------------------------------*/
2794 static void genRet (iCode *ic)
2795 {
2796   int size,offset = 0 , pushed = 0;
2797     
2798   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2799   /* if we have no return value then
2800      just generate the "ret" */
2801   if (!IC_LEFT(ic)) 
2802     goto jumpret;       
2803     
2804   /* we have something to return then
2805      move the return value into place */
2806   aopOp(IC_LEFT(ic),ic,FALSE);
2807   size = AOP_SIZE(IC_LEFT(ic));
2808     
2809   while (size--) {
2810     char *l ;
2811     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
2812       /* #NOCHANGE */
2813       l = aopGet(AOP(IC_LEFT(ic)),offset++,
2814                  FALSE,TRUE);
2815       pic14_emitcode("push","%s",l);
2816       pushed++;
2817     } else {
2818       l = aopGet(AOP(IC_LEFT(ic)),offset,
2819                  FALSE,FALSE);
2820       if (strcmp(fReturn[offset],l)) {
2821         if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD) ||
2822             ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
2823           emitpcode(POC_MOVLW, popGet(AOP(IC_LEFT(ic)),offset));
2824         }else {
2825           emitpcode(POC_MOVFW, popGet(AOP(IC_LEFT(ic)),offset));
2826         }
2827         if(size) {
2828           emitpcode(POC_MOVWF,popRegFromIdx(offset + Gstack_base_addr));
2829           pic14_emitcode("movwf","%s",fReturn[offset]);
2830         }
2831         offset++;
2832       }
2833     }
2834   }    
2835
2836   if (pushed) {
2837     while(pushed) {
2838       pushed--;
2839       if (strcmp(fReturn[pushed],"a"))
2840         pic14_emitcode("pop",fReturn[pushed]);
2841       else
2842         pic14_emitcode("pop","acc");
2843     }
2844   }
2845   freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2846     
2847  jumpret:
2848   /* generate a jump to the return label
2849      if the next is not the return statement */
2850   if (!(ic->next && ic->next->op == LABEL &&
2851         IC_LABEL(ic->next) == returnLabel)) {
2852         
2853     emitpcode(POC_GOTO,popGetLabel(returnLabel->key));
2854     pic14_emitcode("goto","_%05d_DS_",returnLabel->key+100 + labelOffset);
2855   }
2856     
2857 }
2858
2859 /*-----------------------------------------------------------------*/
2860 /* genLabel - generates a label                                    */
2861 /*-----------------------------------------------------------------*/
2862 static void genLabel (iCode *ic)
2863 {
2864     /* special case never generate */
2865     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2866     if (IC_LABEL(ic) == entryLabel)
2867         return ;
2868
2869     emitpLabel(IC_LABEL(ic)->key);
2870     pic14_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
2871 }
2872
2873 /*-----------------------------------------------------------------*/
2874 /* genGoto - generates a goto                                      */
2875 /*-----------------------------------------------------------------*/
2876 //tsd
2877 static void genGoto (iCode *ic)
2878 {
2879   emitpcode(POC_GOTO,popGetLabel(IC_LABEL(ic)->key));
2880   pic14_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
2881 }
2882
2883
2884 /*-----------------------------------------------------------------*/
2885 /* genMultbits :- multiplication of bits                           */
2886 /*-----------------------------------------------------------------*/
2887 static void genMultbits (operand *left, 
2888                          operand *right, 
2889                          operand *result)
2890 {
2891   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2892
2893   if(!pic14_sameRegs(AOP(result),AOP(right)))
2894     emitpcode(POC_BSF,  popGet(AOP(result),0));
2895
2896   emitpcode(POC_BTFSC,popGet(AOP(right),0));
2897   emitpcode(POC_BTFSS,popGet(AOP(left),0));
2898   emitpcode(POC_BCF,  popGet(AOP(result),0));
2899
2900 }
2901
2902
2903 /*-----------------------------------------------------------------*/
2904 /* genMultOneByte : 8 bit multiplication & division                */
2905 /*-----------------------------------------------------------------*/
2906 static void genMultOneByte (operand *left,
2907                             operand *right,
2908                             operand *result)
2909 {
2910     sym_link *opetype = operandType(result);
2911     char *l ;
2912     symbol *lbl ;
2913     int size,offset;
2914
2915     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2916   DEBUGpic14_AopType(__LINE__,left,right,result);
2917
2918     /* (if two literals, the value is computed before) */
2919     /* if one literal, literal on the right */
2920     if (AOP_TYPE(left) == AOP_LIT){
2921         operand *t = right;
2922         right = left;
2923         left = t;
2924     }
2925
2926     size = AOP_SIZE(result);
2927     /* signed or unsigned */
2928     pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
2929     l = aopGet(AOP(left),0,FALSE,FALSE);
2930     MOVA(l);       
2931     pic14_emitcode("mul","ab");
2932     /* if result size = 1, mul signed = mul unsigned */
2933     aopPut(AOP(result),"a",0);
2934     if (size > 1){
2935         if (SPEC_USIGN(opetype)){
2936             aopPut(AOP(result),"b",1);
2937             if (size > 2)
2938                 /* for filling the MSBs */
2939                 pic14_emitcode("clr","a");
2940         }
2941         else{
2942             pic14_emitcode("mov","a,b");
2943
2944             /* adjust the MSB if left or right neg */
2945
2946             /* if one literal */
2947             if (AOP_TYPE(right) == AOP_LIT){
2948                 /* AND literal negative */
2949                 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
2950                     /* adjust MSB (c==0 after mul) */
2951                     pic14_emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
2952                 }
2953             }
2954             else{
2955                 lbl = newiTempLabel(NULL);
2956                 pic14_emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
2957                 pic14_emitcode("cjne","a,#0x80,%05d_DS_", (lbl->key+100));
2958                 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
2959                 pic14_emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
2960                 lbl = newiTempLabel(NULL);      
2961                 pic14_emitcode("jc","%05d_DS_",(lbl->key+100));          
2962                 pic14_emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
2963                 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
2964             }
2965
2966             lbl = newiTempLabel(NULL);
2967             pic14_emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
2968             pic14_emitcode("cjne","a,#0x80,%05d_DS_", (lbl->key+100));
2969             pic14_emitcode("","%05d_DS_:",(lbl->key+100));
2970             pic14_emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
2971             lbl = newiTempLabel(NULL);      
2972             pic14_emitcode("jc","%05d_DS_",(lbl->key+100));          
2973             pic14_emitcode("subb","a,%s", aopGet(AOP(right),0,FALSE,FALSE));
2974             pic14_emitcode("","%05d_DS_:",(lbl->key+100));
2975
2976             aopPut(AOP(result),"a",1);
2977             if(size > 2){
2978                 /* get the sign */
2979                 pic14_emitcode("rlc","a");
2980                 pic14_emitcode("subb","a,acc");
2981             }
2982         }
2983         size -= 2;   
2984         offset = 2;
2985         if (size > 0)
2986             while (size--)
2987                 aopPut(AOP(result),"a",offset++);
2988     }
2989 }
2990
2991 /*-----------------------------------------------------------------*/
2992 /* genMult - generates code for multiplication                     */
2993 /*-----------------------------------------------------------------*/
2994 static void genMult (iCode *ic)
2995 {
2996     operand *left = IC_LEFT(ic);
2997     operand *right = IC_RIGHT(ic);
2998     operand *result= IC_RESULT(ic);   
2999
3000     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3001     /* assign the amsops */
3002     aopOp (left,ic,FALSE);
3003     aopOp (right,ic,FALSE);
3004     aopOp (result,ic,TRUE);
3005
3006   DEBUGpic14_AopType(__LINE__,left,right,result);
3007
3008     /* special cases first */
3009     /* both are bits */
3010     if (AOP_TYPE(left) == AOP_CRY &&
3011         AOP_TYPE(right)== AOP_CRY) {
3012         genMultbits(left,right,result);
3013         goto release ;
3014     }
3015
3016     /* if both are of size == 1 */
3017     if (AOP_SIZE(left) == 1 &&
3018         AOP_SIZE(right) == 1 ) {
3019         genMultOneByte(left,right,result);
3020         goto release ;
3021     }
3022
3023     /* should have been converted to function call */       
3024     assert(0) ;
3025
3026 release :
3027     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3028     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3029     freeAsmop(result,NULL,ic,TRUE); 
3030 }
3031
3032 /*-----------------------------------------------------------------*/
3033 /* genDivbits :- division of bits                                  */
3034 /*-----------------------------------------------------------------*/
3035 static void genDivbits (operand *left, 
3036                         operand *right, 
3037                         operand *result)
3038 {
3039
3040     char *l;
3041
3042     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3043     /* the result must be bit */    
3044     pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3045     l = aopGet(AOP(left),0,FALSE,FALSE);
3046
3047     MOVA(l);    
3048
3049     pic14_emitcode("div","ab");
3050     pic14_emitcode("rrc","a");
3051     aopPut(AOP(result),"c",0);
3052 }
3053
3054 /*-----------------------------------------------------------------*/
3055 /* genDivOneByte : 8 bit division                                  */
3056 /*-----------------------------------------------------------------*/
3057 static void genDivOneByte (operand *left,
3058                            operand *right,
3059                            operand *result)
3060 {
3061     sym_link *opetype = operandType(result);
3062     char *l ;
3063     symbol *lbl ;
3064     int size,offset;
3065
3066     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3067     size = AOP_SIZE(result) - 1;
3068     offset = 1;
3069     /* signed or unsigned */
3070     if (SPEC_USIGN(opetype)) {
3071         /* unsigned is easy */
3072         pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3073         l = aopGet(AOP(left),0,FALSE,FALSE);
3074         MOVA(l);        
3075         pic14_emitcode("div","ab");
3076         aopPut(AOP(result),"a",0);
3077         while (size--)
3078             aopPut(AOP(result),zero,offset++);
3079         return ;
3080     }
3081
3082     /* signed is a little bit more difficult */
3083
3084     /* save the signs of the operands */
3085     l = aopGet(AOP(left),0,FALSE,FALSE);    
3086     MOVA(l);    
3087     pic14_emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE));
3088     pic14_emitcode("push","acc"); /* save it on the stack */
3089
3090     /* now sign adjust for both left & right */
3091     l =  aopGet(AOP(right),0,FALSE,FALSE);    
3092     MOVA(l);       
3093     lbl = newiTempLabel(NULL);
3094     pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
3095     pic14_emitcode("cpl","a");   
3096     pic14_emitcode("inc","a");
3097     pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3098     pic14_emitcode("mov","b,a");
3099
3100     /* sign adjust left side */
3101     l =  aopGet(AOP(left),0,FALSE,FALSE);    
3102     MOVA(l);
3103
3104     lbl = newiTempLabel(NULL);
3105     pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3106     pic14_emitcode("cpl","a");
3107     pic14_emitcode("inc","a");
3108     pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3109
3110     /* now the division */
3111     pic14_emitcode("div","ab");
3112     /* we are interested in the lower order
3113     only */
3114     pic14_emitcode("mov","b,a");
3115     lbl = newiTempLabel(NULL);
3116     pic14_emitcode("pop","acc");   
3117     /* if there was an over flow we don't 
3118     adjust the sign of the result */
3119     pic14_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3120     pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3121     CLRC;
3122     pic14_emitcode("clr","a");
3123     pic14_emitcode("subb","a,b");
3124     pic14_emitcode("mov","b,a");
3125     pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3126
3127     /* now we are done */
3128     aopPut(AOP(result),"b",0);
3129     if(size > 0){
3130         pic14_emitcode("mov","c,b.7");
3131         pic14_emitcode("subb","a,acc");   
3132     }
3133     while (size--)
3134         aopPut(AOP(result),"a",offset++);
3135
3136 }
3137
3138 /*-----------------------------------------------------------------*/
3139 /* genDiv - generates code for division                            */
3140 /*-----------------------------------------------------------------*/
3141 static void genDiv (iCode *ic)
3142 {
3143     operand *left = IC_LEFT(ic);
3144     operand *right = IC_RIGHT(ic);
3145     operand *result= IC_RESULT(ic);   
3146
3147     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3148     /* assign the amsops */
3149     aopOp (left,ic,FALSE);
3150     aopOp (right,ic,FALSE);
3151     aopOp (result,ic,TRUE);
3152
3153     /* special cases first */
3154     /* both are bits */
3155     if (AOP_TYPE(left) == AOP_CRY &&
3156         AOP_TYPE(right)== AOP_CRY) {
3157         genDivbits(left,right,result);
3158         goto release ;
3159     }
3160
3161     /* if both are of size == 1 */
3162     if (AOP_SIZE(left) == 1 &&
3163         AOP_SIZE(right) == 1 ) {
3164         genDivOneByte(left,right,result);
3165         goto release ;
3166     }
3167
3168     /* should have been converted to function call */
3169     assert(0);
3170 release :
3171     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3172     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3173     freeAsmop(result,NULL,ic,TRUE); 
3174 }
3175
3176 /*-----------------------------------------------------------------*/
3177 /* genModbits :- modulus of bits                                   */
3178 /*-----------------------------------------------------------------*/
3179 static void genModbits (operand *left, 
3180                         operand *right, 
3181                         operand *result)
3182 {
3183
3184     char *l;
3185
3186     /* the result must be bit */    
3187     pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3188     l = aopGet(AOP(left),0,FALSE,FALSE);
3189
3190     MOVA(l);       
3191
3192     pic14_emitcode("div","ab");
3193     pic14_emitcode("mov","a,b");
3194     pic14_emitcode("rrc","a");
3195     aopPut(AOP(result),"c",0);
3196 }
3197
3198 /*-----------------------------------------------------------------*/
3199 /* genModOneByte : 8 bit modulus                                   */
3200 /*-----------------------------------------------------------------*/
3201 static void genModOneByte (operand *left,
3202                            operand *right,
3203                            operand *result)
3204 {
3205     sym_link *opetype = operandType(result);
3206     char *l ;
3207     symbol *lbl ;
3208
3209     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3210     /* signed or unsigned */
3211     if (SPEC_USIGN(opetype)) {
3212         /* unsigned is easy */
3213         pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3214         l = aopGet(AOP(left),0,FALSE,FALSE);
3215         MOVA(l);    
3216         pic14_emitcode("div","ab");
3217         aopPut(AOP(result),"b",0);
3218         return ;
3219     }
3220
3221     /* signed is a little bit more difficult */
3222
3223     /* save the signs of the operands */
3224     l = aopGet(AOP(left),0,FALSE,FALSE);    
3225     MOVA(l);
3226
3227     pic14_emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3228     pic14_emitcode("push","acc"); /* save it on the stack */
3229
3230     /* now sign adjust for both left & right */
3231     l =  aopGet(AOP(right),0,FALSE,FALSE);    
3232     MOVA(l);
3233
3234     lbl = newiTempLabel(NULL);
3235     pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
3236     pic14_emitcode("cpl","a");   
3237     pic14_emitcode("inc","a");
3238     pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3239     pic14_emitcode("mov","b,a"); 
3240
3241     /* sign adjust left side */
3242     l =  aopGet(AOP(left),0,FALSE,FALSE);    
3243     MOVA(l);
3244
3245     lbl = newiTempLabel(NULL);
3246     pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3247     pic14_emitcode("cpl","a");   
3248     pic14_emitcode("inc","a");
3249     pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3250
3251     /* now the multiplication */
3252     pic14_emitcode("div","ab");
3253     /* we are interested in the lower order
3254     only */
3255     lbl = newiTempLabel(NULL);
3256     pic14_emitcode("pop","acc");   
3257     /* if there was an over flow we don't 
3258     adjust the sign of the result */
3259     pic14_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3260     pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3261     CLRC ;
3262     pic14_emitcode("clr","a");
3263     pic14_emitcode("subb","a,b");
3264     pic14_emitcode("mov","b,a");
3265     pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3266
3267     /* now we are done */
3268     aopPut(AOP(result),"b",0);
3269
3270 }
3271
3272 /*-----------------------------------------------------------------*/
3273 /* genMod - generates code for division                            */
3274 /*-----------------------------------------------------------------*/
3275 static void genMod (iCode *ic)
3276 {
3277     operand *left = IC_LEFT(ic);
3278     operand *right = IC_RIGHT(ic);
3279     operand *result= IC_RESULT(ic);  
3280
3281     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3282     /* assign the amsops */
3283     aopOp (left,ic,FALSE);
3284     aopOp (right,ic,FALSE);
3285     aopOp (result,ic,TRUE);
3286
3287     /* special cases first */
3288     /* both are bits */
3289     if (AOP_TYPE(left) == AOP_CRY &&
3290         AOP_TYPE(right)== AOP_CRY) {
3291         genModbits(left,right,result);
3292         goto release ;
3293     }
3294
3295     /* if both are of size == 1 */
3296     if (AOP_SIZE(left) == 1 &&
3297         AOP_SIZE(right) == 1 ) {
3298         genModOneByte(left,right,result);
3299         goto release ;
3300     }
3301
3302     /* should have been converted to function call */
3303     assert(0);
3304
3305 release :
3306     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3307     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3308     freeAsmop(result,NULL,ic,TRUE); 
3309 }
3310
3311 /*-----------------------------------------------------------------*/
3312 /* genIfxJump :- will create a jump depending on the ifx           */
3313 /*-----------------------------------------------------------------*/
3314 /*
3315   note: May need to add parameter to indicate when a variable is in bit space.
3316 */
3317 static void genIfxJump (iCode *ic, char *jval)
3318 {
3319
3320     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3321     /* if true label then we jump if condition
3322     supplied is true */
3323     if ( IC_TRUE(ic) ) {
3324
3325         if(strcmp(jval,"a") == 0)
3326           emitSKPZ;
3327         else if (strcmp(jval,"c") == 0)
3328           emitSKPC;
3329         else {
3330           DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
3331           emitpcode(POC_BTFSC,  newpCodeOpBit(jval,-1,1));
3332         }
3333
3334         emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3335         pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3336
3337     }
3338     else {
3339         /* false label is present */
3340         if(strcmp(jval,"a") == 0)
3341           emitSKPNZ;
3342         else if (strcmp(jval,"c") == 0)
3343           emitSKPNC;
3344         else {
3345           DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
3346           emitpcode(POC_BTFSS,  newpCodeOpBit(jval,-1,1));
3347         }
3348
3349         emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
3350         pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3351
3352     }
3353
3354
3355     /* mark the icode as generated */
3356     ic->generated = 1;
3357 }
3358
3359 /*-----------------------------------------------------------------*/
3360 /* genSkip                                                         */
3361 /*-----------------------------------------------------------------*/
3362 static void genSkip(iCode *ifx,int status_bit)
3363 {
3364   if(!ifx)
3365     return;
3366
3367   if ( IC_TRUE(ifx) ) {
3368     switch(status_bit) {
3369     case 'z':
3370       emitSKPNZ;
3371       break;
3372
3373     case 'c':
3374       emitSKPNC;
3375       break;
3376
3377     case 'd':
3378       emitSKPDC;
3379       break;
3380
3381     }
3382
3383     emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3384     pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3385
3386   } else {
3387
3388     switch(status_bit) {
3389
3390     case 'z':
3391       emitSKPZ;
3392       break;
3393
3394     case 'c':
3395       emitSKPC;
3396       break;
3397
3398     case 'd':
3399       emitSKPDC;
3400       break;
3401     }
3402     emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3403     pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3404
3405   }
3406
3407 }
3408
3409 /*-----------------------------------------------------------------*/
3410 /* genSkipc                                                        */
3411 /*-----------------------------------------------------------------*/
3412 static void genSkipc(resolvedIfx *rifx)
3413 {
3414   if(!rifx)
3415     return;
3416
3417   if(rifx->condition)
3418     emitSKPC;
3419   else
3420     emitSKPNC;
3421
3422   emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3423   rifx->generated = 1;
3424 }
3425
3426 /*-----------------------------------------------------------------*/
3427 /* genSkipz2                                                       */
3428 /*-----------------------------------------------------------------*/
3429 static void genSkipz2(resolvedIfx *rifx)
3430 {
3431   if(!rifx)
3432     return;
3433
3434   if(rifx->condition)
3435     emitSKPZ;
3436   else
3437     emitSKPNZ;
3438
3439   emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3440   rifx->generated = 1;
3441 }
3442
3443 /*-----------------------------------------------------------------*/
3444 /* genSkipz                                                        */
3445 /*-----------------------------------------------------------------*/
3446 static void genSkipz(iCode *ifx, int condition)
3447 {
3448   if(!ifx)
3449     return;
3450
3451   if(condition)
3452     emitSKPNZ;
3453   else
3454     emitSKPZ;
3455
3456   if ( IC_TRUE(ifx) )
3457     emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3458   else
3459     emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3460
3461   if ( IC_TRUE(ifx) )
3462     pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3463   else
3464     pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3465
3466 }
3467 /*-----------------------------------------------------------------*/
3468 /* genSkipCond                                                     */
3469 /*-----------------------------------------------------------------*/
3470 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3471 {
3472   if(!rifx)
3473     return;
3474
3475   if(rifx->condition)
3476     emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3477   else
3478     emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3479
3480
3481   emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3482   rifx->generated = 1;
3483 }
3484
3485 #if 0
3486 /*-----------------------------------------------------------------*/
3487 /* genChkZeroes :- greater or less than comparison                 */
3488 /*     For each byte in a literal that is zero, inclusive or the   */
3489 /*     the corresponding byte in the operand with W                */
3490 /*     returns true if any of the bytes are zero                   */
3491 /*-----------------------------------------------------------------*/
3492 static int genChkZeroes(operand *op, int lit,  int size)
3493 {
3494
3495   int i;
3496   int flag =1;
3497
3498   while(size--) {
3499     i = (lit >> (size*8)) & 0xff;
3500
3501     if(i==0) {
3502       if(flag) 
3503         emitpcode(POC_MOVFW, popGet(AOP(op),size));
3504       else
3505         emitpcode(POC_IORFW, popGet(AOP(op),size));
3506       flag = 0;
3507     }
3508   }
3509
3510   return (flag==0);
3511 }
3512 #endif
3513
3514 /*-----------------------------------------------------------------*/
3515 /* genCmp :- greater or less than comparison                       */
3516 /*-----------------------------------------------------------------*/
3517 static void genCmp (operand *left,operand *right,
3518                     operand *result, iCode *ifx, int sign)
3519 {
3520   int size, offset = 0 ;
3521   unsigned long lit = 0L,i = 0;
3522   resolvedIfx rIfx;
3523
3524   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3525   if(ifx) {
3526   DEBUGpic14_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
3527   DEBUGpic14_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
3528   }
3529
3530   resolveIfx(&rIfx,ifx);
3531
3532   /* if left & right are bit variables */
3533   if (AOP_TYPE(left) == AOP_CRY &&
3534       AOP_TYPE(right) == AOP_CRY ) {
3535     pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3536     pic14_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3537   } else {
3538     /* subtract right from left if at the
3539        end the carry flag is set then we know that
3540        left is greater than right */
3541     size = max(AOP_SIZE(left),AOP_SIZE(right));
3542
3543     /* if unsigned char cmp with lit, do cjne left,#right,zz */
3544     if((size == 1) && !sign &&
3545        (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
3546       symbol *lbl  = newiTempLabel(NULL);
3547       pic14_emitcode("cjne","%s,%s,%05d_DS_",
3548                aopGet(AOP(left),offset,FALSE,FALSE),
3549                aopGet(AOP(right),offset,FALSE,FALSE),
3550                lbl->key+100);
3551       pic14_emitcode("","%05d_DS_:",lbl->key+100);
3552     } else {
3553
3554       symbol *lbl  = newiTempLabel(NULL);
3555       int emitFinalCheck=1;
3556       symbol *truelbl  = newiTempLabel(NULL);
3557
3558
3559       if(AOP_TYPE(right) == AOP_LIT) {
3560
3561         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3562
3563         DEBUGpic14_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
3564
3565         /* special cases */
3566
3567         if(lit == 0) {
3568
3569           if(sign != 0) 
3570             genSkipCond(&rIfx,left,size-1,7);
3571           else 
3572             /* no need to compare to 0...*/
3573             /* NOTE: this is a de-generate compare that most certainly 
3574              *       creates some dead code. */
3575             emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
3576
3577           if(ifx) ifx->generated = 1;
3578           return;
3579
3580         }
3581         size--;
3582
3583         if(size == 0) {
3584           //i = (lit >> (size*8)) & 0xff;
3585           DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
3586         
3587           emitpcode(POC_MOVFW, popGet(AOP(left),size));
3588
3589           i = ((0-lit) & 0xff);
3590           if(sign) {
3591             if( i == 0x81) { 
3592               /* lit is 0x7f, all signed chars are less than
3593                * this except for 0x7f itself */
3594               emitpcode(POC_XORLW, popGetLit(0x7f));
3595               genSkipz2(&rIfx);
3596             } else {
3597               emitpcode(POC_ADDLW, popGetLit(0x80));
3598               emitpcode(POC_ADDLW, popGetLit(i^0x80));
3599               genSkipc(&rIfx);
3600             }
3601
3602           } else {
3603             emitpcode(POC_ADDLW, popGetLit(i));
3604             genSkipc(&rIfx);
3605
3606           }
3607
3608           if(ifx) ifx->generated = 1;
3609           return;
3610         }
3611
3612         /* chars are out of the way. now do ints and longs */
3613
3614
3615         DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
3616         
3617         /* special cases */
3618
3619         if(sign) {
3620
3621           if(lit == 0) {
3622             genSkipCond(&rIfx,left,size,7);
3623             if(ifx) ifx->generated = 1;
3624             return;
3625           }
3626
3627           if(lit <0x100) {
3628             DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3629
3630             emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
3631             emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3632             emitpcode(POC_MOVLW, popGetLit(0x100-lit));
3633             emitpcode(POC_ADDFW, popGet(AOP(left),0));
3634             emitpcode(POC_MOVFW, popGet(AOP(left),1));
3635
3636             while(size > 1)
3637               emitpcode(POC_IORFW, popGet(AOP(left),size--));
3638
3639             emitSKPNZ;
3640
3641             genSkipc(&rIfx);
3642             emitpLabel(truelbl->key);
3643             if(ifx) ifx->generated = 1;
3644             return;
3645
3646           }
3647
3648           if(size == 1) {
3649
3650             if( (lit & 0xff) == 0) {
3651               /* lower byte is zero */
3652               DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3653               i = ((lit >> 8) & 0xff) ^0x80;
3654               emitpcode(POC_MOVFW, popGet(AOP(left),size));
3655               emitpcode(POC_ADDLW, popGetLit( 0x80));
3656               emitpcode(POC_ADDLW, popGetLit(0x100-i));
3657               genSkipc(&rIfx);
3658
3659
3660               if(ifx) ifx->generated = 1;
3661               return;
3662
3663             }
3664           } else {
3665             /* Special cases for signed longs */
3666             if( (lit & 0xffffff) == 0) {
3667               /* lower byte is zero */
3668               DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3669               i = ((lit >> 8*3) & 0xff) ^0x80;
3670               emitpcode(POC_MOVFW, popGet(AOP(left),size));
3671               emitpcode(POC_ADDLW, popGetLit( 0x80));
3672               emitpcode(POC_ADDLW, popGetLit(0x100-i));
3673               genSkipc(&rIfx);
3674
3675
3676               if(ifx) ifx->generated = 1;
3677               return;
3678
3679             }
3680
3681 #if 0
3682             if( lit < 0x10000) {
3683               /* upper word is zero */
3684               DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3685
3686               emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
3687               emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3688
3689               emitpcode(POC_MOVLW, popGetLit((lit >> (1*8)) & 0xff));
3690               emitpcode(POC_SUBFW, popGet(AOP(left),1));
3691               emitpcode(POC_MOVLW, popGetLit((lit & 0xff));
3692               emitSKPNZ;
3693               emitpcode(POC_SUBFW, popGet(AOP(left),0));
3694
3695               emitpcode(POC_IORFW, popGet(AOP(left),2));
3696               emitpcode(POC_IORFW, popGet(AOP(left),3));
3697
3698               emitSKPNZ;
3699
3700               genSkipc(&rIfx);
3701               emitpLabel(truelbl->key);
3702               if(ifx) ifx->generated = 1;
3703               return;
3704
3705             }
3706 #endif
3707
3708           }
3709
3710
3711           if(lit & (0x80 << (size*8))) {
3712             /* lit is negative */
3713             DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3714
3715             genSkipCond(&rIfx,left,size,7);
3716           } else {
3717             /* lit is positive */
3718             DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3719             emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
3720             emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3721
3722           }
3723
3724           /*
3725             This works, but is only good for ints.
3726             It also requires a "known zero" register.
3727             emitpcode(POC_MOVLW, popGetLit(mlit & 0xff));
3728             emitpcode(POC_ADDFW, popGet(AOP(left),0));
3729             emitpcode(POC_RLFW,  popCopyReg(&pc_kzero));
3730             emitpcode(POC_ADDLW, popGetLit( ((mlit>>8) & 0xff)));
3731             emitpcode(POC_ADDFW, popGet(AOP(left),1));
3732             genSkipc(&rIfx);
3733
3734             emitpLabel(truelbl->key);
3735             if(ifx) ifx->generated = 1;
3736             return;
3737           **/
3738           
3739           /* There are no more special cases, so perform a general compare */
3740   
3741           emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
3742           emitpcode(POC_SUBFW, popGet(AOP(left),size));
3743
3744           while(size--) {
3745
3746             emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
3747             emitSKPNZ;
3748             emitpcode(POC_SUBFW, popGet(AOP(left),size));
3749           }
3750
3751           genSkipc(&rIfx);
3752
3753           emitpLabel(truelbl->key);
3754
3755           if(ifx) ifx->generated = 1;
3756           return;
3757
3758
3759         }
3760
3761
3762         /* sign is out of the way. So now do an unsigned compare */
3763         DEBUGpic14_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
3764
3765
3766         //genChkZeroes(left)
3767
3768         /* General case - compare to an unsigned literal on the right.*/
3769
3770         i = (lit >> (size*8)) & 0xff;
3771         emitpcode(POC_MOVLW, popGetLit(i));
3772         emitpcode(POC_SUBFW, popGet(AOP(left),size));
3773         while(size--) {
3774           i = (lit >> (size*8)) & 0xff;
3775
3776           if(i) {
3777             emitpcode(POC_MOVLW, popGetLit(i));
3778             emitSKPNZ;
3779             emitpcode(POC_SUBFW, popGet(AOP(left),size));
3780           } else {
3781             /* this byte of the lit is zero, 
3782              *if it's not the last then OR in the variable */
3783             if(size)
3784               emitpcode(POC_IORFW, popGet(AOP(left),size));
3785           }
3786         }
3787
3788
3789         emitpLabel(lbl->key);
3790         if(emitFinalCheck)
3791           genSkipc(&rIfx);
3792         if(sign)
3793           emitpLabel(truelbl->key);
3794
3795         if(ifx) ifx->generated = 1;
3796         return;
3797
3798
3799       }
3800
3801       if(AOP_TYPE(left) == AOP_LIT) {
3802         //symbol *lbl = newiTempLabel(NULL);
3803         unsigned long mlit;
3804         lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
3805         mlit = -lit;
3806
3807         DEBUGpic14_emitcode(";left lit","lit = %d,sign=%d",lit,sign);
3808
3809         /* Special cases */
3810         if((lit == 0) && (sign == 0)){
3811
3812           size--;
3813           emitpcode(POC_MOVFW, popGet(AOP(right),size));
3814           while(size) 
3815             emitpcode(POC_IORFW, popGet(AOP(right),--size));
3816
3817           //rIfx.condition ^= 1;
3818           genSkipz2(&rIfx);
3819           if(ifx) ifx->generated = 1;
3820           return;
3821         }
3822
3823         if(size==1) {
3824           /* Special cases */
3825           lit &= 0xff;
3826           if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
3827             /* degenerate compare can never be true */
3828             emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
3829             if(ifx) ifx->generated = 1;
3830             return;
3831           }
3832
3833           if(sign) {
3834             if((lit+1)&0xff) {
3835               emitpcode(POC_MOVFW, popGet(AOP(right),0));
3836               emitpcode(POC_ADDLW, popGetLit(0x80));
3837               emitpcode(POC_ADDLW, popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
3838               rIfx.condition ^= 1;
3839               genSkipc(&rIfx);
3840             } else {
3841               rIfx.condition ^= 1;
3842               genSkipCond(&rIfx,right,0,7);
3843             }
3844             
3845           } else {
3846             if(lit & 0xff) {
3847               emitpcode(POC_MOVLW, popGetLit((lit+1) & 0xff));
3848               emitpcode(POC_SUBFW, popGet(AOP(right),0));
3849               DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3850               rIfx.condition ^= 1;
3851               genSkipc(&rIfx);
3852             } else { 
3853               emitpcode(POC_MOVFW, popGet(AOP(right),0));
3854               genSkipz2(&rIfx);
3855             }
3856           }
3857
3858           if(ifx) ifx->generated = 1;
3859           return;
3860
3861         } else {
3862
3863           /* Size is greater than 1 */
3864
3865
3866
3867           if(sign) {
3868             int lp1 = lit+1;
3869
3870             size--;
3871
3872             if(lp1 == 0) {
3873               /* this means lit = 0xffffffff, or -1 */
3874
3875
3876               DEBUGpic14_emitcode(";left lit = -1","line = %d ",__LINE__);
3877               rIfx.condition ^= 1;
3878               genSkipCond(&rIfx,right,size,7);
3879               if(ifx) ifx->generated = 1;
3880               return;
3881             }
3882
3883             if(lit == 0) {
3884               int s = size;
3885               emitpcode(POC_MOVFW, popGet(AOP(right),size));
3886               while(size--)
3887                 emitpcode(POC_IORFW, popGet(AOP(right),size));
3888
3889               emitSKPZ;
3890               rIfx.condition ^= 1;
3891               genSkipCond(&rIfx,right,s,7);
3892               if(ifx) ifx->generated = 1;
3893               return;
3894             }
3895
3896
3897             if(lit & (0x80 << (size*8))) {
3898               /* Lit is less than zero */
3899               DEBUGpic14_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
3900               emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
3901               emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3902
3903             } else {
3904               /* Lit is greater than or equal to zero */
3905               DEBUGpic14_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
3906               rIfx.condition ^= 1;
3907               genSkipCond(&rIfx,right,size,7);
3908               rIfx.condition ^= 1;
3909
3910             }
3911             emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
3912             emitpcode(POC_SUBFW, popGet(AOP(right),size));
3913
3914             while(size--) {
3915
3916               emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
3917               emitSKPNZ;
3918               emitpcode(POC_SUBFW, popGet(AOP(right),size));
3919             }
3920             rIfx.condition ^= 1;
3921             genSkipc(&rIfx);
3922
3923             emitpLabel(truelbl->key);
3924
3925             if(ifx) ifx->generated = 1;
3926             return;
3927
3928           } else {
3929             /* Unsigned compare for sizes greater than 1 */
3930
3931             while(size--) {
3932               i = (lit >> (size*8)) & 0xff;
3933
3934
3935               if(size) {
3936                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3937                 emitpcode(POC_MOVLW, popGetLit(i&0xff));
3938                 emitpcode(POC_SUBFW, popGet(AOP(right),size));
3939                 emitSKPZ;
3940                 emitpcode(POC_GOTO,  popGetLabel(lbl->key));
3941               } else {
3942                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3943                 emitpcode(POC_MOVLW, popGetLit((i+1)&0xff));
3944                 emitpcode(POC_SUBFW, popGet(AOP(right),size));
3945
3946               }
3947             }
3948
3949             DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3950
3951             emitpLabel(lbl->key);
3952
3953             rIfx.condition ^= 1;
3954             genSkipc(&rIfx);
3955
3956           }
3957         if(sign)
3958           emitpLabel(truelbl->key);
3959         if(ifx) ifx->generated = 1;
3960         return;
3961         }
3962       }
3963       /* Compare two variables */
3964
3965       DEBUGpic14_emitcode(";sign","%d",sign);
3966
3967       size--;
3968       if(sign) {
3969         /* Sigh. thus sucks... */
3970         if(size) {
3971           emitpcode(POC_MOVFW, popGet(AOP(left),size));
3972           emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3973           emitpcode(POC_MOVLW, popGetLit(0x80));
3974           emitpcode(POC_XORWF, popRegFromIdx(Gstack_base_addr));
3975           emitpcode(POC_XORFW, popGet(AOP(right),size));
3976           emitpcode(POC_SUBFW, popRegFromIdx(Gstack_base_addr));
3977         } else {
3978           /* Signed char comparison */
3979           /* Special thanks to Nikolai Golovchenko for this snippet */
3980           emitpcode(POC_MOVFW, popGet(AOP(right),0));
3981           emitpcode(POC_SUBFW, popGet(AOP(left),0));
3982           emitpcode(POC_RRFW,  popGet(AOP(left),0)); /* could be any register */
3983           emitpcode(POC_XORFW, popGet(AOP(left),0));
3984           emitpcode(POC_XORFW, popGet(AOP(right),0));
3985           emitpcode(POC_ADDLW, popGetLit(0x80));
3986
3987           DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3988           genSkipc(&rIfx);
3989           
3990           if(ifx) ifx->generated = 1;
3991           return;
3992         }
3993
3994       } else {
3995
3996         emitpcode(POC_MOVFW, popGet(AOP(right),size));
3997         emitpcode(POC_SUBFW, popGet(AOP(left),size));
3998       }
3999
4000
4001       /* The rest of the bytes of a multi-byte compare */
4002       while (size) {
4003
4004         emitSKPZ;
4005         emitpcode(POC_GOTO,  popGetLabel(lbl->key));
4006         size--;
4007
4008         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4009         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4010
4011
4012       }
4013
4014       emitpLabel(lbl->key);
4015
4016       DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4017       genSkipc(&rIfx);
4018       if(ifx) ifx->generated = 1;
4019       return;
4020
4021     }
4022   }
4023
4024   //release:
4025   if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4026     pic14_outBitC(result);
4027   } else {
4028     /* if the result is used in the next
4029        ifx conditional branch then generate
4030        code a little differently */
4031     if (ifx )
4032       genIfxJump (ifx,"c");
4033     else
4034       pic14_outBitC(result);
4035     /* leave the result in acc */
4036   }
4037
4038 }
4039
4040 /*-----------------------------------------------------------------*/
4041 /* genCmpGt :- greater than comparison                             */
4042 /*-----------------------------------------------------------------*/
4043 static void genCmpGt (iCode *ic, iCode *ifx)
4044 {
4045     operand *left, *right, *result;
4046     sym_link *letype , *retype;
4047     int sign ;
4048
4049     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4050     left = IC_LEFT(ic);
4051     right= IC_RIGHT(ic);
4052     result = IC_RESULT(ic);
4053
4054     letype = getSpec(operandType(left));
4055     retype =getSpec(operandType(right));
4056     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4057     /* assign the amsops */
4058     aopOp (left,ic,FALSE);
4059     aopOp (right,ic,FALSE);
4060     aopOp (result,ic,TRUE);
4061
4062     genCmp(right, left, result, ifx, sign);
4063
4064     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4065     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4066     freeAsmop(result,NULL,ic,TRUE); 
4067 }
4068
4069 /*-----------------------------------------------------------------*/
4070 /* genCmpLt - less than comparisons                                */
4071 /*-----------------------------------------------------------------*/
4072 static void genCmpLt (iCode *ic, iCode *ifx)
4073 {
4074     operand *left, *right, *result;
4075     sym_link *letype , *retype;
4076     int sign ;
4077
4078     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4079     left = IC_LEFT(ic);
4080     right= IC_RIGHT(ic);
4081     result = IC_RESULT(ic);
4082
4083     letype = getSpec(operandType(left));
4084     retype =getSpec(operandType(right));
4085     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4086
4087     /* assign the amsops */
4088     aopOp (left,ic,FALSE);
4089     aopOp (right,ic,FALSE);
4090     aopOp (result,ic,TRUE);
4091
4092     genCmp(left, right, result, ifx, sign);
4093
4094     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4095     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4096     freeAsmop(result,NULL,ic,TRUE); 
4097 }
4098
4099 /*-----------------------------------------------------------------*/
4100 /* genc16bit2lit - compare a 16 bit value to a literal             */
4101 /*-----------------------------------------------------------------*/
4102 static void genc16bit2lit(operand *op, int lit, int offset)
4103 {
4104   int i;
4105
4106   DEBUGpic14_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
4107   if( (lit&0xff) == 0) 
4108     i=1;
4109   else
4110     i=0;
4111
4112   switch( BYTEofLONG(lit,i)) { 
4113   case 0:
4114     emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4115     break;
4116   case 1:
4117     emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4118     break;
4119   case 0xff:
4120     emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4121     break;
4122   default:
4123     emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4124     emitpcode(POC_XORLW,popGetLit(BYTEofLONG(lit,i)));
4125   }
4126
4127   i ^= 1;
4128
4129   switch( BYTEofLONG(lit,i)) { 
4130   case 0:
4131     emitpcode(POC_IORFW,popGet(AOP(op),offset+i));
4132     break;
4133   case 1:
4134     emitSKPNZ;
4135     emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4136     break;
4137   case 0xff:
4138     emitSKPNZ;
4139     emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4140     break;
4141   default:
4142     emitpcode(POC_MOVLW,popGetLit(BYTEofLONG(lit,i)));
4143     emitSKPNZ;
4144     emitpcode(POC_XORFW,popGet(AOP(op),offset+i));
4145
4146   }
4147
4148 }
4149
4150 /*-----------------------------------------------------------------*/
4151 /* gencjneshort - compare and jump if not equal                    */
4152 /*-----------------------------------------------------------------*/
4153 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4154 {
4155   int size = max(AOP_SIZE(left),AOP_SIZE(right));
4156   int offset = 0;
4157   resolvedIfx rIfx;
4158   symbol *lbl;
4159
4160   unsigned long lit = 0L;
4161   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4162   DEBUGpic14_AopType(__LINE__,left,right,NULL);
4163
4164   resolveIfx(&rIfx,ifx);
4165   lbl =  newiTempLabel(NULL);
4166
4167
4168   /* if the left side is a literal or 
4169      if the right is in a pointer register and left 
4170      is not */
4171   if ((AOP_TYPE(left) == AOP_LIT) || 
4172       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4173     operand *t = right;
4174     right = left;
4175     left = t;
4176   }
4177   if(AOP_TYPE(right) == AOP_LIT)
4178     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4179
4180   /* if the right side is a literal then anything goes */
4181   if (AOP_TYPE(right) == AOP_LIT &&
4182       AOP_TYPE(left) != AOP_DIR ) {
4183     switch(size) {
4184     case 2:
4185       genc16bit2lit(left, lit, 0);
4186       emitSKPNZ;
4187       emitpcode(POC_GOTO,popGetLabel(lbl->key));
4188       break;
4189     default:
4190       while (size--) {
4191         if(lit & 0xff) {
4192           emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4193           emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4194         } else {
4195           emitpcode(POC_MOVF,popGet(AOP(left),offset));
4196         }
4197
4198         emitSKPNZ;
4199         emitpcode(POC_GOTO,popGetLabel(lbl->key));
4200         offset++;
4201         lit >>= 8;
4202       }
4203       break;
4204     }
4205   }
4206
4207   /* if the right side is in a register or in direct space or
4208      if the left is a pointer register & right is not */    
4209   else if (AOP_TYPE(right) == AOP_REG ||
4210            AOP_TYPE(right) == AOP_DIR || 
4211            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4212            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
4213     switch(size) {
4214     case 2:
4215       genc16bit2lit(left, lit, 0);
4216       emitSKPNZ;
4217       emitpcode(POC_GOTO,popGetLabel(lbl->key));
4218       break;
4219     default:
4220       while (size--) {
4221         int emit_skip=1;
4222         if((AOP_TYPE(left) == AOP_DIR) && 
4223            ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
4224
4225           emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4226           emitpcode(POC_XORFW,popGet(AOP(right),offset));
4227
4228         } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
4229             
4230           switch (lit & 0xff) {
4231           case 0:
4232             emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4233             break;
4234           case 1:
4235             emitpcode(POC_DECFSZ,popGet(AOP(left),offset));
4236             emitpcode(POC_GOTO,popGetLabel(lbl->key));
4237             emit_skip=0;
4238             break;
4239           case 0xff:
4240             emitpcode(POC_INCFSZ,popGet(AOP(left),offset));
4241             emitpcode(POC_GOTO,popGetLabel(lbl->key));
4242             emit_skip=0;
4243             break;
4244           default:
4245             emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4246             emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4247           }
4248           lit >>= 8;
4249
4250         } else {
4251           emitpcode(POC_MOVF,popGet(AOP(left),offset));
4252         }
4253         if(emit_skip) {
4254           if(AOP_TYPE(result) == AOP_CRY) {
4255             pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
4256             if(rIfx.condition)
4257               emitSKPNZ;
4258             else
4259               emitSKPZ;
4260             emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4261           } else {
4262             /* fix me. probably need to check result size too */
4263             emitpcode(POC_CLRF,popGet(AOP(result),0));
4264             if(rIfx.condition)
4265               emitSKPNZ;
4266             else
4267               emitSKPZ;
4268             emitpcode(POC_INCF,popGet(AOP(result),0));
4269           }
4270           if(ifx)
4271             ifx->generated=1;
4272         }
4273         emit_skip++;
4274         offset++;
4275       }
4276       break;
4277     }
4278   } else if(AOP_TYPE(right) == AOP_REG &&
4279             AOP_TYPE(left) != AOP_DIR){
4280
4281     while(size--) {
4282       emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4283       emitpcode(POC_XORFW,popGet(AOP(right),offset));
4284       pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
4285       if(rIfx.condition)
4286         emitSKPNZ;
4287       else
4288         emitSKPZ;
4289       emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4290       offset++;
4291     }
4292       
4293   }else{
4294     /* right is a pointer reg need both a & b */
4295     while(size--) {
4296       char *l = aopGet(AOP(left),offset,FALSE,FALSE);
4297       if(strcmp(l,"b"))
4298         pic14_emitcode("mov","b,%s",l);
4299       MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4300       pic14_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
4301       offset++;
4302     }
4303   }
4304   emitpLabel(lbl->key);
4305
4306   if(ifx)
4307     ifx->generated = 1;
4308 }
4309
4310 #if 0
4311 /*-----------------------------------------------------------------*/
4312 /* gencjne - compare and jump if not equal                         */
4313 /*-----------------------------------------------------------------*/
4314 static void gencjne(operand *left, operand *right, iCode *ifx)
4315 {
4316     symbol *tlbl  = newiTempLabel(NULL);
4317
4318     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4319     gencjneshort(left, right, lbl);
4320
4321     pic14_emitcode("mov","a,%s",one);
4322     pic14_emitcode("sjmp","%05d_DS_",tlbl->key+100);
4323     pic14_emitcode("","%05d_DS_:",lbl->key+100);
4324     pic14_emitcode("clr","a");
4325     pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4326
4327     emitpLabel(lbl->key);
4328     emitpLabel(tlbl->key);
4329
4330 }
4331 #endif
4332
4333 /*-----------------------------------------------------------------*/
4334 /* genCmpEq - generates code for equal to                          */
4335 /*-----------------------------------------------------------------*/
4336 static void genCmpEq (iCode *ic, iCode *ifx)
4337 {
4338     operand *left, *right, *result;
4339     unsigned long lit = 0L;
4340     int size,offset=0;
4341
4342     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4343
4344     if(ifx)
4345       DEBUGpic14_emitcode ("; ifx is non-null","");
4346     else
4347       DEBUGpic14_emitcode ("; ifx is null","");
4348
4349     aopOp((left=IC_LEFT(ic)),ic,FALSE);
4350     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4351     aopOp((result=IC_RESULT(ic)),ic,TRUE);
4352
4353     size = max(AOP_SIZE(left),AOP_SIZE(right));
4354
4355     DEBUGpic14_AopType(__LINE__,left,right,result);
4356
4357     /* if literal, literal on the right or 
4358     if the right is in a pointer register and left 
4359     is not */
4360     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
4361         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4362       operand *tmp = right ;
4363       right = left;
4364       left = tmp;
4365     }
4366
4367
4368     if(ifx && !AOP_SIZE(result)){
4369         symbol *tlbl;
4370         /* if they are both bit variables */
4371         if (AOP_TYPE(left) == AOP_CRY &&
4372             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4373             if(AOP_TYPE(right) == AOP_LIT){
4374                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4375                 if(lit == 0L){
4376                     pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4377                     pic14_emitcode("cpl","c");
4378                 } else if(lit == 1L) {
4379                     pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4380                 } else {
4381                     pic14_emitcode("clr","c");
4382                 }
4383                 /* AOP_TYPE(right) == AOP_CRY */
4384             } else {
4385                 symbol *lbl = newiTempLabel(NULL);
4386                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4387                 pic14_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4388                 pic14_emitcode("cpl","c");
4389                 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
4390             }
4391             /* if true label then we jump if condition
4392             supplied is true */
4393             tlbl = newiTempLabel(NULL);
4394             if ( IC_TRUE(ifx) ) {
4395                 pic14_emitcode("jnc","%05d_DS_",tlbl->key+100);
4396                 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
4397             } else {
4398                 pic14_emitcode("jc","%05d_DS_",tlbl->key+100);
4399                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
4400             }
4401             pic14_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
4402         } else {
4403
4404           /* They're not both bit variables. Is the right a literal? */
4405           if(AOP_TYPE(right) == AOP_LIT) {
4406             lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4407             
4408             switch(size) {
4409
4410             case 1:
4411               switch(lit & 0xff) {
4412               case 1:
4413                 if ( IC_TRUE(ifx) ) {
4414                   emitpcode(POC_DECFW,popGet(AOP(left),offset));
4415                   emitSKPNZ;
4416                   emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4417                 } else {
4418                   emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
4419                   emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4420                 }
4421                 break;
4422               case 0xff:
4423                 if ( IC_TRUE(ifx) ) {
4424                   emitpcode(POC_INCFW,popGet(AOP(left),offset));
4425                   emitSKPNZ;
4426                   emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4427                 } else {
4428                   emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4429                   emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4430                 }
4431                 break;
4432               default:
4433                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4434                 if(lit)
4435                   emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4436                 genSkip(ifx,'z');
4437               }
4438
4439
4440               /* end of size == 1 */
4441               break;
4442               
4443             case 2:
4444               genc16bit2lit(left,lit,offset);
4445               genSkip(ifx,'z');
4446               break;
4447               /* end of size == 2 */
4448
4449             default:
4450               /* size is 4 */
4451               if(lit==0) {
4452                 emitpcode(POC_MOVFW,popGet(AOP(left),0));
4453                 emitpcode(POC_IORFW,popGet(AOP(left),1));
4454                 emitpcode(POC_IORFW,popGet(AOP(left),2));
4455                 emitpcode(POC_IORFW,popGet(AOP(left),3));
4456
4457               } else {
4458
4459                 /* search for patterns that can be optimized */
4460
4461                 genc16bit2lit(left,lit,0);
4462                 lit >>= 16;
4463                 if(lit) {
4464                   genSkipz(ifx,IC_TRUE(ifx) == NULL);
4465                   //genSkip(ifx,'z');
4466                   genc16bit2lit(left,lit,2);
4467                 } else {
4468                   emitpcode(POC_IORFW,popGet(AOP(left),2));
4469                   emitpcode(POC_IORFW,popGet(AOP(left),3));
4470
4471                 }
4472                 
4473               }
4474
4475               genSkip(ifx,'z');
4476             }
4477           
4478             ifx->generated = 1;
4479             goto release ;
4480             
4481
4482           } else if(AOP_TYPE(right) == AOP_CRY ) {
4483             /* we know the left is not a bit, but that the right is */
4484             emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4485             emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
4486                       popGet(AOP(right),offset));
4487             emitpcode(POC_XORLW,popGetLit(1));
4488
4489             /* if the two are equal, then W will be 0 and the Z bit is set
4490              * we could test Z now, or go ahead and check the high order bytes if
4491              * the variable we're comparing is larger than a byte. */
4492
4493             while(--size)
4494               emitpcode(POC_IORFW,popGet(AOP(left),offset));
4495
4496             if ( IC_TRUE(ifx) ) {
4497               emitSKPNZ;
4498               emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4499               pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4500             } else {
4501               emitSKPZ;
4502               emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4503               pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4504             }
4505
4506           } else {
4507             /* They're both variables that are larger than bits */
4508             int s = size;
4509
4510             tlbl = newiTempLabel(NULL);
4511
4512             while(size--) {
4513               emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4514               emitpcode(POC_XORFW,popGet(AOP(right),offset));
4515
4516               if ( IC_TRUE(ifx) ) {
4517                 if(size) {
4518                   emitSKPZ;
4519                   emitpcode(POC_GOTO,popGetLabel(tlbl->key));
4520                   pic14_emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset);
4521                 } else {
4522                   emitSKPNZ;
4523                   emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4524                   pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4525                 }
4526               } else {
4527                 emitSKPZ;
4528                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4529                 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4530               }
4531               offset++;
4532             }
4533             if(s>1 && IC_TRUE(ifx)) {
4534               emitpLabel(tlbl->key);
4535               pic14_emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);                
4536             }
4537           }
4538         }
4539         /* mark the icode as generated */
4540         ifx->generated = 1;
4541         goto release ;
4542     }
4543
4544     /* if they are both bit variables */
4545     if (AOP_TYPE(left) == AOP_CRY &&
4546         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4547         if(AOP_TYPE(right) == AOP_LIT){
4548             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4549             if(lit == 0L){
4550                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4551                 pic14_emitcode("cpl","c");
4552             } else if(lit == 1L) {
4553                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4554             } else {
4555                 pic14_emitcode("clr","c");
4556             }
4557             /* AOP_TYPE(right) == AOP_CRY */
4558         } else {
4559             symbol *lbl = newiTempLabel(NULL);
4560             pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4561             pic14_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4562             pic14_emitcode("cpl","c");
4563             pic14_emitcode("","%05d_DS_:",(lbl->key+100));
4564         }
4565         /* c = 1 if egal */
4566         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
4567             pic14_outBitC(result);
4568             goto release ;
4569         }
4570         if (ifx) {
4571             genIfxJump (ifx,"c");
4572             goto release ;
4573         }
4574         /* if the result is used in an arithmetic operation
4575         then put the result in place */
4576         pic14_outBitC(result);
4577     } else {
4578       
4579       gencjne(left,right,result,ifx);
4580 /*
4581       if(ifx) 
4582         gencjne(left,right,newiTempLabel(NULL));
4583       else {
4584         if(IC_TRUE(ifx)->key)
4585           gencjne(left,right,IC_TRUE(ifx)->key);
4586         else
4587           gencjne(left,right,IC_FALSE(ifx)->key);
4588         ifx->generated = 1;
4589         goto release ;
4590       }
4591       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4592         aopPut(AOP(result),"a",0);
4593         goto release ;
4594       }
4595
4596       if (ifx) {
4597         genIfxJump (ifx,"a");
4598         goto release ;
4599       }
4600 */
4601       /* if the result is used in an arithmetic operation
4602          then put the result in place */
4603 /*
4604       if (AOP_TYPE(result) != AOP_CRY) 
4605         pic14_outAcc(result);
4606 */
4607       /* leave the result in acc */
4608     }
4609
4610 release:
4611     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4612     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4613     freeAsmop(result,NULL,ic,TRUE);
4614 }
4615
4616 /*-----------------------------------------------------------------*/
4617 /* ifxForOp - returns the icode containing the ifx for operand     */
4618 /*-----------------------------------------------------------------*/
4619 static iCode *ifxForOp ( operand *op, iCode *ic )
4620 {
4621     /* if true symbol then needs to be assigned */
4622     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4623     if (IS_TRUE_SYMOP(op))
4624         return NULL ;
4625
4626     /* if this has register type condition and
4627     the next instruction is ifx with the same operand
4628     and live to of the operand is upto the ifx only then */
4629     if (ic->next &&
4630         ic->next->op == IFX &&
4631         IC_COND(ic->next)->key == op->key &&
4632         OP_SYMBOL(op)->liveTo <= ic->next->seq )
4633         return ic->next;
4634
4635     if (ic->next &&
4636         ic->next->op == IFX &&
4637         IC_COND(ic->next)->key == op->key) {
4638       DEBUGpic14_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
4639       return ic->next;
4640     }
4641
4642     DEBUGpic14_emitcode ("; NULL :(","%d",__LINE__);
4643     if (ic->next &&
4644         ic->next->op == IFX)
4645       DEBUGpic14_emitcode ("; ic-next"," is an IFX");
4646
4647     if (ic->next &&
4648         ic->next->op == IFX &&
4649         IC_COND(ic->next)->key == op->key) {
4650       DEBUGpic14_emitcode ("; "," key is okay");
4651       DEBUGpic14_emitcode ("; "," key liveTo %d, next->seq = %d",
4652                            OP_SYMBOL(op)->liveTo,
4653                            ic->next->seq);
4654     }
4655
4656
4657     return NULL;
4658 }
4659 /*-----------------------------------------------------------------*/
4660 /* genAndOp - for && operation                                     */
4661 /*-----------------------------------------------------------------*/
4662 static void genAndOp (iCode *ic)
4663 {
4664     operand *left,*right, *result;
4665     symbol *tlbl;
4666
4667     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4668     /* note here that && operations that are in an
4669     if statement are taken away by backPatchLabels
4670     only those used in arthmetic operations remain */
4671     aopOp((left=IC_LEFT(ic)),ic,FALSE);
4672     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4673     aopOp((result=IC_RESULT(ic)),ic,FALSE);
4674
4675     /* if both are bit variables */
4676     if (AOP_TYPE(left) == AOP_CRY &&
4677         AOP_TYPE(right) == AOP_CRY ) {
4678         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4679         pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
4680         pic14_outBitC(result);
4681     } else {
4682         tlbl = newiTempLabel(NULL);
4683         pic14_toBoolean(left);    
4684         pic14_emitcode("jz","%05d_DS_",tlbl->key+100);
4685         pic14_toBoolean(right);
4686         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4687         pic14_outBitAcc(result);
4688     }
4689
4690     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4691     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4692     freeAsmop(result,NULL,ic,TRUE);
4693 }
4694
4695
4696 /*-----------------------------------------------------------------*/
4697 /* genOrOp - for || operation                                      */
4698 /*-----------------------------------------------------------------*/
4699 /*
4700   tsd pic port -
4701   modified this code, but it doesn't appear to ever get called
4702 */
4703
4704 static void genOrOp (iCode *ic)
4705 {
4706     operand *left,*right, *result;
4707     symbol *tlbl;
4708
4709     /* note here that || operations that are in an
4710     if statement are taken away by backPatchLabels
4711     only those used in arthmetic operations remain */
4712     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4713     aopOp((left=IC_LEFT(ic)),ic,FALSE);
4714     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4715     aopOp((result=IC_RESULT(ic)),ic,FALSE);
4716
4717     DEBUGpic14_AopType(__LINE__,left,right,result);
4718
4719     /* if both are bit variables */
4720     if (AOP_TYPE(left) == AOP_CRY &&
4721         AOP_TYPE(right) == AOP_CRY ) {
4722       pic14_emitcode("clrc","");
4723       pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
4724                AOP(left)->aopu.aop_dir,
4725                AOP(left)->aopu.aop_dir);
4726       pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
4727                AOP(right)->aopu.aop_dir,
4728                AOP(right)->aopu.aop_dir);
4729       pic14_emitcode("setc","");
4730
4731     } else {
4732         tlbl = newiTempLabel(NULL);
4733         pic14_toBoolean(left);
4734         emitSKPZ;
4735         pic14_emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
4736         pic14_toBoolean(right);
4737         pic14_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
4738
4739         pic14_outBitAcc(result);
4740     }
4741
4742     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4743     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4744     freeAsmop(result,NULL,ic,TRUE);            
4745 }
4746
4747 /*-----------------------------------------------------------------*/
4748 /* isLiteralBit - test if lit == 2^n                               */
4749 /*-----------------------------------------------------------------*/
4750 static int isLiteralBit(unsigned long lit)
4751 {
4752     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
4753     0x100L,0x200L,0x400L,0x800L,
4754     0x1000L,0x2000L,0x4000L,0x8000L,
4755     0x10000L,0x20000L,0x40000L,0x80000L,
4756     0x100000L,0x200000L,0x400000L,0x800000L,
4757     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
4758     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
4759     int idx;
4760     
4761     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4762     for(idx = 0; idx < 32; idx++)
4763         if(lit == pw[idx])
4764             return idx+1;
4765     return 0;
4766 }
4767
4768 /*-----------------------------------------------------------------*/
4769 /* continueIfTrue -                                                */
4770 /*-----------------------------------------------------------------*/
4771 static void continueIfTrue (iCode *ic)
4772 {
4773     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4774     if(IC_TRUE(ic))
4775         pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
4776     ic->generated = 1;
4777 }
4778
4779 /*-----------------------------------------------------------------*/
4780 /* jmpIfTrue -                                                     */
4781 /*-----------------------------------------------------------------*/
4782 static void jumpIfTrue (iCode *ic)
4783 {
4784     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4785     if(!IC_TRUE(ic))
4786         pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
4787     ic->generated = 1;
4788 }
4789
4790 /*-----------------------------------------------------------------*/
4791 /* jmpTrueOrFalse -                                                */
4792 /*-----------------------------------------------------------------*/
4793 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
4794 {
4795     // ugly but optimized by peephole
4796     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4797     if(IC_TRUE(ic)){
4798         symbol *nlbl = newiTempLabel(NULL);
4799         pic14_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
4800         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4801         pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
4802         pic14_emitcode("","%05d_DS_:",nlbl->key+100);
4803     }
4804     else{
4805         pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
4806         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4807     }
4808     ic->generated = 1;
4809 }
4810
4811 /*-----------------------------------------------------------------*/
4812 /* genAnd  - code for and                                          */
4813 /*-----------------------------------------------------------------*/
4814 static void genAnd (iCode *ic, iCode *ifx)
4815 {
4816   operand *left, *right, *result;
4817   int size, offset=0;  
4818   unsigned long lit = 0L;
4819   int bytelit = 0;
4820   resolvedIfx rIfx;
4821
4822
4823   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4824   aopOp((left = IC_LEFT(ic)),ic,FALSE);
4825   aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4826   aopOp((result=IC_RESULT(ic)),ic,TRUE);
4827
4828   resolveIfx(&rIfx,ifx);
4829
4830   /* if left is a literal & right is not then exchange them */
4831   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4832       AOP_NEEDSACC(left)) {
4833     operand *tmp = right ;
4834     right = left;
4835     left = tmp;
4836   }
4837
4838   /* if result = right then exchange them */
4839   if(pic14_sameRegs(AOP(result),AOP(right))){
4840     operand *tmp = right ;
4841     right = left;
4842     left = tmp;
4843   }
4844
4845   /* if right is bit then exchange them */
4846   if (AOP_TYPE(right) == AOP_CRY &&
4847       AOP_TYPE(left) != AOP_CRY){
4848     operand *tmp = right ;
4849     right = left;
4850     left = tmp;
4851   }
4852   if(AOP_TYPE(right) == AOP_LIT)
4853     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4854
4855   size = AOP_SIZE(result);
4856
4857   DEBUGpic14_AopType(__LINE__,left,right,result);
4858
4859   // if(bit & yy)
4860   // result = bit & yy;
4861   if (AOP_TYPE(left) == AOP_CRY){
4862     // c = bit & literal;
4863     if(AOP_TYPE(right) == AOP_LIT){
4864       if(lit & 1) {
4865         if(size && pic14_sameRegs(AOP(result),AOP(left)))
4866           // no change
4867           goto release;
4868         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4869       } else {
4870         // bit(result) = 0;
4871         if(size && (AOP_TYPE(result) == AOP_CRY)){
4872           pic14_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
4873           goto release;
4874         }
4875         if((AOP_TYPE(result) == AOP_CRY) && ifx){
4876           jumpIfTrue(ifx);
4877           goto release;
4878         }
4879         pic14_emitcode("clr","c");
4880       }
4881     } else {
4882       if (AOP_TYPE(right) == AOP_CRY){
4883         // c = bit & bit;
4884         pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4885         pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4886       } else {
4887         // c = bit & val;
4888         MOVA(aopGet(AOP(right),0,FALSE,FALSE));
4889         // c = lsb
4890         pic14_emitcode("rrc","a");
4891         pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4892       }
4893     }
4894     // bit = c
4895     // val = c
4896     if(size)
4897       pic14_outBitC(result);
4898     // if(bit & ...)
4899     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4900       genIfxJump(ifx, "c");           
4901     goto release ;
4902   }
4903
4904   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
4905   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
4906   if((AOP_TYPE(right) == AOP_LIT) &&
4907      (AOP_TYPE(result) == AOP_CRY) &&
4908      (AOP_TYPE(left) != AOP_CRY)){
4909     int posbit = isLiteralBit(lit);
4910     /* left &  2^n */
4911     if(posbit){
4912       posbit--;
4913       //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
4914       // bit = left & 2^n
4915       if(size)
4916         pic14_emitcode("mov","c,acc.%d",posbit&0x07);
4917       // if(left &  2^n)
4918       else{
4919         if(ifx){
4920 /*
4921           if(IC_TRUE(ifx)) {
4922             emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
4923             emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
4924           } else {
4925             emitpcode(POC_BTFSS,newpCodeOpBit(aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
4926             emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
4927           }
4928 */
4929           emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
4930                     newpCodeOpBit(aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
4931           emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4932           
4933           ifx->generated = 1;
4934         }
4935         goto release;
4936       }
4937     } else {
4938       symbol *tlbl = newiTempLabel(NULL);
4939       int sizel = AOP_SIZE(left);
4940       if(size)
4941         pic14_emitcode("setb","c");
4942       while(sizel--){
4943         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
4944           MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
4945           // byte ==  2^n ?
4946           if((posbit = isLiteralBit(bytelit)) != 0)
4947             pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
4948           else{
4949             if(bytelit != 0x0FFL)
4950               pic14_emitcode("anl","a,%s",
4951                              aopGet(AOP(right),offset,FALSE,TRUE));
4952             pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
4953           }
4954         }
4955         offset++;
4956       }
4957       // bit = left & literal
4958       if(size){
4959         pic14_emitcode("clr","c");
4960         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4961       }
4962       // if(left & literal)
4963       else{
4964         if(ifx)
4965           jmpTrueOrFalse(ifx, tlbl);
4966         goto release ;
4967       }
4968     }
4969     pic14_outBitC(result);
4970     goto release ;
4971   }
4972
4973   /* if left is same as result */
4974   if(pic14_sameRegs(AOP(result),AOP(left))){
4975     int know_W = -1;
4976     for(;size--; offset++,lit>>=8) {
4977       if(AOP_TYPE(right) == AOP_LIT){
4978         switch(lit & 0xff) {
4979         case 0x00:
4980           /*  and'ing with 0 has clears the result */
4981           pic14_emitcode("clrf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
4982           emitpcode(POC_CLRF,popGet(AOP(result),offset));
4983           break;
4984         case 0xff:
4985           /* and'ing with 0xff is a nop when the result and left are the same */
4986           break;
4987
4988         default:
4989           {
4990             int p = my_powof2( (~lit) & 0xff );
4991             if(p>=0) {
4992               /* only one bit is set in the literal, so use a bcf instruction */
4993               pic14_emitcode("bcf","%s,%d",aopGet(AOP(left),offset,FALSE,TRUE),p);
4994               emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
4995
4996             } else {
4997               pic14_emitcode("movlw","0x%x", (lit & 0xff));
4998               pic14_emitcode("andwf","%s,f",aopGet(AOP(left),offset,FALSE,TRUE));
4999               if(know_W != (lit&0xff))
5000                 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5001               know_W = lit &0xff;
5002               emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5003             }
5004           }    
5005         }
5006       } else {
5007         if (AOP_TYPE(left) == AOP_ACC) {
5008           emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5009         } else {                    
5010           emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5011           emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5012
5013         }
5014       }
5015     }
5016
5017   } else {
5018     // left & result in different registers
5019     if(AOP_TYPE(result) == AOP_CRY){
5020       // result = bit
5021       // if(size), result in bit
5022       // if(!size && ifx), conditional oper: if(left & right)
5023       symbol *tlbl = newiTempLabel(NULL);
5024       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5025       if(size)
5026         pic14_emitcode("setb","c");
5027       while(sizer--){
5028         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5029         pic14_emitcode("anl","a,%s",
5030                        aopGet(AOP(left),offset,FALSE,FALSE));
5031         pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5032         offset++;
5033       }
5034       if(size){
5035         CLRC;
5036         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5037         pic14_outBitC(result);
5038       } else if(ifx)
5039         jmpTrueOrFalse(ifx, tlbl);
5040     } else {
5041       for(;(size--);offset++) {
5042         // normal case
5043         // result = left & right
5044         if(AOP_TYPE(right) == AOP_LIT){
5045           int t = (lit >> (offset*8)) & 0x0FFL;
5046           switch(t) { 
5047           case 0x00:
5048             pic14_emitcode("clrf","%s",
5049                            aopGet(AOP(result),offset,FALSE,FALSE));
5050             emitpcode(POC_CLRF,popGet(AOP(result),offset));
5051             break;
5052           case 0xff:
5053             pic14_emitcode("movf","%s,w",
5054                            aopGet(AOP(left),offset,FALSE,FALSE));
5055             pic14_emitcode("movwf","%s",
5056                            aopGet(AOP(result),offset,FALSE,FALSE));
5057             emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5058             emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5059             break;
5060           default:
5061             pic14_emitcode("movlw","0x%x",t);
5062             pic14_emitcode("andwf","%s,w",
5063                            aopGet(AOP(left),offset,FALSE,FALSE));
5064             pic14_emitcode("movwf","%s",
5065                            aopGet(AOP(result),offset,FALSE,FALSE));
5066               
5067             emitpcode(POC_MOVLW, popGetLit(t));
5068             emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5069             emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5070           }
5071           continue;
5072         }
5073
5074         if (AOP_TYPE(left) == AOP_ACC) {
5075           pic14_emitcode("andwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5076           emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5077         } else {
5078           pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5079           pic14_emitcode("andwf","%s,w",
5080                          aopGet(AOP(left),offset,FALSE,FALSE));
5081           emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5082           emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5083         }
5084         pic14_emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5085         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5086       }
5087     }
5088   }
5089
5090   release :
5091     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5092   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5093   freeAsmop(result,NULL,ic,TRUE);     
5094 }
5095
5096 /*-----------------------------------------------------------------*/
5097 /* genOr  - code for or                                            */
5098 /*-----------------------------------------------------------------*/
5099 static void genOr (iCode *ic, iCode *ifx)
5100 {
5101     operand *left, *right, *result;
5102     int size, offset=0;
5103     unsigned long lit = 0L;
5104
5105     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5106
5107     aopOp((left = IC_LEFT(ic)),ic,FALSE);
5108     aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5109     aopOp((result=IC_RESULT(ic)),ic,TRUE);
5110
5111     DEBUGpic14_AopType(__LINE__,left,right,result);
5112
5113     /* if left is a literal & right is not then exchange them */
5114     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5115         AOP_NEEDSACC(left)) {
5116         operand *tmp = right ;
5117         right = left;
5118         left = tmp;
5119     }
5120
5121     /* if result = right then exchange them */
5122     if(pic14_sameRegs(AOP(result),AOP(right))){
5123         operand *tmp = right ;
5124         right = left;
5125         left = tmp;
5126     }
5127
5128     /* if right is bit then exchange them */
5129     if (AOP_TYPE(right) == AOP_CRY &&
5130         AOP_TYPE(left) != AOP_CRY){
5131         operand *tmp = right ;
5132         right = left;
5133         left = tmp;
5134     }
5135
5136     DEBUGpic14_AopType(__LINE__,left,right,result);
5137
5138     if(AOP_TYPE(right) == AOP_LIT)
5139         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5140
5141     size = AOP_SIZE(result);
5142
5143     // if(bit | yy)
5144     // xx = bit | yy;
5145     if (AOP_TYPE(left) == AOP_CRY){
5146         if(AOP_TYPE(right) == AOP_LIT){
5147             // c = bit & literal;
5148             if(lit){
5149                 // lit != 0 => result = 1
5150                 if(AOP_TYPE(result) == AOP_CRY){
5151                   if(size)
5152                     emitpcode(POC_BSF, popGet(AOP(result),0));
5153                   //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5154                   //     AOP(result)->aopu.aop_dir,
5155                   //     AOP(result)->aopu.aop_dir);
5156                     else if(ifx)
5157                         continueIfTrue(ifx);
5158                     goto release;
5159                 }
5160             } else {
5161                 // lit == 0 => result = left
5162                 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5163                     goto release;
5164                 pic14_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5165             }
5166         } else {
5167             if (AOP_TYPE(right) == AOP_CRY){
5168               if(pic14_sameRegs(AOP(result),AOP(left))){
5169                 // c = bit | bit;
5170                 emitpcode(POC_BCF,   popGet(AOP(result),0));
5171                 emitpcode(POC_BTFSC, popGet(AOP(right),0));
5172                 emitpcode(POC_BSF,   popGet(AOP(result),0));
5173
5174                 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5175                          AOP(result)->aopu.aop_dir,
5176                          AOP(result)->aopu.aop_dir);
5177                 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5178                          AOP(right)->aopu.aop_dir,
5179                          AOP(right)->aopu.aop_dir);
5180                 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5181                          AOP(result)->aopu.aop_dir,
5182                          AOP(result)->aopu.aop_dir);
5183               } else {
5184                 if( AOP_TYPE(result) == AOP_ACC) {
5185                   emitpcode(POC_MOVLW, popGetLit(0));
5186                   emitpcode(POC_BTFSS, popGet(AOP(right),0));
5187                   emitpcode(POC_BTFSC, popGet(AOP(left),0));
5188                   emitpcode(POC_MOVLW, popGetLit(1));
5189
5190                 } else {
5191
5192                   emitpcode(POC_BCF,   popGet(AOP(result),0));
5193                   emitpcode(POC_BTFSS, popGet(AOP(right),0));
5194                   emitpcode(POC_BTFSC, popGet(AOP(left),0));
5195                   emitpcode(POC_BSF,   popGet(AOP(result),0));
5196
5197                   pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5198                                  AOP(result)->aopu.aop_dir,
5199                                  AOP(result)->aopu.aop_dir);
5200                   pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5201                                  AOP(right)->aopu.aop_dir,
5202                                  AOP(right)->aopu.aop_dir);
5203                   pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5204                                  AOP(left)->aopu.aop_dir,
5205                                  AOP(left)->aopu.aop_dir);
5206                   pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5207                                  AOP(result)->aopu.aop_dir,
5208                                  AOP(result)->aopu.aop_dir);
5209                 }
5210               }
5211             } else {
5212                 // c = bit | val;
5213                 symbol *tlbl = newiTempLabel(NULL);
5214                 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5215
5216
5217                 emitpcode(POC_BCF,   popGet(AOP(result),0));
5218                 if( AOP_TYPE(right) == AOP_ACC) {
5219                   emitpcode(POC_IORLW, popGetLit(0));
5220                   emitSKPNZ;
5221                   emitpcode(POC_BTFSC, popGet(AOP(left),0));
5222                   emitpcode(POC_BSF,   popGet(AOP(result),0));
5223                 }
5224
5225
5226
5227                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5228                     pic14_emitcode(";XXX setb","c");
5229                 pic14_emitcode(";XXX jb","%s,%05d_DS_",
5230                          AOP(left)->aopu.aop_dir,tlbl->key+100);
5231                 pic14_toBoolean(right);
5232                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5233                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5234                     jmpTrueOrFalse(ifx, tlbl);
5235                     goto release;
5236                 } else {
5237                     CLRC;
5238                     pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5239                 }
5240             }
5241         }
5242         // bit = c
5243         // val = c
5244         if(size)
5245             pic14_outBitC(result);
5246         // if(bit | ...)
5247         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5248             genIfxJump(ifx, "c");           
5249         goto release ;
5250     }
5251
5252     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5253     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5254     if((AOP_TYPE(right) == AOP_LIT) &&
5255        (AOP_TYPE(result) == AOP_CRY) &&
5256        (AOP_TYPE(left) != AOP_CRY)){
5257         if(lit){
5258           pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5259             // result = 1
5260             if(size)
5261                 pic14_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5262             else 
5263                 continueIfTrue(ifx);
5264             goto release;
5265         } else {
5266           pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5267             // lit = 0, result = boolean(left)
5268             if(size)
5269                 pic14_emitcode(";XXX setb","c");
5270             pic14_toBoolean(right);
5271             if(size){
5272                 symbol *tlbl = newiTempLabel(NULL);
5273                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5274                 CLRC;
5275                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5276             } else {
5277                 genIfxJump (ifx,"a");
5278                 goto release;
5279             }
5280         }
5281         pic14_outBitC(result);
5282         goto release ;
5283     }
5284
5285     /* if left is same as result */
5286     if(pic14_sameRegs(AOP(result),AOP(left))){
5287       int know_W = -1;
5288       for(;size--; offset++,lit>>=8) {
5289         if(AOP_TYPE(right) == AOP_LIT){
5290           if((lit & 0xff) == 0)
5291             /*  or'ing with 0 has no effect */
5292             continue;
5293           else {
5294             int p = my_powof2(lit & 0xff);
5295             if(p>=0) {
5296               /* only one bit is set in the literal, so use a bsf instruction */
5297               emitpcode(POC_BSF,
5298                         newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5299             } else {
5300               if(know_W != (lit & 0xff))
5301                 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5302               know_W = lit & 0xff;
5303               emitpcode(POC_IORWF, popGet(AOP(left),offset));
5304             }
5305                     
5306           }
5307         } else {
5308           if (AOP_TYPE(left) == AOP_ACC) {
5309             emitpcode(POC_IORFW,  popGet(AOP(right),offset));
5310             pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5311           } else {                  
5312             emitpcode(POC_MOVFW,  popGet(AOP(right),offset));
5313             emitpcode(POC_IORWF,  popGet(AOP(left),offset));
5314
5315             pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5316             pic14_emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
5317
5318           }
5319         }
5320       }
5321     } else {
5322         // left & result in different registers
5323         if(AOP_TYPE(result) == AOP_CRY){
5324             // result = bit
5325             // if(size), result in bit
5326             // if(!size && ifx), conditional oper: if(left | right)
5327             symbol *tlbl = newiTempLabel(NULL);
5328             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5329             pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5330
5331
5332             if(size)
5333                 pic14_emitcode(";XXX setb","c");
5334             while(sizer--){
5335                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5336                 pic14_emitcode(";XXX orl","a,%s",
5337                          aopGet(AOP(left),offset,FALSE,FALSE));
5338                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5339                 offset++;
5340             }
5341             if(size){
5342                 CLRC;
5343                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5344                 pic14_outBitC(result);
5345             } else if(ifx)
5346                 jmpTrueOrFalse(ifx, tlbl);
5347         } else for(;(size--);offset++){
5348           // normal case
5349           // result = left & right
5350           if(AOP_TYPE(right) == AOP_LIT){
5351             int t = (lit >> (offset*8)) & 0x0FFL;
5352             switch(t) { 
5353             case 0x00:
5354               emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
5355               emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
5356
5357               pic14_emitcode("movf","%s,w",
5358                        aopGet(AOP(left),offset,FALSE,FALSE));
5359               pic14_emitcode("movwf","%s",
5360                        aopGet(AOP(result),offset,FALSE,FALSE));
5361               break;
5362             default:
5363               emitpcode(POC_MOVLW,  popGetLit(t));
5364               emitpcode(POC_IORFW,  popGet(AOP(left),offset));
5365               emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
5366
5367               pic14_emitcode("movlw","0x%x",t);
5368               pic14_emitcode("iorwf","%s,w",
5369                        aopGet(AOP(left),offset,FALSE,FALSE));
5370               pic14_emitcode("movwf","%s",
5371                        aopGet(AOP(result),offset,FALSE,FALSE));
5372               
5373             }
5374             continue;
5375           }
5376
5377           // faster than result <- left, anl result,right
5378           // and better if result is SFR
5379           if (AOP_TYPE(left) == AOP_ACC) {
5380             emitpcode(POC_IORWF,  popGet(AOP(right),offset));
5381             pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5382           } else {
5383             emitpcode(POC_MOVFW,  popGet(AOP(right),offset));
5384             emitpcode(POC_IORFW,  popGet(AOP(left),offset));
5385
5386             pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5387             pic14_emitcode("iorwf","%s,w",
5388                      aopGet(AOP(left),offset,FALSE,FALSE));
5389           }
5390           emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
5391           pic14_emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5392         }
5393     }
5394
5395 release :
5396     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5397     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5398     freeAsmop(result,NULL,ic,TRUE);     
5399 }
5400
5401 /*-----------------------------------------------------------------*/
5402 /* genXor - code for xclusive or                                   */
5403 /*-----------------------------------------------------------------*/
5404 static void genXor (iCode *ic, iCode *ifx)
5405 {
5406   operand *left, *right, *result;
5407   int size, offset=0;
5408   unsigned long lit = 0L;
5409
5410   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5411
5412   aopOp((left = IC_LEFT(ic)),ic,FALSE);
5413   aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5414   aopOp((result=IC_RESULT(ic)),ic,TRUE);
5415
5416   /* if left is a literal & right is not ||
5417      if left needs acc & right does not */
5418   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5419       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
5420     operand *tmp = right ;
5421     right = left;
5422     left = tmp;
5423   }
5424
5425   /* if result = right then exchange them */
5426   if(pic14_sameRegs(AOP(result),AOP(right))){
5427     operand *tmp = right ;
5428     right = left;
5429     left = tmp;
5430   }
5431
5432   /* if right is bit then exchange them */
5433   if (AOP_TYPE(right) == AOP_CRY &&
5434       AOP_TYPE(left) != AOP_CRY){
5435     operand *tmp = right ;
5436     right = left;
5437     left = tmp;
5438   }
5439   if(AOP_TYPE(right) == AOP_LIT)
5440     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5441
5442   size = AOP_SIZE(result);
5443
5444   // if(bit ^ yy)
5445   // xx = bit ^ yy;
5446   if (AOP_TYPE(left) == AOP_CRY){
5447     if(AOP_TYPE(right) == AOP_LIT){
5448       // c = bit & literal;
5449       if(lit>>1){
5450         // lit>>1  != 0 => result = 1
5451         if(AOP_TYPE(result) == AOP_CRY){
5452           if(size)
5453             pic14_emitcode("setb","%s",AOP(result)->aopu.aop_dir);
5454           else if(ifx)
5455             continueIfTrue(ifx);
5456           goto release;
5457         }
5458         pic14_emitcode("setb","c");
5459       } else{
5460         // lit == (0 or 1)
5461         if(lit == 0){
5462           // lit == 0, result = left
5463           if(size && pic14_sameRegs(AOP(result),AOP(left)))
5464             goto release;
5465           pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5466         } else{
5467           // lit == 1, result = not(left)
5468           if(size && pic14_sameRegs(AOP(result),AOP(left))){
5469             pic14_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
5470             goto release;
5471           } else {
5472             pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5473             pic14_emitcode("cpl","c");
5474           }
5475         }
5476       }
5477
5478     } else {
5479       // right != literal
5480       symbol *tlbl = newiTempLabel(NULL);
5481       if (AOP_TYPE(right) == AOP_CRY){
5482         // c = bit ^ bit;
5483         pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5484       }
5485       else{
5486         int sizer = AOP_SIZE(right);
5487         // c = bit ^ val
5488         // if val>>1 != 0, result = 1
5489         pic14_emitcode("setb","c");
5490         while(sizer){
5491           MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
5492           if(sizer == 1)
5493             // test the msb of the lsb
5494             pic14_emitcode("anl","a,#0xfe");
5495           pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5496           sizer--;
5497         }
5498         // val = (0,1)
5499         pic14_emitcode("rrc","a");
5500       }
5501       pic14_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
5502       pic14_emitcode("cpl","c");
5503       pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
5504     }
5505     // bit = c
5506     // val = c
5507     if(size)
5508       pic14_outBitC(result);
5509     // if(bit | ...)
5510     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5511       genIfxJump(ifx, "c");           
5512     goto release ;
5513   }
5514
5515   if(pic14_sameRegs(AOP(result),AOP(left))){
5516     /* if left is same as result */
5517     for(;size--; offset++) {
5518       if(AOP_TYPE(right) == AOP_LIT){
5519         int t  = (lit >> (offset*8)) & 0x0FFL;
5520         if(t == 0x00L)
5521           continue;
5522         else
5523           if (IS_AOP_PREG(left)) {
5524             MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5525             pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
5526             aopPut(AOP(result),"a",offset);
5527           } else {
5528             emitpcode(POC_MOVLW, popGetLit(t));
5529             emitpcode(POC_XORWF,popGet(AOP(left),offset));
5530             pic14_emitcode("xrl","%s,%s",
5531                            aopGet(AOP(left),offset,FALSE,TRUE),
5532                            aopGet(AOP(right),offset,FALSE,FALSE));
5533           }
5534       } else {
5535         if (AOP_TYPE(left) == AOP_ACC)
5536           pic14_emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
5537         else {
5538           emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5539           emitpcode(POC_XORWF,popGet(AOP(left),offset));
5540 /*
5541           if (IS_AOP_PREG(left)) {
5542             pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
5543             aopPut(AOP(result),"a",offset);
5544           } else
5545             pic14_emitcode("xrl","%s,a",
5546                            aopGet(AOP(left),offset,FALSE,TRUE));
5547 */
5548         }
5549       }
5550     }
5551   } else {
5552     // left & result in different registers
5553     if(AOP_TYPE(result) == AOP_CRY){
5554       // result = bit
5555       // if(size), result in bit
5556       // if(!size && ifx), conditional oper: if(left ^ right)
5557       symbol *tlbl = newiTempLabel(NULL);
5558       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5559       if(size)
5560         pic14_emitcode("setb","c");
5561       while(sizer--){
5562         if((AOP_TYPE(right) == AOP_LIT) &&
5563            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
5564           MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
5565         } else {
5566           MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5567           pic14_emitcode("xrl","a,%s",
5568                          aopGet(AOP(left),offset,FALSE,FALSE));
5569         }
5570         pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5571         offset++;
5572       }
5573       if(size){
5574         CLRC;
5575         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5576         pic14_outBitC(result);
5577       } else if(ifx)
5578         jmpTrueOrFalse(ifx, tlbl);
5579     } else for(;(size--);offset++){
5580       // normal case
5581       // result = left & right
5582       if(AOP_TYPE(right) == AOP_LIT){
5583         int t = (lit >> (offset*8)) & 0x0FFL;
5584         switch(t) { 
5585         case 0x00:
5586           emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5587           emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5588           pic14_emitcode("movf","%s,w",
5589                          aopGet(AOP(left),offset,FALSE,FALSE));
5590           pic14_emitcode("movwf","%s",
5591                          aopGet(AOP(result),offset,FALSE,FALSE));
5592           break;
5593         case 0xff:
5594           emitpcode(POC_COMFW,popGet(AOP(left),offset));
5595           emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5596           pic14_emitcode("comf","%s,w",
5597                          aopGet(AOP(left),offset,FALSE,FALSE));
5598           pic14_emitcode("movwf","%s",
5599                          aopGet(AOP(result),offset,FALSE,FALSE));
5600           break;
5601         default:
5602           emitpcode(POC_MOVLW, popGetLit(t));
5603           emitpcode(POC_XORFW,popGet(AOP(left),offset));
5604           emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5605           pic14_emitcode("movlw","0x%x",t);
5606           pic14_emitcode("xorwf","%s,w",
5607                          aopGet(AOP(left),offset,FALSE,FALSE));
5608           pic14_emitcode("movwf","%s",
5609                          aopGet(AOP(result),offset,FALSE,FALSE));
5610
5611         }
5612         continue;
5613       }
5614
5615       // faster than result <- left, anl result,right
5616       // and better if result is SFR
5617       if (AOP_TYPE(left) == AOP_ACC) {
5618         emitpcode(POC_XORFW,popGet(AOP(right),offset));
5619         pic14_emitcode("xorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5620       } else {
5621         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5622         emitpcode(POC_XORFW,popGet(AOP(left),offset));
5623         pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5624         pic14_emitcode("xorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
5625       }
5626       if ( AOP_TYPE(result) != AOP_ACC){
5627         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5628         pic14_emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5629       }
5630     }
5631   }
5632
5633   release :
5634     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5635   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5636   freeAsmop(result,NULL,ic,TRUE);     
5637 }
5638
5639 /*-----------------------------------------------------------------*/
5640 /* genInline - write the inline code out                           */
5641 /*-----------------------------------------------------------------*/
5642 static void genInline (iCode *ic)
5643 {
5644     char *buffer, *bp, *bp1;
5645     
5646     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5647
5648     _G.inLine += (!options.asmpeep);
5649
5650     buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5651     strcpy(buffer,IC_INLINE(ic));
5652
5653     /* emit each line as a code */
5654     while (*bp) {
5655         if (*bp == '\n') {
5656             *bp++ = '\0';
5657             pic14_emitcode(bp1,"");
5658             bp1 = bp;
5659         } else {
5660             if (*bp == ':') {
5661                 bp++;
5662                 *bp = '\0';
5663                 bp++;
5664                 pic14_emitcode(bp1,"");
5665                 bp1 = bp;
5666             } else
5667                 bp++;
5668         }
5669     }
5670     if (bp1 != bp)
5671         pic14_emitcode(bp1,"");
5672     /*     pic14_emitcode("",buffer); */
5673     _G.inLine -= (!options.asmpeep);
5674 }
5675
5676 /*-----------------------------------------------------------------*/
5677 /* genRRC - rotate right with carry                                */
5678 /*-----------------------------------------------------------------*/
5679 static void genRRC (iCode *ic)
5680 {
5681   operand *left , *result ;
5682   int size, offset = 0, same;
5683
5684   /* rotate right with carry */
5685   left = IC_LEFT(ic);
5686   result=IC_RESULT(ic);
5687   aopOp (left,ic,FALSE);
5688   aopOp (result,ic,FALSE);
5689
5690   DEBUGpic14_AopType(__LINE__,left,NULL,result);
5691
5692   same = pic14_sameRegs(AOP(result),AOP(left));
5693
5694   size = AOP_SIZE(result);    
5695
5696   /* get the lsb and put it into the carry */
5697   emitpcode(POC_RRFW, popGet(AOP(left),size-1));
5698
5699   offset = 0 ;
5700
5701   while(size--) {
5702
5703     if(same) {
5704       emitpcode(POC_RRF, popGet(AOP(left),offset));
5705     } else {
5706       emitpcode(POC_RRFW, popGet(AOP(left),offset));
5707       emitpcode(POC_MOVWF, popGet(AOP(result),offset));
5708     }
5709
5710     offset++;
5711   }
5712
5713   freeAsmop(left,NULL,ic,TRUE);
5714   freeAsmop(result,NULL,ic,TRUE);
5715 }
5716
5717 /*-----------------------------------------------------------------*/
5718 /* genRLC - generate code for rotate left with carry               */
5719 /*-----------------------------------------------------------------*/
5720 static void genRLC (iCode *ic)
5721 {    
5722   operand *left , *result ;
5723   int size, offset = 0;
5724   int same;
5725
5726   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5727   /* rotate right with carry */
5728   left = IC_LEFT(ic);
5729   result=IC_RESULT(ic);
5730   aopOp (left,ic,FALSE);
5731   aopOp (result,ic,FALSE);
5732
5733   DEBUGpic14_AopType(__LINE__,left,NULL,result);
5734
5735   same = pic14_sameRegs(AOP(result),AOP(left));
5736
5737   /* move it to the result */
5738   size = AOP_SIZE(result);    
5739
5740   /* get the msb and put it into the carry */
5741   emitpcode(POC_RLFW, popGet(AOP(left),size-1));
5742
5743   offset = 0 ;
5744
5745   while(size--) {
5746
5747     if(same) {
5748       emitpcode(POC_RLF, popGet(AOP(left),offset));
5749     } else {
5750       emitpcode(POC_RLFW, popGet(AOP(left),offset));
5751       emitpcode(POC_MOVWF, popGet(AOP(result),offset));
5752     }
5753
5754     offset++;
5755   }
5756
5757
5758   freeAsmop(left,NULL,ic,TRUE);
5759   freeAsmop(result,NULL,ic,TRUE);
5760 }
5761
5762 /*-----------------------------------------------------------------*/
5763 /* genGetHbit - generates code get highest order bit               */
5764 /*-----------------------------------------------------------------*/
5765 static void genGetHbit (iCode *ic)
5766 {
5767     operand *left, *result;
5768     left = IC_LEFT(ic);
5769     result=IC_RESULT(ic);
5770     aopOp (left,ic,FALSE);
5771     aopOp (result,ic,FALSE);
5772
5773     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5774     /* get the highest order byte into a */
5775     MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
5776     if(AOP_TYPE(result) == AOP_CRY){
5777         pic14_emitcode("rlc","a");
5778         pic14_outBitC(result);
5779     }
5780     else{
5781         pic14_emitcode("rl","a");
5782         pic14_emitcode("anl","a,#0x01");
5783         pic14_outAcc(result);
5784     }
5785
5786
5787     freeAsmop(left,NULL,ic,TRUE);
5788     freeAsmop(result,NULL,ic,TRUE);
5789 }
5790
5791 /*-----------------------------------------------------------------*/
5792 /* AccRol - rotate left accumulator by known count                 */
5793 /*-----------------------------------------------------------------*/
5794 static void AccRol (int shCount)
5795 {
5796     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5797     shCount &= 0x0007;              // shCount : 0..7
5798     switch(shCount){
5799         case 0 :
5800             break;
5801         case 1 :
5802             pic14_emitcode("rl","a");
5803             break;
5804         case 2 :
5805             pic14_emitcode("rl","a");
5806             pic14_emitcode("rl","a");
5807             break;
5808         case 3 :
5809             pic14_emitcode("swap","a");
5810             pic14_emitcode("rr","a");
5811             break;
5812         case 4 :
5813             pic14_emitcode("swap","a");
5814             break;
5815         case 5 :
5816             pic14_emitcode("swap","a");
5817             pic14_emitcode("rl","a");
5818             break;
5819         case 6 :
5820             pic14_emitcode("rr","a");
5821             pic14_emitcode("rr","a");
5822             break;
5823         case 7 :
5824             pic14_emitcode("rr","a");
5825             break;
5826     }
5827 }
5828
5829 /*-----------------------------------------------------------------*/
5830 /* AccLsh - left shift accumulator by known count                  */
5831 /*-----------------------------------------------------------------*/
5832 static void AccLsh (int shCount)
5833 {
5834     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5835     if(shCount != 0){
5836         if(shCount == 1)
5837             pic14_emitcode("add","a,acc");
5838         else 
5839             if(shCount == 2) {
5840             pic14_emitcode("add","a,acc");
5841             pic14_emitcode("add","a,acc");
5842         } else {
5843             /* rotate left accumulator */
5844             AccRol(shCount);
5845             /* and kill the lower order bits */
5846             pic14_emitcode("anl","a,#0x%02x", SLMask[shCount]);
5847         }
5848     }
5849 }
5850
5851 /*-----------------------------------------------------------------*/
5852 /* AccRsh - right shift accumulator by known count                 */
5853 /*-----------------------------------------------------------------*/
5854 static void AccRsh (int shCount)
5855 {
5856     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5857     if(shCount != 0){
5858         if(shCount == 1){
5859             CLRC;
5860             pic14_emitcode("rrc","a");
5861         } else {
5862             /* rotate right accumulator */
5863             AccRol(8 - shCount);
5864             /* and kill the higher order bits */
5865             pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
5866         }
5867     }
5868 }
5869
5870 #if 0
5871 /*-----------------------------------------------------------------*/
5872 /* AccSRsh - signed right shift accumulator by known count                 */
5873 /*-----------------------------------------------------------------*/
5874 static void AccSRsh (int shCount)
5875 {
5876     symbol *tlbl ;
5877     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5878     if(shCount != 0){
5879         if(shCount == 1){
5880             pic14_emitcode("mov","c,acc.7");
5881             pic14_emitcode("rrc","a");
5882         } else if(shCount == 2){
5883             pic14_emitcode("mov","c,acc.7");
5884             pic14_emitcode("rrc","a");
5885             pic14_emitcode("mov","c,acc.7");
5886             pic14_emitcode("rrc","a");
5887         } else {
5888             tlbl = newiTempLabel(NULL);
5889             /* rotate right accumulator */
5890             AccRol(8 - shCount);
5891             /* and kill the higher order bits */
5892             pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
5893             pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
5894             pic14_emitcode("orl","a,#0x%02x",
5895                      (unsigned char)~SRMask[shCount]);
5896             pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5897         }
5898     }
5899 }
5900 #endif
5901 /*-----------------------------------------------------------------*/
5902 /* shiftR1Left2Result - shift right one byte from left to result   */
5903 /*-----------------------------------------------------------------*/
5904 static void shiftR1Left2ResultSigned (operand *left, int offl,
5905                                 operand *result, int offr,
5906                                 int shCount)
5907 {
5908   int same;
5909
5910   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5911
5912   same = (left == result) || (AOP(left) == AOP(result));
5913
5914   switch(shCount) {
5915   case 1:
5916     emitpcode(POC_RLFW, popGet(AOP(left),offl));
5917     if(same) 
5918       emitpcode(POC_RRF, popGet(AOP(result),offr));
5919     else {
5920       emitpcode(POC_RRFW, popGet(AOP(left),offl));
5921       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5922     }
5923
5924     break;
5925
5926   default:
5927     break;
5928   }
5929 }
5930
5931 /*-----------------------------------------------------------------*/
5932 /* shiftR1Left2Result - shift right one byte from left to result   */
5933 /*-----------------------------------------------------------------*/
5934 static void shiftR1Left2Result (operand *left, int offl,
5935                                 operand *result, int offr,
5936                                 int shCount, int sign)
5937 {
5938   int same;
5939
5940   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5941
5942   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
5943
5944   /* Copy the msb into the carry if signed. */
5945   if(sign) {
5946     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
5947     return;
5948   }
5949
5950
5951
5952   switch(shCount) {
5953   case 1:
5954     emitCLRC;
5955     if(same) 
5956       emitpcode(POC_RRF, popGet(AOP(result),offr));
5957     else {
5958       emitpcode(POC_RRFW, popGet(AOP(left),offl));
5959       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5960     }
5961     break;
5962   case 2:
5963     emitCLRC;
5964     if(same) {
5965       emitpcode(POC_RRF, popGet(AOP(result),offr));
5966     } else {
5967       emitpcode(POC_RRFW, popGet(AOP(left),offl));
5968       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5969     }
5970     emitCLRC;
5971     emitpcode(POC_RRF, popGet(AOP(result),offr));
5972
5973     break;
5974   case 3:
5975     if(same) 
5976       emitpcode(POC_SWAPF, popGet(AOP(result),offr));
5977     else {
5978       emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
5979       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5980     }
5981
5982     emitpcode(POC_RLFW,  popGet(AOP(result),offr));
5983     emitpcode(POC_RLFW,  popGet(AOP(result),offr));
5984     emitpcode(POC_ANDLW, popGetLit(0x1f));
5985     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5986     break;
5987       
5988   case 4:
5989     emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
5990     emitpcode(POC_ANDLW, popGetLit(0x0f));
5991     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5992     break;
5993
5994   case 5:
5995     emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
5996     emitpcode(POC_ANDLW, popGetLit(0x0f));
5997     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5998     emitCLRC;
5999     emitpcode(POC_RRF, popGet(AOP(result),offr));
6000
6001     break;
6002   case 6:
6003
6004     emitpcode(POC_RLFW,  popGet(AOP(left),offl));
6005     emitpcode(POC_ANDLW, popGetLit(0x80));
6006     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6007     emitpcode(POC_RLF,   popGet(AOP(result),offr));
6008     emitpcode(POC_RLF,   popGet(AOP(result),offr));
6009     break;
6010
6011   case 7:
6012
6013     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6014     emitpcode(POC_CLRF, popGet(AOP(result),offr));
6015     emitpcode(POC_RLF,  popGet(AOP(result),offr));
6016
6017     break;
6018
6019   default:
6020     break;
6021   }
6022
6023
6024 #if 0
6025     
6026   MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6027
6028   /* shift right accumulator */
6029   if(sign)
6030     AccSRsh(shCount);
6031   else
6032     AccRsh(shCount);
6033   aopPut(AOP(result),"a",offr);
6034 #endif
6035 }
6036
6037 /*-----------------------------------------------------------------*/
6038 /* shiftL1Left2Result - shift left one byte from left to result    */
6039 /*-----------------------------------------------------------------*/
6040 static void shiftL1Left2Result (operand *left, int offl,
6041                                 operand *result, int offr, int shCount)
6042 {
6043   int same;
6044
6045   //    char *l;
6046   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6047
6048   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6049   DEBUGpic14_emitcode ("; ***","same =  %d",same);
6050     //    l = aopGet(AOP(left),offl,FALSE,FALSE);
6051     //    MOVA(l);
6052     /* shift left accumulator */
6053     //AccLsh(shCount); // don't comment out just yet...
6054   //    aopPut(AOP(result),"a",offr);
6055
6056   switch(shCount) {
6057   case 1:
6058     /* Shift left 1 bit position */
6059     emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6060     if(same) {
6061       emitpcode(POC_ADDWF, popGet(AOP(left),offl));
6062     } else {
6063       emitpcode(POC_ADDFW, popGet(AOP(left),offl));
6064       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6065     }
6066     break;
6067   case 2:
6068     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6069     emitpcode(POC_ANDLW,popGetLit(0x7e));
6070     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6071     emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6072     break;
6073   case 3:
6074     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6075     emitpcode(POC_ANDLW,popGetLit(0x3e));
6076     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6077     emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6078     emitpcode(POC_RLF,  popGet(AOP(result),offr));
6079     break;
6080   case 4:
6081     emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6082     emitpcode(POC_ANDLW, popGetLit(0xf0));
6083     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6084     break;
6085   case 5:
6086     emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6087     emitpcode(POC_ANDLW, popGetLit(0xf0));
6088     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6089     emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6090     break;
6091   case 6:
6092     emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6093     emitpcode(POC_ANDLW, popGetLit(0x30));
6094     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6095     emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6096     emitpcode(POC_RLF,  popGet(AOP(result),offr));
6097     break;
6098   case 7:
6099     emitpcode(POC_RRFW, popGet(AOP(left),offl));
6100     emitpcode(POC_CLRF, popGet(AOP(result),offr));
6101     emitpcode(POC_RRF,  popGet(AOP(result),offr));
6102     break;
6103
6104   default:
6105     DEBUGpic14_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6106   }
6107
6108 }
6109
6110 /*-----------------------------------------------------------------*/
6111 /* movLeft2Result - move byte from left to result                  */
6112 /*-----------------------------------------------------------------*/
6113 static void movLeft2Result (operand *left, int offl,
6114                             operand *result, int offr, int sign)
6115 {
6116     char *l;
6117     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6118     if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6119         l = aopGet(AOP(left),offl,FALSE,FALSE);
6120
6121         if (*l == '@' && (IS_AOP_PREG(result))) {
6122             pic14_emitcode("mov","a,%s",l);
6123             aopPut(AOP(result),"a",offr);
6124         } else {
6125           if(!sign) {
6126             emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6127             emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6128
6129             //aopPut(AOP(result),l,offr);
6130           }else{
6131                 /* MSB sign in acc.7 ! */
6132                 if(pic14_getDataSize(left) == offl+1){
6133                     pic14_emitcode("mov","a,%s",l);
6134                     aopPut(AOP(result),"a",offr);
6135                 }
6136             }
6137         }
6138     }
6139 }
6140
6141 /*-----------------------------------------------------------------*/
6142 /* shiftL2Left2Result - shift left two bytes from left to result   */
6143 /*-----------------------------------------------------------------*/
6144 static void shiftL2Left2Result (operand *left, int offl,
6145                                 operand *result, int offr, int shCount)
6146 {
6147
6148
6149   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6150
6151   if(pic14_sameRegs(AOP(result), AOP(left))) {
6152     switch(shCount) {
6153     case 0:
6154       break;
6155     case 1:
6156     case 2:
6157     case 3:
6158
6159       emitpcode(POC_MOVFW,popGet(AOP(result),offr));
6160       emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6161       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6162
6163       while(--shCount) {
6164         emitCLRC;
6165         emitpcode(POC_RLF, popGet(AOP(result),offr));
6166         emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6167       }
6168
6169       break;
6170     case 4:
6171     case 5:
6172       emitpcode(POC_MOVLW, popGetLit(0x0f));
6173       emitpcode(POC_ANDWF, popGet(AOP(result),offr+MSB16));
6174       emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
6175       emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6176       emitpcode(POC_ANDFW, popGet(AOP(result),offr));
6177       emitpcode(POC_XORWF, popGet(AOP(result),offr));
6178       emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
6179       if(shCount >=5) {
6180         emitpcode(POC_RLF, popGet(AOP(result),offr));
6181         emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6182       }
6183       break;
6184     case 6:
6185       emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
6186       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6187       emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
6188       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6189       emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6190       emitpcode(POC_ANDLW,popGetLit(0xc0));
6191       emitpcode(POC_XORFW,popGet(AOP(result),offr));
6192       emitpcode(POC_XORWF,popGet(AOP(result),offr));
6193       emitpcode(POC_XORFW,popGet(AOP(result),offr));
6194       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6195       break;
6196     case 7:
6197       emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6198       emitpcode(POC_RRFW, popGet(AOP(result),offr));
6199       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6200       emitpcode(POC_CLRF, popGet(AOP(result),offr));
6201       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6202     }
6203
6204   } else {
6205     switch(shCount) {
6206     case 0:
6207       break;
6208     case 1:
6209     case 2:
6210     case 3:
6211       /* note, use a mov/add for the shift since the mov has a
6212          chance of getting optimized out */
6213       emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6214       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6215       emitpcode(POC_ADDWF, popGet(AOP(result),offr));
6216       emitpcode(POC_RLFW,  popGet(AOP(left),offl+MSB16));
6217       emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6218
6219       while(--shCount) {
6220         emitCLRC;
6221         emitpcode(POC_RLF, popGet(AOP(result),offr));
6222         emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6223       }
6224       break;
6225
6226     case 4:
6227     case 5:
6228       emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
6229       emitpcode(POC_ANDLW, popGetLit(0xF0));
6230       emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6231       emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6232       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6233       emitpcode(POC_ANDLW, popGetLit(0xF0));
6234       emitpcode(POC_XORWF, popGet(AOP(result),offr));
6235       emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
6236
6237
6238       if(shCount == 5) {
6239         emitpcode(POC_RLF, popGet(AOP(result),offr));
6240         emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6241       }
6242       break;
6243     case 6:
6244       emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
6245       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6246       emitpcode(POC_RRFW, popGet(AOP(result),offl));
6247       emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6248
6249       emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
6250       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6251       emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6252       emitpcode(POC_ANDLW,popGetLit(0xc0));
6253       emitpcode(POC_XORFW,popGet(AOP(result),offr));
6254       emitpcode(POC_XORWF,popGet(AOP(result),offr));
6255       emitpcode(POC_XORFW,popGet(AOP(result),offr));
6256       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6257       break;
6258     case 7:
6259       emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
6260       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6261       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6262       emitpcode(POC_CLRF, popGet(AOP(result),offr));
6263       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6264     }
6265   }
6266
6267 }
6268 /*-----------------------------------------------------------------*/
6269 /* shiftR2Left2Result - shift right two bytes from left to result  */
6270 /*-----------------------------------------------------------------*/
6271 static void shiftR2Left2Result (operand *left, int offl,
6272                                 operand *result, int offr,
6273                                 int shCount, int sign)
6274 {
6275   int same=0;
6276
6277   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6278   same = pic14_sameRegs(AOP(result), AOP(left));
6279
6280   if(same && ((offl + MSB16) == offr)){
6281     same=1;
6282     /* don't crash result[offr] */
6283     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6284     pic14_emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6285   } else {
6286     movLeft2Result(left,offl, result, offr, 0);
6287     MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6288   }
6289   /* a:x >> shCount (x = lsb(result))*/
6290 /*
6291   if(sign)
6292     AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6293   else {
6294     AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6295 */
6296   switch(shCount) {
6297   case 0:
6298     break;
6299   case 1:
6300   case 2:
6301   case 3:
6302     emitCLRC;
6303     if(same) {
6304       emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
6305       emitpcode(POC_RRF,popGet(AOP(result),offr));
6306     } else {
6307
6308       emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
6309       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6310       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6311       emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6312     }
6313
6314     while(--shCount) {
6315       emitCLRC;
6316       emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
6317       emitpcode(POC_RRF,popGet(AOP(result),offr));
6318     }
6319     break;
6320   case 4:
6321   case 5:
6322     if(same) {
6323
6324       emitpcode(POC_MOVLW, popGetLit(0xf0));
6325       emitpcode(POC_ANDWF, popGet(AOP(result),offr));
6326       emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6327
6328       emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
6329       emitpcode(POC_ANDFW, popGet(AOP(result),offr+MSB16));
6330       emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
6331       emitpcode(POC_ADDWF, popGet(AOP(result),offr));
6332     } else {
6333       emitpcode(POC_SWAPF, popGet(AOP(left),offl));
6334       emitpcode(POC_ANDLW, popGetLit(0x0f));
6335       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6336
6337       emitpcode(POC_SWAPF, popGet(AOP(left),offl+MSB16));
6338       emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6339       emitpcode(POC_ANDLW, popGetLit(0xf0));
6340       emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
6341       emitpcode(POC_ADDWF, popGet(AOP(result),offr));
6342     }
6343
6344     if(shCount >=5) {
6345       emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
6346       emitpcode(POC_RRF, popGet(AOP(result),offr));
6347     }
6348
6349     break;
6350
6351   case 6:
6352     if(same) {
6353
6354       emitpcode(POC_RLF,  popGet(AOP(result),offr));
6355       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6356
6357       emitpcode(POC_RLF,  popGet(AOP(result),offr));
6358       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6359       emitpcode(POC_RLFW, popGet(AOP(result),offr));
6360       emitpcode(POC_ANDLW,popGetLit(0x03));
6361       emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
6362       emitpcode(POC_XORWF,popGet(AOP(result),offr+MSB16));
6363       emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
6364       emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6365     } else {
6366       emitpcode(POC_RLFW, popGet(AOP(left),offl));
6367       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6368       emitpcode(POC_RLFW, popGet(AOP(result),offl+MSB16));
6369       emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6370       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6371       emitpcode(POC_RLF,  popGet(AOP(result),offr));
6372       emitpcode(POC_RLFW, popGet(AOP(result),offr));
6373       emitpcode(POC_ANDLW,popGetLit(0x03));
6374       emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6375     }
6376
6377     break;
6378   case 7:
6379     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6380     emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
6381     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6382     emitpcode(POC_CLRF, popGet(AOP(result),offr+MSB16));
6383     emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6384   }
6385 }
6386
6387
6388 /*-----------------------------------------------------------------*/
6389 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
6390 /*-----------------------------------------------------------------*/
6391 static void shiftLLeftOrResult (operand *left, int offl,
6392                                 operand *result, int offr, int shCount)
6393 {
6394     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6395     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6396     /* shift left accumulator */
6397     AccLsh(shCount);
6398     /* or with result */
6399     pic14_emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
6400     /* back to result */
6401     aopPut(AOP(result),"a",offr);
6402 }
6403
6404 /*-----------------------------------------------------------------*/
6405 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
6406 /*-----------------------------------------------------------------*/
6407 static void shiftRLeftOrResult (operand *left, int offl,
6408                                 operand *result, int offr, int shCount)
6409 {
6410     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6411     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6412     /* shift right accumulator */
6413     AccRsh(shCount);
6414     /* or with result */
6415     pic14_emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
6416     /* back to result */
6417     aopPut(AOP(result),"a",offr);
6418 }
6419
6420 /*-----------------------------------------------------------------*/
6421 /* genlshOne - left shift a one byte quantity by known count       */
6422 /*-----------------------------------------------------------------*/
6423 static void genlshOne (operand *result, operand *left, int shCount)
6424 {       
6425     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6426     shiftL1Left2Result(left, LSB, result, LSB, shCount);
6427 }
6428
6429 /*-----------------------------------------------------------------*/
6430 /* genlshTwo - left shift two bytes by known amount != 0           */
6431 /*-----------------------------------------------------------------*/
6432 static void genlshTwo (operand *result,operand *left, int shCount)
6433 {
6434     int size;
6435     
6436     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6437     size = pic14_getDataSize(result);
6438
6439     /* if shCount >= 8 */
6440     if (shCount >= 8) {
6441         shCount -= 8 ;
6442
6443         if (size > 1){
6444             if (shCount)
6445                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6446             else 
6447                 movLeft2Result(left, LSB, result, MSB16, 0);
6448         }
6449         emitpcode(POC_CLRF,popGet(AOP(result),LSB));
6450     }
6451
6452     /*  1 <= shCount <= 7 */
6453     else {  
6454         if(size == 1)
6455             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
6456         else 
6457             shiftL2Left2Result(left, LSB, result, LSB, shCount);
6458     }
6459 }
6460
6461 /*-----------------------------------------------------------------*/
6462 /* shiftLLong - shift left one long from left to result            */
6463 /* offl = LSB or MSB16                                             */
6464 /*-----------------------------------------------------------------*/
6465 static void shiftLLong (operand *left, operand *result, int offr )
6466 {
6467     char *l;
6468     int size = AOP_SIZE(result);
6469
6470     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6471     if(size >= LSB+offr){
6472         l = aopGet(AOP(left),LSB,FALSE,FALSE);
6473         MOVA(l);
6474         pic14_emitcode("add","a,acc");
6475         if (pic14_sameRegs(AOP(left),AOP(result)) && 
6476             size >= MSB16+offr && offr != LSB )
6477             pic14_emitcode("xch","a,%s",
6478                      aopGet(AOP(left),LSB+offr,FALSE,FALSE));
6479         else        
6480             aopPut(AOP(result),"a",LSB+offr);
6481     }
6482
6483     if(size >= MSB16+offr){
6484         if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
6485             l = aopGet(AOP(left),MSB16,FALSE,FALSE);
6486             MOVA(l);
6487         }
6488         pic14_emitcode("rlc","a");
6489         if (pic14_sameRegs(AOP(left),AOP(result)) && 
6490             size >= MSB24+offr && offr != LSB)
6491             pic14_emitcode("xch","a,%s",
6492                      aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
6493         else        
6494             aopPut(AOP(result),"a",MSB16+offr);
6495     }
6496
6497     if(size >= MSB24+offr){
6498         if (!(pic14_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
6499             l = aopGet(AOP(left),MSB24,FALSE,FALSE);
6500             MOVA(l);
6501         }
6502         pic14_emitcode("rlc","a");
6503         if (pic14_sameRegs(AOP(left),AOP(result)) && 
6504             size >= MSB32+offr && offr != LSB )
6505             pic14_emitcode("xch","a,%s",
6506                      aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
6507         else        
6508             aopPut(AOP(result),"a",MSB24+offr);
6509     }
6510
6511     if(size > MSB32+offr){
6512         if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
6513             l = aopGet(AOP(left),MSB32,FALSE,FALSE);
6514             MOVA(l);    
6515         }
6516         pic14_emitcode("rlc","a");
6517         aopPut(AOP(result),"a",MSB32+offr);
6518     }
6519     if(offr != LSB)
6520         aopPut(AOP(result),zero,LSB);       
6521 }
6522
6523 /*-----------------------------------------------------------------*/
6524 /* genlshFour - shift four byte by a known amount != 0             */
6525 /*-----------------------------------------------------------------*/
6526 static void genlshFour (operand *result, operand *left, int shCount)
6527 {
6528     int size;
6529
6530     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6531     size = AOP_SIZE(result);
6532
6533     /* if shifting more that 3 bytes */
6534     if (shCount >= 24 ) {
6535         shCount -= 24;
6536         if (shCount)
6537             /* lowest order of left goes to the highest
6538             order of the destination */
6539             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
6540         else
6541             movLeft2Result(left, LSB, result, MSB32, 0);
6542         aopPut(AOP(result),zero,LSB);
6543         aopPut(AOP(result),zero,MSB16);
6544         aopPut(AOP(result),zero,MSB32);
6545         return;
6546     }
6547
6548     /* more than two bytes */
6549     else if ( shCount >= 16 ) {
6550         /* lower order two bytes goes to higher order two bytes */
6551         shCount -= 16;
6552         /* if some more remaining */
6553         if (shCount)
6554             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
6555         else {
6556             movLeft2Result(left, MSB16, result, MSB32, 0);
6557             movLeft2Result(left, LSB, result, MSB24, 0);
6558         }
6559         aopPut(AOP(result),zero,MSB16);
6560         aopPut(AOP(result),zero,LSB);
6561         return;
6562     }    
6563
6564     /* if more than 1 byte */
6565     else if ( shCount >= 8 ) {
6566         /* lower order three bytes goes to higher order  three bytes */
6567         shCount -= 8;
6568         if(size == 2){
6569             if(shCount)
6570                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6571             else
6572                 movLeft2Result(left, LSB, result, MSB16, 0);
6573         }
6574         else{   /* size = 4 */
6575             if(shCount == 0){
6576                 movLeft2Result(left, MSB24, result, MSB32, 0);
6577                 movLeft2Result(left, MSB16, result, MSB24, 0);
6578                 movLeft2Result(left, LSB, result, MSB16, 0);
6579                 aopPut(AOP(result),zero,LSB);
6580             }
6581             else if(shCount == 1)
6582                 shiftLLong(left, result, MSB16);
6583             else{
6584                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
6585                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6586                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
6587                 aopPut(AOP(result),zero,LSB);
6588             }
6589         }
6590     }
6591
6592     /* 1 <= shCount <= 7 */
6593     else if(shCount <= 2){
6594         shiftLLong(left, result, LSB);
6595         if(shCount == 2)
6596             shiftLLong(result, result, LSB);
6597     }
6598     /* 3 <= shCount <= 7, optimize */
6599     else{
6600         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
6601         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
6602         shiftL2Left2Result(left, LSB, result, LSB, shCount);
6603     }
6604 }
6605
6606 /*-----------------------------------------------------------------*/
6607 /* genLeftShiftLiteral - left shifting by known count              */
6608 /*-----------------------------------------------------------------*/
6609 static void genLeftShiftLiteral (operand *left,
6610                                  operand *right,
6611                                  operand *result,
6612                                  iCode *ic)
6613 {    
6614     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6615     int size;
6616
6617     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6618     freeAsmop(right,NULL,ic,TRUE);
6619
6620     aopOp(left,ic,FALSE);
6621     aopOp(result,ic,FALSE);
6622
6623     size = getSize(operandType(result));
6624
6625 #if VIEW_SIZE
6626     pic14_emitcode("; shift left ","result %d, left %d",size,
6627              AOP_SIZE(left));
6628 #endif
6629
6630     /* I suppose that the left size >= result size */
6631     if(shCount == 0){
6632         while(size--){
6633             movLeft2Result(left, size, result, size, 0);
6634         }
6635     }
6636
6637     else if(shCount >= (size * 8))
6638         while(size--)
6639             aopPut(AOP(result),zero,size);
6640     else{
6641         switch (size) {
6642             case 1:
6643                 genlshOne (result,left,shCount);
6644                 break;
6645
6646             case 2:
6647             case 3:
6648                 genlshTwo (result,left,shCount);
6649                 break;
6650
6651             case 4:
6652                 genlshFour (result,left,shCount);
6653                 break;
6654         }
6655     }
6656     freeAsmop(left,NULL,ic,TRUE);
6657     freeAsmop(result,NULL,ic,TRUE);
6658 }
6659
6660 /*-----------------------------------------------------------------*/
6661 /* genLeftShift - generates code for left shifting                 */
6662 /*-----------------------------------------------------------------*/
6663 static void genLeftShift (iCode *ic)
6664 {
6665     operand *left,*right, *result;
6666     int size, offset;
6667     char *l;
6668     symbol *tlbl , *tlbl1;
6669
6670     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6671
6672     right = IC_RIGHT(ic);
6673     left  = IC_LEFT(ic);
6674     result = IC_RESULT(ic);
6675
6676     aopOp(right,ic,FALSE);
6677
6678     /* if the shift count is known then do it 
6679     as efficiently as possible */
6680     if (AOP_TYPE(right) == AOP_LIT) {
6681         genLeftShiftLiteral (left,right,result,ic);
6682         return ;
6683     }
6684
6685     /* shift count is unknown then we have to form 
6686     a loop get the loop count in B : Note: we take
6687     only the lower order byte since shifting
6688     more that 32 bits make no sense anyway, ( the
6689     largest size of an object can be only 32 bits ) */  
6690
6691     
6692     aopOp(left,ic,FALSE);
6693     aopOp(result,ic,FALSE);
6694
6695     /* now move the left to the result if they are not the
6696     same */
6697     if (!pic14_sameRegs(AOP(left),AOP(result)) && 
6698         AOP_SIZE(result) > 1) {
6699
6700         size = AOP_SIZE(result);
6701         offset=0;
6702         while (size--) {
6703             l = aopGet(AOP(left),offset,FALSE,TRUE);
6704             if (*l == '@' && (IS_AOP_PREG(result))) {
6705
6706                 pic14_emitcode("mov","a,%s",l);
6707                 aopPut(AOP(result),"a",offset);
6708             } else
6709                 aopPut(AOP(result),l,offset);
6710             offset++;
6711         }
6712     }
6713
6714     size = AOP_SIZE(result);
6715
6716     /* if it is only one byte then */
6717     if (size == 1) {
6718       if(optimized_for_speed) {
6719         emitpcode(POC_SWAPFW, popGet(AOP(left),0));
6720         emitpcode(POC_ANDLW,  popGetLit(0xf0));
6721         emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),2,0));
6722         emitpcode(POC_MOVFW,  popGet(AOP(left),0));
6723         emitpcode(POC_MOVWF,  popGet(AOP(result),0));
6724         emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
6725         emitpcode(POC_ADDWF,  popGet(AOP(result),0));
6726         emitpcode(POC_RLFW,   popGet(AOP(result),0));
6727         emitpcode(POC_ANDLW,  popGetLit(0xfe));
6728         emitpcode(POC_ADDFW,  popGet(AOP(result),0));
6729         emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),1,0));
6730         emitpcode(POC_ADDWF,  popGet(AOP(result),0));
6731       } else {
6732
6733         tlbl = newiTempLabel(NULL);
6734         if (!pic14_sameRegs(AOP(left),AOP(result))) {
6735           emitpcode(POC_MOVFW,  popGet(AOP(left),0));
6736           emitpcode(POC_MOVWF,  popGet(AOP(result),0));
6737         }
6738
6739         emitpcode(POC_COMFW,  popGet(AOP(right),0));
6740         emitpcode(POC_RRF,    popGet(AOP(result),0));
6741         emitpLabel(tlbl->key);
6742         emitpcode(POC_RLF,    popGet(AOP(result),0));
6743         emitpcode(POC_ADDLW,  popGetLit(1));
6744         emitSKPC;
6745         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
6746       }
6747       goto release ;
6748     }
6749     
6750
6751     tlbl = newiTempLabel(NULL);
6752     offset = 0 ;   
6753     tlbl1 = newiTempLabel(NULL);
6754
6755     reAdjustPreg(AOP(result));    
6756     
6757     pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
6758     pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
6759     l = aopGet(AOP(result),offset,FALSE,FALSE);
6760     MOVA(l);
6761     pic14_emitcode("add","a,acc");         
6762     aopPut(AOP(result),"a",offset++);
6763     while (--size) {
6764         l = aopGet(AOP(result),offset,FALSE,FALSE);
6765         MOVA(l);
6766         pic14_emitcode("rlc","a");         
6767         aopPut(AOP(result),"a",offset++);
6768     }
6769     reAdjustPreg(AOP(result));
6770
6771     pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
6772     pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6773 release:
6774     freeAsmop (right,NULL,ic,TRUE);
6775     freeAsmop(left,NULL,ic,TRUE);
6776     freeAsmop(result,NULL,ic,TRUE);
6777 }
6778
6779 /*-----------------------------------------------------------------*/
6780 /* genrshOne - right shift a one byte quantity by known count      */
6781 /*-----------------------------------------------------------------*/
6782 static void genrshOne (operand *result, operand *left,
6783                        int shCount, int sign)
6784 {
6785     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6786     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
6787 }
6788
6789 /*-----------------------------------------------------------------*/
6790 /* genrshTwo - right shift two bytes by known amount != 0          */
6791 /*-----------------------------------------------------------------*/
6792 static void genrshTwo (operand *result,operand *left,
6793                        int shCount, int sign)
6794 {
6795     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6796     /* if shCount >= 8 */
6797     if (shCount >= 8) {
6798         shCount -= 8 ;
6799         if (shCount)
6800             shiftR1Left2Result(left, MSB16, result, LSB,
6801                                shCount, sign);
6802         else 
6803             movLeft2Result(left, MSB16, result, LSB, sign);
6804         if(sign)
6805           addSign(result, MSB16, sign);
6806         else
6807           emitpcode(POC_CLRF,popGet(AOP(result),MSB16));
6808
6809     }
6810
6811     /*  1 <= shCount <= 7 */
6812     else
6813         shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
6814 }
6815
6816 /*-----------------------------------------------------------------*/
6817 /* shiftRLong - shift right one long from left to result           */
6818 /* offl = LSB or MSB16                                             */
6819 /*-----------------------------------------------------------------*/
6820 static void shiftRLong (operand *left, int offl,
6821                         operand *result, int sign)
6822 {
6823     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6824     if(!sign)
6825         pic14_emitcode("clr","c");
6826     MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE));
6827     if(sign)
6828         pic14_emitcode("mov","c,acc.7");
6829     pic14_emitcode("rrc","a");
6830     aopPut(AOP(result),"a",MSB32-offl);
6831     if(offl == MSB16)
6832         /* add sign of "a" */
6833         addSign(result, MSB32, sign);
6834
6835     MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE));
6836     pic14_emitcode("rrc","a");
6837     aopPut(AOP(result),"a",MSB24-offl);
6838
6839     MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE));
6840     pic14_emitcode("rrc","a");
6841     aopPut(AOP(result),"a",MSB16-offl);
6842
6843     if(offl == LSB){
6844         MOVA(aopGet(AOP(left),LSB,FALSE,FALSE));
6845         pic14_emitcode("rrc","a");
6846         aopPut(AOP(result),"a",LSB);
6847     }
6848 }
6849
6850 /*-----------------------------------------------------------------*/
6851 /* genrshFour - shift four byte by a known amount != 0             */
6852 /*-----------------------------------------------------------------*/
6853 static void genrshFour (operand *result, operand *left,
6854                         int shCount, int sign)
6855 {
6856     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6857     /* if shifting more that 3 bytes */
6858     if(shCount >= 24 ) {
6859         shCount -= 24;
6860         if(shCount)
6861             shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
6862         else
6863             movLeft2Result(left, MSB32, result, LSB, sign);
6864         addSign(result, MSB16, sign);
6865     }
6866     else if(shCount >= 16){
6867         shCount -= 16;
6868         if(shCount)
6869             shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
6870         else{
6871             movLeft2Result(left, MSB24, result, LSB, 0);
6872             movLeft2Result(left, MSB32, result, MSB16, sign);
6873         }
6874         addSign(result, MSB24, sign);
6875     }
6876     else if(shCount >= 8){
6877         shCount -= 8;
6878         if(shCount == 1)
6879             shiftRLong(left, MSB16, result, sign);
6880         else if(shCount == 0){
6881             movLeft2Result(left, MSB16, result, LSB, 0);
6882             movLeft2Result(left, MSB24, result, MSB16, 0);
6883             movLeft2Result(left, MSB32, result, MSB24, sign);
6884             addSign(result, MSB32, sign);
6885         }
6886         else{
6887             shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
6888             shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
6889             /* the last shift is signed */
6890             shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
6891             addSign(result, MSB32, sign);
6892         }
6893     }
6894     else{   /* 1 <= shCount <= 7 */
6895         if(shCount <= 2){
6896             shiftRLong(left, LSB, result, sign);
6897             if(shCount == 2)
6898                 shiftRLong(result, LSB, result, sign);
6899         }
6900         else{
6901             shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
6902             shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
6903             shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
6904         }
6905     }
6906 }
6907
6908 /*-----------------------------------------------------------------*/
6909 /* genRightShiftLiteral - right shifting by known count            */
6910 /*-----------------------------------------------------------------*/
6911 static void genRightShiftLiteral (operand *left,
6912                                   operand *right,
6913                                   operand *result,
6914                                   iCode *ic,
6915                                   int sign)
6916 {    
6917     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6918     int size;
6919
6920     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6921     freeAsmop(right,NULL,ic,TRUE);
6922
6923     aopOp(left,ic,FALSE);
6924     aopOp(result,ic,FALSE);
6925
6926 #if VIEW_SIZE
6927     pic14_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
6928              AOP_SIZE(left));
6929 #endif
6930
6931     size = pic14_getDataSize(left);
6932     /* test the LEFT size !!! */
6933
6934     /* I suppose that the left size >= result size */
6935     if(shCount == 0){
6936         size = pic14_getDataSize(result);
6937         while(size--)
6938             movLeft2Result(left, size, result, size, 0);
6939     }
6940
6941     else if(shCount >= (size * 8)){
6942         if(sign)
6943             /* get sign in acc.7 */
6944             MOVA(aopGet(AOP(left),size-1,FALSE,FALSE));
6945         addSign(result, LSB, sign);
6946     } else{
6947         switch (size) {
6948             case 1:
6949                 genrshOne (result,left,shCount,sign);
6950                 break;
6951
6952             case 2:
6953                 genrshTwo (result,left,shCount,sign);
6954                 break;
6955
6956             case 4:
6957                 genrshFour (result,left,shCount,sign);
6958                 break;
6959             default :
6960                 break;
6961         }
6962
6963         freeAsmop(left,NULL,ic,TRUE);
6964         freeAsmop(result,NULL,ic,TRUE);
6965     }
6966 }
6967
6968 /*-----------------------------------------------------------------*/
6969 /* genSignedRightShift - right shift of signed number              */
6970 /*-----------------------------------------------------------------*/
6971 static void genSignedRightShift (iCode *ic)
6972 {
6973     operand *right, *left, *result;
6974     int size, offset;
6975     char *l;
6976     symbol *tlbl, *tlbl1 ;
6977
6978     /* we do it the hard way put the shift count in b
6979     and loop thru preserving the sign */
6980     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6981
6982     right = IC_RIGHT(ic);
6983     left  = IC_LEFT(ic);
6984     result = IC_RESULT(ic);
6985
6986     aopOp(right,ic,FALSE);  
6987
6988
6989     if ( AOP_TYPE(right) == AOP_LIT) {
6990         genRightShiftLiteral (left,right,result,ic,1);
6991         return ;
6992     }
6993         /* shift count is unknown then we have to form 
6994        a loop get the loop count in B : Note: we take
6995        only the lower order byte since shifting
6996        more that 32 bits make no sense anyway, ( the
6997        largest size of an object can be only 32 bits ) */  
6998
6999     pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
7000     pic14_emitcode("inc","b");
7001     freeAsmop (right,NULL,ic,TRUE);
7002     aopOp(left,ic,FALSE);
7003     aopOp(result,ic,FALSE);
7004
7005     /* now move the left to the result if they are not the
7006     same */
7007     if (!pic14_sameRegs(AOP(left),AOP(result)) && 
7008         AOP_SIZE(result) > 1) {
7009
7010         size = AOP_SIZE(result);
7011         offset=0;
7012         while (size--) {
7013             l = aopGet(AOP(left),offset,FALSE,TRUE);
7014             if (*l == '@' && IS_AOP_PREG(result)) {
7015
7016                 pic14_emitcode("mov","a,%s",l);
7017                 aopPut(AOP(result),"a",offset);
7018             } else
7019                 aopPut(AOP(result),l,offset);
7020             offset++;
7021         }
7022     }
7023
7024     /* mov the highest order bit to OVR */    
7025     tlbl = newiTempLabel(NULL);
7026     tlbl1= newiTempLabel(NULL);
7027
7028     size = AOP_SIZE(result);
7029     offset = size - 1;
7030     pic14_emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
7031     pic14_emitcode("rlc","a");
7032     pic14_emitcode("mov","ov,c");
7033     /* if it is only one byte then */
7034     if (size == 1) {
7035         l = aopGet(AOP(left),0,FALSE,FALSE);
7036         MOVA(l);
7037         pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7038         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
7039         pic14_emitcode("mov","c,ov");
7040         pic14_emitcode("rrc","a");
7041         pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7042         pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7043         aopPut(AOP(result),"a",0);
7044         goto release ;
7045     }
7046
7047     reAdjustPreg(AOP(result));
7048     pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7049     pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
7050     pic14_emitcode("mov","c,ov");
7051     while (size--) {
7052         l = aopGet(AOP(result),offset,FALSE,FALSE);
7053         MOVA(l);
7054         pic14_emitcode("rrc","a");         
7055         aopPut(AOP(result),"a",offset--);
7056     }
7057     reAdjustPreg(AOP(result));
7058     pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7059     pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7060
7061 release:
7062     freeAsmop(left,NULL,ic,TRUE);
7063     freeAsmop(result,NULL,ic,TRUE);
7064 }
7065
7066 /*-----------------------------------------------------------------*/
7067 /* genRightShift - generate code for right shifting                */
7068 /*-----------------------------------------------------------------*/
7069 static void genRightShift (iCode *ic)
7070 {
7071     operand *right, *left, *result;
7072     sym_link *retype ;
7073     int size, offset;
7074     char *l;
7075     symbol *tlbl, *tlbl1 ;
7076
7077     /* if signed then we do it the hard way preserve the
7078     sign bit moving it inwards */
7079     retype = getSpec(operandType(IC_RESULT(ic)));
7080     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7081
7082     if (!SPEC_USIGN(retype)) {
7083         genSignedRightShift (ic);
7084         return ;
7085     }
7086
7087     /* signed & unsigned types are treated the same : i.e. the
7088     signed is NOT propagated inwards : quoting from the
7089     ANSI - standard : "for E1 >> E2, is equivalent to division
7090     by 2**E2 if unsigned or if it has a non-negative value,
7091     otherwise the result is implementation defined ", MY definition
7092     is that the sign does not get propagated */
7093
7094     right = IC_RIGHT(ic);
7095     left  = IC_LEFT(ic);
7096     result = IC_RESULT(ic);
7097
7098     aopOp(right,ic,FALSE);
7099
7100     /* if the shift count is known then do it 
7101     as efficiently as possible */
7102     if (AOP_TYPE(right) == AOP_LIT) {
7103         genRightShiftLiteral (left,right,result,ic, 0);
7104         return ;
7105     }
7106
7107     /* shift count is unknown then we have to form 
7108     a loop get the loop count in B : Note: we take
7109     only the lower order byte since shifting
7110     more that 32 bits make no sense anyway, ( the
7111     largest size of an object can be only 32 bits ) */  
7112
7113     pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
7114     pic14_emitcode("inc","b");
7115     aopOp(left,ic,FALSE);
7116     aopOp(result,ic,FALSE);
7117
7118     /* now move the left to the result if they are not the
7119     same */
7120     if (!pic14_sameRegs(AOP(left),AOP(result)) && 
7121         AOP_SIZE(result) > 1) {
7122
7123         size = AOP_SIZE(result);
7124         offset=0;
7125         while (size--) {
7126             l = aopGet(AOP(left),offset,FALSE,TRUE);
7127             if (*l == '@' && IS_AOP_PREG(result)) {
7128
7129                 pic14_emitcode("mov","a,%s",l);
7130                 aopPut(AOP(result),"a",offset);
7131             } else
7132                 aopPut(AOP(result),l,offset);
7133             offset++;
7134         }
7135     }
7136
7137     tlbl = newiTempLabel(NULL);
7138     tlbl1= newiTempLabel(NULL);
7139     size = AOP_SIZE(result);
7140     offset = size - 1;
7141
7142     /* if it is only one byte then */
7143     if (size == 1) {
7144 /*
7145         l = aopGet(AOP(left),0,FALSE,FALSE);
7146         MOVA(l);
7147         pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7148         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
7149         CLRC;
7150         pic14_emitcode("rrc","a");
7151         pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7152         pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7153         aopPut(AOP(result),"a",0);
7154 */
7155         tlbl = newiTempLabel(NULL);
7156         if (!pic14_sameRegs(AOP(left),AOP(result))) {
7157           emitpcode(POC_MOVFW,  popGet(AOP(left),0));
7158           emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7159         }
7160
7161         emitpcode(POC_COMFW,  popGet(AOP(right),0));
7162         emitpcode(POC_RLF,    popGet(AOP(result),0));
7163         emitpLabel(tlbl->key);
7164         emitpcode(POC_RRF,    popGet(AOP(result),0));
7165         emitpcode(POC_ADDLW,  popGetLit(1));
7166         emitSKPC;
7167         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7168
7169         goto release ;
7170     }
7171
7172     reAdjustPreg(AOP(result));
7173     pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7174     pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
7175     CLRC;
7176     while (size--) {
7177         l = aopGet(AOP(result),offset,FALSE,FALSE);
7178         MOVA(l);
7179         pic14_emitcode("rrc","a");         
7180         aopPut(AOP(result),"a",offset--);
7181     }
7182     reAdjustPreg(AOP(result));
7183
7184     pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7185     pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7186
7187 release:
7188     freeAsmop(left,NULL,ic,TRUE);
7189     freeAsmop (right,NULL,ic,TRUE);
7190     freeAsmop(result,NULL,ic,TRUE);
7191 }
7192
7193 /*-----------------------------------------------------------------*/
7194 /* genUnpackBits - generates code for unpacking bits               */
7195 /*-----------------------------------------------------------------*/
7196 static void genUnpackBits (operand *result, char *rname, int ptype)
7197 {    
7198     int shCnt ;
7199     int rlen = 0 ;
7200     sym_link *etype;
7201     int offset = 0 ;
7202
7203     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7204     etype = getSpec(operandType(result));
7205
7206     /* read the first byte  */
7207     switch (ptype) {
7208
7209     case POINTER:
7210     case IPOINTER:
7211         pic14_emitcode("mov","a,@%s",rname);
7212         break;
7213         
7214     case PPOINTER:
7215         pic14_emitcode("movx","a,@%s",rname);
7216         break;
7217         
7218     case FPOINTER:
7219         pic14_emitcode("movx","a,@dptr");
7220         break;
7221
7222     case CPOINTER:
7223         pic14_emitcode("clr","a");
7224         pic14_emitcode("movc","a","@a+dptr");
7225         break;
7226
7227     case GPOINTER:
7228         pic14_emitcode("lcall","__gptrget");
7229         break;
7230     }
7231
7232     /* if we have bitdisplacement then it fits   */
7233     /* into this byte completely or if length is */
7234     /* less than a byte                          */
7235     if ((shCnt = SPEC_BSTR(etype)) || 
7236         (SPEC_BLEN(etype) <= 8))  {
7237
7238         /* shift right acc */
7239         AccRsh(shCnt);
7240
7241         pic14_emitcode("anl","a,#0x%02x",
7242                  ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
7243         aopPut(AOP(result),"a",offset);
7244         return ;
7245     }
7246
7247     /* bit field did not fit in a byte  */
7248     rlen = SPEC_BLEN(etype) - 8;
7249     aopPut(AOP(result),"a",offset++);
7250
7251     while (1)  {
7252
7253         switch (ptype) {
7254         case POINTER:
7255         case IPOINTER:
7256             pic14_emitcode("inc","%s",rname);
7257             pic14_emitcode("mov","a,@%s",rname);
7258             break;
7259             
7260         case PPOINTER:
7261             pic14_emitcode("inc","%s",rname);
7262             pic14_emitcode("movx","a,@%s",rname);
7263             break;
7264
7265         case FPOINTER:
7266             pic14_emitcode("inc","dptr");
7267             pic14_emitcode("movx","a,@dptr");
7268             break;
7269             
7270         case CPOINTER:
7271             pic14_emitcode("clr","a");
7272             pic14_emitcode("inc","dptr");
7273             pic14_emitcode("movc","a","@a+dptr");
7274             break;
7275             
7276         case GPOINTER:
7277             pic14_emitcode("inc","dptr");
7278             pic14_emitcode("lcall","__gptrget");
7279             break;
7280         }
7281
7282         rlen -= 8;            
7283         /* if we are done */
7284         if ( rlen <= 0 )
7285             break ;
7286         
7287         aopPut(AOP(result),"a",offset++);
7288                               
7289     }
7290     
7291     if (rlen) {
7292         pic14_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
7293         aopPut(AOP(result),"a",offset);        
7294     }
7295     
7296     return ;
7297 }
7298
7299
7300 /*-----------------------------------------------------------------*/
7301 /* genDataPointerGet - generates code when ptr offset is known     */
7302 /*-----------------------------------------------------------------*/
7303 static void genDataPointerGet (operand *left, 
7304                                operand *result, 
7305                                iCode *ic)
7306 {
7307   int size , offset = 0;
7308
7309
7310   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7311
7312
7313   /* optimization - most of the time, left and result are the same
7314    * address, but different types. for the pic code, we could omit
7315    * the following
7316    */
7317
7318   aopOp(result,ic,TRUE);
7319
7320   emitpcode(POC_MOVFW, popGet(AOP(left),0));
7321
7322   size = AOP_SIZE(result);
7323
7324   while (size--) {
7325     emitpcode(POC_MOVWF, popGet(AOP(result),offset));
7326     offset++;
7327   }
7328
7329   freeAsmop(left,NULL,ic,TRUE);
7330   freeAsmop(result,NULL,ic,TRUE);
7331 }
7332
7333 /*-----------------------------------------------------------------*/
7334 /* genNearPointerGet - pic14_emitcode for near pointer fetch             */
7335 /*-----------------------------------------------------------------*/
7336 static void genNearPointerGet (operand *left, 
7337                                operand *result, 
7338                                iCode *ic)
7339 {
7340     asmop *aop = NULL;
7341     regs *preg = NULL ;
7342     char *rname ;
7343     sym_link *rtype, *retype;
7344     sym_link *ltype = operandType(left);    
7345     char buffer[80];
7346
7347     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7348
7349     rtype = operandType(result);
7350     retype= getSpec(rtype);
7351     
7352     aopOp(left,ic,FALSE);
7353     
7354     /* if left is rematerialisable and
7355        result is not bit variable type and
7356        the left is pointer to data space i.e
7357        lower 128 bytes of space */
7358     if (AOP_TYPE(left) == AOP_IMMD &&
7359         !IS_BITVAR(retype)         &&
7360         DCL_TYPE(ltype) == POINTER) {
7361         genDataPointerGet (left,result,ic);
7362         return ;
7363     }
7364     
7365     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7366
7367         /* if the value is already in a pointer register
7368        then don't need anything more */
7369     if (!AOP_INPREG(AOP(left))) {
7370         /* otherwise get a free pointer register */
7371     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7372         aop = newAsmop(0);
7373         preg = getFreePtr(ic,&aop,FALSE);
7374         pic14_emitcode("mov","%s,%s",
7375                 preg->name,
7376                 aopGet(AOP(left),0,FALSE,TRUE));
7377         rname = preg->name ;
7378     } else
7379         rname = aopGet(AOP(left),0,FALSE,FALSE);
7380     
7381     freeAsmop(left,NULL,ic,TRUE);
7382     aopOp (result,ic,FALSE);
7383     
7384       /* if bitfield then unpack the bits */
7385     if (IS_BITVAR(retype)) 
7386         genUnpackBits (result,rname,POINTER);
7387     else {
7388         /* we have can just get the values */
7389         int size = AOP_SIZE(result);
7390         int offset = 0 ;        
7391         
7392     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7393         while (size--) {
7394             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
7395
7396                 pic14_emitcode("mov","a,@%s",rname);
7397                 aopPut(AOP(result),"a",offset);
7398             } else {
7399                 sprintf(buffer,"@%s",rname);
7400                 aopPut(AOP(result),buffer,offset);
7401             }
7402             offset++ ;
7403             if (size)
7404                 pic14_emitcode("inc","%s",rname);
7405         }
7406     }
7407
7408     /* now some housekeeping stuff */
7409     if (aop) {
7410         /* we had to allocate for this iCode */
7411     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7412         freeAsmop(NULL,aop,ic,TRUE);
7413     } else { 
7414         /* we did not allocate which means left
7415            already in a pointer register, then
7416            if size > 0 && this could be used again
7417            we have to point it back to where it 
7418            belongs */
7419     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7420         if (AOP_SIZE(result) > 1 &&
7421             !OP_SYMBOL(left)->remat &&
7422             ( OP_SYMBOL(left)->liveTo > ic->seq ||
7423               ic->depth )) {
7424             int size = AOP_SIZE(result) - 1;
7425             while (size--)
7426                 pic14_emitcode("dec","%s",rname);
7427         }
7428     }
7429
7430     /* done */
7431     freeAsmop(result,NULL,ic,TRUE);
7432      
7433 }
7434
7435 /*-----------------------------------------------------------------*/
7436 /* genPagedPointerGet - pic14_emitcode for paged pointer fetch           */
7437 /*-----------------------------------------------------------------*/
7438 static void genPagedPointerGet (operand *left, 
7439                                operand *result, 
7440                                iCode *ic)
7441 {
7442     asmop *aop = NULL;
7443     regs *preg = NULL ;
7444     char *rname ;
7445     sym_link *rtype, *retype;    
7446
7447     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7448
7449     rtype = operandType(result);
7450     retype= getSpec(rtype);
7451     
7452     aopOp(left,ic,FALSE);
7453
7454   /* if the value is already in a pointer register
7455        then don't need anything more */
7456     if (!AOP_INPREG(AOP(left))) {
7457         /* otherwise get a free pointer register */
7458         aop = newAsmop(0);
7459         preg = getFreePtr(ic,&aop,FALSE);
7460         pic14_emitcode("mov","%s,%s",
7461                 preg->name,
7462                 aopGet(AOP(left),0,FALSE,TRUE));
7463         rname = preg->name ;
7464     } else
7465         rname = aopGet(AOP(left),0,FALSE,FALSE);
7466     
7467     freeAsmop(left,NULL,ic,TRUE);
7468     aopOp (result,ic,FALSE);
7469
7470     /* if bitfield then unpack the bits */
7471     if (IS_BITVAR(retype)) 
7472         genUnpackBits (result,rname,PPOINTER);
7473     else {
7474         /* we have can just get the values */
7475         int size = AOP_SIZE(result);
7476         int offset = 0 ;        
7477         
7478         while (size--) {
7479             
7480             pic14_emitcode("movx","a,@%s",rname);
7481             aopPut(AOP(result),"a",offset);
7482             
7483             offset++ ;
7484             
7485             if (size)
7486                 pic14_emitcode("inc","%s",rname);
7487         }
7488     }
7489
7490     /* now some housekeeping stuff */
7491     if (aop) {
7492         /* we had to allocate for this iCode */
7493         freeAsmop(NULL,aop,ic,TRUE);
7494     } else { 
7495         /* we did not allocate which means left
7496            already in a pointer register, then
7497            if size > 0 && this could be used again
7498            we have to point it back to where it 
7499            belongs */
7500         if (AOP_SIZE(result) > 1 &&
7501             !OP_SYMBOL(left)->remat &&
7502             ( OP_SYMBOL(left)->liveTo > ic->seq ||
7503               ic->depth )) {
7504             int size = AOP_SIZE(result) - 1;
7505             while (size--)
7506                 pic14_emitcode("dec","%s",rname);
7507         }
7508     }
7509
7510     /* done */
7511     freeAsmop(result,NULL,ic,TRUE);
7512     
7513         
7514 }
7515
7516 /*-----------------------------------------------------------------*/
7517 /* genFarPointerGet - gget value from far space                    */
7518 /*-----------------------------------------------------------------*/
7519 static void genFarPointerGet (operand *left,
7520                               operand *result, iCode *ic)
7521 {
7522     int size, offset ;
7523     sym_link *retype = getSpec(operandType(result));
7524
7525     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7526
7527     aopOp(left,ic,FALSE);
7528
7529     /* if the operand is already in dptr 
7530     then we do nothing else we move the value to dptr */
7531     if (AOP_TYPE(left) != AOP_STR) {
7532         /* if this is remateriazable */
7533         if (AOP_TYPE(left) == AOP_IMMD)
7534             pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
7535         else { /* we need to get it byte by byte */
7536             pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
7537             pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
7538             if (options.model == MODEL_FLAT24)
7539             {
7540                pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
7541             }
7542         }
7543     }
7544     /* so dptr know contains the address */
7545     freeAsmop(left,NULL,ic,TRUE);
7546     aopOp(result,ic,FALSE);
7547
7548     /* if bit then unpack */
7549     if (IS_BITVAR(retype)) 
7550         genUnpackBits(result,"dptr",FPOINTER);
7551     else {
7552         size = AOP_SIZE(result);
7553         offset = 0 ;
7554
7555         while (size--) {
7556             pic14_emitcode("movx","a,@dptr");
7557             aopPut(AOP(result),"a",offset++);
7558             if (size)
7559                 pic14_emitcode("inc","dptr");
7560         }
7561     }
7562
7563     freeAsmop(result,NULL,ic,TRUE);
7564 }
7565
7566 /*-----------------------------------------------------------------*/
7567 /* pic14_emitcodePointerGet - gget value from code space                  */
7568 /*-----------------------------------------------------------------*/
7569 static void pic14_emitcodePointerGet (operand *left,
7570                                 operand *result, iCode *ic)
7571 {
7572     int size, offset ;
7573     sym_link *retype = getSpec(operandType(result));
7574
7575     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7576
7577     aopOp(left,ic,FALSE);
7578
7579     /* if the operand is already in dptr 
7580     then we do nothing else we move the value to dptr */
7581     if (AOP_TYPE(left) != AOP_STR) {
7582         /* if this is remateriazable */
7583         if (AOP_TYPE(left) == AOP_IMMD)
7584             pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
7585         else { /* we need to get it byte by byte */
7586             pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
7587             pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
7588             if (options.model == MODEL_FLAT24)
7589             {
7590                pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
7591             }
7592         }
7593     }
7594     /* so dptr know contains the address */
7595     freeAsmop(left,NULL,ic,TRUE);
7596     aopOp(result,ic,FALSE);
7597
7598     /* if bit then unpack */
7599     if (IS_BITVAR(retype)) 
7600         genUnpackBits(result,"dptr",CPOINTER);
7601     else {
7602         size = AOP_SIZE(result);
7603         offset = 0 ;
7604
7605         while (size--) {
7606             pic14_emitcode("clr","a");
7607             pic14_emitcode("movc","a,@a+dptr");
7608             aopPut(AOP(result),"a",offset++);
7609             if (size)
7610                 pic14_emitcode("inc","dptr");
7611         }
7612     }
7613
7614     freeAsmop(result,NULL,ic,TRUE);
7615 }
7616
7617 /*-----------------------------------------------------------------*/
7618 /* genGenPointerGet - gget value from generic pointer space        */
7619 /*-----------------------------------------------------------------*/
7620 static void genGenPointerGet (operand *left,
7621                               operand *result, iCode *ic)
7622 {
7623   int size, offset ;
7624   sym_link *retype = getSpec(operandType(result));
7625
7626   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7627   aopOp(left,ic,FALSE);
7628   aopOp(result,ic,FALSE);
7629
7630
7631   DEBUGpic14_AopType(__LINE__,left,NULL,result);
7632
7633   /* if the operand is already in dptr 
7634      then we do nothing else we move the value to dptr */
7635   if (AOP_TYPE(left) != AOP_STR) {
7636     /* if this is remateriazable */
7637     if (AOP_TYPE(left) == AOP_IMMD) {
7638       pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
7639       pic14_emitcode("mov","b,#%d",pointerCode(retype));
7640     }
7641     else { /* we need to get it byte by byte */
7642
7643       emitpcode(POC_MOVFW,popGet(AOP(left),0));
7644       emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
7645
7646       size = AOP_SIZE(result);
7647       offset = 0 ;
7648
7649       while(size--) {
7650         emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
7651         emitpcode(POC_MOVWF,popGet(AOP(result),offset++));
7652         if(size)
7653           emitpcode(POC_INCF,popCopyReg(&pc_fsr));
7654       }
7655       goto release;
7656     }
7657   }
7658   /* so dptr know contains the address */
7659
7660   /* if bit then unpack */
7661   if (IS_BITVAR(retype)) 
7662     genUnpackBits(result,"dptr",GPOINTER);
7663
7664  release:
7665   freeAsmop(left,NULL,ic,TRUE);
7666   freeAsmop(result,NULL,ic,TRUE);
7667
7668 }
7669
7670 /*-----------------------------------------------------------------*/
7671 /* genPointerGet - generate code for pointer get                   */
7672 /*-----------------------------------------------------------------*/
7673 static void genPointerGet (iCode *ic)
7674 {
7675     operand *left, *result ;
7676     sym_link *type, *etype;
7677     int p_type;
7678
7679     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7680
7681     left = IC_LEFT(ic);
7682     result = IC_RESULT(ic) ;
7683
7684     /* depending on the type of pointer we need to
7685     move it to the correct pointer register */
7686     type = operandType(left);
7687     etype = getSpec(type);
7688     /* if left is of type of pointer then it is simple */
7689     if (IS_PTR(type) && !IS_FUNC(type->next)) 
7690         p_type = DCL_TYPE(type);
7691     else {
7692         /* we have to go by the storage class */
7693         p_type = PTR_TYPE(SPEC_OCLS(etype));
7694
7695 /*      if (SPEC_OCLS(etype)->codesp ) { */
7696 /*          p_type = CPOINTER ;  */
7697 /*      } */
7698 /*      else */
7699 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
7700 /*              p_type = FPOINTER ; */
7701 /*          else */
7702 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
7703 /*                  p_type = PPOINTER; */
7704 /*              else */
7705 /*                  if (SPEC_OCLS(etype) == idata ) */
7706 /*                      p_type = IPOINTER; */
7707 /*                  else */
7708 /*                      p_type = POINTER ; */
7709     }
7710
7711     /* now that we have the pointer type we assign
7712     the pointer values */
7713     switch (p_type) {
7714
7715     case POINTER:       
7716     case IPOINTER:
7717         genNearPointerGet (left,result,ic);
7718         break;
7719
7720     case PPOINTER:
7721         genPagedPointerGet(left,result,ic);
7722         break;
7723
7724     case FPOINTER:
7725         genFarPointerGet (left,result,ic);
7726         break;
7727
7728     case CPOINTER:
7729         pic14_emitcodePointerGet (left,result,ic);
7730         break;
7731
7732     case GPOINTER:
7733         genGenPointerGet (left,result,ic);
7734         break;
7735     }
7736
7737 }
7738
7739 /*-----------------------------------------------------------------*/
7740 /* genPackBits - generates code for packed bit storage             */
7741 /*-----------------------------------------------------------------*/
7742 static void genPackBits (sym_link    *etype ,
7743                          operand *right ,
7744                          char *rname, int p_type)
7745 {
7746     int shCount = 0 ;
7747     int offset = 0  ;
7748     int rLen = 0 ;
7749     int blen, bstr ;   
7750     char *l ;
7751
7752     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7753     blen = SPEC_BLEN(etype);
7754     bstr = SPEC_BSTR(etype);
7755
7756     l = aopGet(AOP(right),offset++,FALSE,FALSE);
7757     MOVA(l);   
7758
7759     /* if the bit lenth is less than or    */
7760     /* it exactly fits a byte then         */
7761     if (SPEC_BLEN(etype) <= 8 )  {
7762         shCount = SPEC_BSTR(etype) ;
7763
7764         /* shift left acc */
7765         AccLsh(shCount);
7766
7767         if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
7768
7769
7770             switch (p_type) {
7771                 case POINTER:
7772                     pic14_emitcode ("mov","b,a");
7773                     pic14_emitcode("mov","a,@%s",rname);
7774                     break;
7775
7776                 case FPOINTER:
7777                     pic14_emitcode ("mov","b,a");
7778                     pic14_emitcode("movx","a,@dptr");
7779                     break;
7780
7781                 case GPOINTER:
7782                     pic14_emitcode ("push","b");
7783                     pic14_emitcode ("push","acc");
7784                     pic14_emitcode ("lcall","__gptrget");
7785                     pic14_emitcode ("pop","b");
7786                     break;
7787             }
7788
7789             pic14_emitcode ("anl","a,#0x%02x",(unsigned char)
7790                       ((unsigned char)(0xFF << (blen+bstr)) | 
7791                        (unsigned char)(0xFF >> (8-bstr)) ) );
7792             pic14_emitcode ("orl","a,b");
7793             if (p_type == GPOINTER)
7794                 pic14_emitcode("pop","b");
7795         }
7796     }
7797
7798     switch (p_type) {
7799         case POINTER:
7800             pic14_emitcode("mov","@%s,a",rname);
7801             break;
7802
7803         case FPOINTER:
7804             pic14_emitcode("movx","@dptr,a");
7805             break;
7806
7807         case GPOINTER:
7808             DEBUGpic14_emitcode(";lcall","__gptrput");
7809             break;
7810     }
7811
7812     /* if we r done */
7813     if ( SPEC_BLEN(etype) <= 8 )
7814         return ;
7815
7816     pic14_emitcode("inc","%s",rname);
7817     rLen = SPEC_BLEN(etype) ;     
7818
7819     /* now generate for lengths greater than one byte */
7820     while (1) {
7821
7822         l = aopGet(AOP(right),offset++,FALSE,TRUE);
7823
7824         rLen -= 8 ;
7825         if (rLen <= 0 )
7826             break ;
7827
7828         switch (p_type) {
7829             case POINTER:
7830                 if (*l == '@') {
7831                     MOVA(l);
7832                     pic14_emitcode("mov","@%s,a",rname);
7833                 } else
7834                     pic14_emitcode("mov","@%s,%s",rname,l);
7835                 break;
7836
7837             case FPOINTER:
7838                 MOVA(l);
7839                 pic14_emitcode("movx","@dptr,a");
7840                 break;
7841
7842             case GPOINTER:
7843                 MOVA(l);
7844                 DEBUGpic14_emitcode(";lcall","__gptrput");
7845                 break;  
7846         }   
7847         pic14_emitcode ("inc","%s",rname);
7848     }
7849
7850     MOVA(l);
7851
7852     /* last last was not complete */
7853     if (rLen)   {
7854         /* save the byte & read byte */
7855         switch (p_type) {
7856             case POINTER:
7857                 pic14_emitcode ("mov","b,a");
7858                 pic14_emitcode("mov","a,@%s",rname);
7859                 break;
7860
7861             case FPOINTER:
7862                 pic14_emitcode ("mov","b,a");
7863                 pic14_emitcode("movx","a,@dptr");
7864                 break;
7865
7866             case GPOINTER:
7867                 pic14_emitcode ("push","b");
7868                 pic14_emitcode ("push","acc");
7869                 pic14_emitcode ("lcall","__gptrget");
7870                 pic14_emitcode ("pop","b");
7871                 break;
7872         }
7873
7874         pic14_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
7875         pic14_emitcode ("orl","a,b");
7876     }
7877
7878     if (p_type == GPOINTER)
7879         pic14_emitcode("pop","b");
7880
7881     switch (p_type) {
7882
7883     case POINTER:
7884         pic14_emitcode("mov","@%s,a",rname);
7885         break;
7886         
7887     case FPOINTER:
7888         pic14_emitcode("movx","@dptr,a");
7889         break;
7890         
7891     case GPOINTER:
7892         DEBUGpic14_emitcode(";lcall","__gptrput");
7893         break;                  
7894     }
7895 }
7896 /*-----------------------------------------------------------------*/
7897 /* genDataPointerSet - remat pointer to data space                 */
7898 /*-----------------------------------------------------------------*/
7899 static void genDataPointerSet(operand *right,
7900                               operand *result,
7901                               iCode *ic)
7902 {
7903     int size, offset = 0 ;
7904     char *l, buffer[256];
7905
7906     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7907     aopOp(right,ic,FALSE);
7908     
7909     l = aopGet(AOP(result),0,FALSE,TRUE);
7910     size = AOP_SIZE(right);
7911     // tsd, was l+1 - the underline `_' prefix was being stripped
7912     while (size--) {
7913         if (offset)
7914             sprintf(buffer,"(%s + %d)",l,offset);
7915         else
7916             sprintf(buffer,"%s",l);
7917
7918         if (AOP_TYPE(right) == AOP_LIT) {
7919           unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
7920           lit = lit >> (8*offset);
7921           if(lit&0xff) {
7922             pic14_emitcode("movlw","%d",lit);
7923             pic14_emitcode("movwf","%s",buffer);
7924
7925             emitpcode(POC_MOVLW, popGetLit(lit&0xff));
7926             emitpcode(POC_MOVWF, popRegFromString(buffer));
7927
7928           } else {
7929             pic14_emitcode("clrf","%s",buffer);
7930             emitpcode(POC_CLRF, popRegFromString(buffer));
7931           }
7932         }else {
7933           pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
7934           pic14_emitcode("movwf","%s",buffer);
7935
7936           emitpcode(POC_MOVFW, popGet(AOP(right),offset));
7937           emitpcode(POC_MOVWF, popRegFromString(buffer));
7938
7939         }
7940
7941         offset++;
7942     }
7943
7944     freeAsmop(right,NULL,ic,TRUE);
7945     freeAsmop(result,NULL,ic,TRUE);
7946 }
7947
7948 /*-----------------------------------------------------------------*/
7949 /* genNearPointerSet - pic14_emitcode for near pointer put                */
7950 /*-----------------------------------------------------------------*/
7951 static void genNearPointerSet (operand *right,
7952                                operand *result, 
7953                                iCode *ic)
7954 {
7955     asmop *aop = NULL;
7956     char *l;
7957     sym_link *retype;
7958     sym_link *ptype = operandType(result);
7959
7960     
7961     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7962     retype= getSpec(operandType(right));
7963
7964     aopOp(result,ic,FALSE);
7965     
7966     /* if the result is rematerializable &
7967        in data space & not a bit variable */
7968     if (AOP_TYPE(result) == AOP_IMMD &&
7969         DCL_TYPE(ptype) == POINTER   &&
7970         !IS_BITVAR(retype)) {
7971         genDataPointerSet (right,result,ic);
7972         return;
7973     }
7974
7975     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7976
7977     /* if the value is already in a pointer register
7978     then don't need anything more */
7979     if (!AOP_INPREG(AOP(result))) {
7980         /* otherwise get a free pointer register */
7981         //aop = newAsmop(0);
7982         //preg = getFreePtr(ic,&aop,FALSE);
7983         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7984         //pic14_emitcode("mov","%s,%s",
7985         //         preg->name,
7986         //         aopGet(AOP(result),0,FALSE,TRUE));
7987         //rname = preg->name ;
7988         pic14_emitcode("movwf","fsr");
7989     }// else
7990     //   rname = aopGet(AOP(result),0,FALSE,FALSE);
7991
7992     freeAsmop(result,NULL,ic,TRUE);
7993     aopOp (right,ic,FALSE);
7994     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7995
7996     /* if bitfield then unpack the bits */
7997     if (IS_BITVAR(retype)) {
7998       werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
7999              "The programmer is obviously confused");
8000       //genPackBits (retype,right,rname,POINTER);
8001       exit(1);
8002     }
8003     else {
8004         /* we have can just get the values */
8005         int size = AOP_SIZE(right);
8006         int offset = 0 ;    
8007
8008     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8009         while (size--) {
8010             l = aopGet(AOP(right),offset,FALSE,TRUE);
8011             if (*l == '@' ) {
8012               //MOVA(l);
8013               //pic14_emitcode("mov","@%s,a",rname);
8014               pic14_emitcode("movf","indf,w ;1");
8015             } else {
8016
8017               if (AOP_TYPE(right) == AOP_LIT) {
8018                 unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
8019                 if(lit) {
8020                   pic14_emitcode("movlw","%s",l);
8021                   pic14_emitcode("movwf","indf ;2");
8022                 } else 
8023                   pic14_emitcode("clrf","indf");
8024               }else {
8025                 pic14_emitcode("movf","%s,w",l);
8026                 pic14_emitcode("movwf","indf ;2");
8027               }
8028             //pic14_emitcode("mov","@%s,%s",rname,l);
8029             }
8030             if (size)
8031               pic14_emitcode("incf","fsr,f ;3");
8032             //pic14_emitcode("inc","%s",rname);
8033             offset++;
8034         }
8035     }
8036
8037     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8038     /* now some housekeeping stuff */
8039     if (aop) {
8040         /* we had to allocate for this iCode */
8041         freeAsmop(NULL,aop,ic,TRUE);
8042     } else { 
8043         /* we did not allocate which means left
8044         already in a pointer register, then
8045         if size > 0 && this could be used again
8046         we have to point it back to where it 
8047         belongs */
8048     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8049         if (AOP_SIZE(right) > 1 &&
8050             !OP_SYMBOL(result)->remat &&
8051             ( OP_SYMBOL(result)->liveTo > ic->seq ||
8052               ic->depth )) {
8053             int size = AOP_SIZE(right) - 1;
8054             while (size--)
8055               pic14_emitcode("decf","fsr,f");
8056               //pic14_emitcode("dec","%s",rname);
8057         }
8058     }
8059
8060     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8061     /* done */
8062     freeAsmop(right,NULL,ic,TRUE);
8063
8064
8065 }
8066
8067 /*-----------------------------------------------------------------*/
8068 /* genPagedPointerSet - pic14_emitcode for Paged pointer put             */
8069 /*-----------------------------------------------------------------*/
8070 static void genPagedPointerSet (operand *right,
8071                                operand *result, 
8072                                iCode *ic)
8073 {
8074     asmop *aop = NULL;
8075     regs *preg = NULL ;
8076     char *rname , *l;
8077     sym_link *retype;
8078        
8079     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8080
8081     retype= getSpec(operandType(right));
8082     
8083     aopOp(result,ic,FALSE);
8084     
8085     /* if the value is already in a pointer register
8086        then don't need anything more */
8087     if (!AOP_INPREG(AOP(result))) {
8088         /* otherwise get a free pointer register */
8089         aop = newAsmop(0);
8090         preg = getFreePtr(ic,&aop,FALSE);
8091         pic14_emitcode("mov","%s,%s",
8092                 preg->name,
8093                 aopGet(AOP(result),0,FALSE,TRUE));
8094         rname = preg->name ;
8095     } else
8096         rname = aopGet(AOP(result),0,FALSE,FALSE);
8097     
8098     freeAsmop(result,NULL,ic,TRUE);
8099     aopOp (right,ic,FALSE);
8100
8101     /* if bitfield then unpack the bits */
8102     if (IS_BITVAR(retype)) 
8103         genPackBits (retype,right,rname,PPOINTER);
8104     else {
8105         /* we have can just get the values */
8106         int size = AOP_SIZE(right);
8107         int offset = 0 ;        
8108         
8109         while (size--) {
8110             l = aopGet(AOP(right),offset,FALSE,TRUE);
8111             
8112             MOVA(l);
8113             pic14_emitcode("movx","@%s,a",rname);
8114
8115             if (size)
8116                 pic14_emitcode("inc","%s",rname);
8117
8118             offset++;
8119         }
8120     }
8121     
8122     /* now some housekeeping stuff */
8123     if (aop) {
8124         /* we had to allocate for this iCode */
8125         freeAsmop(NULL,aop,ic,TRUE);
8126     } else { 
8127         /* we did not allocate which means left
8128            already in a pointer register, then
8129            if size > 0 && this could be used again
8130            we have to point it back to where it 
8131            belongs */
8132         if (AOP_SIZE(right) > 1 &&
8133             !OP_SYMBOL(result)->remat &&
8134             ( OP_SYMBOL(result)->liveTo > ic->seq ||
8135               ic->depth )) {
8136             int size = AOP_SIZE(right) - 1;
8137             while (size--)
8138                 pic14_emitcode("dec","%s",rname);
8139         }
8140     }
8141
8142     /* done */
8143     freeAsmop(right,NULL,ic,TRUE);
8144     
8145         
8146 }
8147
8148 /*-----------------------------------------------------------------*/
8149 /* genFarPointerSet - set value from far space                     */
8150 /*-----------------------------------------------------------------*/
8151 static void genFarPointerSet (operand *right,
8152                               operand *result, iCode *ic)
8153 {
8154     int size, offset ;
8155     sym_link *retype = getSpec(operandType(right));
8156
8157     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8158     aopOp(result,ic,FALSE);
8159
8160     /* if the operand is already in dptr 
8161     then we do nothing else we move the value to dptr */
8162     if (AOP_TYPE(result) != AOP_STR) {
8163         /* if this is remateriazable */
8164         if (AOP_TYPE(result) == AOP_IMMD)
8165             pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
8166         else { /* we need to get it byte by byte */
8167             pic14_emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
8168             pic14_emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
8169             if (options.model == MODEL_FLAT24)
8170             {
8171                pic14_emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
8172             }
8173         }
8174     }
8175     /* so dptr know contains the address */
8176     freeAsmop(result,NULL,ic,TRUE);
8177     aopOp(right,ic,FALSE);
8178
8179     /* if bit then unpack */
8180     if (IS_BITVAR(retype)) 
8181         genPackBits(retype,right,"dptr",FPOINTER);
8182     else {
8183         size = AOP_SIZE(right);
8184         offset = 0 ;
8185
8186         while (size--) {
8187             char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
8188             MOVA(l);
8189             pic14_emitcode("movx","@dptr,a");
8190             if (size)
8191                 pic14_emitcode("inc","dptr");
8192         }
8193     }
8194
8195     freeAsmop(right,NULL,ic,TRUE);
8196 }
8197
8198 /*-----------------------------------------------------------------*/
8199 /* genGenPointerSet - set value from generic pointer space         */
8200 /*-----------------------------------------------------------------*/
8201 static void genGenPointerSet (operand *right,
8202                               operand *result, iCode *ic)
8203 {
8204   int size, offset ;
8205   sym_link *retype = getSpec(operandType(right));
8206
8207   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8208
8209   aopOp(result,ic,FALSE);
8210   aopOp(right,ic,FALSE);
8211   size = AOP_SIZE(right);
8212
8213   DEBUGpic14_AopType(__LINE__,NULL,right,result);
8214
8215   /* if the operand is already in dptr 
8216      then we do nothing else we move the value to dptr */
8217   if (AOP_TYPE(result) != AOP_STR) {
8218     /* if this is remateriazable */
8219     if (AOP_TYPE(result) == AOP_IMMD) {
8220       pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
8221       pic14_emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
8222     }
8223     else { /* we need to get it byte by byte */
8224       //char *l = aopGet(AOP(result),0,FALSE,FALSE);
8225       size = AOP_SIZE(right);
8226       offset = 0 ;
8227
8228       /* hack hack! see if this the FSR. If so don't load W */
8229       if(AOP_TYPE(right) != AOP_ACC) {
8230
8231         emitpcode(POC_MOVFW,popGet(AOP(result),0));
8232         emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
8233
8234         //if(size==2)
8235         //emitpcode(POC_DECF,popCopyReg(&pc_fsr));
8236         //if(size==4) {
8237         //  emitpcode(POC_MOVLW,popGetLit(0xfd));
8238         //  emitpcode(POC_ADDWF,popCopyReg(&pc_fsr));
8239         //}
8240
8241         while(size--) {
8242           emitpcode(POC_MOVFW,popGet(AOP(right),offset++));
8243           emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
8244           
8245           if(size)
8246             emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8247         }
8248
8249
8250         goto release;
8251       } 
8252
8253       if(aopIdx(AOP(result),0) != 4) {
8254
8255         emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
8256         goto release;
8257       }
8258
8259       emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
8260       goto release;
8261
8262     }
8263   }
8264   /* so dptr know contains the address */
8265
8266
8267   /* if bit then unpack */
8268   if (IS_BITVAR(retype)) 
8269     genPackBits(retype,right,"dptr",GPOINTER);
8270   else {
8271     size = AOP_SIZE(right);
8272     offset = 0 ;
8273
8274     while (--size) {
8275       //char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
8276       if(size)
8277         pic14_emitcode("incf","fsr,f");
8278       pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset++,FALSE,FALSE));
8279       pic14_emitcode("movwf","indf");
8280       //MOVA(l);
8281       //DEBUGpic14_emitcode(";lcall","__gptrput");
8282       //if (size)
8283       //    pic14_emitcode("inc","dptr");
8284     }
8285   }
8286
8287  release:
8288   freeAsmop(right,NULL,ic,TRUE);
8289   freeAsmop(result,NULL,ic,TRUE);
8290 }
8291
8292 /*-----------------------------------------------------------------*/
8293 /* genPointerSet - stores the value into a pointer location        */
8294 /*-----------------------------------------------------------------*/
8295 static void genPointerSet (iCode *ic)
8296 {    
8297     operand *right, *result ;
8298     sym_link *type, *etype;
8299     int p_type;
8300
8301     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8302
8303     right = IC_RIGHT(ic);
8304     result = IC_RESULT(ic) ;
8305
8306     /* depending on the type of pointer we need to
8307     move it to the correct pointer register */
8308     type = operandType(result);
8309     etype = getSpec(type);
8310     /* if left is of type of pointer then it is simple */
8311     if (IS_PTR(type) && !IS_FUNC(type->next)) {
8312         p_type = DCL_TYPE(type);
8313     }
8314     else {
8315         /* we have to go by the storage class */
8316         p_type = PTR_TYPE(SPEC_OCLS(etype));
8317
8318 /*      if (SPEC_OCLS(etype)->codesp ) { */
8319 /*          p_type = CPOINTER ;  */
8320 /*      } */
8321 /*      else */
8322 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
8323 /*              p_type = FPOINTER ; */
8324 /*          else */
8325 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
8326 /*                  p_type = PPOINTER ; */
8327 /*              else */
8328 /*                  if (SPEC_OCLS(etype) == idata ) */
8329 /*                      p_type = IPOINTER ; */
8330 /*                  else */
8331 /*                      p_type = POINTER ; */
8332     }
8333
8334     /* now that we have the pointer type we assign
8335     the pointer values */
8336     switch (p_type) {
8337
8338     case POINTER:
8339     case IPOINTER:
8340         genNearPointerSet (right,result,ic);
8341         break;
8342
8343     case PPOINTER:
8344         genPagedPointerSet (right,result,ic);
8345         break;
8346
8347     case FPOINTER:
8348         genFarPointerSet (right,result,ic);
8349         break;
8350
8351     case GPOINTER:
8352         genGenPointerSet (right,result,ic);
8353         break;
8354     }
8355
8356 }
8357
8358 /*-----------------------------------------------------------------*/
8359 /* genIfx - generate code for Ifx statement                        */
8360 /*-----------------------------------------------------------------*/
8361 static void genIfx (iCode *ic, iCode *popIc)
8362 {
8363   operand *cond = IC_COND(ic);
8364   int isbit =0;
8365
8366   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8367
8368   aopOp(cond,ic,FALSE);
8369
8370   /* get the value into acc */
8371   if (AOP_TYPE(cond) != AOP_CRY)
8372     pic14_toBoolean(cond);
8373   else
8374     isbit = 1;
8375   /* the result is now in the accumulator */
8376   freeAsmop(cond,NULL,ic,TRUE);
8377
8378   /* if there was something to be popped then do it */
8379   if (popIc)
8380     genIpop(popIc);
8381
8382   /* if the condition is  a bit variable */
8383   if (isbit && IS_ITEMP(cond) && 
8384       SPIL_LOC(cond)) {
8385     genIfxJump(ic,SPIL_LOC(cond)->rname);
8386     DEBUGpic14_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
8387   }
8388   else {
8389     if (isbit && !IS_ITEMP(cond))
8390       genIfxJump(ic,OP_SYMBOL(cond)->rname);
8391     else
8392       genIfxJump(ic,"a");
8393   }
8394   ic->generated = 1;
8395
8396 }
8397
8398 /*-----------------------------------------------------------------*/
8399 /* genAddrOf - generates code for address of                       */
8400 /*-----------------------------------------------------------------*/
8401 static void genAddrOf (iCode *ic)
8402 {
8403   //symbol *sym = OP_SYMBOL(IC_LEFT(ic));
8404   operand *right, *result, *left;
8405   //int size, offset ;
8406
8407   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8408
8409
8410   //aopOp(IC_RESULT(ic),ic,FALSE);
8411
8412   aopOp((left=IC_LEFT(ic)),ic,FALSE);
8413   aopOp((right=IC_RIGHT(ic)),ic,FALSE);
8414   aopOp((result=IC_RESULT(ic)),ic,TRUE);
8415
8416   DEBUGpic14_AopType(__LINE__,left,right,result);
8417
8418   emitpcode(POC_MOVLW, popGet(AOP(left),0));
8419   emitpcode(POC_MOVWF, popGet(AOP(result),0));
8420
8421 #if 0
8422   /* object not on stack then we need the name */
8423   size = AOP_SIZE(IC_RESULT(ic));
8424   offset = 0;
8425
8426   while (size--) {
8427     char s[SDCC_NAME_MAX];
8428     if (offset) 
8429       sprintf(s,"#(%s >> %d)",
8430               sym->rname,
8431               offset*8);
8432     else
8433       sprintf(s,"#%s",sym->rname);
8434     aopPut(AOP(IC_RESULT(ic)),s,offset++);
8435   }
8436 #endif
8437
8438
8439   //  freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8440   freeAsmop(left,NULL,ic,FALSE);
8441   freeAsmop(result,NULL,ic,TRUE);
8442
8443 }
8444
8445 #if 0
8446 /*-----------------------------------------------------------------*/
8447 /* genFarFarAssign - assignment when both are in far space         */
8448 /*-----------------------------------------------------------------*/
8449 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
8450 {
8451     int size = AOP_SIZE(right);
8452     int offset = 0;
8453     char *l ;
8454     /* first push the right side on to the stack */
8455     while (size--) {
8456         l = aopGet(AOP(right),offset++,FALSE,FALSE);
8457         MOVA(l);
8458         pic14_emitcode ("push","acc");
8459     }
8460     
8461     freeAsmop(right,NULL,ic,FALSE);
8462     /* now assign DPTR to result */
8463     aopOp(result,ic,FALSE);
8464     size = AOP_SIZE(result);
8465     while (size--) {
8466         pic14_emitcode ("pop","acc");
8467         aopPut(AOP(result),"a",--offset);
8468     }
8469     freeAsmop(result,NULL,ic,FALSE);
8470         
8471 }
8472 #endif
8473
8474 /*-----------------------------------------------------------------*/
8475 /* genAssign - generate code for assignment                        */
8476 /*-----------------------------------------------------------------*/
8477 static void genAssign (iCode *ic)
8478 {
8479   operand *result, *right;
8480   int size, offset,know_W;
8481   unsigned long lit = 0L;
8482
8483   result = IC_RESULT(ic);
8484   right  = IC_RIGHT(ic) ;
8485
8486   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8487
8488   /* if they are the same */
8489   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
8490     return ;
8491
8492   aopOp(right,ic,FALSE);
8493   aopOp(result,ic,TRUE);
8494
8495   DEBUGpic14_AopType(__LINE__,NULL,right,result);
8496
8497   /* if they are the same registers */
8498   if (pic14_sameRegs(AOP(right),AOP(result)))
8499     goto release;
8500
8501   /* if the result is a bit */
8502   if (AOP_TYPE(result) == AOP_CRY) {
8503
8504     /* if the right size is a literal then
8505        we know what the value is */
8506     if (AOP_TYPE(right) == AOP_LIT) {
8507           
8508       emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
8509                   popGet(AOP(result),0));
8510
8511       if (((int) operandLitValue(right))) 
8512         pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
8513                        AOP(result)->aopu.aop_dir,
8514                        AOP(result)->aopu.aop_dir);
8515       else
8516         pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
8517                        AOP(result)->aopu.aop_dir,
8518                        AOP(result)->aopu.aop_dir);
8519       goto release;
8520     }
8521
8522     /* the right is also a bit variable */
8523     if (AOP_TYPE(right) == AOP_CRY) {
8524       emitpcode(POC_BCF,    popGet(AOP(result),0));
8525       emitpcode(POC_BTFSC,  popGet(AOP(right),0));
8526       emitpcode(POC_BSF,    popGet(AOP(result),0));
8527
8528       pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
8529                      AOP(result)->aopu.aop_dir,
8530                      AOP(result)->aopu.aop_dir);
8531       pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
8532                      AOP(right)->aopu.aop_dir,
8533                      AOP(right)->aopu.aop_dir);
8534       pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
8535                      AOP(result)->aopu.aop_dir,
8536                      AOP(result)->aopu.aop_dir);
8537       goto release ;
8538     }
8539
8540     /* we need to or */
8541     emitpcode(POC_BCF,    popGet(AOP(result),0));
8542     pic14_toBoolean(right);
8543     emitSKPZ;
8544     emitpcode(POC_BSF,    popGet(AOP(result),0));
8545     //aopPut(AOP(result),"a",0);
8546     goto release ;
8547   }
8548
8549   /* bit variables done */
8550   /* general case */
8551   size = AOP_SIZE(result);
8552   offset = 0 ;
8553   if(AOP_TYPE(right) == AOP_LIT)
8554     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
8555
8556   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
8557   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8558     if(aopIdx(AOP(result),0) == 4) {
8559   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8560       emitpcode(POC_MOVFW, popGet(AOP(right),offset));
8561       emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8562       goto release;
8563     } else
8564       DEBUGpic14_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
8565   }
8566
8567   know_W=-1;
8568   while (size--) {
8569   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8570     if(AOP_TYPE(right) == AOP_LIT) {
8571       if(lit&0xff) {
8572         if(know_W != (lit&0xff))
8573           emitpcode(POC_MOVLW,popGetLit(lit&0xff));
8574         know_W = lit&0xff;
8575         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8576       } else
8577         emitpcode(POC_CLRF, popGet(AOP(result),offset));
8578
8579       lit >>= 8;
8580
8581     } else if (AOP_TYPE(right) == AOP_CRY) {
8582       emitpcode(POC_CLRF, popGet(AOP(result),offset));
8583       if(offset == 0) {
8584         emitpcode(POC_BTFSS, popGet(AOP(right),0));
8585         emitpcode(POC_INCF, popGet(AOP(result),0));
8586       }
8587     } else {
8588   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8589       emitpcode(POC_MOVFW, popGet(AOP(right),offset));
8590       emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8591     }
8592             
8593     offset++;
8594   }
8595
8596     
8597  release:
8598   freeAsmop (right,NULL,ic,FALSE);
8599   freeAsmop (result,NULL,ic,TRUE);
8600 }   
8601
8602 /*-----------------------------------------------------------------*/
8603 /* genJumpTab - genrates code for jump table                       */
8604 /*-----------------------------------------------------------------*/
8605 static void genJumpTab (iCode *ic)
8606 {
8607     symbol *jtab;
8608     char *l;
8609
8610     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8611
8612     aopOp(IC_JTCOND(ic),ic,FALSE);
8613     /* get the condition into accumulator */
8614     l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
8615     MOVA(l);
8616     /* multiply by three */
8617     pic14_emitcode("add","a,acc");
8618     pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
8619
8620     jtab = newiTempLabel(NULL);
8621     pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
8622     pic14_emitcode("jmp","@a+dptr");
8623     pic14_emitcode("","%05d_DS_:",jtab->key+100);
8624
8625     emitpcode(POC_MOVLW, popGetLabel(jtab->key));
8626     emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
8627     emitSKPNC;
8628     emitpcode(POC_INCF, popCopyReg(&pc_pclath));
8629     emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
8630     emitpLabel(jtab->key);
8631
8632     freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
8633
8634     /* now generate the jump labels */
8635     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
8636          jtab = setNextItem(IC_JTLABELS(ic))) {
8637         pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
8638         emitpcode(POC_GOTO,popGetLabel(jtab->key));
8639         
8640     }
8641
8642 }
8643
8644 /*-----------------------------------------------------------------*/
8645 /* genMixedOperation - gen code for operators between mixed types  */
8646 /*-----------------------------------------------------------------*/
8647 /*
8648   TSD - Written for the PIC port - but this unfortunately is buggy.
8649   This routine is good in that it is able to efficiently promote 
8650   types to different (larger) sizes. Unfortunately, the temporary
8651   variables that are optimized out by this routine are sometimes
8652   used in other places. So until I know how to really parse the 
8653   iCode tree, I'm going to not be using this routine :(.
8654 */
8655 static int genMixedOperation (iCode *ic)
8656 {
8657 #if 0
8658   operand *result = IC_RESULT(ic);
8659   sym_link *ctype = operandType(IC_LEFT(ic));
8660   operand *right = IC_RIGHT(ic);
8661   int ret = 0;
8662   int big,small;
8663   int offset;
8664
8665   iCode *nextic;
8666   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
8667
8668   pic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
8669
8670   nextic = ic->next;
8671   if(!nextic)
8672     return 0;
8673
8674   nextright = IC_RIGHT(nextic);
8675   nextleft  = IC_LEFT(nextic);
8676   nextresult = IC_RESULT(nextic);
8677
8678   aopOp(right,ic,FALSE);
8679   aopOp(result,ic,FALSE);
8680   aopOp(nextright,  nextic, FALSE);
8681   aopOp(nextleft,   nextic, FALSE);
8682   aopOp(nextresult, nextic, FALSE);
8683
8684   if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
8685
8686     operand *t = right;
8687     right = nextright;
8688     nextright = t; 
8689
8690     pic14_emitcode(";remove right +","");
8691
8692   } else   if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
8693 /*
8694     operand *t = right;
8695     right = nextleft;
8696     nextleft = t; 
8697 */
8698     pic14_emitcode(";remove left +","");
8699   } else
8700     return 0;
8701
8702   big = AOP_SIZE(nextleft);
8703   small = AOP_SIZE(nextright);
8704
8705   switch(nextic->op) {
8706
8707   case '+':
8708     pic14_emitcode(";optimize a +","");
8709     /* if unsigned or not an integral type */
8710     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
8711       pic14_emitcode(";add a bit to something","");
8712     } else {
8713
8714       pic14_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
8715
8716       if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
8717         pic14_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
8718         pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
8719       } else
8720         pic14_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
8721
8722       offset = 0;
8723       while(--big) {
8724
8725         offset++;
8726
8727         if(--small) {
8728           if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
8729             pic14_emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8730             pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
8731           }
8732
8733           pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8734           emitSKPNC;
8735           pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
8736                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
8737                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
8738           pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8739           pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
8740
8741         } else {
8742           pic14_emitcode("rlf","known_zero,w");
8743
8744           /*
8745             if right is signed
8746               btfsc  right,7
8747                addlw ff
8748           */
8749           if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
8750             pic14_emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8751             pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
8752           } else {
8753             pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
8754           }
8755         }
8756       }
8757       ret = 1;
8758     }
8759   }
8760   ret = 1;
8761
8762 release:
8763   freeAsmop(right,NULL,ic,TRUE);
8764   freeAsmop(result,NULL,ic,TRUE);
8765   freeAsmop(nextright,NULL,ic,TRUE);
8766   freeAsmop(nextleft,NULL,ic,TRUE);
8767   if(ret)
8768     nextic->generated = 1;
8769
8770   return ret;
8771 #else
8772   return 0;
8773 #endif
8774 }
8775 /*-----------------------------------------------------------------*/
8776 /* genCast - gen code for casting                                  */
8777 /*-----------------------------------------------------------------*/
8778 static void genCast (iCode *ic)
8779 {
8780     operand *result = IC_RESULT(ic);
8781     sym_link *ctype = operandType(IC_LEFT(ic));
8782     operand *right = IC_RIGHT(ic);
8783     int size, offset ;
8784
8785     DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
8786     /* if they are equivalent then do nothing */
8787     if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
8788         return ;
8789
8790     aopOp(right,ic,FALSE) ;
8791     aopOp(result,ic,FALSE);
8792
8793     DEBUGpic14_AopType(__LINE__,NULL,right,result);
8794
8795     /* if the result is a bit */
8796     if (AOP_TYPE(result) == AOP_CRY) {
8797         /* if the right size is a literal then
8798         we know what the value is */
8799         if (AOP_TYPE(right) == AOP_LIT) {
8800
8801           emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
8802                       popGet(AOP(result),0));
8803
8804             if (((int) operandLitValue(right))) 
8805               pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
8806                        AOP(result)->aopu.aop_dir,
8807                        AOP(result)->aopu.aop_dir);
8808             else
8809               pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
8810                        AOP(result)->aopu.aop_dir,
8811                        AOP(result)->aopu.aop_dir);
8812
8813             goto release;
8814         }
8815
8816         /* the right is also a bit variable */
8817         if (AOP_TYPE(right) == AOP_CRY) {
8818
8819           emitCLRC;
8820           emitpcode(POC_BTFSC,  popGet(AOP(right),0));
8821
8822           pic14_emitcode("clrc","");
8823           pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
8824                    AOP(right)->aopu.aop_dir,
8825                    AOP(right)->aopu.aop_dir);
8826             aopPut(AOP(result),"c",0);
8827             goto release ;
8828         }
8829
8830         /* we need to or */
8831         if (AOP_TYPE(right) == AOP_REG) {
8832           emitpcode(POC_BCF,    popGet(AOP(result),0));
8833           emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
8834           emitpcode(POC_BSF,    popGet(AOP(result),0));
8835         }
8836         pic14_toBoolean(right);
8837         aopPut(AOP(result),"a",0);
8838         goto release ;
8839     }
8840
8841     if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
8842       int offset = 1;
8843       size = AOP_SIZE(result);
8844
8845       emitpcode(POC_CLRF,   popGet(AOP(result),0));
8846       emitpcode(POC_BTFSC,  popGet(AOP(right),0));
8847       emitpcode(POC_INCF,   popGet(AOP(result),0));
8848
8849       while (size--)
8850         emitpcode(POC_CLRF,   popGet(AOP(result),offset++));
8851
8852       goto release;
8853     }
8854
8855     /* if they are the same size : or less */
8856     if (AOP_SIZE(result) <= AOP_SIZE(right)) {
8857
8858         /* if they are in the same place */
8859         if (pic14_sameRegs(AOP(right),AOP(result)))
8860             goto release;
8861
8862         /* if they in different places then copy */
8863         size = AOP_SIZE(result);
8864         offset = 0 ;
8865         while (size--) {
8866             aopPut(AOP(result),
8867                    aopGet(AOP(right),offset,FALSE,FALSE),
8868                    offset);
8869             offset++;
8870         }
8871         goto release;
8872     }
8873
8874
8875     /* if the result is of type pointer */
8876     if (IS_PTR(ctype)) {
8877
8878         int p_type;
8879         sym_link *type = operandType(right);
8880         sym_link *etype = getSpec(type);
8881
8882         /* pointer to generic pointer */
8883         if (IS_GENPTR(ctype)) {
8884             char *l = zero;
8885             
8886             if (IS_PTR(type)) 
8887                 p_type = DCL_TYPE(type);
8888             else {
8889                 /* we have to go by the storage class */
8890                 p_type = PTR_TYPE(SPEC_OCLS(etype));
8891
8892 /*              if (SPEC_OCLS(etype)->codesp )  */
8893 /*                  p_type = CPOINTER ;  */
8894 /*              else */
8895 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
8896 /*                      p_type = FPOINTER ; */
8897 /*                  else */
8898 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
8899 /*                          p_type = PPOINTER; */
8900 /*                      else */
8901 /*                          if (SPEC_OCLS(etype) == idata ) */
8902 /*                              p_type = IPOINTER ; */
8903 /*                          else */
8904 /*                              p_type = POINTER ; */
8905             }
8906                 
8907             /* the first two bytes are known */
8908             size = GPTRSIZE - 1; 
8909             offset = 0 ;
8910             while (size--) {
8911                 aopPut(AOP(result),
8912                        aopGet(AOP(right),offset,FALSE,FALSE),
8913                        offset);
8914                 offset++;
8915             }
8916             /* the last byte depending on type */
8917             switch (p_type) {
8918             case IPOINTER:
8919             case POINTER:
8920                 l = zero;
8921                 break;
8922             case FPOINTER:
8923                 l = one;
8924                 break;
8925             case CPOINTER:
8926                 l = "#0x02";
8927                 break;                          
8928             case PPOINTER:
8929                 l = "#0x03";
8930                 break;
8931                 
8932             default:
8933                 /* this should never happen */
8934                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8935                        "got unknown pointer type");
8936                 exit(1);
8937             }
8938             aopPut(AOP(result),l, GPTRSIZE - 1);            
8939             goto release ;
8940         }
8941         
8942         /* just copy the pointers */
8943         size = AOP_SIZE(result);
8944         offset = 0 ;
8945         while (size--) {
8946             aopPut(AOP(result),
8947                    aopGet(AOP(right),offset,FALSE,FALSE),
8948                    offset);
8949             offset++;
8950         }
8951         goto release ;
8952     }
8953     
8954
8955
8956     /* so we now know that the size of destination is greater
8957     than the size of the source.
8958     Now, if the next iCode is an operator then we might be
8959     able to optimize the operation without performing a cast.
8960     */
8961     if(genMixedOperation(ic))
8962       goto release;
8963
8964     
8965     /* we move to result for the size of source */
8966     size = AOP_SIZE(right);
8967     offset = 0 ;
8968     while (size--) {
8969       emitpcode(POC_MOVFW,   popGet(AOP(right),offset));
8970       emitpcode(POC_MOVWF,   popGet(AOP(result),offset));
8971       offset++;
8972     }
8973
8974     /* now depending on the sign of the destination */
8975     size = AOP_SIZE(result) - AOP_SIZE(right);
8976     /* if unsigned or not an integral type */
8977     if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) {
8978       while (size--)
8979         emitpcode(POC_CLRF,   popGet(AOP(result),offset++));
8980     } else {
8981       /* we need to extend the sign :{ */
8982
8983       if(size == 1) {
8984         /* Save one instruction of casting char to int */
8985         emitpcode(POC_CLRF,   popGet(AOP(result),offset));
8986         emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
8987         emitpcode(POC_DECF,   popGet(AOP(result),offset));
8988       } else {
8989         emitpcodeNULLop(POC_CLRW);
8990
8991         if(offset)
8992           emitpcode(POC_BTFSC,   newpCodeOpBit(aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
8993         else
8994           emitpcode(POC_BTFSC,   newpCodeOpBit(aopGet(AOP(right),offset,FALSE,FALSE),7,0));
8995         
8996         emitpcode(POC_MOVLW,   popGetLit(0xff));
8997
8998         while (size--)
8999           emitpcode(POC_MOVWF,   popGet(AOP(result),offset++));
9000       }
9001     }
9002
9003 release:
9004     freeAsmop(right,NULL,ic,TRUE);
9005     freeAsmop(result,NULL,ic,TRUE);
9006
9007 }
9008
9009 /*-----------------------------------------------------------------*/
9010 /* genDjnz - generate decrement & jump if not zero instrucion      */
9011 /*-----------------------------------------------------------------*/
9012 static int genDjnz (iCode *ic, iCode *ifx)
9013 {
9014     symbol *lbl, *lbl1;
9015     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9016
9017     if (!ifx)
9018         return 0;
9019     
9020     /* if the if condition has a false label
9021        then we cannot save */
9022     if (IC_FALSE(ifx))
9023         return 0;
9024
9025     /* if the minus is not of the form 
9026        a = a - 1 */
9027     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
9028         !IS_OP_LITERAL(IC_RIGHT(ic)))
9029         return 0;
9030
9031     if (operandLitValue(IC_RIGHT(ic)) != 1)
9032         return 0;
9033
9034     /* if the size of this greater than one then no
9035        saving */
9036     if (getSize(operandType(IC_RESULT(ic))) > 1)
9037         return 0;
9038
9039     /* otherwise we can save BIG */
9040     lbl = newiTempLabel(NULL);
9041     lbl1= newiTempLabel(NULL);
9042
9043     aopOp(IC_RESULT(ic),ic,FALSE);
9044     
9045     if (IS_AOP_PREG(IC_RESULT(ic))) {
9046         pic14_emitcode("dec","%s",
9047                  aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
9048         pic14_emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
9049         pic14_emitcode("jnz","%05d_DS_",lbl->key+100);
9050     } else {    
9051
9052
9053       emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0));
9054       emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
9055
9056       pic14_emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
9057       pic14_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
9058
9059     }
9060 /*     pic14_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
9061 /*     pic14_emitcode ("","%05d_DS_:",lbl->key+100); */
9062 /*     pic14_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
9063 /*     pic14_emitcode ("","%05d_DS_:",lbl1->key+100); */
9064
9065     
9066     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
9067     ifx->generated = 1;
9068     return 1;
9069 }
9070
9071 /*-----------------------------------------------------------------*/
9072 /* genReceive - generate code for a receive iCode                  */
9073 /*-----------------------------------------------------------------*/
9074 static void genReceive (iCode *ic)
9075 {    
9076     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9077
9078     if (isOperandInFarSpace(IC_RESULT(ic)) && 
9079         ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
9080           IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
9081
9082         int size = getSize(operandType(IC_RESULT(ic)));
9083         int offset =  fReturnSizePic - size;
9084         while (size--) {
9085             pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
9086                                     fReturn[fReturnSizePic - offset - 1] : "acc"));
9087             offset++;
9088         }
9089         aopOp(IC_RESULT(ic),ic,FALSE);  
9090         size = AOP_SIZE(IC_RESULT(ic));
9091         offset = 0;
9092         while (size--) {
9093             pic14_emitcode ("pop","acc");
9094             aopPut (AOP(IC_RESULT(ic)),"a",offset++);
9095         }
9096         
9097     } else {
9098         _G.accInUse++;
9099         aopOp(IC_RESULT(ic),ic,FALSE);  
9100         _G.accInUse--;
9101         assignResultValue(IC_RESULT(ic));       
9102     }
9103
9104     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
9105 }
9106
9107 /*-----------------------------------------------------------------*/
9108 /* genpic14Code - generate code for pic14 based controllers        */
9109 /*-----------------------------------------------------------------*/
9110 /*
9111  * At this point, ralloc.c has gone through the iCode and attempted
9112  * to optimize in a way suitable for a PIC. Now we've got to generate
9113  * PIC instructions that correspond to the iCode.
9114  *
9115  * Once the instructions are generated, we'll pass through both the
9116  * peep hole optimizer and the pCode optimizer.
9117  *-----------------------------------------------------------------*/
9118
9119 void genpic14Code (iCode *lic)
9120 {
9121     iCode *ic;
9122     int cln = 0;
9123
9124     lineHead = lineCurr = NULL;
9125
9126     pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
9127     addpBlock(pb);
9128
9129     /* if debug information required */
9130 /*     if (options.debug && currFunc) { */
9131     if (currFunc) {
9132         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
9133         _G.debugLine = 1;
9134         if (IS_STATIC(currFunc->etype)) {
9135             pic14_emitcode("",";F%s$%s$0$0     %d",moduleName,currFunc->name,__LINE__);
9136             //addpCode2pBlock(pb,newpCodeLabel(moduleName,currFunc->name));
9137         } else {
9138             pic14_emitcode("",";G$%s$0$0   %d",currFunc->name,__LINE__);
9139             //addpCode2pBlock(pb,newpCodeLabel(NULL,currFunc->name));
9140         }
9141         _G.debugLine = 0;
9142     }
9143
9144
9145     for (ic = lic ; ic ; ic = ic->next ) {
9146
9147       DEBUGpic14_emitcode(";ic","");
9148         if ( cln != ic->lineno ) {
9149             if ( options.debug ) {
9150                 _G.debugLine = 1;
9151                 pic14_emitcode("",";C$%s$%d$%d$%d ==.",
9152                          FileBaseName(ic->filename),ic->lineno,
9153                          ic->level,ic->block);
9154                 _G.debugLine = 0;
9155             }
9156             pic14_emitcode("#CSRC","%s %d",FileBaseName(ic->filename),ic->lineno);
9157             cln = ic->lineno ;
9158         }
9159         /* if the result is marked as
9160            spilt and rematerializable or code for
9161            this has already been generated then
9162            do nothing */
9163         if (resultRemat(ic) || ic->generated ) 
9164             continue ;
9165         
9166         /* depending on the operation */
9167         switch (ic->op) {
9168         case '!' :
9169             genNot(ic);
9170             break;
9171             
9172         case '~' :
9173             genCpl(ic);
9174             break;
9175             
9176         case UNARYMINUS:
9177             genUminus (ic);
9178             break;
9179             
9180         case IPUSH:
9181             genIpush (ic);
9182             break;
9183             
9184         case IPOP:
9185             /* IPOP happens only when trying to restore a 
9186                spilt live range, if there is an ifx statement
9187                following this pop then the if statement might
9188                be using some of the registers being popped which
9189                would destory the contents of the register so
9190                we need to check for this condition and handle it */
9191             if (ic->next            && 
9192                 ic->next->op == IFX &&
9193                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
9194                 genIfx (ic->next,ic);
9195             else
9196                 genIpop (ic);
9197             break; 
9198             
9199         case CALL:
9200             genCall (ic);
9201             break;
9202             
9203         case PCALL:
9204             genPcall (ic);
9205             break;
9206             
9207         case FUNCTION:
9208             genFunction (ic);
9209             break;
9210             
9211         case ENDFUNCTION:
9212             genEndFunction (ic);
9213             break;
9214             
9215         case RETURN:
9216             genRet (ic);
9217             break;
9218             
9219         case LABEL:
9220             genLabel (ic);
9221             break;
9222             
9223         case GOTO:
9224             genGoto (ic);
9225             break;
9226             
9227         case '+' :
9228             genPlus (ic) ;
9229             break;
9230             
9231         case '-' :
9232             if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
9233                 genMinus (ic);
9234             break;
9235             
9236         case '*' :
9237             genMult (ic);
9238             break;
9239             
9240         case '/' :
9241             genDiv (ic) ;
9242             break;
9243             
9244         case '%' :
9245             genMod (ic);
9246             break;
9247             
9248         case '>' :
9249             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
9250             break;
9251             
9252         case '<' :
9253             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
9254             break;
9255             
9256         case LE_OP:
9257         case GE_OP:
9258         case NE_OP:
9259             
9260             /* note these two are xlated by algebraic equivalence
9261                during parsing SDCC.y */
9262             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
9263                    "got '>=' or '<=' shouldn't have come here");
9264             break;      
9265             
9266         case EQ_OP:
9267             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
9268             break;          
9269             
9270         case AND_OP:
9271             genAndOp (ic);
9272             break;
9273             
9274         case OR_OP:
9275             genOrOp (ic);
9276             break;
9277             
9278         case '^' :
9279             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
9280             break;
9281             
9282         case '|' :
9283                 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
9284             break;
9285             
9286         case BITWISEAND:
9287             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
9288             break;
9289             
9290         case INLINEASM:
9291             genInline (ic);
9292             break;
9293             
9294         case RRC:
9295             genRRC (ic);
9296             break;
9297             
9298         case RLC:
9299             genRLC (ic);
9300             break;
9301             
9302         case GETHBIT:
9303             genGetHbit (ic);
9304             break;
9305             
9306         case LEFT_OP:
9307             genLeftShift (ic);
9308             break;
9309             
9310         case RIGHT_OP:
9311             genRightShift (ic);
9312             break;
9313             
9314         case GET_VALUE_AT_ADDRESS:
9315             genPointerGet(ic);
9316             break;
9317             
9318         case '=' :
9319             if (POINTER_SET(ic))
9320                 genPointerSet(ic);
9321             else
9322                 genAssign(ic);
9323             break;
9324             
9325         case IFX:
9326             genIfx (ic,NULL);
9327             break;
9328             
9329         case ADDRESS_OF:
9330             genAddrOf (ic);
9331             break;
9332             
9333         case JUMPTABLE:
9334             genJumpTab (ic);
9335             break;
9336             
9337         case CAST:
9338             genCast (ic);
9339             break;
9340             
9341         case RECEIVE:
9342             genReceive(ic);
9343             break;
9344             
9345         case SEND:
9346             addSet(&_G.sendSet,ic);
9347             break;
9348
9349         default :
9350             ic = ic;
9351         }
9352     }
9353     
9354
9355     /* now we are ready to call the 
9356        peep hole optimizer */
9357     if (!options.nopeep) {
9358       printf("peep hole optimizing\n");
9359         peepHole (&lineHead);
9360     }
9361     /* now do the actual printing */
9362     printLine (lineHead,codeOutFile);
9363
9364     printf("printing pBlock\n\n");
9365     printpBlock(stdout,pb);
9366
9367     return;
9368 }