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