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