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