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