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