fixed bug #485513, although a warning should be thrown for non-constant initializers
[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 /* genCmp :- greater or less than comparison                       */
3486 /*-----------------------------------------------------------------*/
3487 static void genCmp (operand *left,operand *right,
3488                     operand *result, iCode *ifx, int sign)
3489 {
3490   int size, offset = 0 ;
3491   unsigned long lit = 0L,i = 0;
3492   resolvedIfx rIfx;
3493
3494   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3495   if(ifx) {
3496   DEBUGpic14_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
3497   DEBUGpic14_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
3498   }
3499
3500   resolveIfx(&rIfx,ifx);
3501
3502   /* if left & right are bit variables */
3503   if (AOP_TYPE(left) == AOP_CRY &&
3504       AOP_TYPE(right) == AOP_CRY ) {
3505     pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3506     pic14_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3507   } else {
3508     /* subtract right from left if at the
3509        end the carry flag is set then we know that
3510        left is greater than right */
3511     size = max(AOP_SIZE(left),AOP_SIZE(right));
3512
3513     /* if unsigned char cmp with lit, do cjne left,#right,zz */
3514     if((size == 1) && !sign &&
3515        (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
3516       symbol *lbl  = newiTempLabel(NULL);
3517       pic14_emitcode("cjne","%s,%s,%05d_DS_",
3518                aopGet(AOP(left),offset,FALSE,FALSE),
3519                aopGet(AOP(right),offset,FALSE,FALSE),
3520                lbl->key+100);
3521       pic14_emitcode("","%05d_DS_:",lbl->key+100);
3522     } else {
3523
3524       symbol *lbl  = newiTempLabel(NULL);
3525       int flag;
3526       symbol *truelbl  = newiTempLabel(NULL);
3527
3528
3529       if(AOP_TYPE(right) == AOP_LIT) {
3530
3531         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3532
3533         DEBUGpic14_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
3534
3535
3536
3537         if(lit == 0 && sign == 0) {
3538           /* no need to compare to 0...*/
3539           if(ifx) ifx->generated = 1;
3540           return;
3541
3542         }
3543         size--;
3544
3545         if(size == 0) {
3546           i = (lit >> (size*8)) & 0xff;
3547           DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
3548         
3549           switch(i) {
3550           case 0:
3551             if(sign) 
3552               genSkipCond(&rIfx,left,0,7);
3553             break;
3554           default:
3555             emitpcode(POC_MOVFW, popGet(AOP(left),size));
3556
3557             i = ((0-i) & 0xff);
3558             if(sign) {
3559               emitpcode(POC_ADDLW, popGetLit(0x80));
3560               emitpcode(POC_ADDLW, popGetLit(i^0x80));
3561             } else {
3562               emitpcode(POC_ADDLW, popGetLit(i));
3563             }
3564             genSkipc(&rIfx);
3565           }
3566
3567           if(ifx) ifx->generated = 1;
3568           return;
3569         }
3570
3571
3572
3573
3574         DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
3575         
3576         flag=1;
3577         size++;
3578         while(size--) {
3579           i = (lit >> (size*8)) & 0xff;
3580           if(sign && flag) {
3581             /* handle the first byte differently in signed compares */
3582
3583               emitpcode(POC_MOVFW, popGet(AOP(left),size));
3584               emitpcode(POC_ADDLW, popGetLit(0x80));
3585               emitpcode(POC_ADDLW, popGetLit(((-i)&0xff) ^ 0x80));
3586               genSkipc(&rIfx);
3587               emitSKPZ;
3588               emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3589
3590             flag=0;
3591           } else {
3592
3593             emitpcode(POC_MOVLW, popGetLit(i));
3594             emitpcode(POC_SUBFW, popGet(AOP(left),size));
3595             if(size) {
3596               emitSKPZ;
3597               emitpcode(POC_GOTO,  popGetLabel(lbl->key));
3598             }
3599           }
3600         }
3601         emitpLabel(lbl->key);
3602         genSkipc(&rIfx);
3603         if(sign)
3604           emitpLabel(truelbl->key);
3605
3606         if(ifx) ifx->generated = 1;
3607         return;
3608
3609
3610       }
3611
3612       if(AOP_TYPE(left) == AOP_LIT) {
3613         //symbol *lbl = newiTempLabel(NULL);
3614
3615         lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
3616
3617         DEBUGpic14_emitcode(";left lit","lit = %d,sign=%d",lit,sign);
3618
3619         /* Special cases */
3620         if((lit == 0)&& (sign==0)) {
3621
3622           size--;
3623           emitpcode(POC_MOVFW, popGet(AOP(right),size));
3624           while(size) 
3625             emitpcode(POC_IORFW, popGet(AOP(right),--size));
3626           genSkipz2(&rIfx);
3627           if(ifx) ifx->generated = 1;
3628           return;
3629         }
3630
3631         if(size==1) {
3632           if(sign) {
3633             if((lit+1)&0xff) {
3634               emitpcode(POC_MOVFW, popGet(AOP(right),0));
3635               emitpcode(POC_ADDLW, popGetLit(0x80));
3636               emitpcode(POC_ADDLW, popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
3637               rIfx.condition ^= 1;
3638               genSkipc(&rIfx);
3639             } else {
3640               genSkipCond(&rIfx,right,0,7);
3641             }
3642             
3643           } else {
3644             if(lit & 0xff) {
3645               emitpcode(POC_MOVLW, popGetLit((lit+1) & 0xff));
3646               emitpcode(POC_SUBFW, popGet(AOP(right),0));
3647               DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3648               rIfx.condition ^= 1;
3649               genSkipc(&rIfx);
3650             } else { 
3651               emitpcode(POC_MOVFW, popGet(AOP(right),0));
3652               genSkipz2(&rIfx);
3653             }
3654           }
3655         } else {
3656
3657           flag = 1;
3658           while(size--) {
3659             i = (lit >> (size*8)) & 0xff;
3660
3661             if(flag && sign) {
3662               /* Handle first byte of compare differently */
3663
3664               DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3665
3666               if(i) {
3667                 emitpcode(POC_MOVFW, popGet(AOP(right),size));
3668                 emitpcode(POC_ADDLW, popGetLit(0x80));
3669                 emitpcode(POC_SUBLW, popGetLit( (i & 0xff) ^ 0x80));
3670                 //rIfx.condition ^= 1;
3671                 genSkipc(&rIfx);
3672                 emitSKPZ;
3673                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3674               } else {
3675                 rIfx.condition ^= 1;
3676                 genSkipCond(&rIfx,right,size,7);
3677                 rIfx.condition ^= 1;
3678               }
3679
3680               flag = 0;
3681             } else {
3682
3683               if(size) {
3684                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3685                 emitpcode(POC_MOVLW, popGetLit(i&0xff));
3686                 emitpcode(POC_SUBFW, popGet(AOP(right),size));
3687                 emitSKPZ;
3688                 emitpcode(POC_GOTO,  popGetLabel(lbl->key));
3689               } else {
3690               DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3691                 emitpcode(POC_MOVLW, popGetLit((i+1)&0xff));
3692                 emitpcode(POC_SUBFW, popGet(AOP(right),size));
3693
3694               }
3695             }
3696           }
3697
3698           DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3699
3700           emitpLabel(lbl->key);
3701
3702           rIfx.condition ^= 1;
3703           genSkipc(&rIfx);
3704
3705         }
3706         if(sign)
3707           emitpLabel(truelbl->key);
3708         if(ifx) ifx->generated = 1;
3709         return;
3710       }
3711
3712       /* Compare two variables */
3713
3714       DEBUGpic14_emitcode(";sign","%d",sign);
3715
3716       size--;
3717       if(sign) {
3718         /* Sigh. thus sucks... */
3719         if(size) {
3720           emitpcode(POC_MOVFW, popGet(AOP(left),size));
3721           emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3722           emitpcode(POC_MOVLW, popGetLit(0x80));
3723           emitpcode(POC_XORWF, popRegFromIdx(Gstack_base_addr));
3724           emitpcode(POC_XORFW, popGet(AOP(right),size));
3725           emitpcode(POC_SUBFW, popRegFromIdx(Gstack_base_addr));
3726         } else {
3727           /* Signed char comparison */
3728           /* Special thanks to Nikolai Golovchenko for this snippet */
3729           emitpcode(POC_MOVFW, popGet(AOP(right),0));
3730           emitpcode(POC_SUBFW, popGet(AOP(left),0));
3731           emitpcode(POC_RRFW,  popGet(AOP(left),0)); /* could be any register */
3732           emitpcode(POC_XORFW, popGet(AOP(left),0));
3733           emitpcode(POC_XORFW, popGet(AOP(right),0));
3734           emitpcode(POC_ADDLW, popGetLit(0x80));
3735
3736           DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3737           genSkipc(&rIfx);
3738           
3739           if(ifx) ifx->generated = 1;
3740           return;
3741         }
3742
3743       } else {
3744
3745         emitpcode(POC_MOVFW, popGet(AOP(right),size));
3746         emitpcode(POC_SUBFW, popGet(AOP(left),size));
3747       }
3748
3749
3750       /* The rest of the bytes of a multi-byte compare */
3751       while (size) {
3752
3753         emitSKPZ;
3754         emitpcode(POC_GOTO,  popGetLabel(lbl->key));
3755         size--;
3756
3757         emitpcode(POC_MOVFW, popGet(AOP(right),size));
3758         emitpcode(POC_SUBFW, popGet(AOP(left),size));
3759
3760
3761       }
3762
3763       emitpLabel(lbl->key);
3764
3765       DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3766       genSkipc(&rIfx);
3767       if(ifx) ifx->generated = 1;
3768       return;
3769
3770     }
3771   }
3772
3773   //release:
3774   if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
3775     pic14_outBitC(result);
3776   } else {
3777     /* if the result is used in the next
3778        ifx conditional branch then generate
3779        code a little differently */
3780     if (ifx )
3781       genIfxJump (ifx,"c");
3782     else
3783       pic14_outBitC(result);
3784     /* leave the result in acc */
3785   }
3786
3787 }
3788
3789 /*-----------------------------------------------------------------*/
3790 /* genCmpGt :- greater than comparison                             */
3791 /*-----------------------------------------------------------------*/
3792 static void genCmpGt (iCode *ic, iCode *ifx)
3793 {
3794     operand *left, *right, *result;
3795     sym_link *letype , *retype;
3796     int sign ;
3797
3798     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3799     left = IC_LEFT(ic);
3800     right= IC_RIGHT(ic);
3801     result = IC_RESULT(ic);
3802
3803     letype = getSpec(operandType(left));
3804     retype =getSpec(operandType(right));
3805     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3806     /* assign the amsops */
3807     aopOp (left,ic,FALSE);
3808     aopOp (right,ic,FALSE);
3809     aopOp (result,ic,TRUE);
3810
3811     genCmp(right, left, result, ifx, sign);
3812
3813     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3814     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3815     freeAsmop(result,NULL,ic,TRUE); 
3816 }
3817
3818 /*-----------------------------------------------------------------*/
3819 /* genCmpLt - less than comparisons                                */
3820 /*-----------------------------------------------------------------*/
3821 static void genCmpLt (iCode *ic, iCode *ifx)
3822 {
3823     operand *left, *right, *result;
3824     sym_link *letype , *retype;
3825     int sign ;
3826
3827     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3828     left = IC_LEFT(ic);
3829     right= IC_RIGHT(ic);
3830     result = IC_RESULT(ic);
3831
3832     letype = getSpec(operandType(left));
3833     retype =getSpec(operandType(right));
3834     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3835
3836     /* assign the amsops */
3837     aopOp (left,ic,FALSE);
3838     aopOp (right,ic,FALSE);
3839     aopOp (result,ic,TRUE);
3840
3841     genCmp(left, right, result, ifx, sign);
3842
3843     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3844     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3845     freeAsmop(result,NULL,ic,TRUE); 
3846 }
3847
3848 /*-----------------------------------------------------------------*/
3849 /* genc16bit2lit - compare a 16 bit value to a literal             */
3850 /*-----------------------------------------------------------------*/
3851 static void genc16bit2lit(operand *op, int lit, int offset)
3852 {
3853   int i;
3854
3855   DEBUGpic14_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
3856   if( (lit&0xff) == 0) 
3857     i=1;
3858   else
3859     i=0;
3860
3861   switch( BYTEofLONG(lit,i)) { 
3862   case 0:
3863     emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
3864     break;
3865   case 1:
3866     emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
3867     break;
3868   case 0xff:
3869     emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
3870     break;
3871   default:
3872     emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
3873     emitpcode(POC_XORLW,popGetLit(BYTEofLONG(lit,i)));
3874   }
3875
3876   i ^= 1;
3877
3878   switch( BYTEofLONG(lit,i)) { 
3879   case 0:
3880     emitpcode(POC_IORFW,popGet(AOP(op),offset+i));
3881     break;
3882   case 1:
3883     emitSKPNZ;
3884     emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
3885     break;
3886   case 0xff:
3887     emitSKPNZ;
3888     emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
3889     break;
3890   default:
3891     emitpcode(POC_MOVLW,popGetLit(BYTEofLONG(lit,i)));
3892     emitSKPNZ;
3893     emitpcode(POC_XORFW,popGet(AOP(op),offset+i));
3894
3895   }
3896
3897 }
3898
3899 /*-----------------------------------------------------------------*/
3900 /* gencjneshort - compare and jump if not equal                    */
3901 /*-----------------------------------------------------------------*/
3902 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
3903 {
3904   int size = max(AOP_SIZE(left),AOP_SIZE(right));
3905   int offset = 0;
3906   resolvedIfx rIfx;
3907   symbol *lbl;
3908
3909   unsigned long lit = 0L;
3910   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3911   DEBUGpic14_AopType(__LINE__,left,right,NULL);
3912
3913   resolveIfx(&rIfx,ifx);
3914   lbl =  newiTempLabel(NULL);
3915
3916
3917   /* if the left side is a literal or 
3918      if the right is in a pointer register and left 
3919      is not */
3920   if ((AOP_TYPE(left) == AOP_LIT) || 
3921       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
3922     operand *t = right;
3923     right = left;
3924     left = t;
3925   }
3926   if(AOP_TYPE(right) == AOP_LIT)
3927     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3928
3929   /* if the right side is a literal then anything goes */
3930   if (AOP_TYPE(right) == AOP_LIT &&
3931       AOP_TYPE(left) != AOP_DIR ) {
3932     switch(size) {
3933     case 2:
3934       genc16bit2lit(left, lit, 0);
3935       emitSKPNZ;
3936       emitpcode(POC_GOTO,popGetLabel(lbl->key));
3937       break;
3938     default:
3939       while (size--) {
3940         if(lit & 0xff) {
3941           emitpcode(POC_MOVFW,popGet(AOP(left),offset));
3942           emitpcode(POC_XORLW,popGetLit(lit & 0xff));
3943         } else {
3944           emitpcode(POC_MOVF,popGet(AOP(left),offset));
3945         }
3946
3947         emitSKPNZ;
3948         emitpcode(POC_GOTO,popGetLabel(lbl->key));
3949         offset++;
3950         lit >>= 8;
3951       }
3952       break;
3953     }
3954   }
3955
3956   /* if the right side is in a register or in direct space or
3957      if the left is a pointer register & right is not */    
3958   else if (AOP_TYPE(right) == AOP_REG ||
3959            AOP_TYPE(right) == AOP_DIR || 
3960            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
3961            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
3962     switch(size) {
3963     case 2:
3964       genc16bit2lit(left, lit, 0);
3965       emitSKPNZ;
3966       emitpcode(POC_GOTO,popGetLabel(lbl->key));
3967       break;
3968     default:
3969       while (size--) {
3970         int emit_skip=1;
3971         if((AOP_TYPE(left) == AOP_DIR) && 
3972            ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
3973
3974           emitpcode(POC_MOVFW,popGet(AOP(left),offset));
3975           emitpcode(POC_XORFW,popGet(AOP(right),offset));
3976
3977         } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
3978             
3979           switch (lit & 0xff) {
3980           case 0:
3981             emitpcode(POC_MOVFW,popGet(AOP(left),offset));
3982             break;
3983           case 1:
3984             emitpcode(POC_DECFSZ,popGet(AOP(left),offset));
3985             emitpcode(POC_GOTO,popGetLabel(lbl->key));
3986             emit_skip=0;
3987             break;
3988           case 0xff:
3989             emitpcode(POC_INCFSZ,popGet(AOP(left),offset));
3990             emitpcode(POC_GOTO,popGetLabel(lbl->key));
3991             emit_skip=0;
3992             break;
3993           default:
3994             emitpcode(POC_MOVFW,popGet(AOP(left),offset));
3995             emitpcode(POC_XORLW,popGetLit(lit & 0xff));
3996           }
3997           lit >>= 8;
3998
3999         } else {
4000           emitpcode(POC_MOVF,popGet(AOP(left),offset));
4001         }
4002         if(emit_skip) {
4003           if(AOP_TYPE(result) == AOP_CRY) {
4004             pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
4005             if(rIfx.condition)
4006               emitSKPNZ;
4007             else
4008               emitSKPZ;
4009             emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4010           } else {
4011             /* fix me. probably need to check result size too */
4012             emitpcode(POC_CLRF,popGet(AOP(result),0));
4013             if(rIfx.condition)
4014               emitSKPNZ;
4015             else
4016               emitSKPZ;
4017             emitpcode(POC_INCF,popGet(AOP(result),0));
4018           }
4019           if(ifx)
4020             ifx->generated=1;
4021         }
4022         emit_skip++;
4023         offset++;
4024       }
4025       break;
4026     }
4027   } else if(AOP_TYPE(right) == AOP_REG &&
4028             AOP_TYPE(left) != AOP_DIR){
4029
4030     while(size--) {
4031       emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4032       emitpcode(POC_XORFW,popGet(AOP(right),offset));
4033       pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
4034       if(rIfx.condition)
4035         emitSKPNZ;
4036       else
4037         emitSKPZ;
4038       emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4039       offset++;
4040     }
4041       
4042   }else{
4043     /* right is a pointer reg need both a & b */
4044     while(size--) {
4045       char *l = aopGet(AOP(left),offset,FALSE,FALSE);
4046       if(strcmp(l,"b"))
4047         pic14_emitcode("mov","b,%s",l);
4048       MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4049       pic14_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
4050       offset++;
4051     }
4052   }
4053   emitpLabel(lbl->key);
4054
4055   if(ifx)
4056     ifx->generated = 1;
4057 }
4058
4059 #if 0
4060 /*-----------------------------------------------------------------*/
4061 /* gencjne - compare and jump if not equal                         */
4062 /*-----------------------------------------------------------------*/
4063 static void gencjne(operand *left, operand *right, iCode *ifx)
4064 {
4065     symbol *tlbl  = newiTempLabel(NULL);
4066
4067     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4068     gencjneshort(left, right, lbl);
4069
4070     pic14_emitcode("mov","a,%s",one);
4071     pic14_emitcode("sjmp","%05d_DS_",tlbl->key+100);
4072     pic14_emitcode("","%05d_DS_:",lbl->key+100);
4073     pic14_emitcode("clr","a");
4074     pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4075
4076     emitpLabel(lbl->key);
4077     emitpLabel(tlbl->key);
4078
4079 }
4080 #endif
4081
4082 /*-----------------------------------------------------------------*/
4083 /* genCmpEq - generates code for equal to                          */
4084 /*-----------------------------------------------------------------*/
4085 static void genCmpEq (iCode *ic, iCode *ifx)
4086 {
4087     operand *left, *right, *result;
4088     unsigned long lit = 0L;
4089     int size,offset=0;
4090
4091     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4092
4093     if(ifx)
4094       DEBUGpic14_emitcode ("; ifx is non-null","");
4095     else
4096       DEBUGpic14_emitcode ("; ifx is null","");
4097
4098     aopOp((left=IC_LEFT(ic)),ic,FALSE);
4099     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4100     aopOp((result=IC_RESULT(ic)),ic,TRUE);
4101
4102     size = max(AOP_SIZE(left),AOP_SIZE(right));
4103
4104     DEBUGpic14_AopType(__LINE__,left,right,result);
4105
4106     /* if literal, literal on the right or 
4107     if the right is in a pointer register and left 
4108     is not */
4109     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
4110         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4111         operand *t = IC_RIGHT(ic);
4112         IC_RIGHT(ic) = IC_LEFT(ic);
4113         IC_LEFT(ic) = t;
4114     }
4115
4116     if(ifx && !AOP_SIZE(result)){
4117         symbol *tlbl;
4118         /* if they are both bit variables */
4119         if (AOP_TYPE(left) == AOP_CRY &&
4120             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4121             if(AOP_TYPE(right) == AOP_LIT){
4122                 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4123                 if(lit == 0L){
4124                     pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4125                     pic14_emitcode("cpl","c");
4126                 } else if(lit == 1L) {
4127                     pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4128                 } else {
4129                     pic14_emitcode("clr","c");
4130                 }
4131                 /* AOP_TYPE(right) == AOP_CRY */
4132             } else {
4133                 symbol *lbl = newiTempLabel(NULL);
4134                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4135                 pic14_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4136                 pic14_emitcode("cpl","c");
4137                 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
4138             }
4139             /* if true label then we jump if condition
4140             supplied is true */
4141             tlbl = newiTempLabel(NULL);
4142             if ( IC_TRUE(ifx) ) {
4143                 pic14_emitcode("jnc","%05d_DS_",tlbl->key+100);
4144                 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
4145             } else {
4146                 pic14_emitcode("jc","%05d_DS_",tlbl->key+100);
4147                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
4148             }
4149             pic14_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
4150         } else {
4151
4152           /* They're not both bit variables. Is the right a literal? */
4153           if(AOP_TYPE(right) == AOP_LIT) {
4154             lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4155             
4156
4157             switch(size) {
4158
4159             case 1:
4160               switch(lit & 0xff) {
4161               case 1:
4162                 if ( IC_TRUE(ifx) ) {
4163                   emitpcode(POC_DECFW,popGet(AOP(left),offset));
4164                   emitSKPNZ;
4165                   emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4166                 } else {
4167                   emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
4168                   emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4169                 }
4170                 break;
4171               case 0xff:
4172                 if ( IC_TRUE(ifx) ) {
4173                   emitpcode(POC_INCFW,popGet(AOP(left),offset));
4174                   emitSKPNZ;
4175                   emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4176                 } else {
4177                   emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4178                   emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4179                 }
4180                 break;
4181               default:
4182                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4183                 if(lit)
4184                   emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4185                 genSkip(ifx,'z');
4186               }
4187
4188
4189               /* end of size == 1 */
4190               break;
4191               
4192             case 2:
4193               genc16bit2lit(left,lit,offset);
4194               genSkip(ifx,'z');
4195               break;
4196               /* end of size == 2 */
4197
4198             default:
4199               /* size is 4 */
4200               if(lit==0) {
4201                 emitpcode(POC_MOVFW,popGet(AOP(left),0));
4202                 emitpcode(POC_IORFW,popGet(AOP(left),1));
4203                 emitpcode(POC_IORFW,popGet(AOP(left),2));
4204                 emitpcode(POC_IORFW,popGet(AOP(left),3));
4205
4206               } else {
4207
4208                 /* search for patterns that can be optimized */
4209
4210                 genc16bit2lit(left,lit,0);
4211                 lit >>= 16;
4212                 if(lit) {
4213                   genSkipz(ifx,IC_TRUE(ifx) == NULL);
4214                   //genSkip(ifx,'z');
4215                   genc16bit2lit(left,lit,2);
4216                 } else {
4217                   emitpcode(POC_IORFW,popGet(AOP(left),2));
4218                   emitpcode(POC_IORFW,popGet(AOP(left),3));
4219
4220                 }
4221                 
4222               }
4223
4224               genSkip(ifx,'z');
4225             }
4226           
4227             ifx->generated = 1;
4228             goto release ;
4229             
4230
4231           } else if(AOP_TYPE(right) == AOP_CRY ) {
4232             /* we know the left is not a bit, but that the right is */
4233             emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4234             emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
4235                       popGet(AOP(right),offset));
4236             emitpcode(POC_XORLW,popGetLit(1));
4237
4238             /* if the two are equal, then W will be 0 and the Z bit is set
4239              * we could test Z now, or go ahead and check the high order bytes if
4240              * the variable we're comparing is larger than a byte. */
4241
4242             while(--size)
4243               emitpcode(POC_IORFW,popGet(AOP(left),offset));
4244
4245             if ( IC_TRUE(ifx) ) {
4246               emitSKPNZ;
4247               emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4248               pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4249             } else {
4250               emitSKPZ;
4251               emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4252               pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4253             }
4254
4255           } else {
4256             /* They're both variables that are larger than bits */
4257             int s = size;
4258
4259             tlbl = newiTempLabel(NULL);
4260
4261             while(size--) {
4262               emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4263               emitpcode(POC_XORFW,popGet(AOP(right),offset));
4264
4265               if ( IC_TRUE(ifx) ) {
4266                 if(size) {
4267                   emitSKPZ;
4268                   emitpcode(POC_GOTO,popGetLabel(tlbl->key));
4269                   pic14_emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset);
4270                 } else {
4271                   emitSKPNZ;
4272                   emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4273                   pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4274                 }
4275               } else {
4276                 emitSKPZ;
4277                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4278                 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4279               }
4280               offset++;
4281             }
4282             if(s>1 && IC_TRUE(ifx)) {
4283               emitpLabel(tlbl->key);
4284               pic14_emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);                
4285             }
4286           }
4287         }
4288         /* mark the icode as generated */
4289         ifx->generated = 1;
4290         goto release ;
4291     }
4292
4293     /* if they are both bit variables */
4294     if (AOP_TYPE(left) == AOP_CRY &&
4295         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4296         if(AOP_TYPE(right) == AOP_LIT){
4297             unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4298             if(lit == 0L){
4299                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4300                 pic14_emitcode("cpl","c");
4301             } else if(lit == 1L) {
4302                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4303             } else {
4304                 pic14_emitcode("clr","c");
4305             }
4306             /* AOP_TYPE(right) == AOP_CRY */
4307         } else {
4308             symbol *lbl = newiTempLabel(NULL);
4309             pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4310             pic14_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4311             pic14_emitcode("cpl","c");
4312             pic14_emitcode("","%05d_DS_:",(lbl->key+100));
4313         }
4314         /* c = 1 if egal */
4315         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
4316             pic14_outBitC(result);
4317             goto release ;
4318         }
4319         if (ifx) {
4320             genIfxJump (ifx,"c");
4321             goto release ;
4322         }
4323         /* if the result is used in an arithmetic operation
4324         then put the result in place */
4325         pic14_outBitC(result);
4326     } else {
4327       
4328       gencjne(left,right,result,ifx);
4329 /*
4330       if(ifx) 
4331         gencjne(left,right,newiTempLabel(NULL));
4332       else {
4333         if(IC_TRUE(ifx)->key)
4334           gencjne(left,right,IC_TRUE(ifx)->key);
4335         else
4336           gencjne(left,right,IC_FALSE(ifx)->key);
4337         ifx->generated = 1;
4338         goto release ;
4339       }
4340       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4341         aopPut(AOP(result),"a",0);
4342         goto release ;
4343       }
4344
4345       if (ifx) {
4346         genIfxJump (ifx,"a");
4347         goto release ;
4348       }
4349 */
4350       /* if the result is used in an arithmetic operation
4351          then put the result in place */
4352 /*
4353       if (AOP_TYPE(result) != AOP_CRY) 
4354         pic14_outAcc(result);
4355 */
4356       /* leave the result in acc */
4357     }
4358
4359 release:
4360     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4361     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4362     freeAsmop(result,NULL,ic,TRUE);
4363 }
4364
4365 /*-----------------------------------------------------------------*/
4366 /* ifxForOp - returns the icode containing the ifx for operand     */
4367 /*-----------------------------------------------------------------*/
4368 static iCode *ifxForOp ( operand *op, iCode *ic )
4369 {
4370     /* if true symbol then needs to be assigned */
4371     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4372     if (IS_TRUE_SYMOP(op))
4373         return NULL ;
4374
4375     /* if this has register type condition and
4376     the next instruction is ifx with the same operand
4377     and live to of the operand is upto the ifx only then */
4378     if (ic->next &&
4379         ic->next->op == IFX &&
4380         IC_COND(ic->next)->key == op->key &&
4381         OP_SYMBOL(op)->liveTo <= ic->next->seq )
4382         return ic->next;
4383
4384     if (ic->next &&
4385         ic->next->op == IFX &&
4386         IC_COND(ic->next)->key == op->key) {
4387       DEBUGpic14_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
4388       return ic->next;
4389     }
4390
4391     DEBUGpic14_emitcode ("; NULL :(","%d",__LINE__);
4392     if (ic->next &&
4393         ic->next->op == IFX)
4394       DEBUGpic14_emitcode ("; ic-next"," is an IFX");
4395
4396     if (ic->next &&
4397         ic->next->op == IFX &&
4398         IC_COND(ic->next)->key == op->key) {
4399       DEBUGpic14_emitcode ("; "," key is okay");
4400       DEBUGpic14_emitcode ("; "," key liveTo %d, next->seq = %d",
4401                            OP_SYMBOL(op)->liveTo,
4402                            ic->next->seq);
4403     }
4404
4405
4406     return NULL;
4407 }
4408 /*-----------------------------------------------------------------*/
4409 /* genAndOp - for && operation                                     */
4410 /*-----------------------------------------------------------------*/
4411 static void genAndOp (iCode *ic)
4412 {
4413     operand *left,*right, *result;
4414     symbol *tlbl;
4415
4416     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4417     /* note here that && operations that are in an
4418     if statement are taken away by backPatchLabels
4419     only those used in arthmetic operations remain */
4420     aopOp((left=IC_LEFT(ic)),ic,FALSE);
4421     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4422     aopOp((result=IC_RESULT(ic)),ic,FALSE);
4423
4424     /* if both are bit variables */
4425     if (AOP_TYPE(left) == AOP_CRY &&
4426         AOP_TYPE(right) == AOP_CRY ) {
4427         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4428         pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
4429         pic14_outBitC(result);
4430     } else {
4431         tlbl = newiTempLabel(NULL);
4432         pic14_toBoolean(left);    
4433         pic14_emitcode("jz","%05d_DS_",tlbl->key+100);
4434         pic14_toBoolean(right);
4435         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4436         pic14_outBitAcc(result);
4437     }
4438
4439     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4440     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4441     freeAsmop(result,NULL,ic,TRUE);
4442 }
4443
4444
4445 /*-----------------------------------------------------------------*/
4446 /* genOrOp - for || operation                                      */
4447 /*-----------------------------------------------------------------*/
4448 /*
4449   tsd pic port -
4450   modified this code, but it doesn't appear to ever get called
4451 */
4452
4453 static void genOrOp (iCode *ic)
4454 {
4455     operand *left,*right, *result;
4456     symbol *tlbl;
4457
4458     /* note here that || operations that are in an
4459     if statement are taken away by backPatchLabels
4460     only those used in arthmetic operations remain */
4461     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4462     aopOp((left=IC_LEFT(ic)),ic,FALSE);
4463     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4464     aopOp((result=IC_RESULT(ic)),ic,FALSE);
4465
4466     DEBUGpic14_AopType(__LINE__,left,right,result);
4467
4468     /* if both are bit variables */
4469     if (AOP_TYPE(left) == AOP_CRY &&
4470         AOP_TYPE(right) == AOP_CRY ) {
4471       pic14_emitcode("clrc","");
4472       pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
4473                AOP(left)->aopu.aop_dir,
4474                AOP(left)->aopu.aop_dir);
4475       pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
4476                AOP(right)->aopu.aop_dir,
4477                AOP(right)->aopu.aop_dir);
4478       pic14_emitcode("setc","");
4479
4480     } else {
4481         tlbl = newiTempLabel(NULL);
4482         pic14_toBoolean(left);
4483         emitSKPZ;
4484         pic14_emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
4485         pic14_toBoolean(right);
4486         pic14_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
4487
4488         pic14_outBitAcc(result);
4489     }
4490
4491     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4492     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4493     freeAsmop(result,NULL,ic,TRUE);            
4494 }
4495
4496 /*-----------------------------------------------------------------*/
4497 /* isLiteralBit - test if lit == 2^n                               */
4498 /*-----------------------------------------------------------------*/
4499 static int isLiteralBit(unsigned long lit)
4500 {
4501     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
4502     0x100L,0x200L,0x400L,0x800L,
4503     0x1000L,0x2000L,0x4000L,0x8000L,
4504     0x10000L,0x20000L,0x40000L,0x80000L,
4505     0x100000L,0x200000L,0x400000L,0x800000L,
4506     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
4507     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
4508     int idx;
4509     
4510     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4511     for(idx = 0; idx < 32; idx++)
4512         if(lit == pw[idx])
4513             return idx+1;
4514     return 0;
4515 }
4516
4517 /*-----------------------------------------------------------------*/
4518 /* continueIfTrue -                                                */
4519 /*-----------------------------------------------------------------*/
4520 static void continueIfTrue (iCode *ic)
4521 {
4522     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4523     if(IC_TRUE(ic))
4524         pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
4525     ic->generated = 1;
4526 }
4527
4528 /*-----------------------------------------------------------------*/
4529 /* jmpIfTrue -                                                     */
4530 /*-----------------------------------------------------------------*/
4531 static void jumpIfTrue (iCode *ic)
4532 {
4533     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4534     if(!IC_TRUE(ic))
4535         pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
4536     ic->generated = 1;
4537 }
4538
4539 /*-----------------------------------------------------------------*/
4540 /* jmpTrueOrFalse -                                                */
4541 /*-----------------------------------------------------------------*/
4542 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
4543 {
4544     // ugly but optimized by peephole
4545     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4546     if(IC_TRUE(ic)){
4547         symbol *nlbl = newiTempLabel(NULL);
4548         pic14_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
4549         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4550         pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
4551         pic14_emitcode("","%05d_DS_:",nlbl->key+100);
4552     }
4553     else{
4554         pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
4555         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4556     }
4557     ic->generated = 1;
4558 }
4559
4560 /*-----------------------------------------------------------------*/
4561 /* genAnd  - code for and                                          */
4562 /*-----------------------------------------------------------------*/
4563 static void genAnd (iCode *ic, iCode *ifx)
4564 {
4565   operand *left, *right, *result;
4566   int size, offset=0;  
4567   unsigned long lit = 0L;
4568   int bytelit = 0;
4569   resolvedIfx rIfx;
4570
4571
4572   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4573   aopOp((left = IC_LEFT(ic)),ic,FALSE);
4574   aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4575   aopOp((result=IC_RESULT(ic)),ic,TRUE);
4576
4577   resolveIfx(&rIfx,ifx);
4578
4579   /* if left is a literal & right is not then exchange them */
4580   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4581       AOP_NEEDSACC(left)) {
4582     operand *tmp = right ;
4583     right = left;
4584     left = tmp;
4585   }
4586
4587   /* if result = right then exchange them */
4588   if(pic14_sameRegs(AOP(result),AOP(right))){
4589     operand *tmp = right ;
4590     right = left;
4591     left = tmp;
4592   }
4593
4594   /* if right is bit then exchange them */
4595   if (AOP_TYPE(right) == AOP_CRY &&
4596       AOP_TYPE(left) != AOP_CRY){
4597     operand *tmp = right ;
4598     right = left;
4599     left = tmp;
4600   }
4601   if(AOP_TYPE(right) == AOP_LIT)
4602     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4603
4604   size = AOP_SIZE(result);
4605
4606   DEBUGpic14_AopType(__LINE__,left,right,result);
4607
4608   // if(bit & yy)
4609   // result = bit & yy;
4610   if (AOP_TYPE(left) == AOP_CRY){
4611     // c = bit & literal;
4612     if(AOP_TYPE(right) == AOP_LIT){
4613       if(lit & 1) {
4614         if(size && pic14_sameRegs(AOP(result),AOP(left)))
4615           // no change
4616           goto release;
4617         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4618       } else {
4619         // bit(result) = 0;
4620         if(size && (AOP_TYPE(result) == AOP_CRY)){
4621           pic14_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
4622           goto release;
4623         }
4624         if((AOP_TYPE(result) == AOP_CRY) && ifx){
4625           jumpIfTrue(ifx);
4626           goto release;
4627         }
4628         pic14_emitcode("clr","c");
4629       }
4630     } else {
4631       if (AOP_TYPE(right) == AOP_CRY){
4632         // c = bit & bit;
4633         pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4634         pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4635       } else {
4636         // c = bit & val;
4637         MOVA(aopGet(AOP(right),0,FALSE,FALSE));
4638         // c = lsb
4639         pic14_emitcode("rrc","a");
4640         pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4641       }
4642     }
4643     // bit = c
4644     // val = c
4645     if(size)
4646       pic14_outBitC(result);
4647     // if(bit & ...)
4648     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4649       genIfxJump(ifx, "c");           
4650     goto release ;
4651   }
4652
4653   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
4654   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
4655   if((AOP_TYPE(right) == AOP_LIT) &&
4656      (AOP_TYPE(result) == AOP_CRY) &&
4657      (AOP_TYPE(left) != AOP_CRY)){
4658     int posbit = isLiteralBit(lit);
4659     /* left &  2^n */
4660     if(posbit){
4661       posbit--;
4662       //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
4663       // bit = left & 2^n
4664       if(size)
4665         pic14_emitcode("mov","c,acc.%d",posbit&0x07);
4666       // if(left &  2^n)
4667       else{
4668         if(ifx){
4669 /*
4670           if(IC_TRUE(ifx)) {
4671             emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
4672             emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
4673           } else {
4674             emitpcode(POC_BTFSS,newpCodeOpBit(aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
4675             emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
4676           }
4677 */
4678           emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
4679                     newpCodeOpBit(aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
4680           emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4681           
4682           ifx->generated = 1;
4683         }
4684         goto release;
4685       }
4686     } else {
4687       symbol *tlbl = newiTempLabel(NULL);
4688       int sizel = AOP_SIZE(left);
4689       if(size)
4690         pic14_emitcode("setb","c");
4691       while(sizel--){
4692         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
4693           MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
4694           // byte ==  2^n ?
4695           if((posbit = isLiteralBit(bytelit)) != 0)
4696             pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
4697           else{
4698             if(bytelit != 0x0FFL)
4699               pic14_emitcode("anl","a,%s",
4700                              aopGet(AOP(right),offset,FALSE,TRUE));
4701             pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
4702           }
4703         }
4704         offset++;
4705       }
4706       // bit = left & literal
4707       if(size){
4708         pic14_emitcode("clr","c");
4709         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4710       }
4711       // if(left & literal)
4712       else{
4713         if(ifx)
4714           jmpTrueOrFalse(ifx, tlbl);
4715         goto release ;
4716       }
4717     }
4718     pic14_outBitC(result);
4719     goto release ;
4720   }
4721
4722   /* if left is same as result */
4723   if(pic14_sameRegs(AOP(result),AOP(left))){
4724     int know_W = -1;
4725     for(;size--; offset++,lit>>=8) {
4726       if(AOP_TYPE(right) == AOP_LIT){
4727         switch(lit & 0xff) {
4728         case 0x00:
4729           /*  and'ing with 0 has clears the result */
4730           pic14_emitcode("clrf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
4731           emitpcode(POC_CLRF,popGet(AOP(result),offset));
4732           break;
4733         case 0xff:
4734           /* and'ing with 0xff is a nop when the result and left are the same */
4735           break;
4736
4737         default:
4738           {
4739             int p = my_powof2( (~lit) & 0xff );
4740             if(p>=0) {
4741               /* only one bit is set in the literal, so use a bcf instruction */
4742               pic14_emitcode("bcf","%s,%d",aopGet(AOP(left),offset,FALSE,TRUE),p);
4743               emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
4744
4745             } else {
4746               pic14_emitcode("movlw","0x%x", (lit & 0xff));
4747               pic14_emitcode("andwf","%s,f",aopGet(AOP(left),offset,FALSE,TRUE));
4748               if(know_W != (lit&0xff))
4749                 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
4750               know_W = lit &0xff;
4751               emitpcode(POC_ANDWF,popGet(AOP(left),offset));
4752             }
4753           }    
4754         }
4755       } else {
4756         if (AOP_TYPE(left) == AOP_ACC) {
4757           emitpcode(POC_ANDFW,popGet(AOP(right),offset));
4758         } else {                    
4759           emitpcode(POC_MOVFW,popGet(AOP(right),offset));
4760           emitpcode(POC_ANDWF,popGet(AOP(left),offset));
4761
4762         }
4763       }
4764     }
4765
4766   } else {
4767     // left & result in different registers
4768     if(AOP_TYPE(result) == AOP_CRY){
4769       // result = bit
4770       // if(size), result in bit
4771       // if(!size && ifx), conditional oper: if(left & right)
4772       symbol *tlbl = newiTempLabel(NULL);
4773       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
4774       if(size)
4775         pic14_emitcode("setb","c");
4776       while(sizer--){
4777         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4778         pic14_emitcode("anl","a,%s",
4779                        aopGet(AOP(left),offset,FALSE,FALSE));
4780         pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
4781         offset++;
4782       }
4783       if(size){
4784         CLRC;
4785         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4786         pic14_outBitC(result);
4787       } else if(ifx)
4788         jmpTrueOrFalse(ifx, tlbl);
4789     } else {
4790       for(;(size--);offset++) {
4791         // normal case
4792         // result = left & right
4793         if(AOP_TYPE(right) == AOP_LIT){
4794           int t = (lit >> (offset*8)) & 0x0FFL;
4795           switch(t) { 
4796           case 0x00:
4797             pic14_emitcode("clrf","%s",
4798                            aopGet(AOP(result),offset,FALSE,FALSE));
4799             emitpcode(POC_CLRF,popGet(AOP(result),offset));
4800             break;
4801           case 0xff:
4802             pic14_emitcode("movf","%s,w",
4803                            aopGet(AOP(left),offset,FALSE,FALSE));
4804             pic14_emitcode("movwf","%s",
4805                            aopGet(AOP(result),offset,FALSE,FALSE));
4806             emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4807             emitpcode(POC_MOVWF,popGet(AOP(result),offset));
4808             break;
4809           default:
4810             pic14_emitcode("movlw","0x%x",t);
4811             pic14_emitcode("andwf","%s,w",
4812                            aopGet(AOP(left),offset,FALSE,FALSE));
4813             pic14_emitcode("movwf","%s",
4814                            aopGet(AOP(result),offset,FALSE,FALSE));
4815               
4816             emitpcode(POC_MOVLW, popGetLit(t));
4817             emitpcode(POC_ANDFW,popGet(AOP(left),offset));
4818             emitpcode(POC_MOVWF,popGet(AOP(result),offset));
4819           }
4820           continue;
4821         }
4822
4823         if (AOP_TYPE(left) == AOP_ACC) {
4824           pic14_emitcode("andwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4825           emitpcode(POC_ANDFW,popGet(AOP(right),offset));
4826         } else {
4827           pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4828           pic14_emitcode("andwf","%s,w",
4829                          aopGet(AOP(left),offset,FALSE,FALSE));
4830           emitpcode(POC_MOVFW,popGet(AOP(right),offset));
4831           emitpcode(POC_ANDFW,popGet(AOP(left),offset));
4832         }
4833         pic14_emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
4834         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
4835       }
4836     }
4837   }
4838
4839   release :
4840     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4841   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4842   freeAsmop(result,NULL,ic,TRUE);     
4843 }
4844
4845 /*-----------------------------------------------------------------*/
4846 /* genOr  - code for or                                            */
4847 /*-----------------------------------------------------------------*/
4848 static void genOr (iCode *ic, iCode *ifx)
4849 {
4850     operand *left, *right, *result;
4851     int size, offset=0;
4852     unsigned long lit = 0L;
4853
4854     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4855
4856     aopOp((left = IC_LEFT(ic)),ic,FALSE);
4857     aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4858     aopOp((result=IC_RESULT(ic)),ic,TRUE);
4859
4860     DEBUGpic14_AopType(__LINE__,left,right,result);
4861
4862     /* if left is a literal & right is not then exchange them */
4863     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4864         AOP_NEEDSACC(left)) {
4865         operand *tmp = right ;
4866         right = left;
4867         left = tmp;
4868     }
4869
4870     /* if result = right then exchange them */
4871     if(pic14_sameRegs(AOP(result),AOP(right))){
4872         operand *tmp = right ;
4873         right = left;
4874         left = tmp;
4875     }
4876
4877     /* if right is bit then exchange them */
4878     if (AOP_TYPE(right) == AOP_CRY &&
4879         AOP_TYPE(left) != AOP_CRY){
4880         operand *tmp = right ;
4881         right = left;
4882         left = tmp;
4883     }
4884
4885     DEBUGpic14_AopType(__LINE__,left,right,result);
4886
4887     if(AOP_TYPE(right) == AOP_LIT)
4888         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4889
4890     size = AOP_SIZE(result);
4891
4892     // if(bit | yy)
4893     // xx = bit | yy;
4894     if (AOP_TYPE(left) == AOP_CRY){
4895         if(AOP_TYPE(right) == AOP_LIT){
4896             // c = bit & literal;
4897             if(lit){
4898                 // lit != 0 => result = 1
4899                 if(AOP_TYPE(result) == AOP_CRY){
4900                   if(size)
4901                     emitpcode(POC_BSF, popGet(AOP(result),0));
4902                   //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
4903                   //     AOP(result)->aopu.aop_dir,
4904                   //     AOP(result)->aopu.aop_dir);
4905                     else if(ifx)
4906                         continueIfTrue(ifx);
4907                     goto release;
4908                 }
4909             } else {
4910                 // lit == 0 => result = left
4911                 if(size && pic14_sameRegs(AOP(result),AOP(left)))
4912                     goto release;
4913                 pic14_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
4914             }
4915         } else {
4916             if (AOP_TYPE(right) == AOP_CRY){
4917               if(pic14_sameRegs(AOP(result),AOP(left))){
4918                 // c = bit | bit;
4919                 emitpcode(POC_BCF,   popGet(AOP(result),0));
4920                 emitpcode(POC_BTFSC, popGet(AOP(right),0));
4921                 emitpcode(POC_BSF,   popGet(AOP(result),0));
4922
4923                 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
4924                          AOP(result)->aopu.aop_dir,
4925                          AOP(result)->aopu.aop_dir);
4926                 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
4927                          AOP(right)->aopu.aop_dir,
4928                          AOP(right)->aopu.aop_dir);
4929                 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
4930                          AOP(result)->aopu.aop_dir,
4931                          AOP(result)->aopu.aop_dir);
4932               } else {
4933                 if( AOP_TYPE(result) == AOP_ACC) {
4934                   emitpcode(POC_MOVLW, popGetLit(0));
4935                   emitpcode(POC_BTFSS, popGet(AOP(right),0));
4936                   emitpcode(POC_BTFSC, popGet(AOP(left),0));
4937                   emitpcode(POC_MOVLW, popGetLit(1));
4938
4939                 } else {
4940
4941                   emitpcode(POC_BCF,   popGet(AOP(result),0));
4942                   emitpcode(POC_BTFSS, popGet(AOP(right),0));
4943                   emitpcode(POC_BTFSC, popGet(AOP(left),0));
4944                   emitpcode(POC_BSF,   popGet(AOP(result),0));
4945
4946                   pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
4947                                  AOP(result)->aopu.aop_dir,
4948                                  AOP(result)->aopu.aop_dir);
4949                   pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
4950                                  AOP(right)->aopu.aop_dir,
4951                                  AOP(right)->aopu.aop_dir);
4952                   pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
4953                                  AOP(left)->aopu.aop_dir,
4954                                  AOP(left)->aopu.aop_dir);
4955                   pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
4956                                  AOP(result)->aopu.aop_dir,
4957                                  AOP(result)->aopu.aop_dir);
4958                 }
4959               }
4960             } else {
4961                 // c = bit | val;
4962                 symbol *tlbl = newiTempLabel(NULL);
4963                 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
4964
4965
4966                 emitpcode(POC_BCF,   popGet(AOP(result),0));
4967                 if( AOP_TYPE(right) == AOP_ACC) {
4968                   emitpcode(POC_IORLW, popGetLit(0));
4969                   emitSKPNZ;
4970                   emitpcode(POC_BTFSC, popGet(AOP(left),0));
4971                   emitpcode(POC_BSF,   popGet(AOP(result),0));
4972                 }
4973
4974
4975
4976                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
4977                     pic14_emitcode(";XXX setb","c");
4978                 pic14_emitcode(";XXX jb","%s,%05d_DS_",
4979                          AOP(left)->aopu.aop_dir,tlbl->key+100);
4980                 pic14_toBoolean(right);
4981                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
4982                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4983                     jmpTrueOrFalse(ifx, tlbl);
4984                     goto release;
4985                 } else {
4986                     CLRC;
4987                     pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4988                 }
4989             }
4990         }
4991         // bit = c
4992         // val = c
4993         if(size)
4994             pic14_outBitC(result);
4995         // if(bit | ...)
4996         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4997             genIfxJump(ifx, "c");           
4998         goto release ;
4999     }
5000
5001     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5002     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5003     if((AOP_TYPE(right) == AOP_LIT) &&
5004        (AOP_TYPE(result) == AOP_CRY) &&
5005        (AOP_TYPE(left) != AOP_CRY)){
5006         if(lit){
5007           pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5008             // result = 1
5009             if(size)
5010                 pic14_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5011             else 
5012                 continueIfTrue(ifx);
5013             goto release;
5014         } else {
5015           pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5016             // lit = 0, result = boolean(left)
5017             if(size)
5018                 pic14_emitcode(";XXX setb","c");
5019             pic14_toBoolean(right);
5020             if(size){
5021                 symbol *tlbl = newiTempLabel(NULL);
5022                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5023                 CLRC;
5024                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5025             } else {
5026                 genIfxJump (ifx,"a");
5027                 goto release;
5028             }
5029         }
5030         pic14_outBitC(result);
5031         goto release ;
5032     }
5033
5034     /* if left is same as result */
5035     if(pic14_sameRegs(AOP(result),AOP(left))){
5036       int know_W = -1;
5037       for(;size--; offset++,lit>>=8) {
5038         if(AOP_TYPE(right) == AOP_LIT){
5039           if((lit & 0xff) == 0)
5040             /*  or'ing with 0 has no effect */
5041             continue;
5042           else {
5043             int p = my_powof2(lit & 0xff);
5044             if(p>=0) {
5045               /* only one bit is set in the literal, so use a bsf instruction */
5046               emitpcode(POC_BSF,
5047                         newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5048             } else {
5049               if(know_W != (lit & 0xff))
5050                 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5051               know_W = lit & 0xff;
5052               emitpcode(POC_IORWF, popGet(AOP(left),offset));
5053             }
5054                     
5055           }
5056         } else {
5057           if (AOP_TYPE(left) == AOP_ACC) {
5058             emitpcode(POC_IORFW,  popGet(AOP(right),offset));
5059             pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5060           } else {                  
5061             emitpcode(POC_MOVFW,  popGet(AOP(right),offset));
5062             emitpcode(POC_IORWF,  popGet(AOP(left),offset));
5063
5064             pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5065             pic14_emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
5066
5067           }
5068         }
5069       }
5070     } else {
5071         // left & result in different registers
5072         if(AOP_TYPE(result) == AOP_CRY){
5073             // result = bit
5074             // if(size), result in bit
5075             // if(!size && ifx), conditional oper: if(left | right)
5076             symbol *tlbl = newiTempLabel(NULL);
5077             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5078             pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5079
5080
5081             if(size)
5082                 pic14_emitcode(";XXX setb","c");
5083             while(sizer--){
5084                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5085                 pic14_emitcode(";XXX orl","a,%s",
5086                          aopGet(AOP(left),offset,FALSE,FALSE));
5087                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5088                 offset++;
5089             }
5090             if(size){
5091                 CLRC;
5092                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5093                 pic14_outBitC(result);
5094             } else if(ifx)
5095                 jmpTrueOrFalse(ifx, tlbl);
5096         } else for(;(size--);offset++){
5097           // normal case
5098           // result = left & right
5099           if(AOP_TYPE(right) == AOP_LIT){
5100             int t = (lit >> (offset*8)) & 0x0FFL;
5101             switch(t) { 
5102             case 0x00:
5103               emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
5104               emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
5105
5106               pic14_emitcode("movf","%s,w",
5107                        aopGet(AOP(left),offset,FALSE,FALSE));
5108               pic14_emitcode("movwf","%s",
5109                        aopGet(AOP(result),offset,FALSE,FALSE));
5110               break;
5111             default:
5112               emitpcode(POC_MOVLW,  popGetLit(t));
5113               emitpcode(POC_IORFW,  popGet(AOP(left),offset));
5114               emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
5115
5116               pic14_emitcode("movlw","0x%x",t);
5117               pic14_emitcode("iorwf","%s,w",
5118                        aopGet(AOP(left),offset,FALSE,FALSE));
5119               pic14_emitcode("movwf","%s",
5120                        aopGet(AOP(result),offset,FALSE,FALSE));
5121               
5122             }
5123             continue;
5124           }
5125
5126           // faster than result <- left, anl result,right
5127           // and better if result is SFR
5128           if (AOP_TYPE(left) == AOP_ACC) {
5129             emitpcode(POC_IORWF,  popGet(AOP(right),offset));
5130             pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5131           } else {
5132             emitpcode(POC_MOVFW,  popGet(AOP(right),offset));
5133             emitpcode(POC_IORFW,  popGet(AOP(left),offset));
5134
5135             pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5136             pic14_emitcode("iorwf","%s,w",
5137                      aopGet(AOP(left),offset,FALSE,FALSE));
5138           }
5139           emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
5140           pic14_emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5141         }
5142     }
5143
5144 release :
5145     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5146     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5147     freeAsmop(result,NULL,ic,TRUE);     
5148 }
5149
5150 /*-----------------------------------------------------------------*/
5151 /* genXor - code for xclusive or                                   */
5152 /*-----------------------------------------------------------------*/
5153 static void genXor (iCode *ic, iCode *ifx)
5154 {
5155   operand *left, *right, *result;
5156   int size, offset=0;
5157   unsigned long lit = 0L;
5158
5159   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5160
5161   aopOp((left = IC_LEFT(ic)),ic,FALSE);
5162   aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5163   aopOp((result=IC_RESULT(ic)),ic,TRUE);
5164
5165   /* if left is a literal & right is not ||
5166      if left needs acc & right does not */
5167   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5168       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
5169     operand *tmp = right ;
5170     right = left;
5171     left = tmp;
5172   }
5173
5174   /* if result = right then exchange them */
5175   if(pic14_sameRegs(AOP(result),AOP(right))){
5176     operand *tmp = right ;
5177     right = left;
5178     left = tmp;
5179   }
5180
5181   /* if right is bit then exchange them */
5182   if (AOP_TYPE(right) == AOP_CRY &&
5183       AOP_TYPE(left) != AOP_CRY){
5184     operand *tmp = right ;
5185     right = left;
5186     left = tmp;
5187   }
5188   if(AOP_TYPE(right) == AOP_LIT)
5189     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5190
5191   size = AOP_SIZE(result);
5192
5193   // if(bit ^ yy)
5194   // xx = bit ^ yy;
5195   if (AOP_TYPE(left) == AOP_CRY){
5196     if(AOP_TYPE(right) == AOP_LIT){
5197       // c = bit & literal;
5198       if(lit>>1){
5199         // lit>>1  != 0 => result = 1
5200         if(AOP_TYPE(result) == AOP_CRY){
5201           if(size)
5202             pic14_emitcode("setb","%s",AOP(result)->aopu.aop_dir);
5203           else if(ifx)
5204             continueIfTrue(ifx);
5205           goto release;
5206         }
5207         pic14_emitcode("setb","c");
5208       } else{
5209         // lit == (0 or 1)
5210         if(lit == 0){
5211           // lit == 0, result = left
5212           if(size && pic14_sameRegs(AOP(result),AOP(left)))
5213             goto release;
5214           pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5215         } else{
5216           // lit == 1, result = not(left)
5217           if(size && pic14_sameRegs(AOP(result),AOP(left))){
5218             pic14_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
5219             goto release;
5220           } else {
5221             pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5222             pic14_emitcode("cpl","c");
5223           }
5224         }
5225       }
5226
5227     } else {
5228       // right != literal
5229       symbol *tlbl = newiTempLabel(NULL);
5230       if (AOP_TYPE(right) == AOP_CRY){
5231         // c = bit ^ bit;
5232         pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5233       }
5234       else{
5235         int sizer = AOP_SIZE(right);
5236         // c = bit ^ val
5237         // if val>>1 != 0, result = 1
5238         pic14_emitcode("setb","c");
5239         while(sizer){
5240           MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
5241           if(sizer == 1)
5242             // test the msb of the lsb
5243             pic14_emitcode("anl","a,#0xfe");
5244           pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5245           sizer--;
5246         }
5247         // val = (0,1)
5248         pic14_emitcode("rrc","a");
5249       }
5250       pic14_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
5251       pic14_emitcode("cpl","c");
5252       pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
5253     }
5254     // bit = c
5255     // val = c
5256     if(size)
5257       pic14_outBitC(result);
5258     // if(bit | ...)
5259     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5260       genIfxJump(ifx, "c");           
5261     goto release ;
5262   }
5263
5264   if(pic14_sameRegs(AOP(result),AOP(left))){
5265     /* if left is same as result */
5266     for(;size--; offset++) {
5267       if(AOP_TYPE(right) == AOP_LIT){
5268         int t  = (lit >> (offset*8)) & 0x0FFL;
5269         if(t == 0x00L)
5270           continue;
5271         else
5272           if (IS_AOP_PREG(left)) {
5273             MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5274             pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
5275             aopPut(AOP(result),"a",offset);
5276           } else {
5277             emitpcode(POC_MOVLW, popGetLit(t));
5278             emitpcode(POC_XORWF,popGet(AOP(left),offset));
5279             pic14_emitcode("xrl","%s,%s",
5280                            aopGet(AOP(left),offset,FALSE,TRUE),
5281                            aopGet(AOP(right),offset,FALSE,FALSE));
5282           }
5283       } else {
5284         if (AOP_TYPE(left) == AOP_ACC)
5285           pic14_emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
5286         else {
5287           emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5288           emitpcode(POC_XORWF,popGet(AOP(left),offset));
5289 /*
5290           if (IS_AOP_PREG(left)) {
5291             pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
5292             aopPut(AOP(result),"a",offset);
5293           } else
5294             pic14_emitcode("xrl","%s,a",
5295                            aopGet(AOP(left),offset,FALSE,TRUE));
5296 */
5297         }
5298       }
5299     }
5300   } else {
5301     // left & result in different registers
5302     if(AOP_TYPE(result) == AOP_CRY){
5303       // result = bit
5304       // if(size), result in bit
5305       // if(!size && ifx), conditional oper: if(left ^ right)
5306       symbol *tlbl = newiTempLabel(NULL);
5307       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5308       if(size)
5309         pic14_emitcode("setb","c");
5310       while(sizer--){
5311         if((AOP_TYPE(right) == AOP_LIT) &&
5312            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
5313           MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
5314         } else {
5315           MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5316           pic14_emitcode("xrl","a,%s",
5317                          aopGet(AOP(left),offset,FALSE,FALSE));
5318         }
5319         pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5320         offset++;
5321       }
5322       if(size){
5323         CLRC;
5324         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5325         pic14_outBitC(result);
5326       } else if(ifx)
5327         jmpTrueOrFalse(ifx, tlbl);
5328     } else for(;(size--);offset++){
5329       // normal case
5330       // result = left & right
5331       if(AOP_TYPE(right) == AOP_LIT){
5332         int t = (lit >> (offset*8)) & 0x0FFL;
5333         switch(t) { 
5334         case 0x00:
5335           emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5336           emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5337           pic14_emitcode("movf","%s,w",
5338                          aopGet(AOP(left),offset,FALSE,FALSE));
5339           pic14_emitcode("movwf","%s",
5340                          aopGet(AOP(result),offset,FALSE,FALSE));
5341           break;
5342         case 0xff:
5343           emitpcode(POC_COMFW,popGet(AOP(left),offset));
5344           emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5345           pic14_emitcode("comf","%s,w",
5346                          aopGet(AOP(left),offset,FALSE,FALSE));
5347           pic14_emitcode("movwf","%s",
5348                          aopGet(AOP(result),offset,FALSE,FALSE));
5349           break;
5350         default:
5351           emitpcode(POC_MOVLW, popGetLit(t));
5352           emitpcode(POC_XORFW,popGet(AOP(left),offset));
5353           emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5354           pic14_emitcode("movlw","0x%x",t);
5355           pic14_emitcode("xorwf","%s,w",
5356                          aopGet(AOP(left),offset,FALSE,FALSE));
5357           pic14_emitcode("movwf","%s",
5358                          aopGet(AOP(result),offset,FALSE,FALSE));
5359
5360         }
5361         continue;
5362       }
5363
5364       // faster than result <- left, anl result,right
5365       // and better if result is SFR
5366       if (AOP_TYPE(left) == AOP_ACC) {
5367         emitpcode(POC_XORFW,popGet(AOP(right),offset));
5368         pic14_emitcode("xorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5369       } else {
5370         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5371         emitpcode(POC_XORFW,popGet(AOP(left),offset));
5372         pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5373         pic14_emitcode("xorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
5374       }
5375       if ( AOP_TYPE(result) != AOP_ACC){
5376         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5377         pic14_emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5378       }
5379     }
5380   }
5381
5382   release :
5383     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5384   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5385   freeAsmop(result,NULL,ic,TRUE);     
5386 }
5387
5388 /*-----------------------------------------------------------------*/
5389 /* genInline - write the inline code out                           */
5390 /*-----------------------------------------------------------------*/
5391 static void genInline (iCode *ic)
5392 {
5393     char *buffer, *bp, *bp1;
5394     
5395     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5396
5397     _G.inLine += (!options.asmpeep);
5398
5399     buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5400     strcpy(buffer,IC_INLINE(ic));
5401
5402     /* emit each line as a code */
5403     while (*bp) {
5404         if (*bp == '\n') {
5405             *bp++ = '\0';
5406             pic14_emitcode(bp1,"");
5407             bp1 = bp;
5408         } else {
5409             if (*bp == ':') {
5410                 bp++;
5411                 *bp = '\0';
5412                 bp++;
5413                 pic14_emitcode(bp1,"");
5414                 bp1 = bp;
5415             } else
5416                 bp++;
5417         }
5418     }
5419     if (bp1 != bp)
5420         pic14_emitcode(bp1,"");
5421     /*     pic14_emitcode("",buffer); */
5422     _G.inLine -= (!options.asmpeep);
5423 }
5424
5425 /*-----------------------------------------------------------------*/
5426 /* genRRC - rotate right with carry                                */
5427 /*-----------------------------------------------------------------*/
5428 static void genRRC (iCode *ic)
5429 {
5430   operand *left , *result ;
5431   int size, offset = 0, same;
5432
5433   /* rotate right with carry */
5434   left = IC_LEFT(ic);
5435   result=IC_RESULT(ic);
5436   aopOp (left,ic,FALSE);
5437   aopOp (result,ic,FALSE);
5438
5439   DEBUGpic14_AopType(__LINE__,left,NULL,result);
5440
5441   same = pic14_sameRegs(AOP(result),AOP(left));
5442
5443   size = AOP_SIZE(result);    
5444
5445   /* get the lsb and put it into the carry */
5446   emitpcode(POC_RRFW, popGet(AOP(left),size-1));
5447
5448   offset = 0 ;
5449
5450   while(size--) {
5451
5452     if(same) {
5453       emitpcode(POC_RRF, popGet(AOP(left),offset));
5454     } else {
5455       emitpcode(POC_RRFW, popGet(AOP(left),offset));
5456       emitpcode(POC_MOVWF, popGet(AOP(result),offset));
5457     }
5458
5459     offset++;
5460   }
5461
5462   freeAsmop(left,NULL,ic,TRUE);
5463   freeAsmop(result,NULL,ic,TRUE);
5464 }
5465
5466 /*-----------------------------------------------------------------*/
5467 /* genRLC - generate code for rotate left with carry               */
5468 /*-----------------------------------------------------------------*/
5469 static void genRLC (iCode *ic)
5470 {    
5471   operand *left , *result ;
5472   int size, offset = 0;
5473   int same;
5474
5475   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5476   /* rotate right with carry */
5477   left = IC_LEFT(ic);
5478   result=IC_RESULT(ic);
5479   aopOp (left,ic,FALSE);
5480   aopOp (result,ic,FALSE);
5481
5482   DEBUGpic14_AopType(__LINE__,left,NULL,result);
5483
5484   same = pic14_sameRegs(AOP(result),AOP(left));
5485
5486   /* move it to the result */
5487   size = AOP_SIZE(result);    
5488
5489   /* get the msb and put it into the carry */
5490   emitpcode(POC_RLFW, popGet(AOP(left),size-1));
5491
5492   offset = 0 ;
5493
5494   while(size--) {
5495
5496     if(same) {
5497       emitpcode(POC_RLF, popGet(AOP(left),offset));
5498     } else {
5499       emitpcode(POC_RLFW, popGet(AOP(left),offset));
5500       emitpcode(POC_MOVWF, popGet(AOP(result),offset));
5501     }
5502
5503     offset++;
5504   }
5505
5506
5507   freeAsmop(left,NULL,ic,TRUE);
5508   freeAsmop(result,NULL,ic,TRUE);
5509 }
5510
5511 /*-----------------------------------------------------------------*/
5512 /* genGetHbit - generates code get highest order bit               */
5513 /*-----------------------------------------------------------------*/
5514 static void genGetHbit (iCode *ic)
5515 {
5516     operand *left, *result;
5517     left = IC_LEFT(ic);
5518     result=IC_RESULT(ic);
5519     aopOp (left,ic,FALSE);
5520     aopOp (result,ic,FALSE);
5521
5522     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5523     /* get the highest order byte into a */
5524     MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
5525     if(AOP_TYPE(result) == AOP_CRY){
5526         pic14_emitcode("rlc","a");
5527         pic14_outBitC(result);
5528     }
5529     else{
5530         pic14_emitcode("rl","a");
5531         pic14_emitcode("anl","a,#0x01");
5532         pic14_outAcc(result);
5533     }
5534
5535
5536     freeAsmop(left,NULL,ic,TRUE);
5537     freeAsmop(result,NULL,ic,TRUE);
5538 }
5539
5540 /*-----------------------------------------------------------------*/
5541 /* AccRol - rotate left accumulator by known count                 */
5542 /*-----------------------------------------------------------------*/
5543 static void AccRol (int shCount)
5544 {
5545     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5546     shCount &= 0x0007;              // shCount : 0..7
5547     switch(shCount){
5548         case 0 :
5549             break;
5550         case 1 :
5551             pic14_emitcode("rl","a");
5552             break;
5553         case 2 :
5554             pic14_emitcode("rl","a");
5555             pic14_emitcode("rl","a");
5556             break;
5557         case 3 :
5558             pic14_emitcode("swap","a");
5559             pic14_emitcode("rr","a");
5560             break;
5561         case 4 :
5562             pic14_emitcode("swap","a");
5563             break;
5564         case 5 :
5565             pic14_emitcode("swap","a");
5566             pic14_emitcode("rl","a");
5567             break;
5568         case 6 :
5569             pic14_emitcode("rr","a");
5570             pic14_emitcode("rr","a");
5571             break;
5572         case 7 :
5573             pic14_emitcode("rr","a");
5574             break;
5575     }
5576 }
5577
5578 /*-----------------------------------------------------------------*/
5579 /* AccLsh - left shift accumulator by known count                  */
5580 /*-----------------------------------------------------------------*/
5581 static void AccLsh (int shCount)
5582 {
5583     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5584     if(shCount != 0){
5585         if(shCount == 1)
5586             pic14_emitcode("add","a,acc");
5587         else 
5588             if(shCount == 2) {
5589             pic14_emitcode("add","a,acc");
5590             pic14_emitcode("add","a,acc");
5591         } else {
5592             /* rotate left accumulator */
5593             AccRol(shCount);
5594             /* and kill the lower order bits */
5595             pic14_emitcode("anl","a,#0x%02x", SLMask[shCount]);
5596         }
5597     }
5598 }
5599
5600 /*-----------------------------------------------------------------*/
5601 /* AccRsh - right shift accumulator by known count                 */
5602 /*-----------------------------------------------------------------*/
5603 static void AccRsh (int shCount)
5604 {
5605     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5606     if(shCount != 0){
5607         if(shCount == 1){
5608             CLRC;
5609             pic14_emitcode("rrc","a");
5610         } else {
5611             /* rotate right accumulator */
5612             AccRol(8 - shCount);
5613             /* and kill the higher order bits */
5614             pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
5615         }
5616     }
5617 }
5618
5619 #if 0
5620 /*-----------------------------------------------------------------*/
5621 /* AccSRsh - signed right shift accumulator by known count                 */
5622 /*-----------------------------------------------------------------*/
5623 static void AccSRsh (int shCount)
5624 {
5625     symbol *tlbl ;
5626     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5627     if(shCount != 0){
5628         if(shCount == 1){
5629             pic14_emitcode("mov","c,acc.7");
5630             pic14_emitcode("rrc","a");
5631         } else if(shCount == 2){
5632             pic14_emitcode("mov","c,acc.7");
5633             pic14_emitcode("rrc","a");
5634             pic14_emitcode("mov","c,acc.7");
5635             pic14_emitcode("rrc","a");
5636         } else {
5637             tlbl = newiTempLabel(NULL);
5638             /* rotate right accumulator */
5639             AccRol(8 - shCount);
5640             /* and kill the higher order bits */
5641             pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
5642             pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
5643             pic14_emitcode("orl","a,#0x%02x",
5644                      (unsigned char)~SRMask[shCount]);
5645             pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5646         }
5647     }
5648 }
5649 #endif
5650 /*-----------------------------------------------------------------*/
5651 /* shiftR1Left2Result - shift right one byte from left to result   */
5652 /*-----------------------------------------------------------------*/
5653 static void shiftR1Left2ResultSigned (operand *left, int offl,
5654                                 operand *result, int offr,
5655                                 int shCount)
5656 {
5657   int same;
5658
5659   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5660
5661   same = (left == result) || (AOP(left) == AOP(result));
5662
5663   switch(shCount) {
5664   case 1:
5665     emitpcode(POC_RLFW, popGet(AOP(left),offl));
5666     if(same) 
5667       emitpcode(POC_RRF, popGet(AOP(result),offr));
5668     else {
5669       emitpcode(POC_RRFW, popGet(AOP(left),offl));
5670       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5671     }
5672
5673     break;
5674
5675   default:
5676     break;
5677   }
5678 }
5679
5680 /*-----------------------------------------------------------------*/
5681 /* shiftR1Left2Result - shift right one byte from left to result   */
5682 /*-----------------------------------------------------------------*/
5683 static void shiftR1Left2Result (operand *left, int offl,
5684                                 operand *result, int offr,
5685                                 int shCount, int sign)
5686 {
5687   int same;
5688
5689   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5690
5691   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
5692
5693   /* Copy the msb into the carry if signed. */
5694   if(sign) {
5695     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
5696     return;
5697   }
5698
5699
5700
5701   switch(shCount) {
5702   case 1:
5703     emitCLRC;
5704     if(same) 
5705       emitpcode(POC_RRF, popGet(AOP(result),offr));
5706     else {
5707       emitpcode(POC_RRFW, popGet(AOP(left),offl));
5708       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5709     }
5710     break;
5711   case 2:
5712     emitCLRC;
5713     if(same) {
5714       emitpcode(POC_RRF, popGet(AOP(result),offr));
5715     } else {
5716       emitpcode(POC_RRFW, popGet(AOP(left),offl));
5717       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5718     }
5719     emitCLRC;
5720     emitpcode(POC_RRF, popGet(AOP(result),offr));
5721
5722     break;
5723   case 3:
5724     if(same) 
5725       emitpcode(POC_SWAPF, popGet(AOP(result),offr));
5726     else {
5727       emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
5728       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5729     }
5730
5731     emitpcode(POC_RLFW,  popGet(AOP(result),offr));
5732     emitpcode(POC_RLFW,  popGet(AOP(result),offr));
5733     emitpcode(POC_ANDLW, popGetLit(0x1f));
5734     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5735     break;
5736       
5737   case 4:
5738     emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
5739     emitpcode(POC_ANDLW, popGetLit(0x0f));
5740     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5741     break;
5742
5743   case 5:
5744     emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
5745     emitpcode(POC_ANDLW, popGetLit(0x0f));
5746     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5747     emitCLRC;
5748     emitpcode(POC_RRF, popGet(AOP(result),offr));
5749
5750     break;
5751   case 6:
5752
5753     emitpcode(POC_RLFW,  popGet(AOP(left),offl));
5754     emitpcode(POC_ANDLW, popGetLit(0x80));
5755     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5756     emitpcode(POC_RLF,   popGet(AOP(result),offr));
5757     emitpcode(POC_RLF,   popGet(AOP(result),offr));
5758     break;
5759
5760   case 7:
5761
5762     emitpcode(POC_RLFW, popGet(AOP(left),offl));
5763     emitpcode(POC_CLRF, popGet(AOP(result),offr));
5764     emitpcode(POC_RLF,  popGet(AOP(result),offr));
5765
5766     break;
5767
5768   default:
5769     break;
5770   }
5771
5772
5773 #if 0
5774     
5775   MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5776
5777   /* shift right accumulator */
5778   if(sign)
5779     AccSRsh(shCount);
5780   else
5781     AccRsh(shCount);
5782   aopPut(AOP(result),"a",offr);
5783 #endif
5784 }
5785
5786 /*-----------------------------------------------------------------*/
5787 /* shiftL1Left2Result - shift left one byte from left to result    */
5788 /*-----------------------------------------------------------------*/
5789 static void shiftL1Left2Result (operand *left, int offl,
5790                                 operand *result, int offr, int shCount)
5791 {
5792   int same;
5793
5794   //    char *l;
5795   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5796
5797   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
5798   DEBUGpic14_emitcode ("; ***","same =  %d",same);
5799     //    l = aopGet(AOP(left),offl,FALSE,FALSE);
5800     //    MOVA(l);
5801     /* shift left accumulator */
5802     //AccLsh(shCount); // don't comment out just yet...
5803   //    aopPut(AOP(result),"a",offr);
5804
5805   switch(shCount) {
5806   case 1:
5807     /* Shift left 1 bit position */
5808     emitpcode(POC_MOVFW, popGet(AOP(left),offl));
5809     if(same) {
5810       emitpcode(POC_ADDWF, popGet(AOP(left),offl));
5811     } else {
5812       emitpcode(POC_ADDFW, popGet(AOP(left),offl));
5813       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5814     }
5815     break;
5816   case 2:
5817     emitpcode(POC_RLFW, popGet(AOP(left),offl));
5818     emitpcode(POC_ANDLW,popGetLit(0x7e));
5819     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
5820     emitpcode(POC_ADDWF,popGet(AOP(result),offr));
5821     break;
5822   case 3:
5823     emitpcode(POC_RLFW, popGet(AOP(left),offl));
5824     emitpcode(POC_ANDLW,popGetLit(0x3e));
5825     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
5826     emitpcode(POC_ADDWF,popGet(AOP(result),offr));
5827     emitpcode(POC_RLF,  popGet(AOP(result),offr));
5828     break;
5829   case 4:
5830     emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
5831     emitpcode(POC_ANDLW, popGetLit(0xf0));
5832     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
5833     break;
5834   case 5:
5835     emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
5836     emitpcode(POC_ANDLW, popGetLit(0xf0));
5837     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
5838     emitpcode(POC_ADDWF,popGet(AOP(result),offr));
5839     break;
5840   case 6:
5841     emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
5842     emitpcode(POC_ANDLW, popGetLit(0x30));
5843     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
5844     emitpcode(POC_ADDWF,popGet(AOP(result),offr));
5845     emitpcode(POC_RLF,  popGet(AOP(result),offr));
5846     break;
5847   case 7:
5848     emitpcode(POC_RRFW, popGet(AOP(left),offl));
5849     emitpcode(POC_CLRF, popGet(AOP(result),offr));
5850     emitpcode(POC_RRF,  popGet(AOP(result),offr));
5851     break;
5852
5853   default:
5854     DEBUGpic14_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
5855   }
5856
5857 }
5858
5859 /*-----------------------------------------------------------------*/
5860 /* movLeft2Result - move byte from left to result                  */
5861 /*-----------------------------------------------------------------*/
5862 static void movLeft2Result (operand *left, int offl,
5863                             operand *result, int offr, int sign)
5864 {
5865     char *l;
5866     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5867     if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
5868         l = aopGet(AOP(left),offl,FALSE,FALSE);
5869
5870         if (*l == '@' && (IS_AOP_PREG(result))) {
5871             pic14_emitcode("mov","a,%s",l);
5872             aopPut(AOP(result),"a",offr);
5873         } else {
5874           if(!sign) {
5875             emitpcode(POC_MOVFW, popGet(AOP(left),offl));
5876             emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5877
5878             //aopPut(AOP(result),l,offr);
5879           }else{
5880                 /* MSB sign in acc.7 ! */
5881                 if(pic14_getDataSize(left) == offl+1){
5882                     pic14_emitcode("mov","a,%s",l);
5883                     aopPut(AOP(result),"a",offr);
5884                 }
5885             }
5886         }
5887     }
5888 }
5889
5890 /*-----------------------------------------------------------------*/
5891 /* shiftL2Left2Result - shift left two bytes from left to result   */
5892 /*-----------------------------------------------------------------*/
5893 static void shiftL2Left2Result (operand *left, int offl,
5894                                 operand *result, int offr, int shCount)
5895 {
5896
5897
5898   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5899
5900   if(pic14_sameRegs(AOP(result), AOP(left))) {
5901     switch(shCount) {
5902     case 0:
5903       break;
5904     case 1:
5905     case 2:
5906     case 3:
5907
5908       emitpcode(POC_MOVFW,popGet(AOP(result),offr));
5909       emitpcode(POC_ADDWF,popGet(AOP(result),offr));
5910       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
5911
5912       while(--shCount) {
5913         emitCLRC;
5914         emitpcode(POC_RLF, popGet(AOP(result),offr));
5915         emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
5916       }
5917
5918       break;
5919     case 4:
5920     case 5:
5921       emitpcode(POC_MOVLW, popGetLit(0x0f));
5922       emitpcode(POC_ANDWF, popGet(AOP(result),offr+MSB16));
5923       emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
5924       emitpcode(POC_SWAPF, popGet(AOP(result),offr));
5925       emitpcode(POC_ANDFW, popGet(AOP(result),offr));
5926       emitpcode(POC_XORWF, popGet(AOP(result),offr));
5927       emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
5928       if(shCount >=5) {
5929         emitpcode(POC_RLF, popGet(AOP(result),offr));
5930         emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
5931       }
5932       break;
5933     case 6:
5934       emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
5935       emitpcode(POC_RRF,  popGet(AOP(result),offr));
5936       emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
5937       emitpcode(POC_RRF,  popGet(AOP(result),offr));
5938       emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
5939       emitpcode(POC_ANDLW,popGetLit(0xc0));
5940       emitpcode(POC_XORFW,popGet(AOP(result),offr));
5941       emitpcode(POC_XORWF,popGet(AOP(result),offr));
5942       emitpcode(POC_XORFW,popGet(AOP(result),offr));
5943       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
5944       break;
5945     case 7:
5946       emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
5947       emitpcode(POC_RRFW, popGet(AOP(result),offr));
5948       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
5949       emitpcode(POC_CLRF, popGet(AOP(result),offr));
5950       emitpcode(POC_RRF,  popGet(AOP(result),offr));
5951     }
5952
5953   } else {
5954     switch(shCount) {
5955     case 0:
5956       break;
5957     case 1:
5958     case 2:
5959     case 3:
5960       /* note, use a mov/add for the shift since the mov has a
5961          chance of getting optimized out */
5962       emitpcode(POC_MOVFW, popGet(AOP(left),offl));
5963       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5964       emitpcode(POC_ADDWF, popGet(AOP(result),offr));
5965       emitpcode(POC_RLFW,  popGet(AOP(left),offl+MSB16));
5966       emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
5967
5968       while(--shCount) {
5969         emitCLRC;
5970         emitpcode(POC_RLF, popGet(AOP(result),offr));
5971         emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
5972       }
5973       break;
5974
5975     case 4:
5976     case 5:
5977       emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
5978       emitpcode(POC_ANDLW, popGetLit(0xF0));
5979       emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
5980       emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
5981       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
5982       emitpcode(POC_ANDLW, popGetLit(0xF0));
5983       emitpcode(POC_XORWF, popGet(AOP(result),offr));
5984       emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
5985
5986
5987       if(shCount == 5) {
5988         emitpcode(POC_RLF, popGet(AOP(result),offr));
5989         emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
5990       }
5991       break;
5992     case 6:
5993       emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
5994       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
5995       emitpcode(POC_RRFW, popGet(AOP(result),offl));
5996       emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
5997
5998       emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
5999       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6000       emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6001       emitpcode(POC_ANDLW,popGetLit(0xc0));
6002       emitpcode(POC_XORFW,popGet(AOP(result),offr));
6003       emitpcode(POC_XORWF,popGet(AOP(result),offr));
6004       emitpcode(POC_XORFW,popGet(AOP(result),offr));
6005       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6006       break;
6007     case 7:
6008       emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
6009       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6010       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6011       emitpcode(POC_CLRF, popGet(AOP(result),offr));
6012       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6013     }
6014   }
6015
6016 }
6017 /*-----------------------------------------------------------------*/
6018 /* shiftR2Left2Result - shift right two bytes from left to result  */
6019 /*-----------------------------------------------------------------*/
6020 static void shiftR2Left2Result (operand *left, int offl,
6021                                 operand *result, int offr,
6022                                 int shCount, int sign)
6023 {
6024   int same=0;
6025
6026   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6027   same = pic14_sameRegs(AOP(result), AOP(left));
6028
6029   if(same && ((offl + MSB16) == offr)){
6030     same=1;
6031     /* don't crash result[offr] */
6032     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6033     pic14_emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6034   } else {
6035     movLeft2Result(left,offl, result, offr, 0);
6036     MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6037   }
6038   /* a:x >> shCount (x = lsb(result))*/
6039 /*
6040   if(sign)
6041     AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6042   else {
6043     AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6044 */
6045   switch(shCount) {
6046   case 0:
6047     break;
6048   case 1:
6049   case 2:
6050   case 3:
6051     emitCLRC;
6052     if(same) {
6053       emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
6054       emitpcode(POC_RRF,popGet(AOP(result),offr));
6055     } else {
6056
6057       emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
6058       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6059       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6060       emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6061     }
6062
6063     while(--shCount) {
6064       emitCLRC;
6065       emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
6066       emitpcode(POC_RRF,popGet(AOP(result),offr));
6067     }
6068     break;
6069   case 4:
6070   case 5:
6071     if(same) {
6072
6073       emitpcode(POC_MOVLW, popGetLit(0xf0));
6074       emitpcode(POC_ANDWF, popGet(AOP(result),offr));
6075       emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6076
6077       emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
6078       emitpcode(POC_ANDFW, popGet(AOP(result),offr+MSB16));
6079       emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
6080       emitpcode(POC_ADDWF, popGet(AOP(result),offr));
6081     } else {
6082       emitpcode(POC_SWAPF, popGet(AOP(left),offl));
6083       emitpcode(POC_ANDLW, popGetLit(0x0f));
6084       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6085
6086       emitpcode(POC_SWAPF, popGet(AOP(left),offl+MSB16));
6087       emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6088       emitpcode(POC_ANDLW, popGetLit(0xf0));
6089       emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
6090       emitpcode(POC_ADDWF, popGet(AOP(result),offr));
6091     }
6092
6093     if(shCount >=5) {
6094       emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
6095       emitpcode(POC_RRF, popGet(AOP(result),offr));
6096     }
6097
6098     break;
6099
6100   case 6:
6101     if(same) {
6102
6103       emitpcode(POC_RLF,  popGet(AOP(result),offr));
6104       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6105
6106       emitpcode(POC_RLF,  popGet(AOP(result),offr));
6107       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6108       emitpcode(POC_RLFW, popGet(AOP(result),offr));
6109       emitpcode(POC_ANDLW,popGetLit(0x03));
6110       emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
6111       emitpcode(POC_XORWF,popGet(AOP(result),offr+MSB16));
6112       emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
6113       emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6114     } else {
6115       emitpcode(POC_RLFW, popGet(AOP(left),offl));
6116       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6117       emitpcode(POC_RLFW, popGet(AOP(result),offl+MSB16));
6118       emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6119       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6120       emitpcode(POC_RLF,  popGet(AOP(result),offr));
6121       emitpcode(POC_RLFW, popGet(AOP(result),offr));
6122       emitpcode(POC_ANDLW,popGetLit(0x03));
6123       emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6124     }
6125
6126     break;
6127   case 7:
6128     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6129     emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
6130     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6131     emitpcode(POC_CLRF, popGet(AOP(result),offr+MSB16));
6132     emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6133   }
6134 }
6135
6136
6137 /*-----------------------------------------------------------------*/
6138 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
6139 /*-----------------------------------------------------------------*/
6140 static void shiftLLeftOrResult (operand *left, int offl,
6141                                 operand *result, int offr, int shCount)
6142 {
6143     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6144     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6145     /* shift left accumulator */
6146     AccLsh(shCount);
6147     /* or with result */
6148     pic14_emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
6149     /* back to result */
6150     aopPut(AOP(result),"a",offr);
6151 }
6152
6153 /*-----------------------------------------------------------------*/
6154 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
6155 /*-----------------------------------------------------------------*/
6156 static void shiftRLeftOrResult (operand *left, int offl,
6157                                 operand *result, int offr, int shCount)
6158 {
6159     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6160     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6161     /* shift right accumulator */
6162     AccRsh(shCount);
6163     /* or with result */
6164     pic14_emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
6165     /* back to result */
6166     aopPut(AOP(result),"a",offr);
6167 }
6168
6169 /*-----------------------------------------------------------------*/
6170 /* genlshOne - left shift a one byte quantity by known count       */
6171 /*-----------------------------------------------------------------*/
6172 static void genlshOne (operand *result, operand *left, int shCount)
6173 {       
6174     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6175     shiftL1Left2Result(left, LSB, result, LSB, shCount);
6176 }
6177
6178 /*-----------------------------------------------------------------*/
6179 /* genlshTwo - left shift two bytes by known amount != 0           */
6180 /*-----------------------------------------------------------------*/
6181 static void genlshTwo (operand *result,operand *left, int shCount)
6182 {
6183     int size;
6184     
6185     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6186     size = pic14_getDataSize(result);
6187
6188     /* if shCount >= 8 */
6189     if (shCount >= 8) {
6190         shCount -= 8 ;
6191
6192         if (size > 1){
6193             if (shCount)
6194                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6195             else 
6196                 movLeft2Result(left, LSB, result, MSB16, 0);
6197         }
6198         emitpcode(POC_CLRF,popGet(AOP(result),LSB));
6199     }
6200
6201     /*  1 <= shCount <= 7 */
6202     else {  
6203         if(size == 1)
6204             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
6205         else 
6206             shiftL2Left2Result(left, LSB, result, LSB, shCount);
6207     }
6208 }
6209
6210 /*-----------------------------------------------------------------*/
6211 /* shiftLLong - shift left one long from left to result            */
6212 /* offl = LSB or MSB16                                             */
6213 /*-----------------------------------------------------------------*/
6214 static void shiftLLong (operand *left, operand *result, int offr )
6215 {
6216     char *l;
6217     int size = AOP_SIZE(result);
6218
6219     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6220     if(size >= LSB+offr){
6221         l = aopGet(AOP(left),LSB,FALSE,FALSE);
6222         MOVA(l);
6223         pic14_emitcode("add","a,acc");
6224         if (pic14_sameRegs(AOP(left),AOP(result)) && 
6225             size >= MSB16+offr && offr != LSB )
6226             pic14_emitcode("xch","a,%s",
6227                      aopGet(AOP(left),LSB+offr,FALSE,FALSE));
6228         else        
6229             aopPut(AOP(result),"a",LSB+offr);
6230     }
6231
6232     if(size >= MSB16+offr){
6233         if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
6234             l = aopGet(AOP(left),MSB16,FALSE,FALSE);
6235             MOVA(l);
6236         }
6237         pic14_emitcode("rlc","a");
6238         if (pic14_sameRegs(AOP(left),AOP(result)) && 
6239             size >= MSB24+offr && offr != LSB)
6240             pic14_emitcode("xch","a,%s",
6241                      aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
6242         else        
6243             aopPut(AOP(result),"a",MSB16+offr);
6244     }
6245
6246     if(size >= MSB24+offr){
6247         if (!(pic14_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
6248             l = aopGet(AOP(left),MSB24,FALSE,FALSE);
6249             MOVA(l);
6250         }
6251         pic14_emitcode("rlc","a");
6252         if (pic14_sameRegs(AOP(left),AOP(result)) && 
6253             size >= MSB32+offr && offr != LSB )
6254             pic14_emitcode("xch","a,%s",
6255                      aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
6256         else        
6257             aopPut(AOP(result),"a",MSB24+offr);
6258     }
6259
6260     if(size > MSB32+offr){
6261         if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
6262             l = aopGet(AOP(left),MSB32,FALSE,FALSE);
6263             MOVA(l);    
6264         }
6265         pic14_emitcode("rlc","a");
6266         aopPut(AOP(result),"a",MSB32+offr);
6267     }
6268     if(offr != LSB)
6269         aopPut(AOP(result),zero,LSB);       
6270 }
6271
6272 /*-----------------------------------------------------------------*/
6273 /* genlshFour - shift four byte by a known amount != 0             */
6274 /*-----------------------------------------------------------------*/
6275 static void genlshFour (operand *result, operand *left, int shCount)
6276 {
6277     int size;
6278
6279     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6280     size = AOP_SIZE(result);
6281
6282     /* if shifting more that 3 bytes */
6283     if (shCount >= 24 ) {
6284         shCount -= 24;
6285         if (shCount)
6286             /* lowest order of left goes to the highest
6287             order of the destination */
6288             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
6289         else
6290             movLeft2Result(left, LSB, result, MSB32, 0);
6291         aopPut(AOP(result),zero,LSB);
6292         aopPut(AOP(result),zero,MSB16);
6293         aopPut(AOP(result),zero,MSB32);
6294         return;
6295     }
6296
6297     /* more than two bytes */
6298     else if ( shCount >= 16 ) {
6299         /* lower order two bytes goes to higher order two bytes */
6300         shCount -= 16;
6301         /* if some more remaining */
6302         if (shCount)
6303             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
6304         else {
6305             movLeft2Result(left, MSB16, result, MSB32, 0);
6306             movLeft2Result(left, LSB, result, MSB24, 0);
6307         }
6308         aopPut(AOP(result),zero,MSB16);
6309         aopPut(AOP(result),zero,LSB);
6310         return;
6311     }    
6312
6313     /* if more than 1 byte */
6314     else if ( shCount >= 8 ) {
6315         /* lower order three bytes goes to higher order  three bytes */
6316         shCount -= 8;
6317         if(size == 2){
6318             if(shCount)
6319                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6320             else
6321                 movLeft2Result(left, LSB, result, MSB16, 0);
6322         }
6323         else{   /* size = 4 */
6324             if(shCount == 0){
6325                 movLeft2Result(left, MSB24, result, MSB32, 0);
6326                 movLeft2Result(left, MSB16, result, MSB24, 0);
6327                 movLeft2Result(left, LSB, result, MSB16, 0);
6328                 aopPut(AOP(result),zero,LSB);
6329             }
6330             else if(shCount == 1)
6331                 shiftLLong(left, result, MSB16);
6332             else{
6333                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
6334                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6335                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
6336                 aopPut(AOP(result),zero,LSB);
6337             }
6338         }
6339     }
6340
6341     /* 1 <= shCount <= 7 */
6342     else if(shCount <= 2){
6343         shiftLLong(left, result, LSB);
6344         if(shCount == 2)
6345             shiftLLong(result, result, LSB);
6346     }
6347     /* 3 <= shCount <= 7, optimize */
6348     else{
6349         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
6350         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
6351         shiftL2Left2Result(left, LSB, result, LSB, shCount);
6352     }
6353 }
6354
6355 /*-----------------------------------------------------------------*/
6356 /* genLeftShiftLiteral - left shifting by known count              */
6357 /*-----------------------------------------------------------------*/
6358 static void genLeftShiftLiteral (operand *left,
6359                                  operand *right,
6360                                  operand *result,
6361                                  iCode *ic)
6362 {    
6363     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6364     int size;
6365
6366     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6367     freeAsmop(right,NULL,ic,TRUE);
6368
6369     aopOp(left,ic,FALSE);
6370     aopOp(result,ic,FALSE);
6371
6372     size = getSize(operandType(result));
6373
6374 #if VIEW_SIZE
6375     pic14_emitcode("; shift left ","result %d, left %d",size,
6376              AOP_SIZE(left));
6377 #endif
6378
6379     /* I suppose that the left size >= result size */
6380     if(shCount == 0){
6381         while(size--){
6382             movLeft2Result(left, size, result, size, 0);
6383         }
6384     }
6385
6386     else if(shCount >= (size * 8))
6387         while(size--)
6388             aopPut(AOP(result),zero,size);
6389     else{
6390         switch (size) {
6391             case 1:
6392                 genlshOne (result,left,shCount);
6393                 break;
6394
6395             case 2:
6396             case 3:
6397                 genlshTwo (result,left,shCount);
6398                 break;
6399
6400             case 4:
6401                 genlshFour (result,left,shCount);
6402                 break;
6403         }
6404     }
6405     freeAsmop(left,NULL,ic,TRUE);
6406     freeAsmop(result,NULL,ic,TRUE);
6407 }
6408
6409 /*-----------------------------------------------------------------*/
6410 /* genLeftShift - generates code for left shifting                 */
6411 /*-----------------------------------------------------------------*/
6412 static void genLeftShift (iCode *ic)
6413 {
6414     operand *left,*right, *result;
6415     int size, offset;
6416     char *l;
6417     symbol *tlbl , *tlbl1;
6418
6419     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6420
6421     right = IC_RIGHT(ic);
6422     left  = IC_LEFT(ic);
6423     result = IC_RESULT(ic);
6424
6425     aopOp(right,ic,FALSE);
6426
6427     /* if the shift count is known then do it 
6428     as efficiently as possible */
6429     if (AOP_TYPE(right) == AOP_LIT) {
6430         genLeftShiftLiteral (left,right,result,ic);
6431         return ;
6432     }
6433
6434     /* shift count is unknown then we have to form 
6435     a loop get the loop count in B : Note: we take
6436     only the lower order byte since shifting
6437     more that 32 bits make no sense anyway, ( the
6438     largest size of an object can be only 32 bits ) */  
6439
6440     
6441     aopOp(left,ic,FALSE);
6442     aopOp(result,ic,FALSE);
6443
6444     /* now move the left to the result if they are not the
6445     same */
6446     if (!pic14_sameRegs(AOP(left),AOP(result)) && 
6447         AOP_SIZE(result) > 1) {
6448
6449         size = AOP_SIZE(result);
6450         offset=0;
6451         while (size--) {
6452             l = aopGet(AOP(left),offset,FALSE,TRUE);
6453             if (*l == '@' && (IS_AOP_PREG(result))) {
6454
6455                 pic14_emitcode("mov","a,%s",l);
6456                 aopPut(AOP(result),"a",offset);
6457             } else
6458                 aopPut(AOP(result),l,offset);
6459             offset++;
6460         }
6461     }
6462
6463     size = AOP_SIZE(result);
6464
6465     /* if it is only one byte then */
6466     if (size == 1) {
6467       if(optimized_for_speed) {
6468         emitpcode(POC_SWAPFW, popGet(AOP(left),0));
6469         emitpcode(POC_ANDLW,  popGetLit(0xf0));
6470         emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),2,0));
6471         emitpcode(POC_MOVFW,  popGet(AOP(left),0));
6472         emitpcode(POC_MOVWF,  popGet(AOP(result),0));
6473         emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
6474         emitpcode(POC_ADDWF,  popGet(AOP(result),0));
6475         emitpcode(POC_RLFW,   popGet(AOP(result),0));
6476         emitpcode(POC_ANDLW,  popGetLit(0xfe));
6477         emitpcode(POC_ADDFW,  popGet(AOP(result),0));
6478         emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),1,0));
6479         emitpcode(POC_ADDWF,  popGet(AOP(result),0));
6480       } else {
6481
6482         tlbl = newiTempLabel(NULL);
6483         if (!pic14_sameRegs(AOP(left),AOP(result))) {
6484           emitpcode(POC_MOVFW,  popGet(AOP(left),0));
6485           emitpcode(POC_MOVWF,  popGet(AOP(result),0));
6486         }
6487
6488         emitpcode(POC_COMFW,  popGet(AOP(right),0));
6489         emitpcode(POC_RRF,    popGet(AOP(result),0));
6490         emitpLabel(tlbl->key);
6491         emitpcode(POC_RLF,    popGet(AOP(result),0));
6492         emitpcode(POC_ADDLW,  popGetLit(1));
6493         emitSKPC;
6494         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
6495       }
6496       goto release ;
6497     }
6498     
6499
6500     tlbl = newiTempLabel(NULL);
6501     offset = 0 ;   
6502     tlbl1 = newiTempLabel(NULL);
6503
6504     reAdjustPreg(AOP(result));    
6505     
6506     pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
6507     pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
6508     l = aopGet(AOP(result),offset,FALSE,FALSE);
6509     MOVA(l);
6510     pic14_emitcode("add","a,acc");         
6511     aopPut(AOP(result),"a",offset++);
6512     while (--size) {
6513         l = aopGet(AOP(result),offset,FALSE,FALSE);
6514         MOVA(l);
6515         pic14_emitcode("rlc","a");         
6516         aopPut(AOP(result),"a",offset++);
6517     }
6518     reAdjustPreg(AOP(result));
6519
6520     pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
6521     pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6522 release:
6523     freeAsmop (right,NULL,ic,TRUE);
6524     freeAsmop(left,NULL,ic,TRUE);
6525     freeAsmop(result,NULL,ic,TRUE);
6526 }
6527
6528 /*-----------------------------------------------------------------*/
6529 /* genrshOne - right shift a one byte quantity by known count      */
6530 /*-----------------------------------------------------------------*/
6531 static void genrshOne (operand *result, operand *left,
6532                        int shCount, int sign)
6533 {
6534     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6535     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
6536 }
6537
6538 /*-----------------------------------------------------------------*/
6539 /* genrshTwo - right shift two bytes by known amount != 0          */
6540 /*-----------------------------------------------------------------*/
6541 static void genrshTwo (operand *result,operand *left,
6542                        int shCount, int sign)
6543 {
6544     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6545     /* if shCount >= 8 */
6546     if (shCount >= 8) {
6547         shCount -= 8 ;
6548         if (shCount)
6549             shiftR1Left2Result(left, MSB16, result, LSB,
6550                                shCount, sign);
6551         else 
6552             movLeft2Result(left, MSB16, result, LSB, sign);
6553         if(sign)
6554           addSign(result, MSB16, sign);
6555         else
6556           emitpcode(POC_CLRF,popGet(AOP(result),MSB16));
6557
6558     }
6559
6560     /*  1 <= shCount <= 7 */
6561     else
6562         shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
6563 }
6564
6565 /*-----------------------------------------------------------------*/
6566 /* shiftRLong - shift right one long from left to result           */
6567 /* offl = LSB or MSB16                                             */
6568 /*-----------------------------------------------------------------*/
6569 static void shiftRLong (operand *left, int offl,
6570                         operand *result, int sign)
6571 {
6572     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6573     if(!sign)
6574         pic14_emitcode("clr","c");
6575     MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE));
6576     if(sign)
6577         pic14_emitcode("mov","c,acc.7");
6578     pic14_emitcode("rrc","a");
6579     aopPut(AOP(result),"a",MSB32-offl);
6580     if(offl == MSB16)
6581         /* add sign of "a" */
6582         addSign(result, MSB32, sign);
6583
6584     MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE));
6585     pic14_emitcode("rrc","a");
6586     aopPut(AOP(result),"a",MSB24-offl);
6587
6588     MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE));
6589     pic14_emitcode("rrc","a");
6590     aopPut(AOP(result),"a",MSB16-offl);
6591
6592     if(offl == LSB){
6593         MOVA(aopGet(AOP(left),LSB,FALSE,FALSE));
6594         pic14_emitcode("rrc","a");
6595         aopPut(AOP(result),"a",LSB);
6596     }
6597 }
6598
6599 /*-----------------------------------------------------------------*/
6600 /* genrshFour - shift four byte by a known amount != 0             */
6601 /*-----------------------------------------------------------------*/
6602 static void genrshFour (operand *result, operand *left,
6603                         int shCount, int sign)
6604 {
6605     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6606     /* if shifting more that 3 bytes */
6607     if(shCount >= 24 ) {
6608         shCount -= 24;
6609         if(shCount)
6610             shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
6611         else
6612             movLeft2Result(left, MSB32, result, LSB, sign);
6613         addSign(result, MSB16, sign);
6614     }
6615     else if(shCount >= 16){
6616         shCount -= 16;
6617         if(shCount)
6618             shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
6619         else{
6620             movLeft2Result(left, MSB24, result, LSB, 0);
6621             movLeft2Result(left, MSB32, result, MSB16, sign);
6622         }
6623         addSign(result, MSB24, sign);
6624     }
6625     else if(shCount >= 8){
6626         shCount -= 8;
6627         if(shCount == 1)
6628             shiftRLong(left, MSB16, result, sign);
6629         else if(shCount == 0){
6630             movLeft2Result(left, MSB16, result, LSB, 0);
6631             movLeft2Result(left, MSB24, result, MSB16, 0);
6632             movLeft2Result(left, MSB32, result, MSB24, sign);
6633             addSign(result, MSB32, sign);
6634         }
6635         else{
6636             shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
6637             shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
6638             /* the last shift is signed */
6639             shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
6640             addSign(result, MSB32, sign);
6641         }
6642     }
6643     else{   /* 1 <= shCount <= 7 */
6644         if(shCount <= 2){
6645             shiftRLong(left, LSB, result, sign);
6646             if(shCount == 2)
6647                 shiftRLong(result, LSB, result, sign);
6648         }
6649         else{
6650             shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
6651             shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
6652             shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
6653         }
6654     }
6655 }
6656
6657 /*-----------------------------------------------------------------*/
6658 /* genRightShiftLiteral - right shifting by known count            */
6659 /*-----------------------------------------------------------------*/
6660 static void genRightShiftLiteral (operand *left,
6661                                   operand *right,
6662                                   operand *result,
6663                                   iCode *ic,
6664                                   int sign)
6665 {    
6666     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6667     int size;
6668
6669     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6670     freeAsmop(right,NULL,ic,TRUE);
6671
6672     aopOp(left,ic,FALSE);
6673     aopOp(result,ic,FALSE);
6674
6675 #if VIEW_SIZE
6676     pic14_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
6677              AOP_SIZE(left));
6678 #endif
6679
6680     size = pic14_getDataSize(left);
6681     /* test the LEFT size !!! */
6682
6683     /* I suppose that the left size >= result size */
6684     if(shCount == 0){
6685         size = pic14_getDataSize(result);
6686         while(size--)
6687             movLeft2Result(left, size, result, size, 0);
6688     }
6689
6690     else if(shCount >= (size * 8)){
6691         if(sign)
6692             /* get sign in acc.7 */
6693             MOVA(aopGet(AOP(left),size-1,FALSE,FALSE));
6694         addSign(result, LSB, sign);
6695     } else{
6696         switch (size) {
6697             case 1:
6698                 genrshOne (result,left,shCount,sign);
6699                 break;
6700
6701             case 2:
6702                 genrshTwo (result,left,shCount,sign);
6703                 break;
6704
6705             case 4:
6706                 genrshFour (result,left,shCount,sign);
6707                 break;
6708             default :
6709                 break;
6710         }
6711
6712         freeAsmop(left,NULL,ic,TRUE);
6713         freeAsmop(result,NULL,ic,TRUE);
6714     }
6715 }
6716
6717 /*-----------------------------------------------------------------*/
6718 /* genSignedRightShift - right shift of signed number              */
6719 /*-----------------------------------------------------------------*/
6720 static void genSignedRightShift (iCode *ic)
6721 {
6722     operand *right, *left, *result;
6723     int size, offset;
6724     char *l;
6725     symbol *tlbl, *tlbl1 ;
6726
6727     /* we do it the hard way put the shift count in b
6728     and loop thru preserving the sign */
6729     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6730
6731     right = IC_RIGHT(ic);
6732     left  = IC_LEFT(ic);
6733     result = IC_RESULT(ic);
6734
6735     aopOp(right,ic,FALSE);  
6736
6737
6738     if ( AOP_TYPE(right) == AOP_LIT) {
6739         genRightShiftLiteral (left,right,result,ic,1);
6740         return ;
6741     }
6742         /* shift count is unknown then we have to form 
6743        a loop get the loop count in B : Note: we take
6744        only the lower order byte since shifting
6745        more that 32 bits make no sense anyway, ( the
6746        largest size of an object can be only 32 bits ) */  
6747
6748     pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
6749     pic14_emitcode("inc","b");
6750     freeAsmop (right,NULL,ic,TRUE);
6751     aopOp(left,ic,FALSE);
6752     aopOp(result,ic,FALSE);
6753
6754     /* now move the left to the result if they are not the
6755     same */
6756     if (!pic14_sameRegs(AOP(left),AOP(result)) && 
6757         AOP_SIZE(result) > 1) {
6758
6759         size = AOP_SIZE(result);
6760         offset=0;
6761         while (size--) {
6762             l = aopGet(AOP(left),offset,FALSE,TRUE);
6763             if (*l == '@' && IS_AOP_PREG(result)) {
6764
6765                 pic14_emitcode("mov","a,%s",l);
6766                 aopPut(AOP(result),"a",offset);
6767             } else
6768                 aopPut(AOP(result),l,offset);
6769             offset++;
6770         }
6771     }
6772
6773     /* mov the highest order bit to OVR */    
6774     tlbl = newiTempLabel(NULL);
6775     tlbl1= newiTempLabel(NULL);
6776
6777     size = AOP_SIZE(result);
6778     offset = size - 1;
6779     pic14_emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
6780     pic14_emitcode("rlc","a");
6781     pic14_emitcode("mov","ov,c");
6782     /* if it is only one byte then */
6783     if (size == 1) {
6784         l = aopGet(AOP(left),0,FALSE,FALSE);
6785         MOVA(l);
6786         pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
6787         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6788         pic14_emitcode("mov","c,ov");
6789         pic14_emitcode("rrc","a");
6790         pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
6791         pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6792         aopPut(AOP(result),"a",0);
6793         goto release ;
6794     }
6795
6796     reAdjustPreg(AOP(result));
6797     pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
6798     pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
6799     pic14_emitcode("mov","c,ov");
6800     while (size--) {
6801         l = aopGet(AOP(result),offset,FALSE,FALSE);
6802         MOVA(l);
6803         pic14_emitcode("rrc","a");         
6804         aopPut(AOP(result),"a",offset--);
6805     }
6806     reAdjustPreg(AOP(result));
6807     pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
6808     pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6809
6810 release:
6811     freeAsmop(left,NULL,ic,TRUE);
6812     freeAsmop(result,NULL,ic,TRUE);
6813 }
6814
6815 /*-----------------------------------------------------------------*/
6816 /* genRightShift - generate code for right shifting                */
6817 /*-----------------------------------------------------------------*/
6818 static void genRightShift (iCode *ic)
6819 {
6820     operand *right, *left, *result;
6821     sym_link *retype ;
6822     int size, offset;
6823     char *l;
6824     symbol *tlbl, *tlbl1 ;
6825
6826     /* if signed then we do it the hard way preserve the
6827     sign bit moving it inwards */
6828     retype = getSpec(operandType(IC_RESULT(ic)));
6829     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6830
6831     if (!SPEC_USIGN(retype)) {
6832         genSignedRightShift (ic);
6833         return ;
6834     }
6835
6836     /* signed & unsigned types are treated the same : i.e. the
6837     signed is NOT propagated inwards : quoting from the
6838     ANSI - standard : "for E1 >> E2, is equivalent to division
6839     by 2**E2 if unsigned or if it has a non-negative value,
6840     otherwise the result is implementation defined ", MY definition
6841     is that the sign does not get propagated */
6842
6843     right = IC_RIGHT(ic);
6844     left  = IC_LEFT(ic);
6845     result = IC_RESULT(ic);
6846
6847     aopOp(right,ic,FALSE);
6848
6849     /* if the shift count is known then do it 
6850     as efficiently as possible */
6851     if (AOP_TYPE(right) == AOP_LIT) {
6852         genRightShiftLiteral (left,right,result,ic, 0);
6853         return ;
6854     }
6855
6856     /* shift count is unknown then we have to form 
6857     a loop get the loop count in B : Note: we take
6858     only the lower order byte since shifting
6859     more that 32 bits make no sense anyway, ( the
6860     largest size of an object can be only 32 bits ) */  
6861
6862     pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
6863     pic14_emitcode("inc","b");
6864     aopOp(left,ic,FALSE);
6865     aopOp(result,ic,FALSE);
6866
6867     /* now move the left to the result if they are not the
6868     same */
6869     if (!pic14_sameRegs(AOP(left),AOP(result)) && 
6870         AOP_SIZE(result) > 1) {
6871
6872         size = AOP_SIZE(result);
6873         offset=0;
6874         while (size--) {
6875             l = aopGet(AOP(left),offset,FALSE,TRUE);
6876             if (*l == '@' && IS_AOP_PREG(result)) {
6877
6878                 pic14_emitcode("mov","a,%s",l);
6879                 aopPut(AOP(result),"a",offset);
6880             } else
6881                 aopPut(AOP(result),l,offset);
6882             offset++;
6883         }
6884     }
6885
6886     tlbl = newiTempLabel(NULL);
6887     tlbl1= newiTempLabel(NULL);
6888     size = AOP_SIZE(result);
6889     offset = size - 1;
6890
6891     /* if it is only one byte then */
6892     if (size == 1) {
6893 /*
6894         l = aopGet(AOP(left),0,FALSE,FALSE);
6895         MOVA(l);
6896         pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
6897         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6898         CLRC;
6899         pic14_emitcode("rrc","a");
6900         pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
6901         pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6902         aopPut(AOP(result),"a",0);
6903 */
6904         tlbl = newiTempLabel(NULL);
6905         if (!pic14_sameRegs(AOP(left),AOP(result))) {
6906           emitpcode(POC_MOVFW,  popGet(AOP(left),0));
6907           emitpcode(POC_MOVWF,  popGet(AOP(result),0));
6908         }
6909
6910         emitpcode(POC_COMFW,  popGet(AOP(right),0));
6911         emitpcode(POC_RLF,    popGet(AOP(result),0));
6912         emitpLabel(tlbl->key);
6913         emitpcode(POC_RRF,    popGet(AOP(result),0));
6914         emitpcode(POC_ADDLW,  popGetLit(1));
6915         emitSKPC;
6916         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
6917
6918         goto release ;
6919     }
6920
6921     reAdjustPreg(AOP(result));
6922     pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
6923     pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
6924     CLRC;
6925     while (size--) {
6926         l = aopGet(AOP(result),offset,FALSE,FALSE);
6927         MOVA(l);
6928         pic14_emitcode("rrc","a");         
6929         aopPut(AOP(result),"a",offset--);
6930     }
6931     reAdjustPreg(AOP(result));
6932
6933     pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
6934     pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6935
6936 release:
6937     freeAsmop(left,NULL,ic,TRUE);
6938     freeAsmop (right,NULL,ic,TRUE);
6939     freeAsmop(result,NULL,ic,TRUE);
6940 }
6941
6942 /*-----------------------------------------------------------------*/
6943 /* genUnpackBits - generates code for unpacking bits               */
6944 /*-----------------------------------------------------------------*/
6945 static void genUnpackBits (operand *result, char *rname, int ptype)
6946 {    
6947     int shCnt ;
6948     int rlen = 0 ;
6949     sym_link *etype;
6950     int offset = 0 ;
6951
6952     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6953     etype = getSpec(operandType(result));
6954
6955     /* read the first byte  */
6956     switch (ptype) {
6957
6958     case POINTER:
6959     case IPOINTER:
6960         pic14_emitcode("mov","a,@%s",rname);
6961         break;
6962         
6963     case PPOINTER:
6964         pic14_emitcode("movx","a,@%s",rname);
6965         break;
6966         
6967     case FPOINTER:
6968         pic14_emitcode("movx","a,@dptr");
6969         break;
6970
6971     case CPOINTER:
6972         pic14_emitcode("clr","a");
6973         pic14_emitcode("movc","a","@a+dptr");
6974         break;
6975
6976     case GPOINTER:
6977         pic14_emitcode("lcall","__gptrget");
6978         break;
6979     }
6980
6981     /* if we have bitdisplacement then it fits   */
6982     /* into this byte completely or if length is */
6983     /* less than a byte                          */
6984     if ((shCnt = SPEC_BSTR(etype)) || 
6985         (SPEC_BLEN(etype) <= 8))  {
6986
6987         /* shift right acc */
6988         AccRsh(shCnt);
6989
6990         pic14_emitcode("anl","a,#0x%02x",
6991                  ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
6992         aopPut(AOP(result),"a",offset);
6993         return ;
6994     }
6995
6996     /* bit field did not fit in a byte  */
6997     rlen = SPEC_BLEN(etype) - 8;
6998     aopPut(AOP(result),"a",offset++);
6999
7000     while (1)  {
7001
7002         switch (ptype) {
7003         case POINTER:
7004         case IPOINTER:
7005             pic14_emitcode("inc","%s",rname);
7006             pic14_emitcode("mov","a,@%s",rname);
7007             break;
7008             
7009         case PPOINTER:
7010             pic14_emitcode("inc","%s",rname);
7011             pic14_emitcode("movx","a,@%s",rname);
7012             break;
7013
7014         case FPOINTER:
7015             pic14_emitcode("inc","dptr");
7016             pic14_emitcode("movx","a,@dptr");
7017             break;
7018             
7019         case CPOINTER:
7020             pic14_emitcode("clr","a");
7021             pic14_emitcode("inc","dptr");
7022             pic14_emitcode("movc","a","@a+dptr");
7023             break;
7024             
7025         case GPOINTER:
7026             pic14_emitcode("inc","dptr");
7027             pic14_emitcode("lcall","__gptrget");
7028             break;
7029         }
7030
7031         rlen -= 8;            
7032         /* if we are done */
7033         if ( rlen <= 0 )
7034             break ;
7035         
7036         aopPut(AOP(result),"a",offset++);
7037                               
7038     }
7039     
7040     if (rlen) {
7041         pic14_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
7042         aopPut(AOP(result),"a",offset);        
7043     }
7044     
7045     return ;
7046 }
7047
7048
7049 /*-----------------------------------------------------------------*/
7050 /* genDataPointerGet - generates code when ptr offset is known     */
7051 /*-----------------------------------------------------------------*/
7052 static void genDataPointerGet (operand *left, 
7053                                operand *result, 
7054                                iCode *ic)
7055 {
7056   int size , offset = 0;
7057
7058
7059   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7060
7061
7062   /* optimization - most of the time, left and result are the same
7063    * address, but different types. for the pic code, we could omit
7064    * the following
7065    */
7066
7067   aopOp(result,ic,TRUE);
7068
7069   emitpcode(POC_MOVFW, popGet(AOP(left),0));
7070
7071   size = AOP_SIZE(result);
7072
7073   while (size--) {
7074     emitpcode(POC_MOVWF, popGet(AOP(result),offset));
7075     offset++;
7076   }
7077
7078   freeAsmop(left,NULL,ic,TRUE);
7079   freeAsmop(result,NULL,ic,TRUE);
7080 }
7081
7082 /*-----------------------------------------------------------------*/
7083 /* genNearPointerGet - pic14_emitcode for near pointer fetch             */
7084 /*-----------------------------------------------------------------*/
7085 static void genNearPointerGet (operand *left, 
7086                                operand *result, 
7087                                iCode *ic)
7088 {
7089     asmop *aop = NULL;
7090     regs *preg = NULL ;
7091     char *rname ;
7092     sym_link *rtype, *retype;
7093     sym_link *ltype = operandType(left);    
7094     char buffer[80];
7095
7096     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7097
7098     rtype = operandType(result);
7099     retype= getSpec(rtype);
7100     
7101     aopOp(left,ic,FALSE);
7102     
7103     /* if left is rematerialisable and
7104        result is not bit variable type and
7105        the left is pointer to data space i.e
7106        lower 128 bytes of space */
7107     if (AOP_TYPE(left) == AOP_IMMD &&
7108         !IS_BITVAR(retype)         &&
7109         DCL_TYPE(ltype) == POINTER) {
7110         genDataPointerGet (left,result,ic);
7111         return ;
7112     }
7113     
7114     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7115
7116         /* if the value is already in a pointer register
7117        then don't need anything more */
7118     if (!AOP_INPREG(AOP(left))) {
7119         /* otherwise get a free pointer register */
7120     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7121         aop = newAsmop(0);
7122         preg = getFreePtr(ic,&aop,FALSE);
7123         pic14_emitcode("mov","%s,%s",
7124                 preg->name,
7125                 aopGet(AOP(left),0,FALSE,TRUE));
7126         rname = preg->name ;
7127     } else
7128         rname = aopGet(AOP(left),0,FALSE,FALSE);
7129     
7130     freeAsmop(left,NULL,ic,TRUE);
7131     aopOp (result,ic,FALSE);
7132     
7133       /* if bitfield then unpack the bits */
7134     if (IS_BITVAR(retype)) 
7135         genUnpackBits (result,rname,POINTER);
7136     else {
7137         /* we have can just get the values */
7138         int size = AOP_SIZE(result);
7139         int offset = 0 ;        
7140         
7141     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7142         while (size--) {
7143             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
7144
7145                 pic14_emitcode("mov","a,@%s",rname);
7146                 aopPut(AOP(result),"a",offset);
7147             } else {
7148                 sprintf(buffer,"@%s",rname);
7149                 aopPut(AOP(result),buffer,offset);
7150             }
7151             offset++ ;
7152             if (size)
7153                 pic14_emitcode("inc","%s",rname);
7154         }
7155     }
7156
7157     /* now some housekeeping stuff */
7158     if (aop) {
7159         /* we had to allocate for this iCode */
7160     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7161         freeAsmop(NULL,aop,ic,TRUE);
7162     } else { 
7163         /* we did not allocate which means left
7164            already in a pointer register, then
7165            if size > 0 && this could be used again
7166            we have to point it back to where it 
7167            belongs */
7168     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7169         if (AOP_SIZE(result) > 1 &&
7170             !OP_SYMBOL(left)->remat &&
7171             ( OP_SYMBOL(left)->liveTo > ic->seq ||
7172               ic->depth )) {
7173             int size = AOP_SIZE(result) - 1;
7174             while (size--)
7175                 pic14_emitcode("dec","%s",rname);
7176         }
7177     }
7178
7179     /* done */
7180     freeAsmop(result,NULL,ic,TRUE);
7181      
7182 }
7183
7184 /*-----------------------------------------------------------------*/
7185 /* genPagedPointerGet - pic14_emitcode for paged pointer fetch           */
7186 /*-----------------------------------------------------------------*/
7187 static void genPagedPointerGet (operand *left, 
7188                                operand *result, 
7189                                iCode *ic)
7190 {
7191     asmop *aop = NULL;
7192     regs *preg = NULL ;
7193     char *rname ;
7194     sym_link *rtype, *retype;    
7195
7196     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7197
7198     rtype = operandType(result);
7199     retype= getSpec(rtype);
7200     
7201     aopOp(left,ic,FALSE);
7202
7203   /* if the value is already in a pointer register
7204        then don't need anything more */
7205     if (!AOP_INPREG(AOP(left))) {
7206         /* otherwise get a free pointer register */
7207         aop = newAsmop(0);
7208         preg = getFreePtr(ic,&aop,FALSE);
7209         pic14_emitcode("mov","%s,%s",
7210                 preg->name,
7211                 aopGet(AOP(left),0,FALSE,TRUE));
7212         rname = preg->name ;
7213     } else
7214         rname = aopGet(AOP(left),0,FALSE,FALSE);
7215     
7216     freeAsmop(left,NULL,ic,TRUE);
7217     aopOp (result,ic,FALSE);
7218
7219     /* if bitfield then unpack the bits */
7220     if (IS_BITVAR(retype)) 
7221         genUnpackBits (result,rname,PPOINTER);
7222     else {
7223         /* we have can just get the values */
7224         int size = AOP_SIZE(result);
7225         int offset = 0 ;        
7226         
7227         while (size--) {
7228             
7229             pic14_emitcode("movx","a,@%s",rname);
7230             aopPut(AOP(result),"a",offset);
7231             
7232             offset++ ;
7233             
7234             if (size)
7235                 pic14_emitcode("inc","%s",rname);
7236         }
7237     }
7238
7239     /* now some housekeeping stuff */
7240     if (aop) {
7241         /* we had to allocate for this iCode */
7242         freeAsmop(NULL,aop,ic,TRUE);
7243     } else { 
7244         /* we did not allocate which means left
7245            already in a pointer register, then
7246            if size > 0 && this could be used again
7247            we have to point it back to where it 
7248            belongs */
7249         if (AOP_SIZE(result) > 1 &&
7250             !OP_SYMBOL(left)->remat &&
7251             ( OP_SYMBOL(left)->liveTo > ic->seq ||
7252               ic->depth )) {
7253             int size = AOP_SIZE(result) - 1;
7254             while (size--)
7255                 pic14_emitcode("dec","%s",rname);
7256         }
7257     }
7258
7259     /* done */
7260     freeAsmop(result,NULL,ic,TRUE);
7261     
7262         
7263 }
7264
7265 /*-----------------------------------------------------------------*/
7266 /* genFarPointerGet - gget value from far space                    */
7267 /*-----------------------------------------------------------------*/
7268 static void genFarPointerGet (operand *left,
7269                               operand *result, iCode *ic)
7270 {
7271     int size, offset ;
7272     sym_link *retype = getSpec(operandType(result));
7273
7274     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7275
7276     aopOp(left,ic,FALSE);
7277
7278     /* if the operand is already in dptr 
7279     then we do nothing else we move the value to dptr */
7280     if (AOP_TYPE(left) != AOP_STR) {
7281         /* if this is remateriazable */
7282         if (AOP_TYPE(left) == AOP_IMMD)
7283             pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
7284         else { /* we need to get it byte by byte */
7285             pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
7286             pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
7287             if (options.model == MODEL_FLAT24)
7288             {
7289                pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
7290             }
7291         }
7292     }
7293     /* so dptr know contains the address */
7294     freeAsmop(left,NULL,ic,TRUE);
7295     aopOp(result,ic,FALSE);
7296
7297     /* if bit then unpack */
7298     if (IS_BITVAR(retype)) 
7299         genUnpackBits(result,"dptr",FPOINTER);
7300     else {
7301         size = AOP_SIZE(result);
7302         offset = 0 ;
7303
7304         while (size--) {
7305             pic14_emitcode("movx","a,@dptr");
7306             aopPut(AOP(result),"a",offset++);
7307             if (size)
7308                 pic14_emitcode("inc","dptr");
7309         }
7310     }
7311
7312     freeAsmop(result,NULL,ic,TRUE);
7313 }
7314
7315 /*-----------------------------------------------------------------*/
7316 /* pic14_emitcodePointerGet - gget value from code space                  */
7317 /*-----------------------------------------------------------------*/
7318 static void pic14_emitcodePointerGet (operand *left,
7319                                 operand *result, iCode *ic)
7320 {
7321     int size, offset ;
7322     sym_link *retype = getSpec(operandType(result));
7323
7324     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7325
7326     aopOp(left,ic,FALSE);
7327
7328     /* if the operand is already in dptr 
7329     then we do nothing else we move the value to dptr */
7330     if (AOP_TYPE(left) != AOP_STR) {
7331         /* if this is remateriazable */
7332         if (AOP_TYPE(left) == AOP_IMMD)
7333             pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
7334         else { /* we need to get it byte by byte */
7335             pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
7336             pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
7337             if (options.model == MODEL_FLAT24)
7338             {
7339                pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
7340             }
7341         }
7342     }
7343     /* so dptr know contains the address */
7344     freeAsmop(left,NULL,ic,TRUE);
7345     aopOp(result,ic,FALSE);
7346
7347     /* if bit then unpack */
7348     if (IS_BITVAR(retype)) 
7349         genUnpackBits(result,"dptr",CPOINTER);
7350     else {
7351         size = AOP_SIZE(result);
7352         offset = 0 ;
7353
7354         while (size--) {
7355             pic14_emitcode("clr","a");
7356             pic14_emitcode("movc","a,@a+dptr");
7357             aopPut(AOP(result),"a",offset++);
7358             if (size)
7359                 pic14_emitcode("inc","dptr");
7360         }
7361     }
7362
7363     freeAsmop(result,NULL,ic,TRUE);
7364 }
7365
7366 /*-----------------------------------------------------------------*/
7367 /* genGenPointerGet - gget value from generic pointer space        */
7368 /*-----------------------------------------------------------------*/
7369 static void genGenPointerGet (operand *left,
7370                               operand *result, iCode *ic)
7371 {
7372   int size, offset ;
7373   sym_link *retype = getSpec(operandType(result));
7374
7375   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7376   aopOp(left,ic,FALSE);
7377   aopOp(result,ic,FALSE);
7378
7379
7380   DEBUGpic14_AopType(__LINE__,left,NULL,result);
7381
7382   /* if the operand is already in dptr 
7383      then we do nothing else we move the value to dptr */
7384   if (AOP_TYPE(left) != AOP_STR) {
7385     /* if this is remateriazable */
7386     if (AOP_TYPE(left) == AOP_IMMD) {
7387       pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
7388       pic14_emitcode("mov","b,#%d",pointerCode(retype));
7389     }
7390     else { /* we need to get it byte by byte */
7391
7392       emitpcode(POC_MOVFW,popGet(AOP(left),0));
7393       emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
7394
7395       size = AOP_SIZE(result);
7396       offset = 0 ;
7397
7398       while(size--) {
7399         emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
7400         emitpcode(POC_MOVWF,popGet(AOP(result),offset++));
7401         if(size)
7402           emitpcode(POC_INCF,popCopyReg(&pc_fsr));
7403       }
7404       goto release;
7405     }
7406   }
7407   /* so dptr know contains the address */
7408
7409   /* if bit then unpack */
7410   if (IS_BITVAR(retype)) 
7411     genUnpackBits(result,"dptr",GPOINTER);
7412
7413  release:
7414   freeAsmop(left,NULL,ic,TRUE);
7415   freeAsmop(result,NULL,ic,TRUE);
7416
7417 }
7418
7419 /*-----------------------------------------------------------------*/
7420 /* genPointerGet - generate code for pointer get                   */
7421 /*-----------------------------------------------------------------*/
7422 static void genPointerGet (iCode *ic)
7423 {
7424     operand *left, *result ;
7425     sym_link *type, *etype;
7426     int p_type;
7427
7428     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7429
7430     left = IC_LEFT(ic);
7431     result = IC_RESULT(ic) ;
7432
7433     /* depending on the type of pointer we need to
7434     move it to the correct pointer register */
7435     type = operandType(left);
7436     etype = getSpec(type);
7437     /* if left is of type of pointer then it is simple */
7438     if (IS_PTR(type) && !IS_FUNC(type->next)) 
7439         p_type = DCL_TYPE(type);
7440     else {
7441         /* we have to go by the storage class */
7442         p_type = PTR_TYPE(SPEC_OCLS(etype));
7443
7444 /*      if (SPEC_OCLS(etype)->codesp ) { */
7445 /*          p_type = CPOINTER ;  */
7446 /*      } */
7447 /*      else */
7448 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
7449 /*              p_type = FPOINTER ; */
7450 /*          else */
7451 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
7452 /*                  p_type = PPOINTER; */
7453 /*              else */
7454 /*                  if (SPEC_OCLS(etype) == idata ) */
7455 /*                      p_type = IPOINTER; */
7456 /*                  else */
7457 /*                      p_type = POINTER ; */
7458     }
7459
7460     /* now that we have the pointer type we assign
7461     the pointer values */
7462     switch (p_type) {
7463
7464     case POINTER:       
7465     case IPOINTER:
7466         genNearPointerGet (left,result,ic);
7467         break;
7468
7469     case PPOINTER:
7470         genPagedPointerGet(left,result,ic);
7471         break;
7472
7473     case FPOINTER:
7474         genFarPointerGet (left,result,ic);
7475         break;
7476
7477     case CPOINTER:
7478         pic14_emitcodePointerGet (left,result,ic);
7479         break;
7480
7481     case GPOINTER:
7482         genGenPointerGet (left,result,ic);
7483         break;
7484     }
7485
7486 }
7487
7488 /*-----------------------------------------------------------------*/
7489 /* genPackBits - generates code for packed bit storage             */
7490 /*-----------------------------------------------------------------*/
7491 static void genPackBits (sym_link    *etype ,
7492                          operand *right ,
7493                          char *rname, int p_type)
7494 {
7495     int shCount = 0 ;
7496     int offset = 0  ;
7497     int rLen = 0 ;
7498     int blen, bstr ;   
7499     char *l ;
7500
7501     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7502     blen = SPEC_BLEN(etype);
7503     bstr = SPEC_BSTR(etype);
7504
7505     l = aopGet(AOP(right),offset++,FALSE,FALSE);
7506     MOVA(l);   
7507
7508     /* if the bit lenth is less than or    */
7509     /* it exactly fits a byte then         */
7510     if (SPEC_BLEN(etype) <= 8 )  {
7511         shCount = SPEC_BSTR(etype) ;
7512
7513         /* shift left acc */
7514         AccLsh(shCount);
7515
7516         if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
7517
7518
7519             switch (p_type) {
7520                 case POINTER:
7521                     pic14_emitcode ("mov","b,a");
7522                     pic14_emitcode("mov","a,@%s",rname);
7523                     break;
7524
7525                 case FPOINTER:
7526                     pic14_emitcode ("mov","b,a");
7527                     pic14_emitcode("movx","a,@dptr");
7528                     break;
7529
7530                 case GPOINTER:
7531                     pic14_emitcode ("push","b");
7532                     pic14_emitcode ("push","acc");
7533                     pic14_emitcode ("lcall","__gptrget");
7534                     pic14_emitcode ("pop","b");
7535                     break;
7536             }
7537
7538             pic14_emitcode ("anl","a,#0x%02x",(unsigned char)
7539                       ((unsigned char)(0xFF << (blen+bstr)) | 
7540                        (unsigned char)(0xFF >> (8-bstr)) ) );
7541             pic14_emitcode ("orl","a,b");
7542             if (p_type == GPOINTER)
7543                 pic14_emitcode("pop","b");
7544         }
7545     }
7546
7547     switch (p_type) {
7548         case POINTER:
7549             pic14_emitcode("mov","@%s,a",rname);
7550             break;
7551
7552         case FPOINTER:
7553             pic14_emitcode("movx","@dptr,a");
7554             break;
7555
7556         case GPOINTER:
7557             DEBUGpic14_emitcode(";lcall","__gptrput");
7558             break;
7559     }
7560
7561     /* if we r done */
7562     if ( SPEC_BLEN(etype) <= 8 )
7563         return ;
7564
7565     pic14_emitcode("inc","%s",rname);
7566     rLen = SPEC_BLEN(etype) ;     
7567
7568     /* now generate for lengths greater than one byte */
7569     while (1) {
7570
7571         l = aopGet(AOP(right),offset++,FALSE,TRUE);
7572
7573         rLen -= 8 ;
7574         if (rLen <= 0 )
7575             break ;
7576
7577         switch (p_type) {
7578             case POINTER:
7579                 if (*l == '@') {
7580                     MOVA(l);
7581                     pic14_emitcode("mov","@%s,a",rname);
7582                 } else
7583                     pic14_emitcode("mov","@%s,%s",rname,l);
7584                 break;
7585
7586             case FPOINTER:
7587                 MOVA(l);
7588                 pic14_emitcode("movx","@dptr,a");
7589                 break;
7590
7591             case GPOINTER:
7592                 MOVA(l);
7593                 DEBUGpic14_emitcode(";lcall","__gptrput");
7594                 break;  
7595         }   
7596         pic14_emitcode ("inc","%s",rname);
7597     }
7598
7599     MOVA(l);
7600
7601     /* last last was not complete */
7602     if (rLen)   {
7603         /* save the byte & read byte */
7604         switch (p_type) {
7605             case POINTER:
7606                 pic14_emitcode ("mov","b,a");
7607                 pic14_emitcode("mov","a,@%s",rname);
7608                 break;
7609
7610             case FPOINTER:
7611                 pic14_emitcode ("mov","b,a");
7612                 pic14_emitcode("movx","a,@dptr");
7613                 break;
7614
7615             case GPOINTER:
7616                 pic14_emitcode ("push","b");
7617                 pic14_emitcode ("push","acc");
7618                 pic14_emitcode ("lcall","__gptrget");
7619                 pic14_emitcode ("pop","b");
7620                 break;
7621         }
7622
7623         pic14_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
7624         pic14_emitcode ("orl","a,b");
7625     }
7626
7627     if (p_type == GPOINTER)
7628         pic14_emitcode("pop","b");
7629
7630     switch (p_type) {
7631
7632     case POINTER:
7633         pic14_emitcode("mov","@%s,a",rname);
7634         break;
7635         
7636     case FPOINTER:
7637         pic14_emitcode("movx","@dptr,a");
7638         break;
7639         
7640     case GPOINTER:
7641         DEBUGpic14_emitcode(";lcall","__gptrput");
7642         break;                  
7643     }
7644 }
7645 /*-----------------------------------------------------------------*/
7646 /* genDataPointerSet - remat pointer to data space                 */
7647 /*-----------------------------------------------------------------*/
7648 static void genDataPointerSet(operand *right,
7649                               operand *result,
7650                               iCode *ic)
7651 {
7652     int size, offset = 0 ;
7653     char *l, buffer[256];
7654
7655     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7656     aopOp(right,ic,FALSE);
7657     
7658     l = aopGet(AOP(result),0,FALSE,TRUE);
7659     size = AOP_SIZE(right);
7660     // tsd, was l+1 - the underline `_' prefix was being stripped
7661     while (size--) {
7662         if (offset)
7663             sprintf(buffer,"(%s + %d)",l,offset);
7664         else
7665             sprintf(buffer,"%s",l);
7666
7667         if (AOP_TYPE(right) == AOP_LIT) {
7668           unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
7669           lit = lit >> (8*offset);
7670           if(lit&0xff) {
7671             pic14_emitcode("movlw","%d",lit);
7672             pic14_emitcode("movwf","%s",buffer);
7673
7674             emitpcode(POC_MOVLW, popGetLit(lit&0xff));
7675             emitpcode(POC_MOVWF, popRegFromString(buffer));
7676
7677           } else {
7678             pic14_emitcode("clrf","%s",buffer);
7679             emitpcode(POC_CLRF, popRegFromString(buffer));
7680           }
7681         }else {
7682           pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
7683           pic14_emitcode("movwf","%s",buffer);
7684
7685           emitpcode(POC_MOVFW, popGet(AOP(right),offset));
7686           emitpcode(POC_MOVWF, popRegFromString(buffer));
7687
7688         }
7689
7690         offset++;
7691     }
7692
7693     freeAsmop(right,NULL,ic,TRUE);
7694     freeAsmop(result,NULL,ic,TRUE);
7695 }
7696
7697 /*-----------------------------------------------------------------*/
7698 /* genNearPointerSet - pic14_emitcode for near pointer put                */
7699 /*-----------------------------------------------------------------*/
7700 static void genNearPointerSet (operand *right,
7701                                operand *result, 
7702                                iCode *ic)
7703 {
7704     asmop *aop = NULL;
7705     char *l;
7706     sym_link *retype;
7707     sym_link *ptype = operandType(result);
7708
7709     
7710     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7711     retype= getSpec(operandType(right));
7712
7713     aopOp(result,ic,FALSE);
7714     
7715     /* if the result is rematerializable &
7716        in data space & not a bit variable */
7717     if (AOP_TYPE(result) == AOP_IMMD &&
7718         DCL_TYPE(ptype) == POINTER   &&
7719         !IS_BITVAR(retype)) {
7720         genDataPointerSet (right,result,ic);
7721         return;
7722     }
7723
7724     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7725
7726     /* if the value is already in a pointer register
7727     then don't need anything more */
7728     if (!AOP_INPREG(AOP(result))) {
7729         /* otherwise get a free pointer register */
7730         //aop = newAsmop(0);
7731         //preg = getFreePtr(ic,&aop,FALSE);
7732         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7733         //pic14_emitcode("mov","%s,%s",
7734         //         preg->name,
7735         //         aopGet(AOP(result),0,FALSE,TRUE));
7736         //rname = preg->name ;
7737         pic14_emitcode("movwf","fsr");
7738     }// else
7739     //   rname = aopGet(AOP(result),0,FALSE,FALSE);
7740
7741     freeAsmop(result,NULL,ic,TRUE);
7742     aopOp (right,ic,FALSE);
7743     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7744
7745     /* if bitfield then unpack the bits */
7746     if (IS_BITVAR(retype)) {
7747       werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
7748              "The programmer is obviously confused");
7749       //genPackBits (retype,right,rname,POINTER);
7750       exit(1);
7751     }
7752     else {
7753         /* we have can just get the values */
7754         int size = AOP_SIZE(right);
7755         int offset = 0 ;    
7756
7757     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7758         while (size--) {
7759             l = aopGet(AOP(right),offset,FALSE,TRUE);
7760             if (*l == '@' ) {
7761               //MOVA(l);
7762               //pic14_emitcode("mov","@%s,a",rname);
7763               pic14_emitcode("movf","indf,w ;1");
7764             } else {
7765
7766               if (AOP_TYPE(right) == AOP_LIT) {
7767                 unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
7768                 if(lit) {
7769                   pic14_emitcode("movlw","%s",l);
7770                   pic14_emitcode("movwf","indf ;2");
7771                 } else 
7772                   pic14_emitcode("clrf","indf");
7773               }else {
7774                 pic14_emitcode("movf","%s,w",l);
7775                 pic14_emitcode("movwf","indf ;2");
7776               }
7777             //pic14_emitcode("mov","@%s,%s",rname,l);
7778             }
7779             if (size)
7780               pic14_emitcode("incf","fsr,f ;3");
7781             //pic14_emitcode("inc","%s",rname);
7782             offset++;
7783         }
7784     }
7785
7786     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7787     /* now some housekeeping stuff */
7788     if (aop) {
7789         /* we had to allocate for this iCode */
7790         freeAsmop(NULL,aop,ic,TRUE);
7791     } else { 
7792         /* we did not allocate which means left
7793         already in a pointer register, then
7794         if size > 0 && this could be used again
7795         we have to point it back to where it 
7796         belongs */
7797     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7798         if (AOP_SIZE(right) > 1 &&
7799             !OP_SYMBOL(result)->remat &&
7800             ( OP_SYMBOL(result)->liveTo > ic->seq ||
7801               ic->depth )) {
7802             int size = AOP_SIZE(right) - 1;
7803             while (size--)
7804               pic14_emitcode("decf","fsr,f");
7805               //pic14_emitcode("dec","%s",rname);
7806         }
7807     }
7808
7809     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7810     /* done */
7811     freeAsmop(right,NULL,ic,TRUE);
7812
7813
7814 }
7815
7816 /*-----------------------------------------------------------------*/
7817 /* genPagedPointerSet - pic14_emitcode for Paged pointer put             */
7818 /*-----------------------------------------------------------------*/
7819 static void genPagedPointerSet (operand *right,
7820                                operand *result, 
7821                                iCode *ic)
7822 {
7823     asmop *aop = NULL;
7824     regs *preg = NULL ;
7825     char *rname , *l;
7826     sym_link *retype;
7827        
7828     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7829
7830     retype= getSpec(operandType(right));
7831     
7832     aopOp(result,ic,FALSE);
7833     
7834     /* if the value is already in a pointer register
7835        then don't need anything more */
7836     if (!AOP_INPREG(AOP(result))) {
7837         /* otherwise get a free pointer register */
7838         aop = newAsmop(0);
7839         preg = getFreePtr(ic,&aop,FALSE);
7840         pic14_emitcode("mov","%s,%s",
7841                 preg->name,
7842                 aopGet(AOP(result),0,FALSE,TRUE));
7843         rname = preg->name ;
7844     } else
7845         rname = aopGet(AOP(result),0,FALSE,FALSE);
7846     
7847     freeAsmop(result,NULL,ic,TRUE);
7848     aopOp (right,ic,FALSE);
7849
7850     /* if bitfield then unpack the bits */
7851     if (IS_BITVAR(retype)) 
7852         genPackBits (retype,right,rname,PPOINTER);
7853     else {
7854         /* we have can just get the values */
7855         int size = AOP_SIZE(right);
7856         int offset = 0 ;        
7857         
7858         while (size--) {
7859             l = aopGet(AOP(right),offset,FALSE,TRUE);
7860             
7861             MOVA(l);
7862             pic14_emitcode("movx","@%s,a",rname);
7863
7864             if (size)
7865                 pic14_emitcode("inc","%s",rname);
7866
7867             offset++;
7868         }
7869     }
7870     
7871     /* now some housekeeping stuff */
7872     if (aop) {
7873         /* we had to allocate for this iCode */
7874         freeAsmop(NULL,aop,ic,TRUE);
7875     } else { 
7876         /* we did not allocate which means left
7877            already in a pointer register, then
7878            if size > 0 && this could be used again
7879            we have to point it back to where it 
7880            belongs */
7881         if (AOP_SIZE(right) > 1 &&
7882             !OP_SYMBOL(result)->remat &&
7883             ( OP_SYMBOL(result)->liveTo > ic->seq ||
7884               ic->depth )) {
7885             int size = AOP_SIZE(right) - 1;
7886             while (size--)
7887                 pic14_emitcode("dec","%s",rname);
7888         }
7889     }
7890
7891     /* done */
7892     freeAsmop(right,NULL,ic,TRUE);
7893     
7894         
7895 }
7896
7897 /*-----------------------------------------------------------------*/
7898 /* genFarPointerSet - set value from far space                     */
7899 /*-----------------------------------------------------------------*/
7900 static void genFarPointerSet (operand *right,
7901                               operand *result, iCode *ic)
7902 {
7903     int size, offset ;
7904     sym_link *retype = getSpec(operandType(right));
7905
7906     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7907     aopOp(result,ic,FALSE);
7908
7909     /* if the operand is already in dptr 
7910     then we do nothing else we move the value to dptr */
7911     if (AOP_TYPE(result) != AOP_STR) {
7912         /* if this is remateriazable */
7913         if (AOP_TYPE(result) == AOP_IMMD)
7914             pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
7915         else { /* we need to get it byte by byte */
7916             pic14_emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
7917             pic14_emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
7918             if (options.model == MODEL_FLAT24)
7919             {
7920                pic14_emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
7921             }
7922         }
7923     }
7924     /* so dptr know contains the address */
7925     freeAsmop(result,NULL,ic,TRUE);
7926     aopOp(right,ic,FALSE);
7927
7928     /* if bit then unpack */
7929     if (IS_BITVAR(retype)) 
7930         genPackBits(retype,right,"dptr",FPOINTER);
7931     else {
7932         size = AOP_SIZE(right);
7933         offset = 0 ;
7934
7935         while (size--) {
7936             char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
7937             MOVA(l);
7938             pic14_emitcode("movx","@dptr,a");
7939             if (size)
7940                 pic14_emitcode("inc","dptr");
7941         }
7942     }
7943
7944     freeAsmop(right,NULL,ic,TRUE);
7945 }
7946
7947 /*-----------------------------------------------------------------*/
7948 /* genGenPointerSet - set value from generic pointer space         */
7949 /*-----------------------------------------------------------------*/
7950 static void genGenPointerSet (operand *right,
7951                               operand *result, iCode *ic)
7952 {
7953   int size, offset ;
7954   sym_link *retype = getSpec(operandType(right));
7955
7956   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7957
7958   aopOp(result,ic,FALSE);
7959   aopOp(right,ic,FALSE);
7960   size = AOP_SIZE(right);
7961
7962   DEBUGpic14_AopType(__LINE__,NULL,right,result);
7963
7964   /* if the operand is already in dptr 
7965      then we do nothing else we move the value to dptr */
7966   if (AOP_TYPE(result) != AOP_STR) {
7967     /* if this is remateriazable */
7968     if (AOP_TYPE(result) == AOP_IMMD) {
7969       pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
7970       pic14_emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
7971     }
7972     else { /* we need to get it byte by byte */
7973       //char *l = aopGet(AOP(result),0,FALSE,FALSE);
7974       size = AOP_SIZE(right);
7975       offset = 0 ;
7976
7977       /* hack hack! see if this the FSR. If so don't load W */
7978       if(AOP_TYPE(right) != AOP_ACC) {
7979
7980         emitpcode(POC_MOVFW,popGet(AOP(result),0));
7981         emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
7982
7983         //if(size==2)
7984         //emitpcode(POC_DECF,popCopyReg(&pc_fsr));
7985         //if(size==4) {
7986         //  emitpcode(POC_MOVLW,popGetLit(0xfd));
7987         //  emitpcode(POC_ADDWF,popCopyReg(&pc_fsr));
7988         //}
7989
7990         while(size--) {
7991           emitpcode(POC_MOVFW,popGet(AOP(right),offset++));
7992           emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
7993           
7994           if(size)
7995             emitpcode(POC_INCF,popCopyReg(&pc_fsr));
7996         }
7997
7998
7999         goto release;
8000       } 
8001
8002       if(aopIdx(AOP(result),0) != 4) {
8003
8004         emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
8005         goto release;
8006       }
8007
8008       emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
8009       goto release;
8010
8011     }
8012   }
8013   /* so dptr know contains the address */
8014
8015
8016   /* if bit then unpack */
8017   if (IS_BITVAR(retype)) 
8018     genPackBits(retype,right,"dptr",GPOINTER);
8019   else {
8020     size = AOP_SIZE(right);
8021     offset = 0 ;
8022
8023     while (--size) {
8024       //char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
8025       if(size)
8026         pic14_emitcode("incf","fsr,f");
8027       pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset++,FALSE,FALSE));
8028       pic14_emitcode("movwf","indf");
8029       //MOVA(l);
8030       //DEBUGpic14_emitcode(";lcall","__gptrput");
8031       //if (size)
8032       //    pic14_emitcode("inc","dptr");
8033     }
8034   }
8035
8036  release:
8037   freeAsmop(right,NULL,ic,TRUE);
8038   freeAsmop(result,NULL,ic,TRUE);
8039 }
8040
8041 /*-----------------------------------------------------------------*/
8042 /* genPointerSet - stores the value into a pointer location        */
8043 /*-----------------------------------------------------------------*/
8044 static void genPointerSet (iCode *ic)
8045 {    
8046     operand *right, *result ;
8047     sym_link *type, *etype;
8048     int p_type;
8049
8050     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8051
8052     right = IC_RIGHT(ic);
8053     result = IC_RESULT(ic) ;
8054
8055     /* depending on the type of pointer we need to
8056     move it to the correct pointer register */
8057     type = operandType(result);
8058     etype = getSpec(type);
8059     /* if left is of type of pointer then it is simple */
8060     if (IS_PTR(type) && !IS_FUNC(type->next)) {
8061         p_type = DCL_TYPE(type);
8062     }
8063     else {
8064         /* we have to go by the storage class */
8065         p_type = PTR_TYPE(SPEC_OCLS(etype));
8066
8067 /*      if (SPEC_OCLS(etype)->codesp ) { */
8068 /*          p_type = CPOINTER ;  */
8069 /*      } */
8070 /*      else */
8071 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
8072 /*              p_type = FPOINTER ; */
8073 /*          else */
8074 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
8075 /*                  p_type = PPOINTER ; */
8076 /*              else */
8077 /*                  if (SPEC_OCLS(etype) == idata ) */
8078 /*                      p_type = IPOINTER ; */
8079 /*                  else */
8080 /*                      p_type = POINTER ; */
8081     }
8082
8083     /* now that we have the pointer type we assign
8084     the pointer values */
8085     switch (p_type) {
8086
8087     case POINTER:
8088     case IPOINTER:
8089         genNearPointerSet (right,result,ic);
8090         break;
8091
8092     case PPOINTER:
8093         genPagedPointerSet (right,result,ic);
8094         break;
8095
8096     case FPOINTER:
8097         genFarPointerSet (right,result,ic);
8098         break;
8099
8100     case GPOINTER:
8101         genGenPointerSet (right,result,ic);
8102         break;
8103     }
8104
8105 }
8106
8107 /*-----------------------------------------------------------------*/
8108 /* genIfx - generate code for Ifx statement                        */
8109 /*-----------------------------------------------------------------*/
8110 static void genIfx (iCode *ic, iCode *popIc)
8111 {
8112   operand *cond = IC_COND(ic);
8113   int isbit =0;
8114
8115   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8116
8117   aopOp(cond,ic,FALSE);
8118
8119   /* get the value into acc */
8120   if (AOP_TYPE(cond) != AOP_CRY)
8121     pic14_toBoolean(cond);
8122   else
8123     isbit = 1;
8124   /* the result is now in the accumulator */
8125   freeAsmop(cond,NULL,ic,TRUE);
8126
8127   /* if there was something to be popped then do it */
8128   if (popIc)
8129     genIpop(popIc);
8130
8131   /* if the condition is  a bit variable */
8132   if (isbit && IS_ITEMP(cond) && 
8133       SPIL_LOC(cond)) {
8134     genIfxJump(ic,SPIL_LOC(cond)->rname);
8135     DEBUGpic14_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
8136   }
8137   else {
8138     if (isbit && !IS_ITEMP(cond))
8139       genIfxJump(ic,OP_SYMBOL(cond)->rname);
8140     else
8141       genIfxJump(ic,"a");
8142   }
8143   ic->generated = 1;
8144
8145 }
8146
8147 /*-----------------------------------------------------------------*/
8148 /* genAddrOf - generates code for address of                       */
8149 /*-----------------------------------------------------------------*/
8150 static void genAddrOf (iCode *ic)
8151 {
8152   //symbol *sym = OP_SYMBOL(IC_LEFT(ic));
8153   operand *right, *result, *left;
8154   //int size, offset ;
8155
8156   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8157
8158
8159   //aopOp(IC_RESULT(ic),ic,FALSE);
8160
8161   aopOp((left=IC_LEFT(ic)),ic,FALSE);
8162   aopOp((right=IC_RIGHT(ic)),ic,FALSE);
8163   aopOp((result=IC_RESULT(ic)),ic,TRUE);
8164
8165   DEBUGpic14_AopType(__LINE__,left,right,result);
8166
8167   emitpcode(POC_MOVLW, popGet(AOP(left),0));
8168   emitpcode(POC_MOVWF, popGet(AOP(result),0));
8169
8170 #if 0
8171   /* object not on stack then we need the name */
8172   size = AOP_SIZE(IC_RESULT(ic));
8173   offset = 0;
8174
8175   while (size--) {
8176     char s[SDCC_NAME_MAX];
8177     if (offset) 
8178       sprintf(s,"#(%s >> %d)",
8179               sym->rname,
8180               offset*8);
8181     else
8182       sprintf(s,"#%s",sym->rname);
8183     aopPut(AOP(IC_RESULT(ic)),s,offset++);
8184   }
8185 #endif
8186
8187
8188   //  freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8189   freeAsmop(left,NULL,ic,FALSE);
8190   freeAsmop(result,NULL,ic,TRUE);
8191
8192 }
8193
8194 #if 0
8195 /*-----------------------------------------------------------------*/
8196 /* genFarFarAssign - assignment when both are in far space         */
8197 /*-----------------------------------------------------------------*/
8198 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
8199 {
8200     int size = AOP_SIZE(right);
8201     int offset = 0;
8202     char *l ;
8203     /* first push the right side on to the stack */
8204     while (size--) {
8205         l = aopGet(AOP(right),offset++,FALSE,FALSE);
8206         MOVA(l);
8207         pic14_emitcode ("push","acc");
8208     }
8209     
8210     freeAsmop(right,NULL,ic,FALSE);
8211     /* now assign DPTR to result */
8212     aopOp(result,ic,FALSE);
8213     size = AOP_SIZE(result);
8214     while (size--) {
8215         pic14_emitcode ("pop","acc");
8216         aopPut(AOP(result),"a",--offset);
8217     }
8218     freeAsmop(result,NULL,ic,FALSE);
8219         
8220 }
8221 #endif
8222
8223 /*-----------------------------------------------------------------*/
8224 /* genAssign - generate code for assignment                        */
8225 /*-----------------------------------------------------------------*/
8226 static void genAssign (iCode *ic)
8227 {
8228   operand *result, *right;
8229   int size, offset,know_W;
8230   unsigned long lit = 0L;
8231
8232   result = IC_RESULT(ic);
8233   right  = IC_RIGHT(ic) ;
8234
8235   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8236
8237   /* if they are the same */
8238   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
8239     return ;
8240
8241   aopOp(right,ic,FALSE);
8242   aopOp(result,ic,TRUE);
8243
8244   DEBUGpic14_AopType(__LINE__,NULL,right,result);
8245
8246   /* if they are the same registers */
8247   if (pic14_sameRegs(AOP(right),AOP(result)))
8248     goto release;
8249
8250   /* if the result is a bit */
8251   if (AOP_TYPE(result) == AOP_CRY) {
8252
8253     /* if the right size is a literal then
8254        we know what the value is */
8255     if (AOP_TYPE(right) == AOP_LIT) {
8256           
8257       emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
8258                   popGet(AOP(result),0));
8259
8260       if (((int) operandLitValue(right))) 
8261         pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
8262                        AOP(result)->aopu.aop_dir,
8263                        AOP(result)->aopu.aop_dir);
8264       else
8265         pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
8266                        AOP(result)->aopu.aop_dir,
8267                        AOP(result)->aopu.aop_dir);
8268       goto release;
8269     }
8270
8271     /* the right is also a bit variable */
8272     if (AOP_TYPE(right) == AOP_CRY) {
8273       emitpcode(POC_BCF,    popGet(AOP(result),0));
8274       emitpcode(POC_BTFSC,  popGet(AOP(right),0));
8275       emitpcode(POC_BSF,    popGet(AOP(result),0));
8276
8277       pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
8278                      AOP(result)->aopu.aop_dir,
8279                      AOP(result)->aopu.aop_dir);
8280       pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
8281                      AOP(right)->aopu.aop_dir,
8282                      AOP(right)->aopu.aop_dir);
8283       pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
8284                      AOP(result)->aopu.aop_dir,
8285                      AOP(result)->aopu.aop_dir);
8286       goto release ;
8287     }
8288
8289     /* we need to or */
8290     emitpcode(POC_BCF,    popGet(AOP(result),0));
8291     pic14_toBoolean(right);
8292     emitSKPZ;
8293     emitpcode(POC_BSF,    popGet(AOP(result),0));
8294     //aopPut(AOP(result),"a",0);
8295     goto release ;
8296   }
8297
8298   /* bit variables done */
8299   /* general case */
8300   size = AOP_SIZE(result);
8301   offset = 0 ;
8302   if(AOP_TYPE(right) == AOP_LIT)
8303     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
8304
8305   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
8306   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8307     if(aopIdx(AOP(result),0) == 4) {
8308   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8309       emitpcode(POC_MOVFW, popGet(AOP(right),offset));
8310       emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8311       goto release;
8312     } else
8313       DEBUGpic14_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
8314   }
8315
8316   know_W=-1;
8317   while (size--) {
8318   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8319     if(AOP_TYPE(right) == AOP_LIT) {
8320       if(lit&0xff) {
8321         if(know_W != (lit&0xff))
8322           emitpcode(POC_MOVLW,popGetLit(lit&0xff));
8323         know_W = lit&0xff;
8324         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8325       } else
8326         emitpcode(POC_CLRF, popGet(AOP(result),offset));
8327
8328       lit >>= 8;
8329
8330     } else if (AOP_TYPE(right) == AOP_CRY) {
8331       emitpcode(POC_CLRF, popGet(AOP(result),offset));
8332       if(offset == 0) {
8333         emitpcode(POC_BTFSS, popGet(AOP(right),0));
8334         emitpcode(POC_INCF, popGet(AOP(result),0));
8335       }
8336     } else {
8337   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8338       emitpcode(POC_MOVFW, popGet(AOP(right),offset));
8339       emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8340     }
8341             
8342     offset++;
8343   }
8344
8345     
8346  release:
8347   freeAsmop (right,NULL,ic,FALSE);
8348   freeAsmop (result,NULL,ic,TRUE);
8349 }   
8350
8351 /*-----------------------------------------------------------------*/
8352 /* genJumpTab - genrates code for jump table                       */
8353 /*-----------------------------------------------------------------*/
8354 static void genJumpTab (iCode *ic)
8355 {
8356     symbol *jtab;
8357     char *l;
8358
8359     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8360
8361     aopOp(IC_JTCOND(ic),ic,FALSE);
8362     /* get the condition into accumulator */
8363     l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
8364     MOVA(l);
8365     /* multiply by three */
8366     pic14_emitcode("add","a,acc");
8367     pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
8368
8369     jtab = newiTempLabel(NULL);
8370     pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
8371     pic14_emitcode("jmp","@a+dptr");
8372     pic14_emitcode("","%05d_DS_:",jtab->key+100);
8373
8374     emitpcode(POC_MOVLW, popGetLabel(jtab->key));
8375     emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
8376     emitSKPNC;
8377     emitpcode(POC_INCF, popCopyReg(&pc_pclath));
8378     emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
8379     emitpLabel(jtab->key);
8380
8381     freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
8382
8383     /* now generate the jump labels */
8384     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
8385          jtab = setNextItem(IC_JTLABELS(ic))) {
8386         pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
8387         emitpcode(POC_GOTO,popGetLabel(jtab->key));
8388         
8389     }
8390
8391 }
8392
8393 /*-----------------------------------------------------------------*/
8394 /* genMixedOperation - gen code for operators between mixed types  */
8395 /*-----------------------------------------------------------------*/
8396 /*
8397   TSD - Written for the PIC port - but this unfortunately is buggy.
8398   This routine is good in that it is able to efficiently promote 
8399   types to different (larger) sizes. Unfortunately, the temporary
8400   variables that are optimized out by this routine are sometimes
8401   used in other places. So until I know how to really parse the 
8402   iCode tree, I'm going to not be using this routine :(.
8403 */
8404 static int genMixedOperation (iCode *ic)
8405 {
8406 #if 0
8407   operand *result = IC_RESULT(ic);
8408   sym_link *ctype = operandType(IC_LEFT(ic));
8409   operand *right = IC_RIGHT(ic);
8410   int ret = 0;
8411   int big,small;
8412   int offset;
8413
8414   iCode *nextic;
8415   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
8416
8417   pic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
8418
8419   nextic = ic->next;
8420   if(!nextic)
8421     return 0;
8422
8423   nextright = IC_RIGHT(nextic);
8424   nextleft  = IC_LEFT(nextic);
8425   nextresult = IC_RESULT(nextic);
8426
8427   aopOp(right,ic,FALSE);
8428   aopOp(result,ic,FALSE);
8429   aopOp(nextright,  nextic, FALSE);
8430   aopOp(nextleft,   nextic, FALSE);
8431   aopOp(nextresult, nextic, FALSE);
8432
8433   if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
8434
8435     operand *t = right;
8436     right = nextright;
8437     nextright = t; 
8438
8439     pic14_emitcode(";remove right +","");
8440
8441   } else   if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
8442 /*
8443     operand *t = right;
8444     right = nextleft;
8445     nextleft = t; 
8446 */
8447     pic14_emitcode(";remove left +","");
8448   } else
8449     return 0;
8450
8451   big = AOP_SIZE(nextleft);
8452   small = AOP_SIZE(nextright);
8453
8454   switch(nextic->op) {
8455
8456   case '+':
8457     pic14_emitcode(";optimize a +","");
8458     /* if unsigned or not an integral type */
8459     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
8460       pic14_emitcode(";add a bit to something","");
8461     } else {
8462
8463       pic14_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
8464
8465       if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
8466         pic14_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
8467         pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
8468       } else
8469         pic14_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
8470
8471       offset = 0;
8472       while(--big) {
8473
8474         offset++;
8475
8476         if(--small) {
8477           if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
8478             pic14_emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8479             pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
8480           }
8481
8482           pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8483           emitSKPNC;
8484           pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
8485                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
8486                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
8487           pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8488           pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
8489
8490         } else {
8491           pic14_emitcode("rlf","known_zero,w");
8492
8493           /*
8494             if right is signed
8495               btfsc  right,7
8496                addlw ff
8497           */
8498           if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
8499             pic14_emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8500             pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
8501           } else {
8502             pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
8503           }
8504         }
8505       }
8506       ret = 1;
8507     }
8508   }
8509   ret = 1;
8510
8511 release:
8512   freeAsmop(right,NULL,ic,TRUE);
8513   freeAsmop(result,NULL,ic,TRUE);
8514   freeAsmop(nextright,NULL,ic,TRUE);
8515   freeAsmop(nextleft,NULL,ic,TRUE);
8516   if(ret)
8517     nextic->generated = 1;
8518
8519   return ret;
8520 #else
8521   return 0;
8522 #endif
8523 }
8524 /*-----------------------------------------------------------------*/
8525 /* genCast - gen code for casting                                  */
8526 /*-----------------------------------------------------------------*/
8527 static void genCast (iCode *ic)
8528 {
8529     operand *result = IC_RESULT(ic);
8530     sym_link *ctype = operandType(IC_LEFT(ic));
8531     operand *right = IC_RIGHT(ic);
8532     int size, offset ;
8533
8534     DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
8535     /* if they are equivalent then do nothing */
8536     if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
8537         return ;
8538
8539     aopOp(right,ic,FALSE) ;
8540     aopOp(result,ic,FALSE);
8541
8542     DEBUGpic14_AopType(__LINE__,NULL,right,result);
8543
8544     /* if the result is a bit */
8545     if (AOP_TYPE(result) == AOP_CRY) {
8546         /* if the right size is a literal then
8547         we know what the value is */
8548         if (AOP_TYPE(right) == AOP_LIT) {
8549
8550           emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
8551                       popGet(AOP(result),0));
8552
8553             if (((int) operandLitValue(right))) 
8554               pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
8555                        AOP(result)->aopu.aop_dir,
8556                        AOP(result)->aopu.aop_dir);
8557             else
8558               pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
8559                        AOP(result)->aopu.aop_dir,
8560                        AOP(result)->aopu.aop_dir);
8561
8562             goto release;
8563         }
8564
8565         /* the right is also a bit variable */
8566         if (AOP_TYPE(right) == AOP_CRY) {
8567
8568           emitCLRC;
8569           emitpcode(POC_BTFSC,  popGet(AOP(right),0));
8570
8571           pic14_emitcode("clrc","");
8572           pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
8573                    AOP(right)->aopu.aop_dir,
8574                    AOP(right)->aopu.aop_dir);
8575             aopPut(AOP(result),"c",0);
8576             goto release ;
8577         }
8578
8579         /* we need to or */
8580         if (AOP_TYPE(right) == AOP_REG) {
8581           emitpcode(POC_BCF,    popGet(AOP(result),0));
8582           emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
8583           emitpcode(POC_BSF,    popGet(AOP(result),0));
8584         }
8585         pic14_toBoolean(right);
8586         aopPut(AOP(result),"a",0);
8587         goto release ;
8588     }
8589
8590     if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
8591       int offset = 1;
8592       size = AOP_SIZE(result);
8593
8594       emitpcode(POC_CLRF,   popGet(AOP(result),0));
8595       emitpcode(POC_BTFSC,  popGet(AOP(right),0));
8596       emitpcode(POC_INCF,   popGet(AOP(result),0));
8597
8598       while (size--)
8599         emitpcode(POC_CLRF,   popGet(AOP(result),offset++));
8600
8601       goto release;
8602     }
8603
8604     /* if they are the same size : or less */
8605     if (AOP_SIZE(result) <= AOP_SIZE(right)) {
8606
8607         /* if they are in the same place */
8608         if (pic14_sameRegs(AOP(right),AOP(result)))
8609             goto release;
8610
8611         /* if they in different places then copy */
8612         size = AOP_SIZE(result);
8613         offset = 0 ;
8614         while (size--) {
8615             aopPut(AOP(result),
8616                    aopGet(AOP(right),offset,FALSE,FALSE),
8617                    offset);
8618             offset++;
8619         }
8620         goto release;
8621     }
8622
8623
8624     /* if the result is of type pointer */
8625     if (IS_PTR(ctype)) {
8626
8627         int p_type;
8628         sym_link *type = operandType(right);
8629         sym_link *etype = getSpec(type);
8630
8631         /* pointer to generic pointer */
8632         if (IS_GENPTR(ctype)) {
8633             char *l = zero;
8634             
8635             if (IS_PTR(type)) 
8636                 p_type = DCL_TYPE(type);
8637             else {
8638                 /* we have to go by the storage class */
8639                 p_type = PTR_TYPE(SPEC_OCLS(etype));
8640
8641 /*              if (SPEC_OCLS(etype)->codesp )  */
8642 /*                  p_type = CPOINTER ;  */
8643 /*              else */
8644 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
8645 /*                      p_type = FPOINTER ; */
8646 /*                  else */
8647 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
8648 /*                          p_type = PPOINTER; */
8649 /*                      else */
8650 /*                          if (SPEC_OCLS(etype) == idata ) */
8651 /*                              p_type = IPOINTER ; */
8652 /*                          else */
8653 /*                              p_type = POINTER ; */
8654             }
8655                 
8656             /* the first two bytes are known */
8657             size = GPTRSIZE - 1; 
8658             offset = 0 ;
8659             while (size--) {
8660                 aopPut(AOP(result),
8661                        aopGet(AOP(right),offset,FALSE,FALSE),
8662                        offset);
8663                 offset++;
8664             }
8665             /* the last byte depending on type */
8666             switch (p_type) {
8667             case IPOINTER:
8668             case POINTER:
8669                 l = zero;
8670                 break;
8671             case FPOINTER:
8672                 l = one;
8673                 break;
8674             case CPOINTER:
8675                 l = "#0x02";
8676                 break;                          
8677             case PPOINTER:
8678                 l = "#0x03";
8679                 break;
8680                 
8681             default:
8682                 /* this should never happen */
8683                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8684                        "got unknown pointer type");
8685                 exit(1);
8686             }
8687             aopPut(AOP(result),l, GPTRSIZE - 1);            
8688             goto release ;
8689         }
8690         
8691         /* just copy the pointers */
8692         size = AOP_SIZE(result);
8693         offset = 0 ;
8694         while (size--) {
8695             aopPut(AOP(result),
8696                    aopGet(AOP(right),offset,FALSE,FALSE),
8697                    offset);
8698             offset++;
8699         }
8700         goto release ;
8701     }
8702     
8703
8704
8705     /* so we now know that the size of destination is greater
8706     than the size of the source.
8707     Now, if the next iCode is an operator then we might be
8708     able to optimize the operation without performing a cast.
8709     */
8710     if(genMixedOperation(ic))
8711       goto release;
8712
8713     
8714     /* we move to result for the size of source */
8715     size = AOP_SIZE(right);
8716     offset = 0 ;
8717     while (size--) {
8718       pic14_emitcode(";","%d",__LINE__);
8719       /* aopPut(AOP(result),
8720              aopGet(AOP(right),offset,FALSE,FALSE),
8721              offset); */
8722       emitpcode(POC_MOVFW,   popGet(AOP(right),offset));
8723       emitpcode(POC_MOVWF,   popGet(AOP(result),offset));
8724       offset++;
8725     }
8726
8727     /* now depending on the sign of the destination */
8728     size = AOP_SIZE(result) - AOP_SIZE(right);
8729     /* if unsigned or not an integral type */
8730     if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) {
8731       while (size--) {
8732           emitpcode(POC_CLRF,   popGet(AOP(result),offset));
8733           pic14_emitcode("clrf","%s  ;%d",aopGet(AOP(result),offset,FALSE,FALSE),__LINE__);
8734           offset++;
8735       }
8736     } else {
8737       /* we need to extend the sign :{ */
8738
8739       emitpcodeNULLop(POC_CLRW);
8740
8741       if(offset)
8742         emitpcode(POC_BTFSC,   newpCodeOpBit(aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
8743       else
8744         emitpcode(POC_BTFSC,   newpCodeOpBit(aopGet(AOP(right),offset,FALSE,FALSE),7,0));
8745
8746       emitpcode(POC_MOVLW,   popGetLit(0xff));
8747
8748         pic14_emitcode("clrw","");
8749         pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
8750                  AOP(right)->aopu.aop_dir,
8751                  AOP(right)->aopu.aop_dir);
8752         pic14_emitcode("movlw","0xff");
8753         while (size--) {
8754           emitpcode(POC_MOVWF,   popGet(AOP(result),offset));
8755           pic14_emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
8756           offset++;
8757           // aopPut(AOP(result),"a",offset++);
8758         }
8759
8760     }
8761
8762     /* we are done hurray !!!! */
8763
8764 release:
8765     freeAsmop(right,NULL,ic,TRUE);
8766     freeAsmop(result,NULL,ic,TRUE);
8767
8768 }
8769
8770 /*-----------------------------------------------------------------*/
8771 /* genDjnz - generate decrement & jump if not zero instrucion      */
8772 /*-----------------------------------------------------------------*/
8773 static int genDjnz (iCode *ic, iCode *ifx)
8774 {
8775     symbol *lbl, *lbl1;
8776     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8777
8778     if (!ifx)
8779         return 0;
8780     
8781     /* if the if condition has a false label
8782        then we cannot save */
8783     if (IC_FALSE(ifx))
8784         return 0;
8785
8786     /* if the minus is not of the form 
8787        a = a - 1 */
8788     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
8789         !IS_OP_LITERAL(IC_RIGHT(ic)))
8790         return 0;
8791
8792     if (operandLitValue(IC_RIGHT(ic)) != 1)
8793         return 0;
8794
8795     /* if the size of this greater than one then no
8796        saving */
8797     if (getSize(operandType(IC_RESULT(ic))) > 1)
8798         return 0;
8799
8800     /* otherwise we can save BIG */
8801     lbl = newiTempLabel(NULL);
8802     lbl1= newiTempLabel(NULL);
8803
8804     aopOp(IC_RESULT(ic),ic,FALSE);
8805     
8806     if (IS_AOP_PREG(IC_RESULT(ic))) {
8807         pic14_emitcode("dec","%s",
8808                  aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
8809         pic14_emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
8810         pic14_emitcode("jnz","%05d_DS_",lbl->key+100);
8811     } else {    
8812
8813
8814       emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0));
8815       emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
8816
8817       pic14_emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
8818       pic14_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
8819
8820     }
8821 /*     pic14_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
8822 /*     pic14_emitcode ("","%05d_DS_:",lbl->key+100); */
8823 /*     pic14_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
8824 /*     pic14_emitcode ("","%05d_DS_:",lbl1->key+100); */
8825
8826     
8827     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8828     ifx->generated = 1;
8829     return 1;
8830 }
8831
8832 /*-----------------------------------------------------------------*/
8833 /* genReceive - generate code for a receive iCode                  */
8834 /*-----------------------------------------------------------------*/
8835 static void genReceive (iCode *ic)
8836 {    
8837     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8838
8839     if (isOperandInFarSpace(IC_RESULT(ic)) && 
8840         ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
8841           IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
8842
8843         int size = getSize(operandType(IC_RESULT(ic)));
8844         int offset =  fReturnSizePic - size;
8845         while (size--) {
8846             pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
8847                                     fReturn[fReturnSizePic - offset - 1] : "acc"));
8848             offset++;
8849         }
8850         aopOp(IC_RESULT(ic),ic,FALSE);  
8851         size = AOP_SIZE(IC_RESULT(ic));
8852         offset = 0;
8853         while (size--) {
8854             pic14_emitcode ("pop","acc");
8855             aopPut (AOP(IC_RESULT(ic)),"a",offset++);
8856         }
8857         
8858     } else {
8859         _G.accInUse++;
8860         aopOp(IC_RESULT(ic),ic,FALSE);  
8861         _G.accInUse--;
8862         assignResultValue(IC_RESULT(ic));       
8863     }
8864
8865     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8866 }
8867
8868 /*-----------------------------------------------------------------*/
8869 /* genpic14Code - generate code for pic14 based controllers        */
8870 /*-----------------------------------------------------------------*/
8871 /*
8872  * At this point, ralloc.c has gone through the iCode and attempted
8873  * to optimize in a way suitable for a PIC. Now we've got to generate
8874  * PIC instructions that correspond to the iCode.
8875  *
8876  * Once the instructions are generated, we'll pass through both the
8877  * peep hole optimizer and the pCode optimizer.
8878  *-----------------------------------------------------------------*/
8879
8880 void genpic14Code (iCode *lic)
8881 {
8882     iCode *ic;
8883     int cln = 0;
8884
8885     lineHead = lineCurr = NULL;
8886
8887     pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
8888     addpBlock(pb);
8889
8890     /* if debug information required */
8891 /*     if (options.debug && currFunc) { */
8892     if (currFunc) {
8893         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
8894         _G.debugLine = 1;
8895         if (IS_STATIC(currFunc->etype)) {
8896             pic14_emitcode("",";F%s$%s$0$0     %d",moduleName,currFunc->name,__LINE__);
8897             //addpCode2pBlock(pb,newpCodeLabel(moduleName,currFunc->name));
8898         } else {
8899             pic14_emitcode("",";G$%s$0$0   %d",currFunc->name,__LINE__);
8900             //addpCode2pBlock(pb,newpCodeLabel(NULL,currFunc->name));
8901         }
8902         _G.debugLine = 0;
8903     }
8904
8905
8906     for (ic = lic ; ic ; ic = ic->next ) {
8907
8908       DEBUGpic14_emitcode(";ic","");
8909         if ( cln != ic->lineno ) {
8910             if ( options.debug ) {
8911                 _G.debugLine = 1;
8912                 pic14_emitcode("",";C$%s$%d$%d$%d ==.",
8913                          FileBaseName(ic->filename),ic->lineno,
8914                          ic->level,ic->block);
8915                 _G.debugLine = 0;
8916             }
8917             pic14_emitcode("#CSRC","%s %d",FileBaseName(ic->filename),ic->lineno);
8918             cln = ic->lineno ;
8919         }
8920         /* if the result is marked as
8921            spilt and rematerializable or code for
8922            this has already been generated then
8923            do nothing */
8924         if (resultRemat(ic) || ic->generated ) 
8925             continue ;
8926         
8927         /* depending on the operation */
8928         switch (ic->op) {
8929         case '!' :
8930             genNot(ic);
8931             break;
8932             
8933         case '~' :
8934             genCpl(ic);
8935             break;
8936             
8937         case UNARYMINUS:
8938             genUminus (ic);
8939             break;
8940             
8941         case IPUSH:
8942             genIpush (ic);
8943             break;
8944             
8945         case IPOP:
8946             /* IPOP happens only when trying to restore a 
8947                spilt live range, if there is an ifx statement
8948                following this pop then the if statement might
8949                be using some of the registers being popped which
8950                would destory the contents of the register so
8951                we need to check for this condition and handle it */
8952             if (ic->next            && 
8953                 ic->next->op == IFX &&
8954                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
8955                 genIfx (ic->next,ic);
8956             else
8957                 genIpop (ic);
8958             break; 
8959             
8960         case CALL:
8961             genCall (ic);
8962             break;
8963             
8964         case PCALL:
8965             genPcall (ic);
8966             break;
8967             
8968         case FUNCTION:
8969             genFunction (ic);
8970             break;
8971             
8972         case ENDFUNCTION:
8973             genEndFunction (ic);
8974             break;
8975             
8976         case RETURN:
8977             genRet (ic);
8978             break;
8979             
8980         case LABEL:
8981             genLabel (ic);
8982             break;
8983             
8984         case GOTO:
8985             genGoto (ic);
8986             break;
8987             
8988         case '+' :
8989             genPlus (ic) ;
8990             break;
8991             
8992         case '-' :
8993             if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
8994                 genMinus (ic);
8995             break;
8996             
8997         case '*' :
8998             genMult (ic);
8999             break;
9000             
9001         case '/' :
9002             genDiv (ic) ;
9003             break;
9004             
9005         case '%' :
9006             genMod (ic);
9007             break;
9008             
9009         case '>' :
9010             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
9011             break;
9012             
9013         case '<' :
9014             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
9015             break;
9016             
9017         case LE_OP:
9018         case GE_OP:
9019         case NE_OP:
9020             
9021             /* note these two are xlated by algebraic equivalence
9022                during parsing SDCC.y */
9023             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
9024                    "got '>=' or '<=' shouldn't have come here");
9025             break;      
9026             
9027         case EQ_OP:
9028             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
9029             break;          
9030             
9031         case AND_OP:
9032             genAndOp (ic);
9033             break;
9034             
9035         case OR_OP:
9036             genOrOp (ic);
9037             break;
9038             
9039         case '^' :
9040             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
9041             break;
9042             
9043         case '|' :
9044                 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
9045             break;
9046             
9047         case BITWISEAND:
9048             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
9049             break;
9050             
9051         case INLINEASM:
9052             genInline (ic);
9053             break;
9054             
9055         case RRC:
9056             genRRC (ic);
9057             break;
9058             
9059         case RLC:
9060             genRLC (ic);
9061             break;
9062             
9063         case GETHBIT:
9064             genGetHbit (ic);
9065             break;
9066             
9067         case LEFT_OP:
9068             genLeftShift (ic);
9069             break;
9070             
9071         case RIGHT_OP:
9072             genRightShift (ic);
9073             break;
9074             
9075         case GET_VALUE_AT_ADDRESS:
9076             genPointerGet(ic);
9077             break;
9078             
9079         case '=' :
9080             if (POINTER_SET(ic))
9081                 genPointerSet(ic);
9082             else
9083                 genAssign(ic);
9084             break;
9085             
9086         case IFX:
9087             genIfx (ic,NULL);
9088             break;
9089             
9090         case ADDRESS_OF:
9091             genAddrOf (ic);
9092             break;
9093             
9094         case JUMPTABLE:
9095             genJumpTab (ic);
9096             break;
9097             
9098         case CAST:
9099             genCast (ic);
9100             break;
9101             
9102         case RECEIVE:
9103             genReceive(ic);
9104             break;
9105             
9106         case SEND:
9107             addSet(&_G.sendSet,ic);
9108             break;
9109
9110         default :
9111             ic = ic;
9112         }
9113     }
9114     
9115
9116     /* now we are ready to call the 
9117        peep hole optimizer */
9118     if (!options.nopeep) {
9119       printf("peep hole optimizing\n");
9120         peepHole (&lineHead);
9121     }
9122     /* now do the actual printing */
9123     printLine (lineHead,codeOutFile);
9124
9125     printf("printing pBlock\n\n");
9126     printpBlock(stdout,pb);
9127
9128     return;
9129 }