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