Added -p command line option to allow selection of port dependent processor.
[fw/sdcc] / src / pic / gen.c
1 /*-------------------------------------------------------------------------
2   SDCCgen51.c - source file for code generation for 8051
3   
4   Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
5          and -  Jean-Louis VERN.jlvern@writeme.com (1999)
6   Bug Fixes  -  Wojciech Stryjewski  wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7   PIC port   -  Scott Dattalo scott@dattalo.com (2000)
8   
9   This program is free software; you can redistribute it and/or modify it
10   under the terms of the GNU General Public License as published by the
11   Free Software Foundation; either version 2, or (at your option) any
12   later version.
13   
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License for more details.
18   
19   You should have received a copy of the GNU General Public License
20   along with this program; if not, write to the Free Software
21   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22   
23   In other words, you are welcome to use, share and improve this program.
24   You are forbidden to forbid anyone else to use, share and improve
25   what you give them.   Help stamp out software-hoarding!
26   
27   Notes:
28   000123 mlh    Moved aopLiteral to SDCCglue.c to help the split
29                 Made everything static
30 -------------------------------------------------------------------------*/
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <ctype.h>
36 #include "SDCCglobl.h"
37 #include "newalloc.h"
38
39 #ifdef HAVE_SYS_ISA_DEFS_H
40 #include <sys/isa_defs.h>
41 #else
42 #ifdef HAVE_MACHINE_ENDIAN_H
43 #include <machine/endian.h>
44 #else
45 #ifdef HAVE_ENDIAN_H
46 #include <endian.h>
47 #else
48 #if !defined(__BORLANDC__) && !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__CYGWIN__)
49 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
50 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
51 #endif
52 #endif
53 #endif
54 #endif
55
56 #include "common.h"
57 #include "SDCCpeeph.h"
58 #include "ralloc.h"
59 #include "pcode.h"
60 #include "gen.h"
61
62
63 static int labelOffset=0;
64 static int debug_verbose=1;
65 static int optimized_for_speed = 0;
66
67 /* max_key keeps track of the largest label number used in 
68    a function. This is then used to adjust the label offset
69    for the next function.
70 */
71 static int max_key=0;
72 static int GpsuedoStkPtr=0;
73
74 unsigned int pic14aopLiteral (value *val, int offset);
75 const char *AopType(short type);
76 static iCode *ifxForOp ( operand *op, iCode *ic );
77
78 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
79
80 /* this is the down and dirty file with all kinds of 
81    kludgy & hacky stuff. This is what it is all about
82    CODE GENERATION for a specific MCU . some of the
83    routines may be reusable, will have to see */
84
85 static char *zero = "#0x00";
86 static char *one  = "#0x01";
87 static char *spname = "sp";
88
89 char *fReturnpic14[] = {"temp1","temp2","temp3","temp4" };
90 //char *fReturn390[] = {"dpl","dph","dpx", "b","a" };
91 unsigned fReturnSizePic = 4; /* shared with ralloc.c */
92 static char **fReturn = fReturnpic14;
93
94 static char *accUse[] = {"a","b"};
95
96 //static short rbank = -1;
97
98 static struct {
99     short r0Pushed;
100     short r1Pushed;
101     short accInUse;
102     short inLine;
103     short debugLine;
104     short nRegsSaved;
105     set *sendSet;
106 } _G;
107
108 /* Resolved ifx structure. This structure stores information
109    about an iCode ifx that makes it easier to generate code.
110 */
111 typedef struct resolvedIfx {
112   symbol *lbl;     /* pointer to a label */
113   int condition;   /* true or false ifx */
114   int generated;   /* set true when the code associated with the ifx
115                     * is generated */
116 } resolvedIfx;
117
118 extern int pic14_ptrRegReq ;
119 extern int pic14_nRegs;
120 extern FILE *codeOutFile;
121 static void saverbank (int, iCode *,bool);
122
123 static lineNode *lineHead = NULL;
124 static lineNode *lineCurr = NULL;
125
126 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
127 0xE0, 0xC0, 0x80, 0x00};
128 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
129 0x07, 0x03, 0x01, 0x00};
130
131 static  pBlock *pb;
132
133 /*-----------------------------------------------------------------*/
134 /*  my_powof2(n) - If `n' is an integaer power of 2, then the      */
135 /*                 exponent of 2 is returned, otherwise -1 is      */
136 /*                 returned.                                       */
137 /* note that this is similar to the function `powof2' in SDCCsymt  */
138 /* if(n == 2^y)                                                    */
139 /*   return y;                                                     */
140 /* return -1;                                                      */
141 /*-----------------------------------------------------------------*/
142 static int my_powof2 (unsigned long num)
143 {
144   if(num) {
145     if( (num & (num-1)) == 0) {
146       int nshifts = -1;
147       while(num) {
148         num>>=1;
149         nshifts++;
150       }
151       return nshifts;
152     }
153   }
154
155   return -1;
156 }
157
158 void DEBUGpic14_AopType(int line_no, operand *left, operand *right, operand *result)
159 {
160
161   DEBUGpic14_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
162                        line_no,
163                        ((result) ? AopType(AOP_TYPE(result)) : "-"),
164                        ((result) ? aopGet(AOP(result),0,TRUE,FALSE) : "-"),
165                        ((left)   ? AopType(AOP_TYPE(left)) : "-"),
166                        ((left)   ? aopGet(AOP(left),0,TRUE,FALSE) : "-"),
167                        ((right)  ? AopType(AOP_TYPE(right)) : "-"),
168                        ((right)  ? aopGet(AOP(right),0,FALSE,FALSE) : "-"),
169                        ((result) ? AOP_SIZE(result) : 0));
170
171 }
172
173 void DEBUGpic14_emitcode (char *inst,char *fmt, ...)
174 {
175     va_list ap;
176     char lb[INITIAL_INLINEASM];  
177     char *lbp = lb;
178
179     if(!debug_verbose)
180       return;
181
182     va_start(ap,fmt);   
183
184     if (inst && *inst) {
185         if (fmt && *fmt)
186             sprintf(lb,"%s\t",inst);
187         else
188             sprintf(lb,"%s",inst);
189         vsprintf(lb+(strlen(lb)),fmt,ap);
190     }  else
191         vsprintf(lb,fmt,ap);
192
193     while (isspace(*lbp)) lbp++;
194
195     if (lbp && *lbp) 
196         lineCurr = (lineCurr ?
197                     connectLine(lineCurr,newLineNode(lb)) :
198                     (lineHead = newLineNode(lb)));
199     lineCurr->isInline = _G.inLine;
200     lineCurr->isDebug  = _G.debugLine;
201
202     addpCode2pBlock(pb,newpCodeCharP(lb));
203
204     va_end(ap);
205 }
206
207
208 static void emitpLabel(int key)
209 {
210   addpCode2pBlock(pb,newpCodeLabel(NULL,key+100+labelOffset));
211 }
212
213 void emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
214 {
215
216   if(pcop)
217     addpCode2pBlock(pb,newpCode(poc,pcop));
218   else
219     DEBUGpic14_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
220 }
221
222 void emitpcodeNULLop(PIC_OPCODE poc)
223 {
224
225   addpCode2pBlock(pb,newpCode(poc,NULL));
226
227 }
228
229 /*-----------------------------------------------------------------*/
230 /* pic14_emitcode - writes the code into a file : for now it is simple    */
231 /*-----------------------------------------------------------------*/
232 void pic14_emitcode (char *inst,char *fmt, ...)
233 {
234     va_list ap;
235     char lb[INITIAL_INLINEASM];  
236     char *lbp = lb;
237
238     va_start(ap,fmt);   
239
240     if (inst && *inst) {
241         if (fmt && *fmt)
242             sprintf(lb,"%s\t",inst);
243         else
244             sprintf(lb,"%s",inst);
245         vsprintf(lb+(strlen(lb)),fmt,ap);
246     }  else
247         vsprintf(lb,fmt,ap);
248
249     while (isspace(*lbp)) lbp++;
250
251     if (lbp && *lbp) 
252         lineCurr = (lineCurr ?
253                     connectLine(lineCurr,newLineNode(lb)) :
254                     (lineHead = newLineNode(lb)));
255     lineCurr->isInline = _G.inLine;
256     lineCurr->isDebug  = _G.debugLine;
257
258     if(debug_verbose)
259       addpCode2pBlock(pb,newpCodeCharP(lb));
260
261     va_end(ap);
262 }
263
264
265 /*-----------------------------------------------------------------*/
266 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
267 /*-----------------------------------------------------------------*/
268 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
269 {
270     bool r0iu = FALSE , r1iu = FALSE;
271     bool r0ou = FALSE , r1ou = FALSE;
272
273     /* the logic: if r0 & r1 used in the instruction
274     then we are in trouble otherwise */
275
276     /* first check if r0 & r1 are used by this
277     instruction, in which case we are in trouble */
278     if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
279         (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
280     {
281         goto endOfWorld;      
282     }
283
284     r0ou = bitVectBitValue(ic->rMask,R0_IDX);
285     r1ou = bitVectBitValue(ic->rMask,R1_IDX);
286
287     /* if no usage of r0 then return it */
288     if (!r0iu && !r0ou) {
289         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
290         (*aopp)->type = AOP_R0;
291         
292         return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
293     }
294
295     /* if no usage of r1 then return it */
296     if (!r1iu && !r1ou) {
297         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
298         (*aopp)->type = AOP_R1;
299
300         return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R1_IDX);
301     }    
302
303     /* now we know they both have usage */
304     /* if r0 not used in this instruction */
305     if (!r0iu) {
306         /* push it if not already pushed */
307         if (!_G.r0Pushed) {
308           //pic14_emitcode ("push","%s",
309           //          pic14_regWithIdx(R0_IDX)->dname);
310             _G.r0Pushed++ ;
311         }
312         
313         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
314         (*aopp)->type = AOP_R0;
315
316         return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
317     }
318
319     /* if r1 not used then */
320
321     if (!r1iu) {
322         /* push it if not already pushed */
323         if (!_G.r1Pushed) {
324           //pic14_emitcode ("push","%s",
325           //          pic14_regWithIdx(R1_IDX)->dname);
326             _G.r1Pushed++ ;
327         }
328         
329         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
330         (*aopp)->type = AOP_R1;
331         return pic14_regWithIdx(R1_IDX);
332     }
333
334 endOfWorld :
335     /* I said end of world but not quite end of world yet */
336     /* if this is a result then we can push it on the stack*/
337     if (result) {
338         (*aopp)->type = AOP_STK;    
339         return NULL;
340     }
341
342     /* other wise this is true end of the world */
343     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
344            "getFreePtr should never reach here");
345     exit(0);
346 }
347
348 /*-----------------------------------------------------------------*/
349 /* newAsmop - creates a new asmOp                                  */
350 /*-----------------------------------------------------------------*/
351 asmop *newAsmop (short type)
352 {
353     asmop *aop;
354
355     aop = Safe_calloc(1,sizeof(asmop));
356     aop->type = type;
357     return aop;
358 }
359
360 static void genSetDPTR(int n)
361 {
362     if (!n)
363     {
364         pic14_emitcode(";", "Select standard DPTR");
365         pic14_emitcode("mov", "dps, #0x00");
366     }
367     else
368     {
369         pic14_emitcode(";", "Select alternate DPTR");
370         pic14_emitcode("mov", "dps, #0x01");
371     }
372 }
373
374 /*-----------------------------------------------------------------*/
375 /* resolveIfx - converts an iCode ifx into a form more useful for  */
376 /*              generating code                                    */
377 /*-----------------------------------------------------------------*/
378 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
379 {
380   if(!resIfx) 
381     return;
382
383   DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
384
385   resIfx->condition = 1;    /* assume that the ifx is true */
386   resIfx->generated = 0;    /* indicate that the ifx has not been used */
387
388   if(!ifx) {
389     resIfx->lbl = newiTempLabel(NULL);  /* oops, there is no ifx. so create a label */
390     DEBUGpic14_emitcode("; ***","%s %d null ifx creating new label key =%d",
391                         __FUNCTION__,__LINE__,resIfx->lbl->key);
392   } else {
393     if(IC_TRUE(ifx)) {
394       resIfx->lbl = IC_TRUE(ifx);
395     } else {
396       resIfx->lbl = IC_FALSE(ifx);
397       resIfx->condition = 0;
398     }
399     if(IC_TRUE(ifx)) 
400       DEBUGpic14_emitcode("; ***","ifx true is non-null");
401     if(IC_FALSE(ifx)) 
402       DEBUGpic14_emitcode("; ***","ifx false is non-null");
403   }
404
405   DEBUGpic14_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,labelOffset);
406
407 }
408 /*-----------------------------------------------------------------*/
409 /* pointerCode - returns the code for a pointer type               */
410 /*-----------------------------------------------------------------*/
411 static int pointerCode (sym_link *etype)
412 {
413
414     return PTR_TYPE(SPEC_OCLS(etype));
415
416 }
417
418 /*-----------------------------------------------------------------*/
419 /* aopForSym - for a true symbol                                   */
420 /*-----------------------------------------------------------------*/
421 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
422 {
423     asmop *aop;
424     memmap *space= SPEC_OCLS(sym->etype);
425
426     DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
427     /* if already has one */
428     if (sym->aop)
429         return sym->aop;
430
431     /* assign depending on the storage class */
432     /* if it is on the stack or indirectly addressable */
433     /* space we need to assign either r0 or r1 to it   */    
434     if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
435         sym->aop = aop = newAsmop(0);
436         aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
437         aop->size = getSize(sym->type);
438
439         /* now assign the address of the variable to 
440         the pointer register */
441         if (aop->type != AOP_STK) {
442
443             if (sym->onStack) {
444                     if ( _G.accInUse )
445                         pic14_emitcode("push","acc");
446
447                     pic14_emitcode("mov","a,_bp");
448                     pic14_emitcode("add","a,#0x%02x",
449                              ((sym->stack < 0) ?
450                               ((char)(sym->stack - _G.nRegsSaved )) :
451                               ((char)sym->stack)) & 0xff);
452                     pic14_emitcode("mov","%s,a",
453                              aop->aopu.aop_ptr->name);
454
455                     if ( _G.accInUse )
456                         pic14_emitcode("pop","acc");
457             } else
458                 pic14_emitcode("mov","%s,#%s",
459                          aop->aopu.aop_ptr->name,
460                          sym->rname);
461             aop->paged = space->paged;
462         } else
463             aop->aopu.aop_stk = sym->stack;
464         return aop;
465     }
466     
467     if (sym->onStack && options.stack10bit)
468     {
469         /* It's on the 10 bit stack, which is located in
470          * far data space.
471          */
472          
473       //DEBUGpic14_emitcode(";","%d",__LINE__);
474
475         if ( _G.accInUse )
476                 pic14_emitcode("push","acc");
477
478         pic14_emitcode("mov","a,_bp");
479         pic14_emitcode("add","a,#0x%02x",
480                  ((sym->stack < 0) ?
481                    ((char)(sym->stack - _G.nRegsSaved )) :
482                    ((char)sym->stack)) & 0xff);
483         
484         genSetDPTR(1);
485         pic14_emitcode ("mov","dpx1,#0x40");
486         pic14_emitcode ("mov","dph1,#0x00");
487         pic14_emitcode ("mov","dpl1, a");
488         genSetDPTR(0);
489         
490         if ( _G.accInUse )
491             pic14_emitcode("pop","acc");
492             
493         sym->aop = aop = newAsmop(AOP_DPTR2);
494         aop->size = getSize(sym->type); 
495         return aop;
496     }
497
498     //DEBUGpic14_emitcode(";","%d",__LINE__);
499     /* if in bit space */
500     if (IN_BITSPACE(space)) {
501         sym->aop = aop = newAsmop (AOP_CRY);
502         aop->aopu.aop_dir = sym->rname ;
503         aop->size = getSize(sym->type);
504         //DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
505         return aop;
506     }
507     /* if it is in direct space */
508     if (IN_DIRSPACE(space)) {
509         sym->aop = aop = newAsmop (AOP_DIR);
510         aop->aopu.aop_dir = sym->rname ;
511         aop->size = getSize(sym->type);
512         DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
513         return aop;
514     }
515
516     /* special case for a function */
517     if (IS_FUNC(sym->type)) {   
518         sym->aop = aop = newAsmop(AOP_IMMD);    
519         //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
520         aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
521         strcpy(aop->aopu.aop_immd,sym->rname);
522         aop->size = FPTRSIZE; 
523         DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
524         return aop;
525     }
526
527
528     /* only remaining is far space */
529     /* in which case DPTR gets the address */
530     sym->aop = aop = newAsmop(AOP_DPTR);
531     pic14_emitcode ("mov","dptr,#%s", sym->rname);
532     aop->size = getSize(sym->type);
533
534     DEBUGpic14_emitcode(";","%d size = %d",__LINE__,aop->size);
535     /* if it is in code space */
536     if (IN_CODESPACE(space))
537         aop->code = 1;
538
539     return aop;     
540 }
541
542 /*-----------------------------------------------------------------*/
543 /* aopForRemat - rematerialzes an object                           */
544 /*-----------------------------------------------------------------*/
545 static asmop *aopForRemat (symbol *sym)
546 {
547     iCode *ic = sym->rematiCode;
548     asmop *aop = newAsmop(AOP_IMMD);
549     int val = 0;
550     DEBUGpic14_emitcode(";","%s %d",__FUNCTION__,__LINE__);
551     for (;;) {
552         if (ic->op == '+')
553             val += (int) operandLitValue(IC_RIGHT(ic));
554         else if (ic->op == '-')
555             val -= (int) operandLitValue(IC_RIGHT(ic));
556         else
557             break;
558         
559         ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
560     }
561
562     if (val)
563         sprintf(buffer,"(%s %c 0x%04x)",
564                 OP_SYMBOL(IC_LEFT(ic))->rname, 
565                 val >= 0 ? '+' : '-',
566                 abs(val) & 0xffff);
567     else
568         strcpy(buffer,OP_SYMBOL(IC_LEFT(ic))->rname);
569
570     //DEBUGpic14_emitcode(";","%s",buffer);
571     aop->aopu.aop_immd = Safe_calloc(1,strlen(buffer)+1);
572     strcpy(aop->aopu.aop_immd,buffer);    
573     //aop->aopu.aop_alloc_reg = allocDirReg (IC_LEFT(ic));
574     allocDirReg (IC_LEFT(ic));
575     return aop;        
576 }
577
578 int aopIdx (asmop *aop, int offset)
579 {
580   if(!aop)
581     return -1;
582
583   if(aop->type !=  AOP_REG)
584     return -2;
585         
586   return aop->aopu.aop_reg[offset]->rIdx;
587
588 }
589 /*-----------------------------------------------------------------*/
590 /* regsInCommon - two operands have some registers in common       */
591 /*-----------------------------------------------------------------*/
592 static bool regsInCommon (operand *op1, operand *op2)
593 {
594     symbol *sym1, *sym2;
595     int i;
596
597     /* if they have registers in common */
598     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
599         return FALSE ;
600
601     sym1 = OP_SYMBOL(op1);
602     sym2 = OP_SYMBOL(op2);
603
604     if (sym1->nRegs == 0 || sym2->nRegs == 0)
605         return FALSE ;
606
607     for (i = 0 ; i < sym1->nRegs ; i++) {
608         int j;
609         if (!sym1->regs[i])
610             continue ;
611
612         for (j = 0 ; j < sym2->nRegs ;j++ ) {
613             if (!sym2->regs[j])
614                 continue ;
615
616             if (sym2->regs[j] == sym1->regs[i])
617                 return TRUE ;
618         }
619     }
620
621     return FALSE ;
622 }
623
624 /*-----------------------------------------------------------------*/
625 /* operandsEqu - equivalent                                        */
626 /*-----------------------------------------------------------------*/
627 static bool operandsEqu ( operand *op1, operand *op2)
628 {
629     symbol *sym1, *sym2;
630
631     /* if they not symbols */
632     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
633         return FALSE;
634
635     sym1 = OP_SYMBOL(op1);
636     sym2 = OP_SYMBOL(op2);
637
638     /* if both are itemps & one is spilt
639        and the other is not then false */
640     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
641         sym1->isspilt != sym2->isspilt )
642         return FALSE ;
643
644     /* if they are the same */
645     if (sym1 == sym2)
646         return TRUE ;
647
648     if (strcmp(sym1->rname,sym2->rname) == 0)
649         return TRUE;
650
651
652     /* if left is a tmp & right is not */
653     if (IS_ITEMP(op1)  && 
654         !IS_ITEMP(op2) &&
655         sym1->isspilt  &&
656         (sym1->usl.spillLoc == sym2))
657         return TRUE;
658
659     if (IS_ITEMP(op2)  && 
660         !IS_ITEMP(op1) &&
661         sym2->isspilt  &&
662         sym1->level > 0 &&
663         (sym2->usl.spillLoc == sym1))
664         return TRUE ;
665
666     return FALSE ;
667 }
668
669 /*-----------------------------------------------------------------*/
670 /* pic14_sameRegs - two asmops have the same registers                   */
671 /*-----------------------------------------------------------------*/
672 bool pic14_sameRegs (asmop *aop1, asmop *aop2 )
673 {
674     int i;
675
676     if (aop1 == aop2)
677         return TRUE ;
678
679     if (aop1->type != AOP_REG ||
680         aop2->type != AOP_REG )
681         return FALSE ;
682
683     if (aop1->size != aop2->size )
684         return FALSE ;
685
686     for (i = 0 ; i < aop1->size ; i++ )
687         if (aop1->aopu.aop_reg[i] !=
688             aop2->aopu.aop_reg[i] )
689             return FALSE ;
690
691     return TRUE ;
692 }
693
694 /*-----------------------------------------------------------------*/
695 /* aopOp - allocates an asmop for an operand  :                    */
696 /*-----------------------------------------------------------------*/
697 void aopOp (operand *op, iCode *ic, bool result)
698 {
699     asmop *aop;
700     symbol *sym;
701     int i;
702
703     if (!op)
704         return ;
705
706     //    DEBUGpic14_emitcode(";","%d",__LINE__);
707     /* if this a literal */
708     if (IS_OP_LITERAL(op)) {
709         op->aop = aop = newAsmop(AOP_LIT);
710         aop->aopu.aop_lit = op->operand.valOperand;
711         aop->size = getSize(operandType(op));
712         return;
713     }
714
715     {
716       sym_link *type = operandType(op);
717       if(IS_PTR_CONST(type))
718         DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
719     }
720
721     /* if already has a asmop then continue */
722     if (op->aop)
723         return ;
724
725     /* if the underlying symbol has a aop */
726     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
727       DEBUGpic14_emitcode(";","%d",__LINE__);
728         op->aop = OP_SYMBOL(op)->aop;
729         return;
730     }
731
732     /* if this is a true symbol */
733     if (IS_TRUE_SYMOP(op)) {    
734       //DEBUGpic14_emitcode(";","%d - true symop",__LINE__);
735       op->aop = aopForSym(ic,OP_SYMBOL(op),result);
736       return ;
737     }
738
739     /* this is a temporary : this has
740     only four choices :
741     a) register
742     b) spillocation
743     c) rematerialize 
744     d) conditional   
745     e) can be a return use only */
746
747     sym = OP_SYMBOL(op);
748
749
750     /* if the type is a conditional */
751     if (sym->regType == REG_CND) {
752         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
753         aop->size = 0;
754         return;
755     }
756
757     /* if it is spilt then two situations
758     a) is rematerialize 
759     b) has a spill location */
760     if (sym->isspilt || sym->nRegs == 0) {
761
762       DEBUGpic14_emitcode(";","%d",__LINE__);
763         /* rematerialize it NOW */
764         if (sym->remat) {
765             sym->aop = op->aop = aop =
766                                       aopForRemat (sym);
767             aop->size = getSize(sym->type);
768             return;
769         }
770
771         if (sym->accuse) {
772             int i;
773             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
774             aop->size = getSize(sym->type);
775             for ( i = 0 ; i < 2 ; i++ )
776                 aop->aopu.aop_str[i] = accUse[i];
777             DEBUGpic14_emitcode(";","%d",__LINE__);
778             return;  
779         }
780
781         if (sym->ruonly ) {
782             unsigned i;
783             aop = op->aop = sym->aop = newAsmop(AOP_STR);
784             aop->size = getSize(sym->type);
785             for ( i = 0 ; i < fReturnSizePic ; i++ )
786               aop->aopu.aop_str[i] = fReturn[i];
787             DEBUGpic14_emitcode(";","%d",__LINE__);
788             return;
789         }
790
791         /* else spill location  */
792         if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
793             /* force a new aop if sizes differ */
794             sym->usl.spillLoc->aop = NULL;
795         }
796         DEBUGpic14_emitcode(";","%s %d %s",__FUNCTION__,__LINE__,sym->usl.spillLoc->rname);
797         sym->aop = op->aop = aop = 
798                                   aopForSym(ic,sym->usl.spillLoc,result);
799         aop->size = getSize(sym->type);
800         return;
801     }
802
803     {
804       sym_link *type = operandType(op);
805       if(IS_PTR_CONST(type)) 
806         DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
807     }
808
809     /* must be in a register */
810     sym->aop = op->aop = aop = newAsmop(AOP_REG);
811     aop->size = sym->nRegs;
812     for ( i = 0 ; i < sym->nRegs ;i++)
813         aop->aopu.aop_reg[i] = sym->regs[i];
814 }
815
816 /*-----------------------------------------------------------------*/
817 /* freeAsmop - free up the asmop given to an operand               */
818 /*----------------------------------------------------------------*/
819 void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
820 {   
821     asmop *aop ;
822
823     if (!op)
824         aop = aaop;
825     else 
826         aop = op->aop;
827
828     if (!aop)
829         return ;
830
831     if (aop->freed)
832         goto dealloc; 
833
834     aop->freed = 1;
835
836     /* depending on the asmop type only three cases need work AOP_RO
837        , AOP_R1 && AOP_STK */
838 #if 0
839     switch (aop->type) {
840         case AOP_R0 :
841             if (_G.r0Pushed ) {
842                 if (pop) {
843                     pic14_emitcode ("pop","ar0");     
844                     _G.r0Pushed--;
845                 }
846             }
847             bitVectUnSetBit(ic->rUsed,R0_IDX);
848             break;
849
850         case AOP_R1 :
851             if (_G.r1Pushed ) {
852                 if (pop) {
853                     pic14_emitcode ("pop","ar1");
854                     _G.r1Pushed--;
855                 }
856             }
857             bitVectUnSetBit(ic->rUsed,R1_IDX);          
858             break;
859
860         case AOP_STK :
861         {
862             int sz = aop->size;    
863             int stk = aop->aopu.aop_stk + aop->size;
864             bitVectUnSetBit(ic->rUsed,R0_IDX);
865             bitVectUnSetBit(ic->rUsed,R1_IDX);          
866
867             getFreePtr(ic,&aop,FALSE);
868             
869             if (options.stack10bit)
870             {
871                 /* I'm not sure what to do here yet... */
872                 /* #STUB */
873                 fprintf(stderr, 
874                         "*** Warning: probably generating bad code for "
875                         "10 bit stack mode.\n");
876             }
877             
878             if (stk) {
879                 pic14_emitcode ("mov","a,_bp");
880                 pic14_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
881                 pic14_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
882             } else {
883                 pic14_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
884             }
885
886             while (sz--) {
887                 pic14_emitcode("pop","acc");
888                 pic14_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
889                 if (!sz) break;
890                 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
891             }
892             op->aop = aop;
893             freeAsmop(op,NULL,ic,TRUE);
894             if (_G.r0Pushed) {
895                 pic14_emitcode("pop","ar0");
896                 _G.r0Pushed--;
897             }
898
899             if (_G.r1Pushed) {
900                 pic14_emitcode("pop","ar1");
901                 _G.r1Pushed--;
902             }       
903         }
904     }
905 #endif
906
907 dealloc:
908     /* all other cases just dealloc */
909     if (op ) {
910         op->aop = NULL;
911         if (IS_SYMOP(op)) {
912             OP_SYMBOL(op)->aop = NULL;    
913             /* if the symbol has a spill */
914             if (SPIL_LOC(op))
915                 SPIL_LOC(op)->aop = NULL;
916         }
917     }
918 }
919
920 /*-----------------------------------------------------------------*/
921 /* aopGet - for fetching value of the aop                          */
922 /*-----------------------------------------------------------------*/
923 char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
924 {
925     char *s = buffer ;
926     char *rs;
927
928     //DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
929     /* offset is greater than
930     size then zero */
931     if (offset > (aop->size - 1) &&
932         aop->type != AOP_LIT)
933         return zero;
934
935     /* depending on type */
936     switch (aop->type) {
937         
938     case AOP_R0:
939     case AOP_R1:
940         DEBUGpic14_emitcode(";","%d",__LINE__);
941         /* if we need to increment it */       
942         while (offset > aop->coff) {        
943             pic14_emitcode ("inc","%s",aop->aopu.aop_ptr->name);  
944             aop->coff++;
945         }
946         
947         while (offset < aop->coff) {
948             pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
949             aop->coff--;
950         }
951         
952         aop->coff = offset ;
953         if (aop->paged) {
954             pic14_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
955             return (dname ? "acc" : "a");
956         }       
957         sprintf(s,"@%s",aop->aopu.aop_ptr->name);
958         rs = Safe_calloc(1,strlen(s)+1);
959         strcpy(rs,s);   
960         return rs;
961         
962     case AOP_DPTR:
963     case AOP_DPTR2:
964         DEBUGpic14_emitcode(";","%d",__LINE__);
965     if (aop->type == AOP_DPTR2)
966     {
967         genSetDPTR(1);
968     }
969     
970         while (offset > aop->coff) {
971             pic14_emitcode ("inc","dptr");
972             aop->coff++;
973         }
974         
975         while (offset < aop->coff) {        
976             pic14_emitcode("lcall","__decdptr");
977             aop->coff--;
978         }
979         
980         aop->coff = offset;
981         if (aop->code) {
982             pic14_emitcode("clr","a");
983             pic14_emitcode("movc","a,@a+dptr");
984         }
985     else {
986             pic14_emitcode("movx","a,@dptr");
987     }
988             
989     if (aop->type == AOP_DPTR2)
990     {
991         genSetDPTR(0);
992     }
993             
994     return (dname ? "acc" : "a");
995         
996         
997     case AOP_IMMD:
998         if (bit16) 
999             sprintf (s,"%s",aop->aopu.aop_immd);
1000         else
1001             if (offset) 
1002                 sprintf(s,"(%s >> %d)",
1003                         aop->aopu.aop_immd,
1004                         offset*8);
1005             else
1006                 sprintf(s,"%s",
1007                         aop->aopu.aop_immd);
1008         DEBUGpic14_emitcode(";","%d immd %s",__LINE__,s);
1009         rs = Safe_calloc(1,strlen(s)+1);
1010         strcpy(rs,s);   
1011         return rs;
1012         
1013     case AOP_DIR:
1014         if (offset)
1015             sprintf(s,"(%s + %d)",
1016                     aop->aopu.aop_dir,
1017                     offset);
1018         else
1019             sprintf(s,"%s",aop->aopu.aop_dir);
1020         rs = Safe_calloc(1,strlen(s)+1);
1021         strcpy(rs,s);   
1022         return rs;
1023         
1024     case AOP_REG:
1025       //if (dname) 
1026       //    return aop->aopu.aop_reg[offset]->dname;
1027       //else
1028             return aop->aopu.aop_reg[offset]->name;
1029         
1030     case AOP_CRY:
1031       //pic14_emitcode(";","%d",__LINE__);
1032       return aop->aopu.aop_dir;
1033         
1034     case AOP_ACC:
1035         DEBUGpic14_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1036         return "AOP_accumulator_bug";
1037
1038     case AOP_LIT:
1039         sprintf(s,"0x%02x", pic14aopLiteral (aop->aopu.aop_lit,offset));
1040         rs = Safe_calloc(1,strlen(s)+1);
1041         strcpy(rs,s);   
1042         return rs;
1043         
1044     case AOP_STR:
1045         DEBUGpic14_emitcode(";","%d",__LINE__);
1046         aop->coff = offset ;
1047         if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1048             dname)
1049             return "acc";
1050         
1051         return aop->aopu.aop_str[offset];
1052         
1053     }
1054
1055     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1056            "aopget got unsupported aop->type");
1057     exit(0);
1058 }
1059
1060 /*-----------------------------------------------------------------*/
1061 /* popGetLabel - create a new pCodeOp of type PO_LABEL             */
1062 /*-----------------------------------------------------------------*/
1063 pCodeOp *popGetLabel(unsigned int key)
1064 {
1065
1066   DEBUGpic14_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1067
1068   if(key>max_key)
1069     max_key = key;
1070
1071   return newpCodeOpLabel(NULL,key+100+labelOffset);
1072 }
1073
1074 /*-----------------------------------------------------------------*/
1075 /* popCopyReg - copy a pcode operator                              */
1076 /*-----------------------------------------------------------------*/
1077 pCodeOp *popCopyReg(pCodeOpReg *pc)
1078 {
1079   pCodeOpReg *pcor;
1080
1081   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1082   pcor->pcop.type = pc->pcop.type;
1083   if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1084     fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1085   pcor->r = pc->r;
1086   pcor->rIdx = pc->rIdx;
1087   pcor->r->wasUsed=1;
1088
1089   //DEBUGpic14_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1090
1091   return PCOP(pcor);
1092 }
1093 /*-----------------------------------------------------------------*/
1094 /* popGet - asm operator to pcode operator conversion              */
1095 /*-----------------------------------------------------------------*/
1096 pCodeOp *popGetLit(unsigned int lit)
1097 {
1098
1099   return newpCodeOpLit(lit);
1100 }
1101
1102
1103 /*-----------------------------------------------------------------*/
1104 /* popGetImmd - asm operator to pcode immediate conversion         */
1105 /*-----------------------------------------------------------------*/
1106 pCodeOp *popGetImmd(char *name, unsigned int offset)
1107 {
1108
1109   return newpCodeOpImmd(name, offset);
1110 }
1111
1112
1113 /*-----------------------------------------------------------------*/
1114 /* popGet - asm operator to pcode operator conversion              */
1115 /*-----------------------------------------------------------------*/
1116 pCodeOp *popGetWithString(char *str)
1117 {
1118   pCodeOp *pcop;
1119
1120
1121   if(!str) {
1122     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1123     exit (1);
1124   }
1125
1126   pcop = newpCodeOp(str,PO_STR);
1127
1128   return pcop;
1129 }
1130
1131 pCodeOp *popRegFromString(char *str)
1132 {
1133
1134   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOp) );
1135   pcop->type = PO_DIR;
1136
1137   DEBUGpic14_emitcode(";","%d",__LINE__);
1138   pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1139
1140   return pcop;
1141 }
1142
1143 pCodeOp *popRegFromIdx(int rIdx)
1144 {
1145   pCodeOp *pcop;
1146
1147   DEBUGpic14_emitcode ("; ***","%s,%d  , rIdx=0x%x",
1148                        __FUNCTION__,__LINE__,rIdx);
1149
1150   pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1151
1152   PCOR(pcop)->rIdx = rIdx;
1153   PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1154   PCOR(pcop)->r->isFree = 0;
1155   PCOR(pcop)->r->wasUsed = 1;
1156
1157   pcop->type = PCOR(pcop)->r->pc_type;
1158
1159
1160   return pcop;
1161 }
1162 /*-----------------------------------------------------------------*/
1163 /* popGet - asm operator to pcode operator conversion              */
1164 /*-----------------------------------------------------------------*/
1165 pCodeOp *popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1166 {
1167     char *s = buffer ;
1168     //char *rs;
1169
1170     pCodeOp *pcop;
1171
1172     //DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1173     /* offset is greater than
1174     size then zero */
1175
1176     if (offset > (aop->size - 1) &&
1177         aop->type != AOP_LIT)
1178       return NULL;  //zero;
1179
1180     /* depending on type */
1181     switch (aop->type) {
1182         
1183     case AOP_R0:
1184     case AOP_R1:
1185     case AOP_DPTR:
1186     case AOP_DPTR2:
1187     case AOP_ACC:
1188         DEBUGpic14_emitcode(";8051 legacy","%d type = %s",__LINE__,AopType(aop->type));
1189         return NULL;
1190         
1191     case AOP_IMMD:
1192       DEBUGpic14_emitcode(";","%d",__LINE__);
1193       return popGetImmd(aop->aopu.aop_immd,offset);
1194
1195     case AOP_DIR:
1196         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1197         pcop->type = PO_DIR;
1198
1199         if (offset)
1200             sprintf(s,"(%s + %d)",
1201                     aop->aopu.aop_dir,
1202                     offset);
1203         else
1204             sprintf(s,"%s",aop->aopu.aop_dir);
1205         pcop->name = Safe_calloc(1,strlen(s)+1);
1206         strcpy(pcop->name,s);   
1207         PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1208         if(PCOR(pcop)->r == NULL)
1209           fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1210         else
1211           PCOR(pcop)->instance = offset;
1212
1213         return pcop;
1214         
1215     case AOP_REG:
1216       {
1217         int rIdx = aop->aopu.aop_reg[offset]->rIdx;
1218
1219         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1220         PCOR(pcop)->rIdx = rIdx;
1221         PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1222         PCOR(pcop)->instance = offset;
1223         pcop->type = PCOR(pcop)->r->pc_type;
1224         //rs = aop->aopu.aop_reg[offset]->name;
1225         //DEBUGpic14_emitcode(";","%d regiser idx = %d name =%s",__LINE__,rIdx,rs);
1226         return pcop;
1227       }
1228
1229     case AOP_CRY:
1230       pcop = newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1231       PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1232       if(PCOR(pcop)->r == NULL)
1233         fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1234       return pcop;
1235         
1236     case AOP_LIT:
1237       return newpCodeOpLit(pic14aopLiteral (aop->aopu.aop_lit,offset));
1238
1239     case AOP_STR:
1240       DEBUGpic14_emitcode(";","%d",__LINE__);
1241       return newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1242       /*
1243       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1244       PCOR(pcop)->r = allocRegByName(aop->aopu.aop_str[offset]);
1245       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1246       pcop->type = PCOR(pcop)->r->pc_type;
1247       pcop->name = PCOR(pcop)->r->name;
1248
1249       return pcop;
1250       */
1251     }
1252
1253     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1254            "popGet got unsupported aop->type");
1255     exit(0);
1256 }
1257 /*-----------------------------------------------------------------*/
1258 /* aopPut - puts a string for a aop                                */
1259 /*-----------------------------------------------------------------*/
1260 void aopPut (asmop *aop, char *s, int offset)
1261 {
1262     char *d = buffer ;
1263     symbol *lbl ;
1264
1265     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1266
1267     if (aop->size && offset > ( aop->size - 1)) {
1268         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1269                "aopPut got offset > aop->size");
1270         exit(0);
1271     }
1272
1273     /* will assign value to value */
1274     /* depending on where it is ofcourse */
1275     switch (aop->type) {
1276     case AOP_DIR:
1277         if (offset)
1278             sprintf(d,"(%s + %d)",
1279                     aop->aopu.aop_dir,offset);
1280         else
1281             sprintf(d,"%s",aop->aopu.aop_dir);
1282         
1283         if (strcmp(d,s)) {
1284           DEBUGpic14_emitcode(";","%d",__LINE__);
1285           if(strcmp(s,"W"))
1286             pic14_emitcode("movf","%s,w",s);
1287           pic14_emitcode("movwf","%s",d);
1288
1289           if(strcmp(s,"W")) {
1290             pic14_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
1291             if(offset >= aop->size) {
1292               emitpcode(POC_CLRF,popGet(aop,offset));
1293               break;
1294             } else
1295               emitpcode(POC_MOVLW,popGetImmd(s,offset));
1296           }
1297
1298           emitpcode(POC_MOVWF,popGet(aop,offset));
1299
1300
1301         }
1302         break;
1303         
1304     case AOP_REG:
1305       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
1306         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1307           /*
1308             if (*s == '@'           ||
1309                 strcmp(s,"r0") == 0 ||
1310                 strcmp(s,"r1") == 0 ||
1311                 strcmp(s,"r2") == 0 ||
1312                 strcmp(s,"r3") == 0 ||
1313                 strcmp(s,"r4") == 0 ||
1314                 strcmp(s,"r5") == 0 ||
1315                 strcmp(s,"r6") == 0 || 
1316                 strcmp(s,"r7") == 0 )
1317                 pic14_emitcode("mov","%s,%s  ; %d",
1318                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1319             else
1320           */
1321
1322           if(strcmp(s,"W"))
1323             pic14_emitcode("movf","%s,w  ; %d",s,__LINE__);
1324
1325           pic14_emitcode("movwf","%s",
1326                    aop->aopu.aop_reg[offset]->name);
1327
1328           if(strcmp(s,"W")) {
1329             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1330             pcop->type = PO_GPR_REGISTER;
1331
1332             PCOR(pcop)->rIdx = -1;
1333             PCOR(pcop)->r = NULL;
1334
1335             DEBUGpic14_emitcode(";","%d",__LINE__);
1336             pcop->name = Safe_strdup(s);
1337             emitpcode(POC_MOVFW,pcop);
1338           }
1339           emitpcode(POC_MOVWF,popGet(aop,offset));
1340
1341         }
1342         break;
1343         
1344     case AOP_DPTR:
1345     case AOP_DPTR2:
1346     
1347     if (aop->type == AOP_DPTR2)
1348     {
1349         genSetDPTR(1);
1350     }
1351     
1352         if (aop->code) {
1353             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1354                    "aopPut writting to code space");
1355             exit(0);
1356         }
1357         
1358         while (offset > aop->coff) {
1359             aop->coff++;
1360             pic14_emitcode ("inc","dptr");
1361         }
1362         
1363         while (offset < aop->coff) {
1364             aop->coff-- ;
1365             pic14_emitcode("lcall","__decdptr");
1366         }
1367         
1368         aop->coff = offset;
1369         
1370         /* if not in accumulater */
1371         MOVA(s);        
1372         
1373         pic14_emitcode ("movx","@dptr,a");
1374         
1375     if (aop->type == AOP_DPTR2)
1376     {
1377         genSetDPTR(0);
1378     }
1379         break;
1380         
1381     case AOP_R0:
1382     case AOP_R1:
1383         while (offset > aop->coff) {
1384             aop->coff++;
1385             pic14_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1386         }
1387         while (offset < aop->coff) {
1388             aop->coff-- ;
1389             pic14_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1390         }
1391         aop->coff = offset;
1392         
1393         if (aop->paged) {
1394             MOVA(s);           
1395             pic14_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1396             
1397         } else
1398             if (*s == '@') {
1399                 MOVA(s);
1400                 pic14_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1401             } else
1402                 if (strcmp(s,"r0") == 0 ||
1403                     strcmp(s,"r1") == 0 ||
1404                     strcmp(s,"r2") == 0 ||
1405                     strcmp(s,"r3") == 0 ||
1406                     strcmp(s,"r4") == 0 ||
1407                     strcmp(s,"r5") == 0 ||
1408                     strcmp(s,"r6") == 0 || 
1409                     strcmp(s,"r7") == 0 ) {
1410                     char buffer[10];
1411                     sprintf(buffer,"a%s",s);
1412                     pic14_emitcode("mov","@%s,%s",
1413                              aop->aopu.aop_ptr->name,buffer);
1414                 } else
1415                     pic14_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1416         
1417         break;
1418         
1419     case AOP_STK:
1420         if (strcmp(s,"a") == 0)
1421             pic14_emitcode("push","acc");
1422         else
1423             pic14_emitcode("push","%s",s);
1424         
1425         break;
1426         
1427     case AOP_CRY:
1428         /* if bit variable */
1429         if (!aop->aopu.aop_dir) {
1430             pic14_emitcode("clr","a");
1431             pic14_emitcode("rlc","a");
1432         } else {
1433             if (s == zero) 
1434                 pic14_emitcode("clr","%s",aop->aopu.aop_dir);
1435             else
1436                 if (s == one)
1437                     pic14_emitcode("setb","%s",aop->aopu.aop_dir);
1438                 else
1439                     if (!strcmp(s,"c"))
1440                         pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1441                     else {
1442                         lbl = newiTempLabel(NULL);
1443                         
1444                         if (strcmp(s,"a")) {
1445                             MOVA(s);
1446                         }
1447                         pic14_emitcode("clr","c");
1448                         pic14_emitcode("jz","%05d_DS_",lbl->key+100);
1449                         pic14_emitcode("cpl","c");
1450                         pic14_emitcode("","%05d_DS_:",lbl->key+100);
1451                         pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1452                     }
1453         }
1454         break;
1455         
1456     case AOP_STR:
1457         aop->coff = offset;
1458         if (strcmp(aop->aopu.aop_str[offset],s))
1459             pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1460         break;
1461         
1462     case AOP_ACC:
1463         aop->coff = offset;
1464         if (!offset && (strcmp(s,"acc") == 0))
1465             break;
1466         
1467         if (strcmp(aop->aopu.aop_str[offset],s))
1468             pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1469         break;
1470
1471     default :
1472         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1473                "aopPut got unsupported aop->type");
1474         exit(0);    
1475     }    
1476
1477 }
1478
1479 /*-----------------------------------------------------------------*/
1480 /* reAdjustPreg - points a register back to where it should        */
1481 /*-----------------------------------------------------------------*/
1482 static void reAdjustPreg (asmop *aop)
1483 {
1484     int size ;
1485
1486     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1487     aop->coff = 0;
1488     if ((size = aop->size) <= 1)
1489         return ;
1490     size-- ;
1491     switch (aop->type) {
1492         case AOP_R0 :
1493         case AOP_R1 :
1494             while (size--)
1495                 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1496             break;          
1497         case AOP_DPTR :
1498         case AOP_DPTR2:
1499             if (aop->type == AOP_DPTR2)
1500             {
1501                 genSetDPTR(1);
1502             } 
1503             while (size--)
1504             {
1505                 pic14_emitcode("lcall","__decdptr");
1506             }
1507                 
1508             if (aop->type == AOP_DPTR2)
1509             {
1510                 genSetDPTR(0);
1511             }                
1512             break;  
1513
1514     }   
1515
1516 }
1517
1518 /*-----------------------------------------------------------------*/
1519 /* genNotFloat - generates not for float operations              */
1520 /*-----------------------------------------------------------------*/
1521 static void genNotFloat (operand *op, operand *res)
1522 {
1523     int size, offset;
1524     char *l;
1525     symbol *tlbl ;
1526
1527     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1528     /* we will put 127 in the first byte of 
1529     the result */
1530     aopPut(AOP(res),"#127",0);
1531     size = AOP_SIZE(op) - 1;
1532     offset = 1;
1533
1534     l = aopGet(op->aop,offset++,FALSE,FALSE);
1535     MOVA(l);    
1536
1537     while(size--) {
1538         pic14_emitcode("orl","a,%s",
1539                  aopGet(op->aop,
1540                         offset++,FALSE,FALSE));
1541     }
1542     tlbl = newiTempLabel(NULL);
1543
1544     tlbl = newiTempLabel(NULL);
1545     aopPut(res->aop,one,1);
1546     pic14_emitcode("jz","%05d_DS_",(tlbl->key+100));
1547     aopPut(res->aop,zero,1);
1548     pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
1549
1550     size = res->aop->size - 2;
1551     offset = 2;    
1552     /* put zeros in the rest */
1553     while (size--) 
1554         aopPut(res->aop,zero,offset++);
1555 }
1556
1557 #if 0
1558 /*-----------------------------------------------------------------*/
1559 /* opIsGptr: returns non-zero if the passed operand is             */   
1560 /* a generic pointer type.                                         */
1561 /*-----------------------------------------------------------------*/ 
1562 static int opIsGptr(operand *op)
1563 {
1564     sym_link *type = operandType(op);
1565     
1566     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1567     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1568     {
1569         return 1;
1570     }
1571     return 0;        
1572 }
1573 #endif
1574
1575 /*-----------------------------------------------------------------*/
1576 /* pic14_getDataSize - get the operand data size                         */
1577 /*-----------------------------------------------------------------*/
1578 int pic14_getDataSize(operand *op)
1579 {
1580     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1581
1582
1583     return AOP_SIZE(op);
1584
1585     // tsd- in the pic port, the genptr size is 1, so this code here
1586     // fails. ( in the 8051 port, the size was 4).
1587 #if 0
1588     int size;
1589     size = AOP_SIZE(op);
1590     if (size == GPTRSIZE)
1591     {
1592         sym_link *type = operandType(op);
1593         if (IS_GENPTR(type))
1594         {
1595             /* generic pointer; arithmetic operations
1596              * should ignore the high byte (pointer type).
1597              */
1598             size--;
1599     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1600         }
1601     }
1602     return size;
1603 #endif
1604 }
1605
1606 /*-----------------------------------------------------------------*/
1607 /* pic14_outAcc - output Acc                                             */
1608 /*-----------------------------------------------------------------*/
1609 void pic14_outAcc(operand *result)
1610 {
1611   int size,offset;
1612   DEBUGpic14_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
1613   DEBUGpic14_AopType(__LINE__,NULL,NULL,result);
1614
1615
1616   size = pic14_getDataSize(result);
1617   if(size){
1618     emitpcode(POC_MOVWF,popGet(AOP(result),0));
1619     size--;
1620     offset = 1;
1621     /* unsigned or positive */
1622     while(size--)
1623       emitpcode(POC_CLRF,popGet(AOP(result),offset++));
1624   }
1625
1626 }
1627
1628 /*-----------------------------------------------------------------*/
1629 /* pic14_outBitC - output a bit C                                        */
1630 /*-----------------------------------------------------------------*/
1631 void pic14_outBitC(operand *result)
1632 {
1633
1634     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1635     /* if the result is bit */
1636     if (AOP_TYPE(result) == AOP_CRY) 
1637         aopPut(AOP(result),"c",0);
1638     else {
1639         pic14_emitcode("clr","a  ; %d", __LINE__);
1640         pic14_emitcode("rlc","a");
1641         pic14_outAcc(result);
1642     }
1643 }
1644
1645 /*-----------------------------------------------------------------*/
1646 /* pic14_toBoolean - emit code for orl a,operator(sizeop)                */
1647 /*-----------------------------------------------------------------*/
1648 void pic14_toBoolean(operand *oper)
1649 {
1650     int size = AOP_SIZE(oper) - 1;
1651     int offset = 1;
1652
1653     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1654
1655     if ( AOP_TYPE(oper) != AOP_ACC) {
1656       emitpcode(POC_MOVFW,popGet(AOP(oper),0));
1657     }
1658     while (size--) {
1659       emitpcode(POC_IORFW, popGet(AOP(oper),offset++));
1660     }
1661 }
1662
1663
1664 /*-----------------------------------------------------------------*/
1665 /* genNot - generate code for ! operation                          */
1666 /*-----------------------------------------------------------------*/
1667 static void genNot (iCode *ic)
1668 {
1669   symbol *tlbl;
1670   sym_link *optype = operandType(IC_LEFT(ic));
1671   int size;
1672
1673   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1674   /* assign asmOps to operand & result */
1675   aopOp (IC_LEFT(ic),ic,FALSE);
1676   aopOp (IC_RESULT(ic),ic,TRUE);
1677
1678   DEBUGpic14_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
1679   /* if in bit space then a special case */
1680   if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1681     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
1682       emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(ic)),0));
1683       emitpcode(POC_XORWF,popGet(AOP(IC_RESULT(ic)),0));
1684     } else {
1685       emitpcode(POC_CLRF,popGet(AOP(IC_RESULT(ic)),0));
1686       emitpcode(POC_BTFSS,popGet(AOP(IC_LEFT(ic)),0));
1687       emitpcode(POC_INCF,popGet(AOP(IC_RESULT(ic)),0));
1688     }
1689     goto release;
1690   }
1691
1692   /* if type float then do float */
1693   if (IS_FLOAT(optype)) {
1694     genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
1695     goto release;
1696   }
1697
1698   size = AOP_SIZE(IC_RESULT(ic));
1699   if(size == 1) {
1700     emitpcode(POC_COMFW,popGet(AOP(IC_LEFT(ic)),0));
1701     emitpcode(POC_ANDLW,popGetLit(1));
1702     emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0));
1703     goto release;
1704   }
1705   pic14_toBoolean(IC_LEFT(ic));
1706
1707   tlbl = newiTempLabel(NULL);
1708   pic14_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
1709   pic14_emitcode("","%05d_DS_:",tlbl->key+100);
1710   pic14_outBitC(IC_RESULT(ic));
1711
1712  release:    
1713   /* release the aops */
1714   freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1715   freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1716 }
1717
1718
1719 /*-----------------------------------------------------------------*/
1720 /* genCpl - generate code for complement                           */
1721 /*-----------------------------------------------------------------*/
1722 static void genCpl (iCode *ic)
1723 {
1724     int offset = 0;
1725     int size ;
1726
1727
1728     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1729     /* assign asmOps to operand & result */
1730     aopOp (IC_LEFT(ic),ic,FALSE);
1731     aopOp (IC_RESULT(ic),ic,TRUE);
1732
1733     /* if both are in bit space then 
1734     a special case */
1735     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1736         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
1737
1738         pic14_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
1739         pic14_emitcode("cpl","c"); 
1740         pic14_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
1741         goto release; 
1742     } 
1743
1744     size = AOP_SIZE(IC_RESULT(ic));
1745     while (size--) {
1746         char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1747         MOVA(l);       
1748         pic14_emitcode("cpl","a");
1749         aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1750     }
1751
1752
1753 release:
1754     /* release the aops */
1755     freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1756     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1757 }
1758
1759 /*-----------------------------------------------------------------*/
1760 /* genUminusFloat - unary minus for floating points                */
1761 /*-----------------------------------------------------------------*/
1762 static void genUminusFloat(operand *op,operand *result)
1763 {
1764     int size ,offset =0 ;
1765     char *l;
1766
1767     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1768     /* for this we just need to flip the 
1769     first it then copy the rest in place */
1770     size = AOP_SIZE(op) - 1;
1771     l = aopGet(AOP(op),3,FALSE,FALSE);
1772
1773     MOVA(l);    
1774
1775     pic14_emitcode("cpl","acc.7");
1776     aopPut(AOP(result),"a",3);    
1777
1778     while(size--) {
1779         aopPut(AOP(result),
1780                aopGet(AOP(op),offset,FALSE,FALSE),
1781                offset);
1782         offset++;
1783     }          
1784 }
1785
1786 /*-----------------------------------------------------------------*/
1787 /* genUminus - unary minus code generation                         */
1788 /*-----------------------------------------------------------------*/
1789 static void genUminus (iCode *ic)
1790 {
1791   int size, i;
1792   sym_link *optype, *rtype;
1793
1794
1795   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1796   /* assign asmops */
1797   aopOp(IC_LEFT(ic),ic,FALSE);
1798   aopOp(IC_RESULT(ic),ic,TRUE);
1799
1800   /* if both in bit space then special
1801      case */
1802   if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1803       AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
1804
1805     emitpcode(POC_BCF,   popGet(AOP(IC_RESULT(ic)),0));
1806     emitpcode(POC_BTFSS, popGet(AOP(IC_LEFT(ic)),0));
1807     emitpcode(POC_BSF,   popGet(AOP(IC_RESULT(ic)),0));
1808
1809     goto release; 
1810   } 
1811
1812   optype = operandType(IC_LEFT(ic));
1813   rtype = operandType(IC_RESULT(ic));
1814
1815   /* if float then do float stuff */
1816   if (IS_FLOAT(optype)) {
1817     genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1818     goto release;
1819   }
1820
1821   /* otherwise subtract from zero by taking the 2's complement */
1822   size = AOP_SIZE(IC_LEFT(ic));
1823
1824   for(i=0; i<size; i++) {
1825     if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
1826       emitpcode(POC_COMF,  popGet(AOP(IC_LEFT(ic)),i));
1827     else {
1828       emitpcode(POC_COMFW, popGet(AOP(IC_LEFT(ic)),i));
1829       emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),i));
1830     }
1831   }
1832
1833   emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),0));
1834   for(i=1; i<size; i++) {
1835     emitSKPNZ;
1836     emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),i));
1837   }
1838
1839  release:
1840   /* release the aops */
1841   freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1842   freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
1843 }
1844
1845 /*-----------------------------------------------------------------*/
1846 /* saveRegisters - will look for a call and save the registers     */
1847 /*-----------------------------------------------------------------*/
1848 static void saveRegisters(iCode *lic) 
1849 {
1850     int i;
1851     iCode *ic;
1852     bitVect *rsave;
1853     sym_link *dtype;
1854
1855     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1856     /* look for call */
1857     for (ic = lic ; ic ; ic = ic->next) 
1858         if (ic->op == CALL || ic->op == PCALL)
1859             break;
1860
1861     if (!ic) {
1862         fprintf(stderr,"found parameter push with no function call\n");
1863         return ;
1864     }
1865
1866     /* if the registers have been saved already then
1867     do nothing */
1868     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
1869         return ;
1870
1871     /* find the registers in use at this time 
1872     and push them away to safety */
1873     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1874                           ic->rUsed);
1875
1876     ic->regsSaved = 1;
1877     if (options.useXstack) {
1878         if (bitVectBitValue(rsave,R0_IDX))
1879             pic14_emitcode("mov","b,r0");
1880         pic14_emitcode("mov","r0,%s",spname);
1881         for (i = 0 ; i < pic14_nRegs ; i++) {
1882             if (bitVectBitValue(rsave,i)) {
1883                 if (i == R0_IDX)
1884                     pic14_emitcode("mov","a,b");
1885                 else
1886                     pic14_emitcode("mov","a,%s",pic14_regWithIdx(i)->name);
1887                 pic14_emitcode("movx","@r0,a");
1888                 pic14_emitcode("inc","r0");
1889             }
1890         }
1891         pic14_emitcode("mov","%s,r0",spname);
1892         if (bitVectBitValue(rsave,R0_IDX))
1893             pic14_emitcode("mov","r0,b");           
1894     }// else
1895     //for (i = 0 ; i < pic14_nRegs ; i++) {
1896     //    if (bitVectBitValue(rsave,i))
1897     //  pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
1898     //}
1899
1900     dtype = operandType(IC_LEFT(ic));
1901     if (currFunc && dtype && 
1902         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
1903         IFFUNC_ISISR(currFunc->type) &&
1904         !ic->bankSaved) 
1905
1906         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
1907
1908 }
1909 /*-----------------------------------------------------------------*/
1910 /* unsaveRegisters - pop the pushed registers                      */
1911 /*-----------------------------------------------------------------*/
1912 static void unsaveRegisters (iCode *ic)
1913 {
1914     int i;
1915     bitVect *rsave;
1916
1917     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1918     /* find the registers in use at this time 
1919     and push them away to safety */
1920     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1921                           ic->rUsed);
1922     
1923     if (options.useXstack) {
1924         pic14_emitcode("mov","r0,%s",spname);   
1925         for (i =  pic14_nRegs ; i >= 0 ; i--) {
1926             if (bitVectBitValue(rsave,i)) {
1927                 pic14_emitcode("dec","r0");
1928                 pic14_emitcode("movx","a,@r0");
1929                 if (i == R0_IDX)
1930                     pic14_emitcode("mov","b,a");
1931                 else
1932                     pic14_emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
1933             }       
1934
1935         }
1936         pic14_emitcode("mov","%s,r0",spname);
1937         if (bitVectBitValue(rsave,R0_IDX))
1938             pic14_emitcode("mov","r0,b");
1939     } //else
1940     //for (i =  pic14_nRegs ; i >= 0 ; i--) {
1941     //    if (bitVectBitValue(rsave,i))
1942     //  pic14_emitcode("pop","%s",pic14_regWithIdx(i)->dname);
1943     //}
1944
1945 }  
1946
1947
1948 /*-----------------------------------------------------------------*/
1949 /* pushSide -                                                      */
1950 /*-----------------------------------------------------------------*/
1951 static void pushSide(operand * oper, int size)
1952 {
1953 #if 0
1954         int offset = 0;
1955     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1956         while (size--) {
1957                 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
1958                 if (AOP_TYPE(oper) != AOP_REG &&
1959                     AOP_TYPE(oper) != AOP_DIR &&
1960                     strcmp(l,"a") ) {
1961                         pic14_emitcode("mov","a,%s",l);
1962                         pic14_emitcode("push","acc");
1963                 } else
1964                         pic14_emitcode("push","%s",l);
1965         }
1966 #endif
1967 }
1968
1969 /*-----------------------------------------------------------------*/
1970 /* assignResultValue -                                             */
1971 /*-----------------------------------------------------------------*/
1972 static void assignResultValue(operand * oper)
1973 {
1974   int size = AOP_SIZE(oper);
1975
1976   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1977
1978   DEBUGpic14_AopType(__LINE__,oper,NULL,NULL);
1979
1980   if(!GpsuedoStkPtr) {
1981     /* The last byte in the assignment is in W */
1982     size--;
1983     emitpcode(POC_MOVWF, popGet(AOP(oper),size));
1984     GpsuedoStkPtr++;
1985   }
1986
1987   while (size--) {
1988     emitpcode(POC_MOVFW,popRegFromIdx(GpsuedoStkPtr-1 + Gstack_base_addr));
1989     GpsuedoStkPtr++;
1990     emitpcode(POC_MOVWF, popGet(AOP(oper),size));
1991   }
1992 }
1993
1994
1995 /*-----------------------------------------------------------------*/
1996 /* genIpush - genrate code for pushing this gets a little complex  */
1997 /*-----------------------------------------------------------------*/
1998 static void genIpush (iCode *ic)
1999 {
2000
2001   DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2002 #if 0
2003     int size, offset = 0 ;
2004     char *l;
2005
2006
2007     /* if this is not a parm push : ie. it is spill push 
2008     and spill push is always done on the local stack */
2009     if (!ic->parmPush) {
2010
2011         /* and the item is spilt then do nothing */
2012         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2013             return ;
2014
2015         aopOp(IC_LEFT(ic),ic,FALSE);
2016         size = AOP_SIZE(IC_LEFT(ic));
2017         /* push it on the stack */
2018         while(size--) {
2019             l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2020             if (*l == '#') {
2021                 MOVA(l);
2022                 l = "acc";
2023             }
2024             pic14_emitcode("push","%s",l);
2025         }
2026         return ;        
2027     }
2028
2029     /* this is a paramter push: in this case we call
2030     the routine to find the call and save those
2031     registers that need to be saved */   
2032     saveRegisters(ic);
2033
2034     /* then do the push */
2035     aopOp(IC_LEFT(ic),ic,FALSE);
2036
2037
2038         // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2039     size = AOP_SIZE(IC_LEFT(ic));
2040
2041     while (size--) {
2042         l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2043         if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && 
2044             AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2045             strcmp(l,"a") ) {
2046             pic14_emitcode("mov","a,%s",l);
2047             pic14_emitcode("push","acc");
2048         } else
2049             pic14_emitcode("push","%s",l);
2050     }       
2051
2052     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2053 #endif
2054 }
2055
2056 /*-----------------------------------------------------------------*/
2057 /* genIpop - recover the registers: can happen only for spilling   */
2058 /*-----------------------------------------------------------------*/
2059 static void genIpop (iCode *ic)
2060 {
2061   DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2062 #if 0
2063     int size,offset ;
2064
2065
2066     /* if the temp was not pushed then */
2067     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2068         return ;
2069
2070     aopOp(IC_LEFT(ic),ic,FALSE);
2071     size = AOP_SIZE(IC_LEFT(ic));
2072     offset = (size-1);
2073     while (size--) 
2074         pic14_emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
2075                                    FALSE,TRUE));
2076
2077     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2078 #endif
2079 }
2080
2081 /*-----------------------------------------------------------------*/
2082 /* unsaverbank - restores the resgister bank from stack            */
2083 /*-----------------------------------------------------------------*/
2084 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2085 {
2086   DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2087 #if 0
2088     int i;
2089     asmop *aop ;
2090     regs *r = NULL;
2091
2092     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2093     if (popPsw) {
2094         if (options.useXstack) {
2095             aop = newAsmop(0);
2096             r = getFreePtr(ic,&aop,FALSE);
2097             
2098             
2099             pic14_emitcode("mov","%s,_spx",r->name);
2100             pic14_emitcode("movx","a,@%s",r->name);
2101             pic14_emitcode("mov","psw,a");
2102             pic14_emitcode("dec","%s",r->name);
2103             
2104         }else
2105             pic14_emitcode ("pop","psw");
2106     }
2107
2108     for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
2109         if (options.useXstack) {       
2110             pic14_emitcode("movx","a,@%s",r->name);
2111             //pic14_emitcode("mov","(%s+%d),a",
2112             //       regspic14[i].base,8*bank+regspic14[i].offset);
2113             pic14_emitcode("dec","%s",r->name);
2114
2115         } else 
2116           pic14_emitcode("pop",""); //"(%s+%d)",
2117         //regspic14[i].base,8*bank); //+regspic14[i].offset);
2118     }
2119
2120     if (options.useXstack) {
2121
2122         pic14_emitcode("mov","_spx,%s",r->name);
2123         freeAsmop(NULL,aop,ic,TRUE);
2124
2125     }
2126 #endif 
2127 }
2128
2129 /*-----------------------------------------------------------------*/
2130 /* saverbank - saves an entire register bank on the stack          */
2131 /*-----------------------------------------------------------------*/
2132 static void saverbank (int bank, iCode *ic, bool pushPsw)
2133 {
2134   DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2135 #if 0
2136     int i;
2137     asmop *aop ;
2138     regs *r = NULL;
2139
2140     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2141     if (options.useXstack) {
2142
2143         aop = newAsmop(0);
2144         r = getFreePtr(ic,&aop,FALSE);  
2145         pic14_emitcode("mov","%s,_spx",r->name);
2146
2147     }
2148
2149     for (i = 0 ; i < pic14_nRegs ;i++) {
2150         if (options.useXstack) {
2151             pic14_emitcode("inc","%s",r->name);
2152             //pic14_emitcode("mov","a,(%s+%d)",
2153             //         regspic14[i].base,8*bank+regspic14[i].offset);
2154             pic14_emitcode("movx","@%s,a",r->name);           
2155         } else 
2156           pic14_emitcode("push","");// "(%s+%d)",
2157                      //regspic14[i].base,8*bank+regspic14[i].offset);
2158     }
2159     
2160     if (pushPsw) {
2161         if (options.useXstack) {
2162             pic14_emitcode("mov","a,psw");
2163             pic14_emitcode("movx","@%s,a",r->name);     
2164             pic14_emitcode("inc","%s",r->name);
2165             pic14_emitcode("mov","_spx,%s",r->name);       
2166             freeAsmop (NULL,aop,ic,TRUE);
2167             
2168         } else
2169             pic14_emitcode("push","psw");
2170         
2171         pic14_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2172     }
2173     ic->bankSaved = 1;
2174 #endif
2175 }
2176
2177 /*-----------------------------------------------------------------*/
2178 /* genCall - generates a call statement                            */
2179 /*-----------------------------------------------------------------*/
2180 static void genCall (iCode *ic)
2181 {
2182   sym_link *dtype;   
2183
2184   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2185
2186   /* if caller saves & we have not saved then */
2187   if (!ic->regsSaved)
2188     saveRegisters(ic);
2189
2190   /* if we are calling a function that is not using
2191      the same register bank then we need to save the
2192      destination registers on the stack */
2193   dtype = operandType(IC_LEFT(ic));
2194   if (currFunc && dtype && 
2195       (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2196       IFFUNC_ISISR(currFunc->type) &&
2197       !ic->bankSaved) 
2198
2199     saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2200
2201   /* if send set is not empty the assign */
2202   if (_G.sendSet) {
2203     iCode *sic;
2204     /* For the Pic port, there is no data stack.
2205      * So parameters passed to functions are stored
2206      * in registers. (The pCode optimizer will get
2207      * rid of most of these :).
2208      */
2209     int psuedoStkPtr=-1; 
2210     int firstTimeThruLoop = 1;
2211
2212     _G.sendSet = reverseSet(_G.sendSet);
2213
2214     /* First figure how many parameters are getting passed */
2215     for (sic = setFirstItem(_G.sendSet) ; sic ; 
2216          sic = setNextItem(_G.sendSet)) {
2217
2218       aopOp(IC_LEFT(sic),sic,FALSE);
2219       psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2220       freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2221     }
2222
2223     for (sic = setFirstItem(_G.sendSet) ; sic ; 
2224          sic = setNextItem(_G.sendSet)) {
2225       int size, offset = 0;
2226
2227       aopOp(IC_LEFT(sic),sic,FALSE);
2228       size = AOP_SIZE(IC_LEFT(sic));
2229
2230
2231       while (size--) {
2232         DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2233                              AopType(AOP_TYPE(IC_LEFT(sic))));
2234
2235         if(!firstTimeThruLoop) {
2236           /* If this is not the first time we've been through the loop
2237            * then we need to save the parameter in a temporary
2238            * register. The last byte of the last parameter is
2239            * passed in W. */
2240           emitpcode(POC_MOVWF,popRegFromIdx(--psuedoStkPtr + Gstack_base_addr));
2241
2242         }
2243         firstTimeThruLoop=0;
2244
2245         //if (strcmp(l,fReturn[offset])) {
2246
2247         if ( ((AOP(IC_LEFT(sic))->type) == AOP_IMMD) ||
2248              ((AOP(IC_LEFT(sic))->type) == AOP_LIT) )
2249           emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(sic)),offset));
2250         else
2251           emitpcode(POC_MOVFW,popGet(AOP(IC_LEFT(sic)),offset));
2252
2253         //}
2254         offset++;
2255       }
2256       freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2257     }
2258     _G.sendSet = NULL;
2259   }
2260   /* make the call */
2261   emitpcode(POC_CALL,popGetWithString(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2262                                       OP_SYMBOL(IC_LEFT(ic))->rname :
2263                                       OP_SYMBOL(IC_LEFT(ic))->name));
2264
2265   GpsuedoStkPtr=0;
2266   /* if we need assign a result value */
2267   if ((IS_ITEMP(IC_RESULT(ic)) && 
2268        (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2269         OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2270       IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2271
2272     _G.accInUse++;
2273     aopOp(IC_RESULT(ic),ic,FALSE);
2274     _G.accInUse--;
2275
2276     assignResultValue(IC_RESULT(ic));
2277
2278     DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2279                          AopType(AOP_TYPE(IC_RESULT(ic))));
2280                 
2281     freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2282   }
2283
2284   /* adjust the stack for parameters if 
2285      required */
2286   if (ic->parmBytes) {
2287     int i;
2288     if (ic->parmBytes > 3) {
2289       pic14_emitcode("mov","a,%s",spname);
2290       pic14_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2291       pic14_emitcode("mov","%s,a",spname);
2292     } else 
2293       for ( i = 0 ; i <  ic->parmBytes ;i++)
2294         pic14_emitcode("dec","%s",spname);
2295
2296   }
2297
2298   /* if register bank was saved then pop them */
2299   if (ic->bankSaved)
2300     unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2301
2302   /* if we hade saved some registers then unsave them */
2303   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2304     unsaveRegisters (ic);
2305
2306
2307 }
2308
2309 /*-----------------------------------------------------------------*/
2310 /* genPcall - generates a call by pointer statement                */
2311 /*-----------------------------------------------------------------*/
2312 static void genPcall (iCode *ic)
2313 {
2314     sym_link *dtype;
2315     symbol *rlbl = newiTempLabel(NULL);
2316
2317
2318     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2319     /* if caller saves & we have not saved then */
2320     if (!ic->regsSaved)
2321         saveRegisters(ic);
2322
2323     /* if we are calling a function that is not using
2324     the same register bank then we need to save the
2325     destination registers on the stack */
2326     dtype = operandType(IC_LEFT(ic));
2327     if (currFunc && dtype && 
2328         IFFUNC_ISISR(currFunc->type) &&
2329         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2330         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2331
2332
2333     /* push the return address on to the stack */
2334     pic14_emitcode("mov","a,#%05d_DS_",(rlbl->key+100));
2335     pic14_emitcode("push","acc");    
2336     pic14_emitcode("mov","a,#(%05d_DS_ >> 8)",(rlbl->key+100));
2337     pic14_emitcode("push","acc");
2338     
2339     if (options.model == MODEL_FLAT24)
2340     {
2341         pic14_emitcode("mov","a,#(%05d_DS_ >> 16)",(rlbl->key+100));
2342         pic14_emitcode("push","acc");    
2343     }
2344
2345     /* now push the calling address */
2346     aopOp(IC_LEFT(ic),ic,FALSE);
2347
2348     pushSide(IC_LEFT(ic), FPTRSIZE);
2349
2350     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
2351
2352     /* if send set is not empty the assign */
2353     if (_G.sendSet) {
2354         iCode *sic ;
2355
2356         for (sic = setFirstItem(_G.sendSet) ; sic ; 
2357              sic = setNextItem(_G.sendSet)) {
2358             int size, offset = 0;
2359             aopOp(IC_LEFT(sic),sic,FALSE);
2360             size = AOP_SIZE(IC_LEFT(sic));
2361             while (size--) {
2362                 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
2363                                 FALSE,FALSE);
2364                 if (strcmp(l,fReturn[offset]))
2365                     pic14_emitcode("mov","%s,%s",
2366                              fReturn[offset],
2367                              l);
2368                 offset++;
2369             }
2370             freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2371         }
2372         _G.sendSet = NULL;
2373     }
2374
2375     pic14_emitcode("ret","");
2376     pic14_emitcode("","%05d_DS_:",(rlbl->key+100));
2377
2378
2379     /* if we need assign a result value */
2380     if ((IS_ITEMP(IC_RESULT(ic)) &&
2381          (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2382           OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2383         IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2384
2385         _G.accInUse++;
2386         aopOp(IC_RESULT(ic),ic,FALSE);
2387         _G.accInUse--;
2388         
2389         assignResultValue(IC_RESULT(ic));
2390
2391         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2392     }
2393
2394     /* adjust the stack for parameters if 
2395     required */
2396     if (ic->parmBytes) {
2397         int i;
2398         if (ic->parmBytes > 3) {
2399             pic14_emitcode("mov","a,%s",spname);
2400             pic14_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2401             pic14_emitcode("mov","%s,a",spname);
2402         } else 
2403             for ( i = 0 ; i <  ic->parmBytes ;i++)
2404                 pic14_emitcode("dec","%s",spname);
2405
2406     }
2407
2408     /* if register bank was saved then unsave them */
2409     if (currFunc && dtype && 
2410         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2411         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2412
2413     /* if we hade saved some registers then
2414     unsave them */
2415     if (ic->regsSaved)
2416         unsaveRegisters (ic);
2417
2418 }
2419
2420 /*-----------------------------------------------------------------*/
2421 /* resultRemat - result  is rematerializable                       */
2422 /*-----------------------------------------------------------------*/
2423 static int resultRemat (iCode *ic)
2424 {
2425     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2426     if (SKIP_IC(ic) || ic->op == IFX)
2427         return 0;
2428
2429     if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2430         symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2431         if (sym->remat && !POINTER_SET(ic)) 
2432             return 1;
2433     }
2434
2435     return 0;
2436 }
2437
2438 #if defined(__BORLANDC__) || defined(_MSC_VER)
2439 #define STRCASECMP stricmp
2440 #else
2441 #define STRCASECMP strcasecmp
2442 #endif
2443
2444 /*-----------------------------------------------------------------*/
2445 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2446 /*-----------------------------------------------------------------*/
2447 static bool inExcludeList(char *s)
2448 {
2449   DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2450 #if 0
2451     int i =0;
2452     
2453     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2454     if (options.excludeRegs[i] &&
2455     STRCASECMP(options.excludeRegs[i],"none") == 0)
2456         return FALSE ;
2457
2458     for ( i = 0 ; options.excludeRegs[i]; i++) {
2459         if (options.excludeRegs[i] &&
2460         STRCASECMP(s,options.excludeRegs[i]) == 0)
2461             return TRUE;
2462     }
2463 #endif
2464     return FALSE ;
2465 }
2466
2467 /*-----------------------------------------------------------------*/
2468 /* genFunction - generated code for function entry                 */
2469 /*-----------------------------------------------------------------*/
2470 static void genFunction (iCode *ic)
2471 {
2472     symbol *sym;
2473     sym_link *ftype;
2474
2475     DEBUGpic14_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2476
2477     labelOffset += (max_key+4);
2478     max_key=0;
2479     GpsuedoStkPtr=0;
2480     _G.nRegsSaved = 0;
2481     /* create the function header */
2482     pic14_emitcode(";","-----------------------------------------");
2483     pic14_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2484     pic14_emitcode(";","-----------------------------------------");
2485
2486     pic14_emitcode("","%s:",sym->rname);
2487     addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname));
2488
2489     ftype = operandType(IC_LEFT(ic));
2490
2491     /* if critical function then turn interrupts off */
2492     if (IFFUNC_ISCRITICAL(ftype))
2493         pic14_emitcode("clr","ea");
2494
2495     /* here we need to generate the equates for the
2496        register bank if required */
2497 #if 0
2498     if (FUNC_REGBANK(ftype) != rbank) {
2499         int i ;
2500
2501         rbank = FUNC_REGBANK(ftype);
2502         for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2503             if (strcmp(regspic14[i].base,"0") == 0)
2504                 pic14_emitcode("","%s = 0x%02x",
2505                          regspic14[i].dname,
2506                          8*rbank+regspic14[i].offset);
2507             else
2508                 pic14_emitcode ("","%s = %s + 0x%02x",
2509                           regspic14[i].dname,
2510                           regspic14[i].base,
2511                           8*rbank+regspic14[i].offset);
2512         }
2513     }
2514 #endif
2515
2516     /* if this is an interrupt service routine then
2517     save acc, b, dpl, dph  */
2518     if (IFFUNC_ISISR(sym->type)) {
2519       addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("END_OF_INTERRUPT+1",PO_STR)));
2520       emitpcodeNULLop(POC_NOP);
2521       emitpcodeNULLop(POC_NOP);
2522       emitpcodeNULLop(POC_NOP);
2523       emitpcode(POC_MOVWF,  popCopyReg(&pc_wsave));
2524       emitpcode(POC_SWAPFW, popCopyReg(&pc_status));
2525       emitpcode(POC_CLRF,   popCopyReg(&pc_status));
2526       emitpcode(POC_MOVWF,  popCopyReg(&pc_ssave));
2527
2528       pBlockConvert2ISR(pb);
2529 #if 0  
2530         if (!inExcludeList("acc"))          
2531             pic14_emitcode ("push","acc");      
2532         if (!inExcludeList("b"))
2533             pic14_emitcode ("push","b");
2534         if (!inExcludeList("dpl"))
2535             pic14_emitcode ("push","dpl");
2536         if (!inExcludeList("dph"))
2537             pic14_emitcode ("push","dph");
2538         if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2539         {
2540             pic14_emitcode ("push", "dpx");
2541             /* Make sure we're using standard DPTR */
2542             pic14_emitcode ("push", "dps");
2543             pic14_emitcode ("mov", "dps, #0x00");
2544             if (options.stack10bit)
2545             {   
2546                 /* This ISR could conceivably use DPTR2. Better save it. */
2547                 pic14_emitcode ("push", "dpl1");
2548                 pic14_emitcode ("push", "dph1");
2549                 pic14_emitcode ("push", "dpx1");
2550             }
2551         }
2552         /* if this isr has no bank i.e. is going to
2553            run with bank 0 , then we need to save more
2554            registers :-) */
2555         if (!FUNC_REGBANK(sym->type)) {
2556
2557             /* if this function does not call any other
2558                function then we can be economical and
2559                save only those registers that are used */
2560             if (! IFFUNC_HASFCALL(sym->type)) {
2561                 int i;
2562
2563                 /* if any registers used */
2564                 if (sym->regsUsed) {
2565                     /* save the registers used */
2566                     for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2567                         if (bitVectBitValue(sym->regsUsed,i) ||
2568                           (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2569                           pic14_emitcode("push","junk");//"%s",pic14_regWithIdx(i)->dname);                         
2570                     }
2571                 }
2572                 
2573             } else {
2574                 /* this function has  a function call cannot
2575                    determines register usage so we will have the
2576                    entire bank */
2577                 saverbank(0,ic,FALSE);
2578             }       
2579         }
2580 #endif
2581     } else {
2582         /* if callee-save to be used for this function
2583            then save the registers being used in this function */
2584         if (IFFUNC_CALLEESAVES(sym->type)) {
2585             int i;
2586             
2587             /* if any registers used */
2588             if (sym->regsUsed) {
2589                 /* save the registers used */
2590                 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2591                     if (bitVectBitValue(sym->regsUsed,i) ||
2592                       (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2593                       //pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2594                         _G.nRegsSaved++;
2595                     }
2596                 }
2597             }
2598         }
2599     }
2600
2601     /* set the register bank to the desired value */
2602     if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type)) {
2603         pic14_emitcode("push","psw");
2604         pic14_emitcode("mov","psw,#0x%02x",(FUNC_REGBANK(sym->type) << 3)&0x00ff);   
2605     }
2606
2607     if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
2608
2609         if (options.useXstack) {
2610             pic14_emitcode("mov","r0,%s",spname);
2611             pic14_emitcode("mov","a,_bp");
2612             pic14_emitcode("movx","@r0,a");
2613             pic14_emitcode("inc","%s",spname);
2614         }
2615         else
2616         {
2617             /* set up the stack */
2618             pic14_emitcode ("push","_bp");     /* save the callers stack  */
2619         }
2620         pic14_emitcode ("mov","_bp,%s",spname);
2621     }
2622
2623     /* adjust the stack for the function */
2624     if (sym->stack) {
2625
2626         int i = sym->stack;
2627         if (i > 256 ) 
2628             werror(W_STACK_OVERFLOW,sym->name);
2629
2630         if (i > 3 && sym->recvSize < 4) {              
2631
2632             pic14_emitcode ("mov","a,sp");
2633             pic14_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2634             pic14_emitcode ("mov","sp,a");
2635            
2636         }
2637         else
2638             while(i--)
2639                 pic14_emitcode("inc","sp");
2640     }
2641
2642      if (sym->xstack) {
2643
2644         pic14_emitcode ("mov","a,_spx");
2645         pic14_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2646         pic14_emitcode ("mov","_spx,a");
2647     }    
2648
2649 }
2650
2651 /*-----------------------------------------------------------------*/
2652 /* genEndFunction - generates epilogue for functions               */
2653 /*-----------------------------------------------------------------*/
2654 static void genEndFunction (iCode *ic)
2655 {
2656     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2657
2658     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2659
2660     if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
2661     {
2662         pic14_emitcode ("mov","%s,_bp",spname);
2663     }
2664
2665     /* if use external stack but some variables were
2666     added to the local stack then decrement the
2667     local stack */
2668     if (options.useXstack && sym->stack) {      
2669         pic14_emitcode("mov","a,sp");
2670         pic14_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2671         pic14_emitcode("mov","sp,a");
2672     }
2673
2674
2675     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
2676         if (options.useXstack) {
2677             pic14_emitcode("mov","r0,%s",spname);
2678             pic14_emitcode("movx","a,@r0");
2679             pic14_emitcode("mov","_bp,a");
2680             pic14_emitcode("dec","%s",spname);
2681         }
2682         else
2683         {
2684             pic14_emitcode ("pop","_bp");
2685         }
2686     }
2687
2688     /* restore the register bank  */    
2689     if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
2690         pic14_emitcode ("pop","psw");
2691
2692     if (IFFUNC_ISISR(sym->type)) {
2693
2694         /* now we need to restore the registers */
2695         /* if this isr has no bank i.e. is going to
2696            run with bank 0 , then we need to save more
2697            registers :-) */
2698         if (!FUNC_REGBANK(sym->type)) {
2699             
2700             /* if this function does not call any other
2701                function then we can be economical and
2702                save only those registers that are used */
2703             if (! IFFUNC_HASFCALL(sym->type)) {
2704                 int i;
2705                 
2706                 /* if any registers used */
2707                 if (sym->regsUsed) {
2708                     /* save the registers used */
2709                     for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2710                         if (bitVectBitValue(sym->regsUsed,i) ||
2711                           (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2712                           pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
2713                     }
2714                 }
2715                 
2716             } else {
2717                 /* this function has  a function call cannot
2718                    determines register usage so we will have the
2719                    entire bank */
2720                 unsaverbank(0,ic,FALSE);
2721             }       
2722         }
2723 #if 0
2724         if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2725         {
2726             if (options.stack10bit)
2727             {
2728                 pic14_emitcode ("pop", "dpx1");
2729                 pic14_emitcode ("pop", "dph1");
2730                 pic14_emitcode ("pop", "dpl1");
2731             }   
2732             pic14_emitcode ("pop", "dps");
2733             pic14_emitcode ("pop", "dpx");
2734         }
2735         if (!inExcludeList("dph"))
2736             pic14_emitcode ("pop","dph");
2737         if (!inExcludeList("dpl"))
2738             pic14_emitcode ("pop","dpl");
2739         if (!inExcludeList("b"))
2740             pic14_emitcode ("pop","b");
2741         if (!inExcludeList("acc"))
2742             pic14_emitcode ("pop","acc");
2743
2744         if (IFFUNC_ISCRITICAL(sym->type))
2745             pic14_emitcode("setb","ea");
2746 #endif
2747
2748         /* if debug then send end of function */
2749 /*      if (options.debug && currFunc) { */
2750         if (currFunc) {
2751             _G.debugLine = 1;
2752             pic14_emitcode(";","C$%s$%d$%d$%d ==.",
2753                      FileBaseName(ic->filename),currFunc->lastLine,
2754                      ic->level,ic->block); 
2755             if (IS_STATIC(currFunc->etype))         
2756                 pic14_emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
2757             else
2758                 pic14_emitcode(";","XG$%s$0$0 ==.",currFunc->name);
2759             _G.debugLine = 0;
2760         }
2761         
2762         pic14_emitcode ("reti","");
2763
2764         emitpcode(POC_CLRF,   popCopyReg(&pc_status));
2765         emitpcode(POC_SWAPFW, popCopyReg(&pc_ssave));
2766         emitpcode(POC_MOVWF,  popCopyReg(&pc_status));
2767         emitpcode(POC_SWAPF,  popCopyReg(&pc_wsave));
2768         emitpcode(POC_MOVFW,  popCopyReg(&pc_wsave));
2769         addpCode2pBlock(pb,newpCodeLabel("END_OF_INTERRUPT",-1));
2770
2771         emitpcodeNULLop(POC_RETFIE);
2772
2773     }
2774     else {
2775         if (IFFUNC_ISCRITICAL(sym->type))
2776             pic14_emitcode("setb","ea");
2777         
2778         if (IFFUNC_CALLEESAVES(sym->type)) {
2779             int i;
2780             
2781             /* if any registers used */
2782             if (sym->regsUsed) {
2783                 /* save the registers used */
2784                 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2785                     if (bitVectBitValue(sym->regsUsed,i) ||
2786                       (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2787                       pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
2788                 }
2789             }
2790             
2791         }
2792
2793         /* if debug then send end of function */
2794         if (currFunc) {
2795             _G.debugLine = 1;
2796             pic14_emitcode(";","C$%s$%d$%d$%d ==.",
2797                      FileBaseName(ic->filename),currFunc->lastLine,
2798                      ic->level,ic->block); 
2799             if (IS_STATIC(currFunc->etype))         
2800                 pic14_emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
2801             else
2802                 pic14_emitcode(";","XG$%s$0$0 ==.",currFunc->name);
2803             _G.debugLine = 0;
2804         }
2805
2806         pic14_emitcode ("return","");
2807         emitpcodeNULLop(POC_RETURN);
2808
2809         /* Mark the end of a function */
2810         addpCode2pBlock(pb,newpCodeFunction(NULL,NULL));
2811     }
2812
2813 }
2814
2815 /*-----------------------------------------------------------------*/
2816 /* genRet - generate code for return statement                     */
2817 /*-----------------------------------------------------------------*/
2818 static void genRet (iCode *ic)
2819 {
2820   int size,offset = 0 , pushed = 0;
2821     
2822   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2823   /* if we have no return value then
2824      just generate the "ret" */
2825   if (!IC_LEFT(ic)) 
2826     goto jumpret;       
2827     
2828   /* we have something to return then
2829      move the return value into place */
2830   aopOp(IC_LEFT(ic),ic,FALSE);
2831   size = AOP_SIZE(IC_LEFT(ic));
2832     
2833   while (size--) {
2834     char *l ;
2835     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
2836       /* #NOCHANGE */
2837       l = aopGet(AOP(IC_LEFT(ic)),offset++,
2838                  FALSE,TRUE);
2839       pic14_emitcode("push","%s",l);
2840       pushed++;
2841     } else {
2842       l = aopGet(AOP(IC_LEFT(ic)),offset,
2843                  FALSE,FALSE);
2844       if (strcmp(fReturn[offset],l)) {
2845         if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD) ||
2846             ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
2847           emitpcode(POC_MOVLW, popGet(AOP(IC_LEFT(ic)),offset));
2848         }else {
2849           emitpcode(POC_MOVFW, popGet(AOP(IC_LEFT(ic)),offset));
2850         }
2851         if(size) {
2852           emitpcode(POC_MOVWF,popRegFromIdx(offset + Gstack_base_addr));
2853           pic14_emitcode("movwf","%s",fReturn[offset]);
2854         }
2855         offset++;
2856       }
2857     }
2858   }    
2859
2860   if (pushed) {
2861     while(pushed) {
2862       pushed--;
2863       if (strcmp(fReturn[pushed],"a"))
2864         pic14_emitcode("pop",fReturn[pushed]);
2865       else
2866         pic14_emitcode("pop","acc");
2867     }
2868   }
2869   freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2870     
2871  jumpret:
2872   /* generate a jump to the return label
2873      if the next is not the return statement */
2874   if (!(ic->next && ic->next->op == LABEL &&
2875         IC_LABEL(ic->next) == returnLabel)) {
2876         
2877     emitpcode(POC_GOTO,popGetLabel(returnLabel->key));
2878     pic14_emitcode("goto","_%05d_DS_",returnLabel->key+100 + labelOffset);
2879   }
2880     
2881 }
2882
2883 /*-----------------------------------------------------------------*/
2884 /* genLabel - generates a label                                    */
2885 /*-----------------------------------------------------------------*/
2886 static void genLabel (iCode *ic)
2887 {
2888     /* special case never generate */
2889     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2890     if (IC_LABEL(ic) == entryLabel)
2891         return ;
2892
2893     emitpLabel(IC_LABEL(ic)->key);
2894     pic14_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
2895 }
2896
2897 /*-----------------------------------------------------------------*/
2898 /* genGoto - generates a goto                                      */
2899 /*-----------------------------------------------------------------*/
2900 //tsd
2901 static void genGoto (iCode *ic)
2902 {
2903   emitpcode(POC_GOTO,popGetLabel(IC_LABEL(ic)->key));
2904   pic14_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
2905 }
2906
2907
2908 /*-----------------------------------------------------------------*/
2909 /* genMultbits :- multiplication of bits                           */
2910 /*-----------------------------------------------------------------*/
2911 static void genMultbits (operand *left, 
2912                          operand *right, 
2913                          operand *result)
2914 {
2915   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2916
2917   if(!pic14_sameRegs(AOP(result),AOP(right)))
2918     emitpcode(POC_BSF,  popGet(AOP(result),0));
2919
2920   emitpcode(POC_BTFSC,popGet(AOP(right),0));
2921   emitpcode(POC_BTFSS,popGet(AOP(left),0));
2922   emitpcode(POC_BCF,  popGet(AOP(result),0));
2923
2924 }
2925
2926
2927 /*-----------------------------------------------------------------*/
2928 /* genMultOneByte : 8 bit multiplication & division                */
2929 /*-----------------------------------------------------------------*/
2930 static void genMultOneByte (operand *left,
2931                             operand *right,
2932                             operand *result)
2933 {
2934     sym_link *opetype = operandType(result);
2935     char *l ;
2936     symbol *lbl ;
2937     int size,offset;
2938
2939     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2940   DEBUGpic14_AopType(__LINE__,left,right,result);
2941
2942     /* (if two literals, the value is computed before) */
2943     /* if one literal, literal on the right */
2944     if (AOP_TYPE(left) == AOP_LIT){
2945         operand *t = right;
2946         right = left;
2947         left = t;
2948     }
2949
2950     size = AOP_SIZE(result);
2951     /* signed or unsigned */
2952     pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
2953     l = aopGet(AOP(left),0,FALSE,FALSE);
2954     MOVA(l);       
2955     pic14_emitcode("mul","ab");
2956     /* if result size = 1, mul signed = mul unsigned */
2957     aopPut(AOP(result),"a",0);
2958     if (size > 1){
2959         if (SPEC_USIGN(opetype)){
2960             aopPut(AOP(result),"b",1);
2961             if (size > 2)
2962                 /* for filling the MSBs */
2963                 pic14_emitcode("clr","a");
2964         }
2965         else{
2966             pic14_emitcode("mov","a,b");
2967
2968             /* adjust the MSB if left or right neg */
2969
2970             /* if one literal */
2971             if (AOP_TYPE(right) == AOP_LIT){
2972                 /* AND literal negative */
2973                 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
2974                     /* adjust MSB (c==0 after mul) */
2975                     pic14_emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
2976                 }
2977             }
2978             else{
2979                 lbl = newiTempLabel(NULL);
2980                 pic14_emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
2981                 pic14_emitcode("cjne","a,#0x80,%05d_DS_", (lbl->key+100));
2982                 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
2983                 pic14_emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
2984                 lbl = newiTempLabel(NULL);      
2985                 pic14_emitcode("jc","%05d_DS_",(lbl->key+100));          
2986                 pic14_emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
2987                 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
2988             }
2989
2990             lbl = newiTempLabel(NULL);
2991             pic14_emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
2992             pic14_emitcode("cjne","a,#0x80,%05d_DS_", (lbl->key+100));
2993             pic14_emitcode("","%05d_DS_:",(lbl->key+100));
2994             pic14_emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
2995             lbl = newiTempLabel(NULL);      
2996             pic14_emitcode("jc","%05d_DS_",(lbl->key+100));          
2997             pic14_emitcode("subb","a,%s", aopGet(AOP(right),0,FALSE,FALSE));
2998             pic14_emitcode("","%05d_DS_:",(lbl->key+100));
2999
3000             aopPut(AOP(result),"a",1);
3001             if(size > 2){
3002                 /* get the sign */
3003                 pic14_emitcode("rlc","a");
3004                 pic14_emitcode("subb","a,acc");
3005             }
3006         }
3007         size -= 2;   
3008         offset = 2;
3009         if (size > 0)
3010             while (size--)
3011                 aopPut(AOP(result),"a",offset++);
3012     }
3013 }
3014
3015 /*-----------------------------------------------------------------*/
3016 /* genMult - generates code for multiplication                     */
3017 /*-----------------------------------------------------------------*/
3018 static void genMult (iCode *ic)
3019 {
3020     operand *left = IC_LEFT(ic);
3021     operand *right = IC_RIGHT(ic);
3022     operand *result= IC_RESULT(ic);   
3023
3024     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3025     /* assign the amsops */
3026     aopOp (left,ic,FALSE);
3027     aopOp (right,ic,FALSE);
3028     aopOp (result,ic,TRUE);
3029
3030   DEBUGpic14_AopType(__LINE__,left,right,result);
3031
3032     /* special cases first */
3033     /* both are bits */
3034     if (AOP_TYPE(left) == AOP_CRY &&
3035         AOP_TYPE(right)== AOP_CRY) {
3036         genMultbits(left,right,result);
3037         goto release ;
3038     }
3039
3040     /* if both are of size == 1 */
3041     if (AOP_SIZE(left) == 1 &&
3042         AOP_SIZE(right) == 1 ) {
3043         genMultOneByte(left,right,result);
3044         goto release ;
3045     }
3046
3047     /* should have been converted to function call */       
3048     assert(0) ;
3049
3050 release :
3051     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3052     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3053     freeAsmop(result,NULL,ic,TRUE); 
3054 }
3055
3056 /*-----------------------------------------------------------------*/
3057 /* genDivbits :- division of bits                                  */
3058 /*-----------------------------------------------------------------*/
3059 static void genDivbits (operand *left, 
3060                         operand *right, 
3061                         operand *result)
3062 {
3063
3064     char *l;
3065
3066     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3067     /* the result must be bit */    
3068     pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3069     l = aopGet(AOP(left),0,FALSE,FALSE);
3070
3071     MOVA(l);    
3072
3073     pic14_emitcode("div","ab");
3074     pic14_emitcode("rrc","a");
3075     aopPut(AOP(result),"c",0);
3076 }
3077
3078 /*-----------------------------------------------------------------*/
3079 /* genDivOneByte : 8 bit division                                  */
3080 /*-----------------------------------------------------------------*/
3081 static void genDivOneByte (operand *left,
3082                            operand *right,
3083                            operand *result)
3084 {
3085     sym_link *opetype = operandType(result);
3086     char *l ;
3087     symbol *lbl ;
3088     int size,offset;
3089
3090     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3091     size = AOP_SIZE(result) - 1;
3092     offset = 1;
3093     /* signed or unsigned */
3094     if (SPEC_USIGN(opetype)) {
3095         /* unsigned is easy */
3096         pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3097         l = aopGet(AOP(left),0,FALSE,FALSE);
3098         MOVA(l);        
3099         pic14_emitcode("div","ab");
3100         aopPut(AOP(result),"a",0);
3101         while (size--)
3102             aopPut(AOP(result),zero,offset++);
3103         return ;
3104     }
3105
3106     /* signed is a little bit more difficult */
3107
3108     /* save the signs of the operands */
3109     l = aopGet(AOP(left),0,FALSE,FALSE);    
3110     MOVA(l);    
3111     pic14_emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE));
3112     pic14_emitcode("push","acc"); /* save it on the stack */
3113
3114     /* now sign adjust for both left & right */
3115     l =  aopGet(AOP(right),0,FALSE,FALSE);    
3116     MOVA(l);       
3117     lbl = newiTempLabel(NULL);
3118     pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
3119     pic14_emitcode("cpl","a");   
3120     pic14_emitcode("inc","a");
3121     pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3122     pic14_emitcode("mov","b,a");
3123
3124     /* sign adjust left side */
3125     l =  aopGet(AOP(left),0,FALSE,FALSE);    
3126     MOVA(l);
3127
3128     lbl = newiTempLabel(NULL);
3129     pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3130     pic14_emitcode("cpl","a");
3131     pic14_emitcode("inc","a");
3132     pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3133
3134     /* now the division */
3135     pic14_emitcode("div","ab");
3136     /* we are interested in the lower order
3137     only */
3138     pic14_emitcode("mov","b,a");
3139     lbl = newiTempLabel(NULL);
3140     pic14_emitcode("pop","acc");   
3141     /* if there was an over flow we don't 
3142     adjust the sign of the result */
3143     pic14_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3144     pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3145     CLRC;
3146     pic14_emitcode("clr","a");
3147     pic14_emitcode("subb","a,b");
3148     pic14_emitcode("mov","b,a");
3149     pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3150
3151     /* now we are done */
3152     aopPut(AOP(result),"b",0);
3153     if(size > 0){
3154         pic14_emitcode("mov","c,b.7");
3155         pic14_emitcode("subb","a,acc");   
3156     }
3157     while (size--)
3158         aopPut(AOP(result),"a",offset++);
3159
3160 }
3161
3162 /*-----------------------------------------------------------------*/
3163 /* genDiv - generates code for division                            */
3164 /*-----------------------------------------------------------------*/
3165 static void genDiv (iCode *ic)
3166 {
3167     operand *left = IC_LEFT(ic);
3168     operand *right = IC_RIGHT(ic);
3169     operand *result= IC_RESULT(ic);   
3170
3171     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3172     /* assign the amsops */
3173     aopOp (left,ic,FALSE);
3174     aopOp (right,ic,FALSE);
3175     aopOp (result,ic,TRUE);
3176
3177     /* special cases first */
3178     /* both are bits */
3179     if (AOP_TYPE(left) == AOP_CRY &&
3180         AOP_TYPE(right)== AOP_CRY) {
3181         genDivbits(left,right,result);
3182         goto release ;
3183     }
3184
3185     /* if both are of size == 1 */
3186     if (AOP_SIZE(left) == 1 &&
3187         AOP_SIZE(right) == 1 ) {
3188         genDivOneByte(left,right,result);
3189         goto release ;
3190     }
3191
3192     /* should have been converted to function call */
3193     assert(0);
3194 release :
3195     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3196     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3197     freeAsmop(result,NULL,ic,TRUE); 
3198 }
3199
3200 /*-----------------------------------------------------------------*/
3201 /* genModbits :- modulus of bits                                   */
3202 /*-----------------------------------------------------------------*/
3203 static void genModbits (operand *left, 
3204                         operand *right, 
3205                         operand *result)
3206 {
3207
3208     char *l;
3209
3210     /* the result must be bit */    
3211     pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3212     l = aopGet(AOP(left),0,FALSE,FALSE);
3213
3214     MOVA(l);       
3215
3216     pic14_emitcode("div","ab");
3217     pic14_emitcode("mov","a,b");
3218     pic14_emitcode("rrc","a");
3219     aopPut(AOP(result),"c",0);
3220 }
3221
3222 /*-----------------------------------------------------------------*/
3223 /* genModOneByte : 8 bit modulus                                   */
3224 /*-----------------------------------------------------------------*/
3225 static void genModOneByte (operand *left,
3226                            operand *right,
3227                            operand *result)
3228 {
3229     sym_link *opetype = operandType(result);
3230     char *l ;
3231     symbol *lbl ;
3232
3233     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3234     /* signed or unsigned */
3235     if (SPEC_USIGN(opetype)) {
3236         /* unsigned is easy */
3237         pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3238         l = aopGet(AOP(left),0,FALSE,FALSE);
3239         MOVA(l);    
3240         pic14_emitcode("div","ab");
3241         aopPut(AOP(result),"b",0);
3242         return ;
3243     }
3244
3245     /* signed is a little bit more difficult */
3246
3247     /* save the signs of the operands */
3248     l = aopGet(AOP(left),0,FALSE,FALSE);    
3249     MOVA(l);
3250
3251     pic14_emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3252     pic14_emitcode("push","acc"); /* save it on the stack */
3253
3254     /* now sign adjust for both left & right */
3255     l =  aopGet(AOP(right),0,FALSE,FALSE);    
3256     MOVA(l);
3257
3258     lbl = newiTempLabel(NULL);
3259     pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
3260     pic14_emitcode("cpl","a");   
3261     pic14_emitcode("inc","a");
3262     pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3263     pic14_emitcode("mov","b,a"); 
3264
3265     /* sign adjust left side */
3266     l =  aopGet(AOP(left),0,FALSE,FALSE);    
3267     MOVA(l);
3268
3269     lbl = newiTempLabel(NULL);
3270     pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3271     pic14_emitcode("cpl","a");   
3272     pic14_emitcode("inc","a");
3273     pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3274
3275     /* now the multiplication */
3276     pic14_emitcode("div","ab");
3277     /* we are interested in the lower order
3278     only */
3279     lbl = newiTempLabel(NULL);
3280     pic14_emitcode("pop","acc");   
3281     /* if there was an over flow we don't 
3282     adjust the sign of the result */
3283     pic14_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3284     pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3285     CLRC ;
3286     pic14_emitcode("clr","a");
3287     pic14_emitcode("subb","a,b");
3288     pic14_emitcode("mov","b,a");
3289     pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3290
3291     /* now we are done */
3292     aopPut(AOP(result),"b",0);
3293
3294 }
3295
3296 /*-----------------------------------------------------------------*/
3297 /* genMod - generates code for division                            */
3298 /*-----------------------------------------------------------------*/
3299 static void genMod (iCode *ic)
3300 {
3301     operand *left = IC_LEFT(ic);
3302     operand *right = IC_RIGHT(ic);
3303     operand *result= IC_RESULT(ic);  
3304
3305     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3306     /* assign the amsops */
3307     aopOp (left,ic,FALSE);
3308     aopOp (right,ic,FALSE);
3309     aopOp (result,ic,TRUE);
3310
3311     /* special cases first */
3312     /* both are bits */
3313     if (AOP_TYPE(left) == AOP_CRY &&
3314         AOP_TYPE(right)== AOP_CRY) {
3315         genModbits(left,right,result);
3316         goto release ;
3317     }
3318
3319     /* if both are of size == 1 */
3320     if (AOP_SIZE(left) == 1 &&
3321         AOP_SIZE(right) == 1 ) {
3322         genModOneByte(left,right,result);
3323         goto release ;
3324     }
3325
3326     /* should have been converted to function call */
3327     assert(0);
3328
3329 release :
3330     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3331     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3332     freeAsmop(result,NULL,ic,TRUE); 
3333 }
3334
3335 /*-----------------------------------------------------------------*/
3336 /* genIfxJump :- will create a jump depending on the ifx           */
3337 /*-----------------------------------------------------------------*/
3338 /*
3339   note: May need to add parameter to indicate when a variable is in bit space.
3340 */
3341 static void genIfxJump (iCode *ic, char *jval)
3342 {
3343
3344     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3345     /* if true label then we jump if condition
3346     supplied is true */
3347     if ( IC_TRUE(ic) ) {
3348
3349         if(strcmp(jval,"a") == 0)
3350           emitSKPZ;
3351         else if (strcmp(jval,"c") == 0)
3352           emitSKPC;
3353         else {
3354           DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
3355           emitpcode(POC_BTFSC,  newpCodeOpBit(jval,-1,1));
3356         }
3357
3358         emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3359         pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3360
3361     }
3362     else {
3363         /* false label is present */
3364         if(strcmp(jval,"a") == 0)
3365           emitSKPNZ;
3366         else if (strcmp(jval,"c") == 0)
3367           emitSKPNC;
3368         else {
3369           DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
3370           emitpcode(POC_BTFSS,  newpCodeOpBit(jval,-1,1));
3371         }
3372
3373         emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
3374         pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3375
3376     }
3377
3378
3379     /* mark the icode as generated */
3380     ic->generated = 1;
3381 }
3382
3383 /*-----------------------------------------------------------------*/
3384 /* genSkip                                                         */
3385 /*-----------------------------------------------------------------*/
3386 static void genSkip(iCode *ifx,int status_bit)
3387 {
3388   if(!ifx)
3389     return;
3390
3391   if ( IC_TRUE(ifx) ) {
3392     switch(status_bit) {
3393     case 'z':
3394       emitSKPNZ;
3395       break;
3396
3397     case 'c':
3398       emitSKPNC;
3399       break;
3400
3401     case 'd':
3402       emitSKPDC;
3403       break;
3404
3405     }
3406
3407     emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3408     pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3409
3410   } else {
3411
3412     switch(status_bit) {
3413
3414     case 'z':
3415       emitSKPZ;
3416       break;
3417
3418     case 'c':
3419       emitSKPC;
3420       break;
3421
3422     case 'd':
3423       emitSKPDC;
3424       break;
3425     }
3426     emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3427     pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3428
3429   }
3430
3431 }
3432
3433 /*-----------------------------------------------------------------*/
3434 /* genSkipc                                                        */
3435 /*-----------------------------------------------------------------*/
3436 static void genSkipc(resolvedIfx *rifx)
3437 {
3438   if(!rifx)
3439     return;
3440
3441   if(rifx->condition)
3442     emitSKPC;
3443   else
3444     emitSKPNC;
3445
3446   emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3447   rifx->generated = 1;
3448 }
3449
3450 /*-----------------------------------------------------------------*/
3451 /* genSkipz2                                                       */
3452 /*-----------------------------------------------------------------*/
3453 static void genSkipz2(resolvedIfx *rifx)
3454 {
3455   if(!rifx)
3456     return;
3457
3458   if(rifx->condition)
3459     emitSKPZ;
3460   else
3461     emitSKPNZ;
3462
3463   emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3464   rifx->generated = 1;
3465 }
3466
3467 /*-----------------------------------------------------------------*/
3468 /* genSkipz                                                        */
3469 /*-----------------------------------------------------------------*/
3470 static void genSkipz(iCode *ifx, int condition)
3471 {
3472   if(!ifx)
3473     return;
3474
3475   if(condition)
3476     emitSKPNZ;
3477   else
3478     emitSKPZ;
3479
3480   if ( IC_TRUE(ifx) )
3481     emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3482   else
3483     emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3484
3485   if ( IC_TRUE(ifx) )
3486     pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3487   else
3488     pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3489
3490 }
3491 /*-----------------------------------------------------------------*/
3492 /* genSkipCond                                                     */
3493 /*-----------------------------------------------------------------*/
3494 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3495 {
3496   if(!rifx)
3497     return;
3498
3499   if(rifx->condition)
3500     emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3501   else
3502     emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3503
3504
3505   emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3506   rifx->generated = 1;
3507 }
3508
3509 #if 0
3510 /*-----------------------------------------------------------------*/
3511 /* genChkZeroes :- greater or less than comparison                 */
3512 /*     For each byte in a literal that is zero, inclusive or the   */
3513 /*     the corresponding byte in the operand with W                */
3514 /*     returns true if any of the bytes are zero                   */
3515 /*-----------------------------------------------------------------*/
3516 static int genChkZeroes(operand *op, int lit,  int size)
3517 {
3518
3519   int i;
3520   int flag =1;
3521
3522   while(size--) {
3523     i = (lit >> (size*8)) & 0xff;
3524
3525     if(i==0) {
3526       if(flag) 
3527         emitpcode(POC_MOVFW, popGet(AOP(op),size));
3528       else
3529         emitpcode(POC_IORFW, popGet(AOP(op),size));
3530       flag = 0;
3531     }
3532   }
3533
3534   return (flag==0);
3535 }
3536 #endif
3537
3538 /*-----------------------------------------------------------------*/
3539 /* genCmp :- greater or less than comparison                       */
3540 /*-----------------------------------------------------------------*/
3541 static void genCmp (operand *left,operand *right,
3542                     operand *result, iCode *ifx, int sign)
3543 {
3544   int size, offset = 0 ;
3545   unsigned long lit = 0L,i = 0;
3546   resolvedIfx rFalseIfx;
3547   //  resolvedIfx rTrueIfx;
3548   symbol *truelbl;
3549   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3550   if(ifx) {
3551   DEBUGpic14_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
3552   DEBUGpic14_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
3553   }
3554
3555
3556   resolveIfx(&rFalseIfx,ifx);
3557   truelbl  = newiTempLabel(NULL);
3558
3559   //if(IC_TRUE(ifx) == NULL)
3560   /* if left & right are bit variables */
3561   if (AOP_TYPE(left) == AOP_CRY &&
3562       AOP_TYPE(right) == AOP_CRY ) {
3563     pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3564     pic14_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3565   } else {
3566     /* subtract right from left if at the
3567        end the carry flag is set then we know that
3568        left is greater than right */
3569     size = max(AOP_SIZE(left),AOP_SIZE(right));
3570
3571     /* if unsigned char cmp with lit, do cjne left,#right,zz */
3572     if((size == 1) && !sign &&
3573        (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
3574       symbol *lbl  = newiTempLabel(NULL);
3575       pic14_emitcode("cjne","%s,%s,%05d_DS_",
3576                aopGet(AOP(left),offset,FALSE,FALSE),
3577                aopGet(AOP(right),offset,FALSE,FALSE),
3578                lbl->key+100);
3579       pic14_emitcode("","%05d_DS_:",lbl->key+100);
3580     } else {
3581
3582       symbol *lbl  = newiTempLabel(NULL);
3583
3584       if(AOP_TYPE(right) == AOP_LIT) {
3585
3586         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3587
3588         DEBUGpic14_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
3589
3590         /* special cases */
3591
3592         if(lit == 0) {
3593
3594           if(sign != 0) 
3595             genSkipCond(&rFalseIfx,left,size-1,7);
3596           else 
3597             /* no need to compare to 0...*/
3598             /* NOTE: this is a de-generate compare that most certainly 
3599              *       creates some dead code. */
3600             emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
3601
3602           if(ifx) ifx->generated = 1;
3603           return;
3604
3605         }
3606         size--;
3607
3608         if(size == 0) {
3609           //i = (lit >> (size*8)) & 0xff;
3610           DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
3611         
3612           emitpcode(POC_MOVFW, popGet(AOP(left),size));
3613
3614           i = ((0-lit) & 0xff);
3615           if(sign) {
3616             if( i == 0x81) { 
3617               /* lit is 0x7f, all signed chars are less than
3618                * this except for 0x7f itself */
3619               emitpcode(POC_XORLW, popGetLit(0x7f));
3620               genSkipz2(&rFalseIfx);
3621             } else {
3622               emitpcode(POC_ADDLW, popGetLit(0x80));
3623               emitpcode(POC_ADDLW, popGetLit(i^0x80));
3624               genSkipc(&rFalseIfx);
3625             }
3626
3627           } else {
3628             emitpcode(POC_ADDLW, popGetLit(i));
3629             genSkipc(&rFalseIfx);
3630
3631           }
3632
3633           if(ifx) ifx->generated = 1;
3634           return;
3635         }
3636
3637         /* chars are out of the way. now do ints and longs */
3638
3639
3640         DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
3641         
3642         /* special cases */
3643
3644         if(sign) {
3645
3646           if(lit == 0) {
3647             genSkipCond(&rFalseIfx,left,size,7);
3648             if(ifx) ifx->generated = 1;
3649             return;
3650           }
3651
3652           if(lit <0x100) {
3653             DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3654
3655             //rFalseIfx.condition ^= 1;
3656             //genSkipCond(&rFalseIfx,left,size,7);
3657             //rFalseIfx.condition ^= 1;
3658
3659             emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
3660             if(rFalseIfx.condition)
3661               emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
3662             else
3663               emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3664
3665             emitpcode(POC_MOVLW, popGetLit(0x100-lit));
3666             emitpcode(POC_ADDFW, popGet(AOP(left),0));
3667             emitpcode(POC_MOVFW, popGet(AOP(left),1));
3668
3669             while(size > 1)
3670               emitpcode(POC_IORFW, popGet(AOP(left),size--));
3671
3672             if(rFalseIfx.condition) {
3673               emitSKPZ;
3674               emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3675
3676             } else {
3677               emitSKPNZ;
3678             }
3679
3680             genSkipc(&rFalseIfx);
3681             emitpLabel(truelbl->key);
3682             if(ifx) ifx->generated = 1;
3683             return;
3684
3685           }
3686
3687           if(size == 1) {
3688
3689             if( (lit & 0xff) == 0) {
3690               /* lower byte is zero */
3691               DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3692               i = ((lit >> 8) & 0xff) ^0x80;
3693               emitpcode(POC_MOVFW, popGet(AOP(left),size));
3694               emitpcode(POC_ADDLW, popGetLit( 0x80));
3695               emitpcode(POC_ADDLW, popGetLit(0x100-i));
3696               genSkipc(&rFalseIfx);
3697
3698
3699               if(ifx) ifx->generated = 1;
3700               return;
3701
3702             }
3703           } else {
3704             /* Special cases for signed longs */
3705             if( (lit & 0xffffff) == 0) {
3706               /* lower byte is zero */
3707               DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3708               i = ((lit >> 8*3) & 0xff) ^0x80;
3709               emitpcode(POC_MOVFW, popGet(AOP(left),size));
3710               emitpcode(POC_ADDLW, popGetLit( 0x80));
3711               emitpcode(POC_ADDLW, popGetLit(0x100-i));
3712               genSkipc(&rFalseIfx);
3713
3714
3715               if(ifx) ifx->generated = 1;
3716               return;
3717
3718             }
3719
3720           }
3721
3722
3723           if(lit & (0x80 << (size*8))) {
3724             /* lit is negative */
3725             DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3726
3727             //genSkipCond(&rFalseIfx,left,size,7);
3728
3729             emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
3730
3731             if(rFalseIfx.condition)
3732               emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3733             else
3734               emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
3735
3736
3737           } else {
3738             /* lit is positive */
3739             DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3740             emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
3741             if(rFalseIfx.condition)
3742               emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
3743             else
3744               emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3745
3746             //emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
3747             //emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3748             //rFalseIfx.condition ^= 1;
3749             //genSkipCond(&rFalseIfx,left,size,7);
3750             //rFalseIfx.condition ^= 1;
3751           }
3752
3753           /*
3754             This works, but is only good for ints.
3755             It also requires a "known zero" register.
3756             emitpcode(POC_MOVLW, popGetLit(mlit & 0xff));
3757             emitpcode(POC_ADDFW, popGet(AOP(left),0));
3758             emitpcode(POC_RLFW,  popCopyReg(&pc_kzero));
3759             emitpcode(POC_ADDLW, popGetLit( ((mlit>>8) & 0xff)));
3760             emitpcode(POC_ADDFW, popGet(AOP(left),1));
3761             genSkipc(&rFalseIfx);
3762
3763             emitpLabel(truelbl->key);
3764             if(ifx) ifx->generated = 1;
3765             return;
3766           **/
3767           
3768           /* There are no more special cases, so perform a general compare */
3769   
3770           emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
3771           emitpcode(POC_SUBFW, popGet(AOP(left),size));
3772
3773           while(size--) {
3774
3775             emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
3776             emitSKPNZ;
3777             emitpcode(POC_SUBFW, popGet(AOP(left),size));
3778           }
3779           //rFalseIfx.condition ^= 1;
3780           genSkipc(&rFalseIfx);
3781
3782           emitpLabel(truelbl->key);
3783
3784           if(ifx) ifx->generated = 1;
3785           return;
3786
3787
3788         }
3789
3790
3791         /* sign is out of the way. So now do an unsigned compare */
3792         DEBUGpic14_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
3793
3794
3795         //genChkZeroes(left)
3796
3797         /* General case - compare to an unsigned literal on the right.*/
3798
3799         i = (lit >> (size*8)) & 0xff;
3800         emitpcode(POC_MOVLW, popGetLit(i));
3801         emitpcode(POC_SUBFW, popGet(AOP(left),size));
3802         while(size--) {
3803           i = (lit >> (size*8)) & 0xff;
3804
3805           if(i) {
3806             emitpcode(POC_MOVLW, popGetLit(i));
3807             emitSKPNZ;
3808             emitpcode(POC_SUBFW, popGet(AOP(left),size));
3809           } else {
3810             /* this byte of the lit is zero, 
3811              *if it's not the last then OR in the variable */
3812             if(size)
3813               emitpcode(POC_IORFW, popGet(AOP(left),size));
3814           }
3815         }
3816
3817
3818         emitpLabel(lbl->key);
3819         //if(emitFinalCheck)
3820           genSkipc(&rFalseIfx);
3821         if(sign)
3822           emitpLabel(truelbl->key);
3823
3824         if(ifx) ifx->generated = 1;
3825         return;
3826
3827
3828       }
3829
3830       if(AOP_TYPE(left) == AOP_LIT) {
3831         //symbol *lbl = newiTempLabel(NULL);
3832
3833         lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
3834
3835
3836         DEBUGpic14_emitcode(";left lit","lit = %d,sign=%d",lit,sign);
3837
3838         /* Special cases */
3839         if((lit == 0) && (sign == 0)){
3840
3841           size--;
3842           emitpcode(POC_MOVFW, popGet(AOP(right),size));
3843           while(size) 
3844             emitpcode(POC_IORFW, popGet(AOP(right),--size));
3845
3846           //rFalseIfx.condition ^= 1;
3847           genSkipz2(&rFalseIfx);
3848           if(ifx) ifx->generated = 1;
3849           return;
3850         }
3851
3852         if(size==1) {
3853           /* Special cases */
3854           lit &= 0xff;
3855           if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
3856             /* degenerate compare can never be true */
3857             if(rFalseIfx.condition == 0)
3858               emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
3859
3860             if(ifx) ifx->generated = 1;
3861             return;
3862           }
3863
3864           if(sign) {
3865             if((lit+1)&0xff) {
3866               emitpcode(POC_MOVFW, popGet(AOP(right),0));
3867               emitpcode(POC_ADDLW, popGetLit(0x80));
3868               emitpcode(POC_ADDLW, popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
3869               rFalseIfx.condition ^= 1;
3870               genSkipc(&rFalseIfx);
3871             } else {
3872               rFalseIfx.condition ^= 1;
3873               genSkipCond(&rFalseIfx,right,0,7);
3874             }
3875             
3876           } else {
3877             if(lit & 0xff) {
3878               emitpcode(POC_MOVLW, popGetLit((lit+1) & 0xff));
3879               emitpcode(POC_SUBFW, popGet(AOP(right),0));
3880               DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3881               rFalseIfx.condition ^= 1;
3882               genSkipc(&rFalseIfx);
3883             } else { 
3884               emitpcode(POC_MOVFW, popGet(AOP(right),0));
3885               genSkipz2(&rFalseIfx);
3886             }
3887           }
3888
3889           if(ifx) ifx->generated = 1;
3890           return;
3891
3892         } else {
3893
3894           /* Size is greater than 1 */
3895
3896
3897
3898           if(sign) {
3899             int lp1 = lit+1;
3900
3901             size--;
3902
3903             if(lp1 == 0) {
3904               /* this means lit = 0xffffffff, or -1 */
3905
3906
3907               DEBUGpic14_emitcode(";left lit = -1","line = %d ",__LINE__);
3908               rFalseIfx.condition ^= 1;
3909               genSkipCond(&rFalseIfx,right,size,7);
3910               if(ifx) ifx->generated = 1;
3911               return;
3912             }
3913
3914             if(lit == 0) {
3915               int s = size;
3916
3917               if(rFalseIfx.condition) {
3918                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
3919                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3920               }
3921
3922               emitpcode(POC_MOVFW, popGet(AOP(right),size));
3923               while(size--)
3924                 emitpcode(POC_IORFW, popGet(AOP(right),size));
3925
3926
3927               emitSKPZ;
3928               if(rFalseIfx.condition) {
3929                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
3930                 emitpLabel(truelbl->key);
3931               }else {
3932                 rFalseIfx.condition ^= 1;
3933                 genSkipCond(&rFalseIfx,right,s,7);
3934               }
3935
3936               if(ifx) ifx->generated = 1;
3937               return;
3938             }
3939
3940
3941             if(lit & (0x80 << (size*8))) {
3942               /* Lit is less than zero */
3943               DEBUGpic14_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
3944               //rFalseIfx.condition ^= 1;
3945               //genSkipCond(&rFalseIfx,left,size,7);
3946               //rFalseIfx.condition ^= 1;
3947               emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
3948               //emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3949
3950               if(rFalseIfx.condition)
3951                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
3952               else
3953                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3954
3955
3956             } else {
3957               /* Lit is greater than or equal to zero */
3958               DEBUGpic14_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
3959               //rFalseIfx.condition ^= 1;
3960               //genSkipCond(&rFalseIfx,right,size,7);
3961               //rFalseIfx.condition ^= 1;
3962
3963               //emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
3964               //emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
3965
3966               emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
3967               if(rFalseIfx.condition)
3968                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3969               else
3970                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
3971
3972             }
3973             emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
3974             emitpcode(POC_SUBFW, popGet(AOP(right),size));
3975
3976             while(size--) {
3977
3978               emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
3979               emitSKPNZ;
3980               emitpcode(POC_SUBFW, popGet(AOP(right),size));
3981             }
3982             rFalseIfx.condition ^= 1;
3983             //rFalseIfx.condition = 1;
3984             genSkipc(&rFalseIfx);
3985
3986             emitpLabel(truelbl->key);
3987
3988             if(ifx) ifx->generated = 1;
3989             return;
3990
3991           } else {
3992             /* Unsigned compare for sizes greater than 1 */
3993
3994             while(size--) {
3995               i = (lit >> (size*8)) & 0xff;
3996
3997
3998               if(size) {
3999                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4000                 emitpcode(POC_MOVLW, popGetLit(i&0xff));
4001                 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4002                 emitSKPZ;
4003                 emitpcode(POC_GOTO,  popGetLabel(lbl->key));
4004               } else {
4005                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4006                 emitpcode(POC_MOVLW, popGetLit((i+1)&0xff));
4007                 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4008
4009               }
4010             }
4011
4012             DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4013
4014             emitpLabel(lbl->key);
4015
4016             rFalseIfx.condition ^= 1;
4017             genSkipc(&rFalseIfx);
4018
4019           }
4020         if(sign)
4021           emitpLabel(truelbl->key);
4022         if(ifx) ifx->generated = 1;
4023         return;
4024         }
4025       }
4026       /* Compare two variables */
4027
4028       DEBUGpic14_emitcode(";sign","%d",sign);
4029
4030       size--;
4031       if(sign) {
4032         /* Sigh. thus sucks... */
4033         if(size) {
4034           emitpcode(POC_MOVFW, popGet(AOP(left),size));
4035           emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
4036           emitpcode(POC_MOVLW, popGetLit(0x80));
4037           emitpcode(POC_XORWF, popRegFromIdx(Gstack_base_addr));
4038           emitpcode(POC_XORFW, popGet(AOP(right),size));
4039           emitpcode(POC_SUBFW, popRegFromIdx(Gstack_base_addr));
4040         } else {
4041           /* Signed char comparison */
4042           /* Special thanks to Nikolai Golovchenko for this snippet */
4043           emitpcode(POC_MOVFW, popGet(AOP(right),0));
4044           emitpcode(POC_SUBFW, popGet(AOP(left),0));
4045           emitpcode(POC_RRFW,  popGet(AOP(left),0)); /* could be any register */
4046           emitpcode(POC_XORFW, popGet(AOP(left),0));
4047           emitpcode(POC_XORFW, popGet(AOP(right),0));
4048           emitpcode(POC_ADDLW, popGetLit(0x80));
4049
4050           DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4051           genSkipc(&rFalseIfx);
4052           
4053           if(ifx) ifx->generated = 1;
4054           return;
4055         }
4056
4057       } else {
4058
4059         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4060         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4061       }
4062
4063
4064       /* The rest of the bytes of a multi-byte compare */
4065       while (size) {
4066
4067         emitSKPZ;
4068         emitpcode(POC_GOTO,  popGetLabel(lbl->key));
4069         size--;
4070
4071         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4072         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4073
4074
4075       }
4076
4077       emitpLabel(lbl->key);
4078
4079       DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4080       genSkipc(&rFalseIfx);
4081       if(ifx) ifx->generated = 1;
4082       return;
4083
4084     }
4085   }
4086
4087   //release:
4088   if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4089     pic14_outBitC(result);
4090   } else {
4091     /* if the result is used in the next
4092        ifx conditional branch then generate
4093        code a little differently */
4094     if (ifx )
4095       genIfxJump (ifx,"c");
4096     else
4097       pic14_outBitC(result);
4098     /* leave the result in acc */
4099   }
4100
4101 }
4102
4103 /*-----------------------------------------------------------------*/
4104 /* genCmpGt :- greater than comparison                             */
4105 /*-----------------------------------------------------------------*/
4106 static void genCmpGt (iCode *ic, iCode *ifx)
4107 {
4108     operand *left, *right, *result;
4109     sym_link *letype , *retype;
4110     int sign ;
4111
4112     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4113     left = IC_LEFT(ic);
4114     right= IC_RIGHT(ic);
4115     result = IC_RESULT(ic);
4116
4117     letype = getSpec(operandType(left));
4118     retype =getSpec(operandType(right));
4119     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4120     /* assign the amsops */
4121     aopOp (left,ic,FALSE);
4122     aopOp (right,ic,FALSE);
4123     aopOp (result,ic,TRUE);
4124
4125     genCmp(right, left, result, ifx, sign);
4126
4127     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4128     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4129     freeAsmop(result,NULL,ic,TRUE); 
4130 }
4131
4132 /*-----------------------------------------------------------------*/
4133 /* genCmpLt - less than comparisons                                */
4134 /*-----------------------------------------------------------------*/
4135 static void genCmpLt (iCode *ic, iCode *ifx)
4136 {
4137     operand *left, *right, *result;
4138     sym_link *letype , *retype;
4139     int sign ;
4140
4141     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4142     left = IC_LEFT(ic);
4143     right= IC_RIGHT(ic);
4144     result = IC_RESULT(ic);
4145
4146     letype = getSpec(operandType(left));
4147     retype =getSpec(operandType(right));
4148     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4149
4150     /* assign the amsops */
4151     aopOp (left,ic,FALSE);
4152     aopOp (right,ic,FALSE);
4153     aopOp (result,ic,TRUE);
4154
4155     genCmp(left, right, result, ifx, sign);
4156
4157     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4158     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4159     freeAsmop(result,NULL,ic,TRUE); 
4160 }
4161
4162 /*-----------------------------------------------------------------*/
4163 /* genc16bit2lit - compare a 16 bit value to a literal             */
4164 /*-----------------------------------------------------------------*/
4165 static void genc16bit2lit(operand *op, int lit, int offset)
4166 {
4167   int i;
4168
4169   DEBUGpic14_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
4170   if( (lit&0xff) == 0) 
4171     i=1;
4172   else
4173     i=0;
4174
4175   switch( BYTEofLONG(lit,i)) { 
4176   case 0:
4177     emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4178     break;
4179   case 1:
4180     emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4181     break;
4182   case 0xff:
4183     emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4184     break;
4185   default:
4186     emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4187     emitpcode(POC_XORLW,popGetLit(BYTEofLONG(lit,i)));
4188   }
4189
4190   i ^= 1;
4191
4192   switch( BYTEofLONG(lit,i)) { 
4193   case 0:
4194     emitpcode(POC_IORFW,popGet(AOP(op),offset+i));
4195     break;
4196   case 1:
4197     emitSKPNZ;
4198     emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4199     break;
4200   case 0xff:
4201     emitSKPNZ;
4202     emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4203     break;
4204   default:
4205     emitpcode(POC_MOVLW,popGetLit(BYTEofLONG(lit,i)));
4206     emitSKPNZ;
4207     emitpcode(POC_XORFW,popGet(AOP(op),offset+i));
4208
4209   }
4210
4211 }
4212
4213 /*-----------------------------------------------------------------*/
4214 /* gencjneshort - compare and jump if not equal                    */
4215 /*-----------------------------------------------------------------*/
4216 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4217 {
4218   int size = max(AOP_SIZE(left),AOP_SIZE(right));
4219   int offset = 0;
4220   resolvedIfx rIfx;
4221   symbol *lbl;
4222
4223   unsigned long lit = 0L;
4224   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4225   DEBUGpic14_AopType(__LINE__,left,right,NULL);
4226
4227   resolveIfx(&rIfx,ifx);
4228   lbl =  newiTempLabel(NULL);
4229
4230
4231   /* if the left side is a literal or 
4232      if the right is in a pointer register and left 
4233      is not */
4234   if ((AOP_TYPE(left) == AOP_LIT) || 
4235       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4236     operand *t = right;
4237     right = left;
4238     left = t;
4239   }
4240   if(AOP_TYPE(right) == AOP_LIT)
4241     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4242
4243   /* if the right side is a literal then anything goes */
4244   if (AOP_TYPE(right) == AOP_LIT &&
4245       AOP_TYPE(left) != AOP_DIR ) {
4246     switch(size) {
4247     case 2:
4248       genc16bit2lit(left, lit, 0);
4249       emitSKPNZ;
4250       emitpcode(POC_GOTO,popGetLabel(lbl->key));
4251       break;
4252     default:
4253       while (size--) {
4254         if(lit & 0xff) {
4255           emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4256           emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4257         } else {
4258           emitpcode(POC_MOVF,popGet(AOP(left),offset));
4259         }
4260
4261         emitSKPNZ;
4262         emitpcode(POC_GOTO,popGetLabel(lbl->key));
4263         offset++;
4264         lit >>= 8;
4265       }
4266       break;
4267     }
4268   }
4269
4270   /* if the right side is in a register or in direct space or
4271      if the left is a pointer register & right is not */    
4272   else if (AOP_TYPE(right) == AOP_REG ||
4273            AOP_TYPE(right) == AOP_DIR || 
4274            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4275            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
4276     switch(size) {
4277     case 2:
4278       genc16bit2lit(left, lit, 0);
4279       emitSKPNZ;
4280       emitpcode(POC_GOTO,popGetLabel(lbl->key));
4281       break;
4282     default:
4283       while (size--) {
4284         int emit_skip=1;
4285         if((AOP_TYPE(left) == AOP_DIR) && 
4286            ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
4287
4288           emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4289           emitpcode(POC_XORFW,popGet(AOP(right),offset));
4290
4291         } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
4292             
4293           switch (lit & 0xff) {
4294           case 0:
4295             emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4296             break;
4297           case 1:
4298             emitpcode(POC_DECFSZ,popGet(AOP(left),offset));
4299             emitpcode(POC_GOTO,popGetLabel(lbl->key));
4300             emit_skip=0;
4301             break;
4302           case 0xff:
4303             emitpcode(POC_INCFSZ,popGet(AOP(left),offset));
4304             emitpcode(POC_GOTO,popGetLabel(lbl->key));
4305             emit_skip=0;
4306             break;
4307           default:
4308             emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4309             emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4310           }
4311           lit >>= 8;
4312
4313         } else {
4314           emitpcode(POC_MOVF,popGet(AOP(left),offset));
4315         }
4316         if(emit_skip) {
4317           if(AOP_TYPE(result) == AOP_CRY) {
4318             pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
4319             if(rIfx.condition)
4320               emitSKPNZ;
4321             else
4322               emitSKPZ;
4323             emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4324           } else {
4325             /* fix me. probably need to check result size too */
4326             emitpcode(POC_CLRF,popGet(AOP(result),0));
4327             if(rIfx.condition)
4328               emitSKPNZ;
4329             else
4330               emitSKPZ;
4331             emitpcode(POC_INCF,popGet(AOP(result),0));
4332           }
4333           if(ifx)
4334             ifx->generated=1;
4335         }
4336         emit_skip++;
4337         offset++;
4338       }
4339       break;
4340     }
4341   } else if(AOP_TYPE(right) == AOP_REG &&
4342             AOP_TYPE(left) != AOP_DIR){
4343
4344     while(size--) {
4345       emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4346       emitpcode(POC_XORFW,popGet(AOP(right),offset));
4347       pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
4348       if(rIfx.condition)
4349         emitSKPNZ;
4350       else
4351         emitSKPZ;
4352       emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4353       offset++;
4354     }
4355       
4356   }else{
4357     /* right is a pointer reg need both a & b */
4358     while(size--) {
4359       char *l = aopGet(AOP(left),offset,FALSE,FALSE);
4360       if(strcmp(l,"b"))
4361         pic14_emitcode("mov","b,%s",l);
4362       MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4363       pic14_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
4364       offset++;
4365     }
4366   }
4367   emitpLabel(lbl->key);
4368
4369   if(ifx)
4370     ifx->generated = 1;
4371 }
4372
4373 #if 0
4374 /*-----------------------------------------------------------------*/
4375 /* gencjne - compare and jump if not equal                         */
4376 /*-----------------------------------------------------------------*/
4377 static void gencjne(operand *left, operand *right, iCode *ifx)
4378 {
4379     symbol *tlbl  = newiTempLabel(NULL);
4380
4381     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4382     gencjneshort(left, right, lbl);
4383
4384     pic14_emitcode("mov","a,%s",one);
4385     pic14_emitcode("sjmp","%05d_DS_",tlbl->key+100);
4386     pic14_emitcode("","%05d_DS_:",lbl->key+100);
4387     pic14_emitcode("clr","a");
4388     pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4389
4390     emitpLabel(lbl->key);
4391     emitpLabel(tlbl->key);
4392
4393 }
4394 #endif
4395
4396 /*-----------------------------------------------------------------*/
4397 /* genCmpEq - generates code for equal to                          */
4398 /*-----------------------------------------------------------------*/
4399 static void genCmpEq (iCode *ic, iCode *ifx)
4400 {
4401     operand *left, *right, *result;
4402     unsigned long lit = 0L;
4403     int size,offset=0;
4404
4405     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4406
4407     if(ifx)
4408       DEBUGpic14_emitcode ("; ifx is non-null","");
4409     else
4410       DEBUGpic14_emitcode ("; ifx is null","");
4411
4412     aopOp((left=IC_LEFT(ic)),ic,FALSE);
4413     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4414     aopOp((result=IC_RESULT(ic)),ic,TRUE);
4415
4416     size = max(AOP_SIZE(left),AOP_SIZE(right));
4417
4418     DEBUGpic14_AopType(__LINE__,left,right,result);
4419
4420     /* if literal, literal on the right or 
4421     if the right is in a pointer register and left 
4422     is not */
4423     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
4424         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4425       operand *tmp = right ;
4426       right = left;
4427       left = tmp;
4428     }
4429
4430
4431     if(ifx && !AOP_SIZE(result)){
4432         symbol *tlbl;
4433         /* if they are both bit variables */
4434         if (AOP_TYPE(left) == AOP_CRY &&
4435             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4436             if(AOP_TYPE(right) == AOP_LIT){
4437                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4438                 if(lit == 0L){
4439                     pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4440                     pic14_emitcode("cpl","c");
4441                 } else if(lit == 1L) {
4442                     pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4443                 } else {
4444                     pic14_emitcode("clr","c");
4445                 }
4446                 /* AOP_TYPE(right) == AOP_CRY */
4447             } else {
4448                 symbol *lbl = newiTempLabel(NULL);
4449                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4450                 pic14_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4451                 pic14_emitcode("cpl","c");
4452                 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
4453             }
4454             /* if true label then we jump if condition
4455             supplied is true */
4456             tlbl = newiTempLabel(NULL);
4457             if ( IC_TRUE(ifx) ) {
4458                 pic14_emitcode("jnc","%05d_DS_",tlbl->key+100);
4459                 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
4460             } else {
4461                 pic14_emitcode("jc","%05d_DS_",tlbl->key+100);
4462                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
4463             }
4464             pic14_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
4465
4466             {
4467               /* left and right are both bit variables, result is carry */
4468               resolvedIfx rIfx;
4469               
4470               resolveIfx(&rIfx,ifx);
4471
4472               emitpcode(POC_MOVLW,popGet(AOP(left),0));
4473               emitpcode(POC_ANDFW,popGet(AOP(left),0));
4474               emitpcode(POC_BTFSC,popGet(AOP(right),0));
4475               emitpcode(POC_ANDLW,popGet(AOP(left),0));
4476               genSkipz2(&rIfx);
4477             }
4478         } else {
4479
4480           /* They're not both bit variables. Is the right a literal? */
4481           if(AOP_TYPE(right) == AOP_LIT) {
4482             lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4483             
4484             switch(size) {
4485
4486             case 1:
4487               switch(lit & 0xff) {
4488               case 1:
4489                 if ( IC_TRUE(ifx) ) {
4490                   emitpcode(POC_DECFW,popGet(AOP(left),offset));
4491                   emitSKPNZ;
4492                   emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4493                 } else {
4494                   emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
4495                   emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4496                 }
4497                 break;
4498               case 0xff:
4499                 if ( IC_TRUE(ifx) ) {
4500                   emitpcode(POC_INCFW,popGet(AOP(left),offset));
4501                   emitSKPNZ;
4502                   emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4503                 } else {
4504                   emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4505                   emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4506                 }
4507                 break;
4508               default:
4509                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4510                 if(lit)
4511                   emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4512                 genSkip(ifx,'z');
4513               }
4514
4515
4516               /* end of size == 1 */
4517               break;
4518               
4519             case 2:
4520               genc16bit2lit(left,lit,offset);
4521               genSkip(ifx,'z');
4522               break;
4523               /* end of size == 2 */
4524
4525             default:
4526               /* size is 4 */
4527               if(lit==0) {
4528                 emitpcode(POC_MOVFW,popGet(AOP(left),0));
4529                 emitpcode(POC_IORFW,popGet(AOP(left),1));
4530                 emitpcode(POC_IORFW,popGet(AOP(left),2));
4531                 emitpcode(POC_IORFW,popGet(AOP(left),3));
4532
4533               } else {
4534
4535                 /* search for patterns that can be optimized */
4536
4537                 genc16bit2lit(left,lit,0);
4538                 lit >>= 16;
4539                 if(lit) {
4540                   genSkipz(ifx,IC_TRUE(ifx) == NULL);
4541                   //genSkip(ifx,'z');
4542                   genc16bit2lit(left,lit,2);
4543                 } else {
4544                   emitpcode(POC_IORFW,popGet(AOP(left),2));
4545                   emitpcode(POC_IORFW,popGet(AOP(left),3));
4546
4547                 }
4548                 
4549               }
4550
4551               genSkip(ifx,'z');
4552             }
4553           
4554             ifx->generated = 1;
4555             goto release ;
4556             
4557
4558           } else if(AOP_TYPE(right) == AOP_CRY ) {
4559             /* we know the left is not a bit, but that the right is */
4560             emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4561             emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
4562                       popGet(AOP(right),offset));
4563             emitpcode(POC_XORLW,popGetLit(1));
4564
4565             /* if the two are equal, then W will be 0 and the Z bit is set
4566              * we could test Z now, or go ahead and check the high order bytes if
4567              * the variable we're comparing is larger than a byte. */
4568
4569             while(--size)
4570               emitpcode(POC_IORFW,popGet(AOP(left),offset));
4571
4572             if ( IC_TRUE(ifx) ) {
4573               emitSKPNZ;
4574               emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4575               pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4576             } else {
4577               emitSKPZ;
4578               emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4579               pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4580             }
4581
4582           } else {
4583             /* They're both variables that are larger than bits */
4584             int s = size;
4585
4586             tlbl = newiTempLabel(NULL);
4587
4588             while(size--) {
4589               emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4590               emitpcode(POC_XORFW,popGet(AOP(right),offset));
4591
4592               if ( IC_TRUE(ifx) ) {
4593                 if(size) {
4594                   emitSKPZ;
4595                   emitpcode(POC_GOTO,popGetLabel(tlbl->key));
4596                   pic14_emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset);
4597                 } else {
4598                   emitSKPNZ;
4599                   emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4600                   pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4601                 }
4602               } else {
4603                 emitSKPZ;
4604                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4605                 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4606               }
4607               offset++;
4608             }
4609             if(s>1 && IC_TRUE(ifx)) {
4610               emitpLabel(tlbl->key);
4611               pic14_emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);                
4612             }
4613           }
4614         }
4615         /* mark the icode as generated */
4616         ifx->generated = 1;
4617         goto release ;
4618     }
4619
4620     /* if they are both bit variables */
4621     if (AOP_TYPE(left) == AOP_CRY &&
4622         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4623         if(AOP_TYPE(right) == AOP_LIT){
4624             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4625             if(lit == 0L){
4626                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4627                 pic14_emitcode("cpl","c");
4628             } else if(lit == 1L) {
4629                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4630             } else {
4631                 pic14_emitcode("clr","c");
4632             }
4633             /* AOP_TYPE(right) == AOP_CRY */
4634         } else {
4635             symbol *lbl = newiTempLabel(NULL);
4636             pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4637             pic14_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4638             pic14_emitcode("cpl","c");
4639             pic14_emitcode("","%05d_DS_:",(lbl->key+100));
4640         }
4641         /* c = 1 if egal */
4642         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
4643             pic14_outBitC(result);
4644             goto release ;
4645         }
4646         if (ifx) {
4647             genIfxJump (ifx,"c");
4648             goto release ;
4649         }
4650         /* if the result is used in an arithmetic operation
4651         then put the result in place */
4652         pic14_outBitC(result);
4653     } else {
4654       
4655       gencjne(left,right,result,ifx);
4656 /*
4657       if(ifx) 
4658         gencjne(left,right,newiTempLabel(NULL));
4659       else {
4660         if(IC_TRUE(ifx)->key)
4661           gencjne(left,right,IC_TRUE(ifx)->key);
4662         else
4663           gencjne(left,right,IC_FALSE(ifx)->key);
4664         ifx->generated = 1;
4665         goto release ;
4666       }
4667       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4668         aopPut(AOP(result),"a",0);
4669         goto release ;
4670       }
4671
4672       if (ifx) {
4673         genIfxJump (ifx,"a");
4674         goto release ;
4675       }
4676 */
4677       /* if the result is used in an arithmetic operation
4678          then put the result in place */
4679 /*
4680       if (AOP_TYPE(result) != AOP_CRY) 
4681         pic14_outAcc(result);
4682 */
4683       /* leave the result in acc */
4684     }
4685
4686 release:
4687     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4688     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4689     freeAsmop(result,NULL,ic,TRUE);
4690 }
4691
4692 /*-----------------------------------------------------------------*/
4693 /* ifxForOp - returns the icode containing the ifx for operand     */
4694 /*-----------------------------------------------------------------*/
4695 static iCode *ifxForOp ( operand *op, iCode *ic )
4696 {
4697     /* if true symbol then needs to be assigned */
4698     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4699     if (IS_TRUE_SYMOP(op))
4700         return NULL ;
4701
4702     /* if this has register type condition and
4703     the next instruction is ifx with the same operand
4704     and live to of the operand is upto the ifx only then */
4705     if (ic->next &&
4706         ic->next->op == IFX &&
4707         IC_COND(ic->next)->key == op->key &&
4708         OP_SYMBOL(op)->liveTo <= ic->next->seq )
4709         return ic->next;
4710
4711     if (ic->next &&
4712         ic->next->op == IFX &&
4713         IC_COND(ic->next)->key == op->key) {
4714       DEBUGpic14_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
4715       return ic->next;
4716     }
4717
4718     DEBUGpic14_emitcode ("; NULL :(","%d",__LINE__);
4719     if (ic->next &&
4720         ic->next->op == IFX)
4721       DEBUGpic14_emitcode ("; ic-next"," is an IFX");
4722
4723     if (ic->next &&
4724         ic->next->op == IFX &&
4725         IC_COND(ic->next)->key == op->key) {
4726       DEBUGpic14_emitcode ("; "," key is okay");
4727       DEBUGpic14_emitcode ("; "," key liveTo %d, next->seq = %d",
4728                            OP_SYMBOL(op)->liveTo,
4729                            ic->next->seq);
4730     }
4731
4732
4733     return NULL;
4734 }
4735 /*-----------------------------------------------------------------*/
4736 /* genAndOp - for && operation                                     */
4737 /*-----------------------------------------------------------------*/
4738 static void genAndOp (iCode *ic)
4739 {
4740     operand *left,*right, *result;
4741     symbol *tlbl;
4742
4743     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4744     /* note here that && operations that are in an
4745     if statement are taken away by backPatchLabels
4746     only those used in arthmetic operations remain */
4747     aopOp((left=IC_LEFT(ic)),ic,FALSE);
4748     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4749     aopOp((result=IC_RESULT(ic)),ic,FALSE);
4750
4751     /* if both are bit variables */
4752     if (AOP_TYPE(left) == AOP_CRY &&
4753         AOP_TYPE(right) == AOP_CRY ) {
4754         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4755         pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
4756         pic14_outBitC(result);
4757     } else {
4758         tlbl = newiTempLabel(NULL);
4759         pic14_toBoolean(left);    
4760         pic14_emitcode("jz","%05d_DS_",tlbl->key+100);
4761         pic14_toBoolean(right);
4762         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4763         pic14_outBitAcc(result);
4764     }
4765
4766     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4767     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4768     freeAsmop(result,NULL,ic,TRUE);
4769 }
4770
4771
4772 /*-----------------------------------------------------------------*/
4773 /* genOrOp - for || operation                                      */
4774 /*-----------------------------------------------------------------*/
4775 /*
4776   tsd pic port -
4777   modified this code, but it doesn't appear to ever get called
4778 */
4779
4780 static void genOrOp (iCode *ic)
4781 {
4782     operand *left,*right, *result;
4783     symbol *tlbl;
4784
4785     /* note here that || operations that are in an
4786     if statement are taken away by backPatchLabels
4787     only those used in arthmetic operations remain */
4788     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4789     aopOp((left=IC_LEFT(ic)),ic,FALSE);
4790     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4791     aopOp((result=IC_RESULT(ic)),ic,FALSE);
4792
4793     DEBUGpic14_AopType(__LINE__,left,right,result);
4794
4795     /* if both are bit variables */
4796     if (AOP_TYPE(left) == AOP_CRY &&
4797         AOP_TYPE(right) == AOP_CRY ) {
4798       pic14_emitcode("clrc","");
4799       pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
4800                AOP(left)->aopu.aop_dir,
4801                AOP(left)->aopu.aop_dir);
4802       pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
4803                AOP(right)->aopu.aop_dir,
4804                AOP(right)->aopu.aop_dir);
4805       pic14_emitcode("setc","");
4806
4807     } else {
4808         tlbl = newiTempLabel(NULL);
4809         pic14_toBoolean(left);
4810         emitSKPZ;
4811         pic14_emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
4812         pic14_toBoolean(right);
4813         pic14_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
4814
4815         pic14_outBitAcc(result);
4816     }
4817
4818     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4819     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4820     freeAsmop(result,NULL,ic,TRUE);            
4821 }
4822
4823 /*-----------------------------------------------------------------*/
4824 /* isLiteralBit - test if lit == 2^n                               */
4825 /*-----------------------------------------------------------------*/
4826 static int isLiteralBit(unsigned long lit)
4827 {
4828     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
4829     0x100L,0x200L,0x400L,0x800L,
4830     0x1000L,0x2000L,0x4000L,0x8000L,
4831     0x10000L,0x20000L,0x40000L,0x80000L,
4832     0x100000L,0x200000L,0x400000L,0x800000L,
4833     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
4834     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
4835     int idx;
4836     
4837     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4838     for(idx = 0; idx < 32; idx++)
4839         if(lit == pw[idx])
4840             return idx+1;
4841     return 0;
4842 }
4843
4844 /*-----------------------------------------------------------------*/
4845 /* continueIfTrue -                                                */
4846 /*-----------------------------------------------------------------*/
4847 static void continueIfTrue (iCode *ic)
4848 {
4849     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4850     if(IC_TRUE(ic))
4851         pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
4852     ic->generated = 1;
4853 }
4854
4855 /*-----------------------------------------------------------------*/
4856 /* jmpIfTrue -                                                     */
4857 /*-----------------------------------------------------------------*/
4858 static void jumpIfTrue (iCode *ic)
4859 {
4860     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4861     if(!IC_TRUE(ic))
4862         pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
4863     ic->generated = 1;
4864 }
4865
4866 /*-----------------------------------------------------------------*/
4867 /* jmpTrueOrFalse -                                                */
4868 /*-----------------------------------------------------------------*/
4869 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
4870 {
4871     // ugly but optimized by peephole
4872     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4873     if(IC_TRUE(ic)){
4874         symbol *nlbl = newiTempLabel(NULL);
4875         pic14_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
4876         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4877         pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
4878         pic14_emitcode("","%05d_DS_:",nlbl->key+100);
4879     }
4880     else{
4881         pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
4882         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4883     }
4884     ic->generated = 1;
4885 }
4886
4887 /*-----------------------------------------------------------------*/
4888 /* genAnd  - code for and                                          */
4889 /*-----------------------------------------------------------------*/
4890 static void genAnd (iCode *ic, iCode *ifx)
4891 {
4892   operand *left, *right, *result;
4893   int size, offset=0;  
4894   unsigned long lit = 0L;
4895   int bytelit = 0;
4896   resolvedIfx rIfx;
4897
4898
4899   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4900   aopOp((left = IC_LEFT(ic)),ic,FALSE);
4901   aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4902   aopOp((result=IC_RESULT(ic)),ic,TRUE);
4903
4904   resolveIfx(&rIfx,ifx);
4905
4906   /* if left is a literal & right is not then exchange them */
4907   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4908       AOP_NEEDSACC(left)) {
4909     operand *tmp = right ;
4910     right = left;
4911     left = tmp;
4912   }
4913
4914   /* if result = right then exchange them */
4915   if(pic14_sameRegs(AOP(result),AOP(right))){
4916     operand *tmp = right ;
4917     right = left;
4918     left = tmp;
4919   }
4920
4921   /* if right is bit then exchange them */
4922   if (AOP_TYPE(right) == AOP_CRY &&
4923       AOP_TYPE(left) != AOP_CRY){
4924     operand *tmp = right ;
4925     right = left;
4926     left = tmp;
4927   }
4928   if(AOP_TYPE(right) == AOP_LIT)
4929     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4930
4931   size = AOP_SIZE(result);
4932
4933   DEBUGpic14_AopType(__LINE__,left,right,result);
4934
4935   // if(bit & yy)
4936   // result = bit & yy;
4937   if (AOP_TYPE(left) == AOP_CRY){
4938     // c = bit & literal;
4939     if(AOP_TYPE(right) == AOP_LIT){
4940       if(lit & 1) {
4941         if(size && pic14_sameRegs(AOP(result),AOP(left)))
4942           // no change
4943           goto release;
4944         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4945       } else {
4946         // bit(result) = 0;
4947         if(size && (AOP_TYPE(result) == AOP_CRY)){
4948           pic14_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
4949           goto release;
4950         }
4951         if((AOP_TYPE(result) == AOP_CRY) && ifx){
4952           jumpIfTrue(ifx);
4953           goto release;
4954         }
4955         pic14_emitcode("clr","c");
4956       }
4957     } else {
4958       if (AOP_TYPE(right) == AOP_CRY){
4959         // c = bit & bit;
4960         pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4961         pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4962       } else {
4963         // c = bit & val;
4964         MOVA(aopGet(AOP(right),0,FALSE,FALSE));
4965         // c = lsb
4966         pic14_emitcode("rrc","a");
4967         pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4968       }
4969     }
4970     // bit = c
4971     // val = c
4972     if(size)
4973       pic14_outBitC(result);
4974     // if(bit & ...)
4975     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4976       genIfxJump(ifx, "c");           
4977     goto release ;
4978   }
4979
4980   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
4981   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
4982   if((AOP_TYPE(right) == AOP_LIT) &&
4983      (AOP_TYPE(result) == AOP_CRY) &&
4984      (AOP_TYPE(left) != AOP_CRY)){
4985     int posbit = isLiteralBit(lit);
4986     /* left &  2^n */
4987     if(posbit){
4988       posbit--;
4989       //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
4990       // bit = left & 2^n
4991       if(size)
4992         pic14_emitcode("mov","c,acc.%d",posbit&0x07);
4993       // if(left &  2^n)
4994       else{
4995         if(ifx){
4996 /*
4997           if(IC_TRUE(ifx)) {
4998             emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
4999             emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
5000           } else {
5001             emitpcode(POC_BTFSS,newpCodeOpBit(aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5002             emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
5003           }
5004 */
5005           emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5006                     newpCodeOpBit(aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5007           emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5008           
5009           ifx->generated = 1;
5010         }
5011         goto release;
5012       }
5013     } else {
5014       symbol *tlbl = newiTempLabel(NULL);
5015       int sizel = AOP_SIZE(left);
5016       if(size)
5017         pic14_emitcode("setb","c");
5018       while(sizel--){
5019         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5020           MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
5021           // byte ==  2^n ?
5022           if((posbit = isLiteralBit(bytelit)) != 0)
5023             pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5024           else{
5025             if(bytelit != 0x0FFL)
5026               pic14_emitcode("anl","a,%s",
5027                              aopGet(AOP(right),offset,FALSE,TRUE));
5028             pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5029           }
5030         }
5031         offset++;
5032       }
5033       // bit = left & literal
5034       if(size){
5035         pic14_emitcode("clr","c");
5036         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5037       }
5038       // if(left & literal)
5039       else{
5040         if(ifx)
5041           jmpTrueOrFalse(ifx, tlbl);
5042         goto release ;
5043       }
5044     }
5045     pic14_outBitC(result);
5046     goto release ;
5047   }
5048
5049   /* if left is same as result */
5050   if(pic14_sameRegs(AOP(result),AOP(left))){
5051     int know_W = -1;
5052     for(;size--; offset++,lit>>=8) {
5053       if(AOP_TYPE(right) == AOP_LIT){
5054         switch(lit & 0xff) {
5055         case 0x00:
5056           /*  and'ing with 0 has clears the result */
5057           pic14_emitcode("clrf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5058           emitpcode(POC_CLRF,popGet(AOP(result),offset));
5059           break;
5060         case 0xff:
5061           /* and'ing with 0xff is a nop when the result and left are the same */
5062           break;
5063
5064         default:
5065           {
5066             int p = my_powof2( (~lit) & 0xff );
5067             if(p>=0) {
5068               /* only one bit is set in the literal, so use a bcf instruction */
5069               pic14_emitcode("bcf","%s,%d",aopGet(AOP(left),offset,FALSE,TRUE),p);
5070               emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5071
5072             } else {
5073               pic14_emitcode("movlw","0x%x", (lit & 0xff));
5074               pic14_emitcode("andwf","%s,f",aopGet(AOP(left),offset,FALSE,TRUE));
5075               if(know_W != (lit&0xff))
5076                 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5077               know_W = lit &0xff;
5078               emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5079             }
5080           }    
5081         }
5082       } else {
5083         if (AOP_TYPE(left) == AOP_ACC) {
5084           emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5085         } else {                    
5086           emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5087           emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5088
5089         }
5090       }
5091     }
5092
5093   } else {
5094     // left & result in different registers
5095     if(AOP_TYPE(result) == AOP_CRY){
5096       // result = bit
5097       // if(size), result in bit
5098       // if(!size && ifx), conditional oper: if(left & right)
5099       symbol *tlbl = newiTempLabel(NULL);
5100       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5101       if(size)
5102         pic14_emitcode("setb","c");
5103       while(sizer--){
5104         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5105         pic14_emitcode("anl","a,%s",
5106                        aopGet(AOP(left),offset,FALSE,FALSE));
5107         pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5108         offset++;
5109       }
5110       if(size){
5111         CLRC;
5112         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5113         pic14_outBitC(result);
5114       } else if(ifx)
5115         jmpTrueOrFalse(ifx, tlbl);
5116     } else {
5117       for(;(size--);offset++) {
5118         // normal case
5119         // result = left & right
5120         if(AOP_TYPE(right) == AOP_LIT){
5121           int t = (lit >> (offset*8)) & 0x0FFL;
5122           switch(t) { 
5123           case 0x00:
5124             pic14_emitcode("clrf","%s",
5125                            aopGet(AOP(result),offset,FALSE,FALSE));
5126             emitpcode(POC_CLRF,popGet(AOP(result),offset));
5127             break;
5128           case 0xff:
5129             pic14_emitcode("movf","%s,w",
5130                            aopGet(AOP(left),offset,FALSE,FALSE));
5131             pic14_emitcode("movwf","%s",
5132                            aopGet(AOP(result),offset,FALSE,FALSE));
5133             emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5134             emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5135             break;
5136           default:
5137             pic14_emitcode("movlw","0x%x",t);
5138             pic14_emitcode("andwf","%s,w",
5139                            aopGet(AOP(left),offset,FALSE,FALSE));
5140             pic14_emitcode("movwf","%s",
5141                            aopGet(AOP(result),offset,FALSE,FALSE));
5142               
5143             emitpcode(POC_MOVLW, popGetLit(t));
5144             emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5145             emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5146           }
5147           continue;
5148         }
5149
5150         if (AOP_TYPE(left) == AOP_ACC) {
5151           pic14_emitcode("andwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5152           emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5153         } else {
5154           pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5155           pic14_emitcode("andwf","%s,w",
5156                          aopGet(AOP(left),offset,FALSE,FALSE));
5157           emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5158           emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5159         }
5160         pic14_emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5161         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5162       }
5163     }
5164   }
5165
5166   release :
5167     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5168   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5169   freeAsmop(result,NULL,ic,TRUE);     
5170 }
5171
5172 /*-----------------------------------------------------------------*/
5173 /* genOr  - code for or                                            */
5174 /*-----------------------------------------------------------------*/
5175 static void genOr (iCode *ic, iCode *ifx)
5176 {
5177     operand *left, *right, *result;
5178     int size, offset=0;
5179     unsigned long lit = 0L;
5180
5181     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5182
5183     aopOp((left = IC_LEFT(ic)),ic,FALSE);
5184     aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5185     aopOp((result=IC_RESULT(ic)),ic,TRUE);
5186
5187     DEBUGpic14_AopType(__LINE__,left,right,result);
5188
5189     /* if left is a literal & right is not then exchange them */
5190     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5191         AOP_NEEDSACC(left)) {
5192         operand *tmp = right ;
5193         right = left;
5194         left = tmp;
5195     }
5196
5197     /* if result = right then exchange them */
5198     if(pic14_sameRegs(AOP(result),AOP(right))){
5199         operand *tmp = right ;
5200         right = left;
5201         left = tmp;
5202     }
5203
5204     /* if right is bit then exchange them */
5205     if (AOP_TYPE(right) == AOP_CRY &&
5206         AOP_TYPE(left) != AOP_CRY){
5207         operand *tmp = right ;
5208         right = left;
5209         left = tmp;
5210     }
5211
5212     DEBUGpic14_AopType(__LINE__,left,right,result);
5213
5214     if(AOP_TYPE(right) == AOP_LIT)
5215         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5216
5217     size = AOP_SIZE(result);
5218
5219     // if(bit | yy)
5220     // xx = bit | yy;
5221     if (AOP_TYPE(left) == AOP_CRY){
5222         if(AOP_TYPE(right) == AOP_LIT){
5223             // c = bit & literal;
5224             if(lit){
5225                 // lit != 0 => result = 1
5226                 if(AOP_TYPE(result) == AOP_CRY){
5227                   if(size)
5228                     emitpcode(POC_BSF, popGet(AOP(result),0));
5229                   //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5230                   //     AOP(result)->aopu.aop_dir,
5231                   //     AOP(result)->aopu.aop_dir);
5232                     else if(ifx)
5233                         continueIfTrue(ifx);
5234                     goto release;
5235                 }
5236             } else {
5237                 // lit == 0 => result = left
5238                 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5239                     goto release;
5240                 pic14_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5241             }
5242         } else {
5243             if (AOP_TYPE(right) == AOP_CRY){
5244               if(pic14_sameRegs(AOP(result),AOP(left))){
5245                 // c = bit | bit;
5246                 emitpcode(POC_BCF,   popGet(AOP(result),0));
5247                 emitpcode(POC_BTFSC, popGet(AOP(right),0));
5248                 emitpcode(POC_BSF,   popGet(AOP(result),0));
5249
5250                 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5251                          AOP(result)->aopu.aop_dir,
5252                          AOP(result)->aopu.aop_dir);
5253                 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5254                          AOP(right)->aopu.aop_dir,
5255                          AOP(right)->aopu.aop_dir);
5256                 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5257                          AOP(result)->aopu.aop_dir,
5258                          AOP(result)->aopu.aop_dir);
5259               } else {
5260                 if( AOP_TYPE(result) == AOP_ACC) {
5261                   emitpcode(POC_MOVLW, popGetLit(0));
5262                   emitpcode(POC_BTFSS, popGet(AOP(right),0));
5263                   emitpcode(POC_BTFSC, popGet(AOP(left),0));
5264                   emitpcode(POC_MOVLW, popGetLit(1));
5265
5266                 } else {
5267
5268                   emitpcode(POC_BCF,   popGet(AOP(result),0));
5269                   emitpcode(POC_BTFSS, popGet(AOP(right),0));
5270                   emitpcode(POC_BTFSC, popGet(AOP(left),0));
5271                   emitpcode(POC_BSF,   popGet(AOP(result),0));
5272
5273                   pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5274                                  AOP(result)->aopu.aop_dir,
5275                                  AOP(result)->aopu.aop_dir);
5276                   pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5277                                  AOP(right)->aopu.aop_dir,
5278                                  AOP(right)->aopu.aop_dir);
5279                   pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5280                                  AOP(left)->aopu.aop_dir,
5281                                  AOP(left)->aopu.aop_dir);
5282                   pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5283                                  AOP(result)->aopu.aop_dir,
5284                                  AOP(result)->aopu.aop_dir);
5285                 }
5286               }
5287             } else {
5288                 // c = bit | val;
5289                 symbol *tlbl = newiTempLabel(NULL);
5290                 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5291
5292
5293                 emitpcode(POC_BCF,   popGet(AOP(result),0));
5294                 if( AOP_TYPE(right) == AOP_ACC) {
5295                   emitpcode(POC_IORLW, popGetLit(0));
5296                   emitSKPNZ;
5297                   emitpcode(POC_BTFSC, popGet(AOP(left),0));
5298                   emitpcode(POC_BSF,   popGet(AOP(result),0));
5299                 }
5300
5301
5302
5303                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5304                     pic14_emitcode(";XXX setb","c");
5305                 pic14_emitcode(";XXX jb","%s,%05d_DS_",
5306                          AOP(left)->aopu.aop_dir,tlbl->key+100);
5307                 pic14_toBoolean(right);
5308                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5309                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5310                     jmpTrueOrFalse(ifx, tlbl);
5311                     goto release;
5312                 } else {
5313                     CLRC;
5314                     pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5315                 }
5316             }
5317         }
5318         // bit = c
5319         // val = c
5320         if(size)
5321             pic14_outBitC(result);
5322         // if(bit | ...)
5323         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5324             genIfxJump(ifx, "c");           
5325         goto release ;
5326     }
5327
5328     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5329     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5330     if((AOP_TYPE(right) == AOP_LIT) &&
5331        (AOP_TYPE(result) == AOP_CRY) &&
5332        (AOP_TYPE(left) != AOP_CRY)){
5333         if(lit){
5334           pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5335             // result = 1
5336             if(size)
5337                 pic14_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5338             else 
5339                 continueIfTrue(ifx);
5340             goto release;
5341         } else {
5342           pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5343             // lit = 0, result = boolean(left)
5344             if(size)
5345                 pic14_emitcode(";XXX setb","c");
5346             pic14_toBoolean(right);
5347             if(size){
5348                 symbol *tlbl = newiTempLabel(NULL);
5349                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5350                 CLRC;
5351                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5352             } else {
5353                 genIfxJump (ifx,"a");
5354                 goto release;
5355             }
5356         }
5357         pic14_outBitC(result);
5358         goto release ;
5359     }
5360
5361     /* if left is same as result */
5362     if(pic14_sameRegs(AOP(result),AOP(left))){
5363       int know_W = -1;
5364       for(;size--; offset++,lit>>=8) {
5365         if(AOP_TYPE(right) == AOP_LIT){
5366           if((lit & 0xff) == 0)
5367             /*  or'ing with 0 has no effect */
5368             continue;
5369           else {
5370             int p = my_powof2(lit & 0xff);
5371             if(p>=0) {
5372               /* only one bit is set in the literal, so use a bsf instruction */
5373               emitpcode(POC_BSF,
5374                         newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5375             } else {
5376               if(know_W != (lit & 0xff))
5377                 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5378               know_W = lit & 0xff;
5379               emitpcode(POC_IORWF, popGet(AOP(left),offset));
5380             }
5381                     
5382           }
5383         } else {
5384           if (AOP_TYPE(left) == AOP_ACC) {
5385             emitpcode(POC_IORFW,  popGet(AOP(right),offset));
5386             pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5387           } else {                  
5388             emitpcode(POC_MOVFW,  popGet(AOP(right),offset));
5389             emitpcode(POC_IORWF,  popGet(AOP(left),offset));
5390
5391             pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5392             pic14_emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
5393
5394           }
5395         }
5396       }
5397     } else {
5398         // left & result in different registers
5399         if(AOP_TYPE(result) == AOP_CRY){
5400             // result = bit
5401             // if(size), result in bit
5402             // if(!size && ifx), conditional oper: if(left | right)
5403             symbol *tlbl = newiTempLabel(NULL);
5404             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5405             pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5406
5407
5408             if(size)
5409                 pic14_emitcode(";XXX setb","c");
5410             while(sizer--){
5411                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5412                 pic14_emitcode(";XXX orl","a,%s",
5413                          aopGet(AOP(left),offset,FALSE,FALSE));
5414                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5415                 offset++;
5416             }
5417             if(size){
5418                 CLRC;
5419                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5420                 pic14_outBitC(result);
5421             } else if(ifx)
5422                 jmpTrueOrFalse(ifx, tlbl);
5423         } else for(;(size--);offset++){
5424           // normal case
5425           // result = left & right
5426           if(AOP_TYPE(right) == AOP_LIT){
5427             int t = (lit >> (offset*8)) & 0x0FFL;
5428             switch(t) { 
5429             case 0x00:
5430               emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
5431               emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
5432
5433               pic14_emitcode("movf","%s,w",
5434                        aopGet(AOP(left),offset,FALSE,FALSE));
5435               pic14_emitcode("movwf","%s",
5436                        aopGet(AOP(result),offset,FALSE,FALSE));
5437               break;
5438             default:
5439               emitpcode(POC_MOVLW,  popGetLit(t));
5440               emitpcode(POC_IORFW,  popGet(AOP(left),offset));
5441               emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
5442
5443               pic14_emitcode("movlw","0x%x",t);
5444               pic14_emitcode("iorwf","%s,w",
5445                        aopGet(AOP(left),offset,FALSE,FALSE));
5446               pic14_emitcode("movwf","%s",
5447                        aopGet(AOP(result),offset,FALSE,FALSE));
5448               
5449             }
5450             continue;
5451           }
5452
5453           // faster than result <- left, anl result,right
5454           // and better if result is SFR
5455           if (AOP_TYPE(left) == AOP_ACC) {
5456             emitpcode(POC_IORWF,  popGet(AOP(right),offset));
5457             pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5458           } else {
5459             emitpcode(POC_MOVFW,  popGet(AOP(right),offset));
5460             emitpcode(POC_IORFW,  popGet(AOP(left),offset));
5461
5462             pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5463             pic14_emitcode("iorwf","%s,w",
5464                      aopGet(AOP(left),offset,FALSE,FALSE));
5465           }
5466           emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
5467           pic14_emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5468         }
5469     }
5470
5471 release :
5472     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5473     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5474     freeAsmop(result,NULL,ic,TRUE);     
5475 }
5476
5477 /*-----------------------------------------------------------------*/
5478 /* genXor - code for xclusive or                                   */
5479 /*-----------------------------------------------------------------*/
5480 static void genXor (iCode *ic, iCode *ifx)
5481 {
5482   operand *left, *right, *result;
5483   int size, offset=0;
5484   unsigned long lit = 0L;
5485
5486   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5487
5488   aopOp((left = IC_LEFT(ic)),ic,FALSE);
5489   aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5490   aopOp((result=IC_RESULT(ic)),ic,TRUE);
5491
5492   /* if left is a literal & right is not ||
5493      if left needs acc & right does not */
5494   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5495       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
5496     operand *tmp = right ;
5497     right = left;
5498     left = tmp;
5499   }
5500
5501   /* if result = right then exchange them */
5502   if(pic14_sameRegs(AOP(result),AOP(right))){
5503     operand *tmp = right ;
5504     right = left;
5505     left = tmp;
5506   }
5507
5508   /* if right is bit then exchange them */
5509   if (AOP_TYPE(right) == AOP_CRY &&
5510       AOP_TYPE(left) != AOP_CRY){
5511     operand *tmp = right ;
5512     right = left;
5513     left = tmp;
5514   }
5515   if(AOP_TYPE(right) == AOP_LIT)
5516     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5517
5518   size = AOP_SIZE(result);
5519
5520   // if(bit ^ yy)
5521   // xx = bit ^ yy;
5522   if (AOP_TYPE(left) == AOP_CRY){
5523     if(AOP_TYPE(right) == AOP_LIT){
5524       // c = bit & literal;
5525       if(lit>>1){
5526         // lit>>1  != 0 => result = 1
5527         if(AOP_TYPE(result) == AOP_CRY){
5528           if(size)
5529             {emitpcode(POC_BSF,  popGet(AOP(result),offset));
5530             pic14_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
5531           else if(ifx)
5532             continueIfTrue(ifx);
5533           goto release;
5534         }
5535         pic14_emitcode("setb","c");
5536       } else{
5537         // lit == (0 or 1)
5538         if(lit == 0){
5539           // lit == 0, result = left
5540           if(size && pic14_sameRegs(AOP(result),AOP(left)))
5541             goto release;
5542           pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5543         } else{
5544           // lit == 1, result = not(left)
5545           if(size && pic14_sameRegs(AOP(result),AOP(left))){
5546             emitpcode(POC_MOVLW,  popGet(AOP(result),offset));
5547             emitpcode(POC_XORWF,  popGet(AOP(result),offset));
5548             pic14_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
5549             goto release;
5550           } else {
5551             pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5552             pic14_emitcode("cpl","c");
5553           }
5554         }
5555       }
5556
5557     } else {
5558       // right != literal
5559       symbol *tlbl = newiTempLabel(NULL);
5560       if (AOP_TYPE(right) == AOP_CRY){
5561         // c = bit ^ bit;
5562         pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5563       }
5564       else{
5565         int sizer = AOP_SIZE(right);
5566         // c = bit ^ val
5567         // if val>>1 != 0, result = 1
5568         pic14_emitcode("setb","c");
5569         while(sizer){
5570           MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
5571           if(sizer == 1)
5572             // test the msb of the lsb
5573             pic14_emitcode("anl","a,#0xfe");
5574           pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5575           sizer--;
5576         }
5577         // val = (0,1)
5578         pic14_emitcode("rrc","a");
5579       }
5580       pic14_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
5581       pic14_emitcode("cpl","c");
5582       pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
5583     }
5584     // bit = c
5585     // val = c
5586     if(size)
5587       pic14_outBitC(result);
5588     // if(bit | ...)
5589     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5590       genIfxJump(ifx, "c");           
5591     goto release ;
5592   }
5593
5594   if(pic14_sameRegs(AOP(result),AOP(left))){
5595     /* if left is same as result */
5596     for(;size--; offset++) {
5597       if(AOP_TYPE(right) == AOP_LIT){
5598         int t  = (lit >> (offset*8)) & 0x0FFL;
5599         if(t == 0x00L)
5600           continue;
5601         else
5602           if (IS_AOP_PREG(left)) {
5603             MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5604             pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
5605             aopPut(AOP(result),"a",offset);
5606           } else {
5607             emitpcode(POC_MOVLW, popGetLit(t));
5608             emitpcode(POC_XORWF,popGet(AOP(left),offset));
5609             pic14_emitcode("xrl","%s,%s",
5610                            aopGet(AOP(left),offset,FALSE,TRUE),
5611                            aopGet(AOP(right),offset,FALSE,FALSE));
5612           }
5613       } else {
5614         if (AOP_TYPE(left) == AOP_ACC)
5615           pic14_emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
5616         else {
5617           emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5618           emitpcode(POC_XORWF,popGet(AOP(left),offset));
5619 /*
5620           if (IS_AOP_PREG(left)) {
5621             pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
5622             aopPut(AOP(result),"a",offset);
5623           } else
5624             pic14_emitcode("xrl","%s,a",
5625                            aopGet(AOP(left),offset,FALSE,TRUE));
5626 */
5627         }
5628       }
5629     }
5630   } else {
5631     // left & result in different registers
5632     if(AOP_TYPE(result) == AOP_CRY){
5633       // result = bit
5634       // if(size), result in bit
5635       // if(!size && ifx), conditional oper: if(left ^ right)
5636       symbol *tlbl = newiTempLabel(NULL);
5637       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5638       if(size)
5639         pic14_emitcode("setb","c");
5640       while(sizer--){
5641         if((AOP_TYPE(right) == AOP_LIT) &&
5642            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
5643           MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
5644         } else {
5645           MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5646           pic14_emitcode("xrl","a,%s",
5647                          aopGet(AOP(left),offset,FALSE,FALSE));
5648         }
5649         pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5650         offset++;
5651       }
5652       if(size){
5653         CLRC;
5654         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5655         pic14_outBitC(result);
5656       } else if(ifx)
5657         jmpTrueOrFalse(ifx, tlbl);
5658     } else for(;(size--);offset++){
5659       // normal case
5660       // result = left & right
5661       if(AOP_TYPE(right) == AOP_LIT){
5662         int t = (lit >> (offset*8)) & 0x0FFL;
5663         switch(t) { 
5664         case 0x00:
5665           emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5666           emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5667           pic14_emitcode("movf","%s,w",
5668                          aopGet(AOP(left),offset,FALSE,FALSE));
5669           pic14_emitcode("movwf","%s",
5670                          aopGet(AOP(result),offset,FALSE,FALSE));
5671           break;
5672         case 0xff:
5673           emitpcode(POC_COMFW,popGet(AOP(left),offset));
5674           emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5675           pic14_emitcode("comf","%s,w",
5676                          aopGet(AOP(left),offset,FALSE,FALSE));
5677           pic14_emitcode("movwf","%s",
5678                          aopGet(AOP(result),offset,FALSE,FALSE));
5679           break;
5680         default:
5681           emitpcode(POC_MOVLW, popGetLit(t));
5682           emitpcode(POC_XORFW,popGet(AOP(left),offset));
5683           emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5684           pic14_emitcode("movlw","0x%x",t);
5685           pic14_emitcode("xorwf","%s,w",
5686                          aopGet(AOP(left),offset,FALSE,FALSE));
5687           pic14_emitcode("movwf","%s",
5688                          aopGet(AOP(result),offset,FALSE,FALSE));
5689
5690         }
5691         continue;
5692       }
5693
5694       // faster than result <- left, anl result,right
5695       // and better if result is SFR
5696       if (AOP_TYPE(left) == AOP_ACC) {
5697         emitpcode(POC_XORFW,popGet(AOP(right),offset));
5698         pic14_emitcode("xorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5699       } else {
5700         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5701         emitpcode(POC_XORFW,popGet(AOP(left),offset));
5702         pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5703         pic14_emitcode("xorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
5704       }
5705       if ( AOP_TYPE(result) != AOP_ACC){
5706         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5707         pic14_emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5708       }
5709     }
5710   }
5711
5712   release :
5713     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5714   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5715   freeAsmop(result,NULL,ic,TRUE);     
5716 }
5717
5718 /*-----------------------------------------------------------------*/
5719 /* genInline - write the inline code out                           */
5720 /*-----------------------------------------------------------------*/
5721 static void genInline (iCode *ic)
5722 {
5723     char *buffer, *bp, *bp1;
5724     
5725     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5726
5727     _G.inLine += (!options.asmpeep);
5728
5729     buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5730     strcpy(buffer,IC_INLINE(ic));
5731
5732     /* emit each line as a code */
5733     while (*bp) {
5734         if (*bp == '\n') {
5735             *bp++ = '\0';
5736             pic14_emitcode(bp1,"");
5737             bp1 = bp;
5738         } else {
5739             if (*bp == ':') {
5740                 bp++;
5741                 *bp = '\0';
5742                 bp++;
5743                 pic14_emitcode(bp1,"");
5744                 bp1 = bp;
5745             } else
5746                 bp++;
5747         }
5748     }
5749     if (bp1 != bp)
5750         pic14_emitcode(bp1,"");
5751     /*     pic14_emitcode("",buffer); */
5752     _G.inLine -= (!options.asmpeep);
5753 }
5754
5755 /*-----------------------------------------------------------------*/
5756 /* genRRC - rotate right with carry                                */
5757 /*-----------------------------------------------------------------*/
5758 static void genRRC (iCode *ic)
5759 {
5760   operand *left , *result ;
5761   int size, offset = 0, same;
5762
5763   /* rotate right with carry */
5764   left = IC_LEFT(ic);
5765   result=IC_RESULT(ic);
5766   aopOp (left,ic,FALSE);
5767   aopOp (result,ic,FALSE);
5768
5769   DEBUGpic14_AopType(__LINE__,left,NULL,result);
5770
5771   same = pic14_sameRegs(AOP(result),AOP(left));
5772
5773   size = AOP_SIZE(result);    
5774
5775   /* get the lsb and put it into the carry */
5776   emitpcode(POC_RRFW, popGet(AOP(left),size-1));
5777
5778   offset = 0 ;
5779
5780   while(size--) {
5781
5782     if(same) {
5783       emitpcode(POC_RRF, popGet(AOP(left),offset));
5784     } else {
5785       emitpcode(POC_RRFW, popGet(AOP(left),offset));
5786       emitpcode(POC_MOVWF, popGet(AOP(result),offset));
5787     }
5788
5789     offset++;
5790   }
5791
5792   freeAsmop(left,NULL,ic,TRUE);
5793   freeAsmop(result,NULL,ic,TRUE);
5794 }
5795
5796 /*-----------------------------------------------------------------*/
5797 /* genRLC - generate code for rotate left with carry               */
5798 /*-----------------------------------------------------------------*/
5799 static void genRLC (iCode *ic)
5800 {    
5801   operand *left , *result ;
5802   int size, offset = 0;
5803   int same;
5804
5805   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5806   /* rotate right with carry */
5807   left = IC_LEFT(ic);
5808   result=IC_RESULT(ic);
5809   aopOp (left,ic,FALSE);
5810   aopOp (result,ic,FALSE);
5811
5812   DEBUGpic14_AopType(__LINE__,left,NULL,result);
5813
5814   same = pic14_sameRegs(AOP(result),AOP(left));
5815
5816   /* move it to the result */
5817   size = AOP_SIZE(result);    
5818
5819   /* get the msb and put it into the carry */
5820   emitpcode(POC_RLFW, popGet(AOP(left),size-1));
5821
5822   offset = 0 ;
5823
5824   while(size--) {
5825
5826     if(same) {
5827       emitpcode(POC_RLF, popGet(AOP(left),offset));
5828     } else {
5829       emitpcode(POC_RLFW, popGet(AOP(left),offset));
5830       emitpcode(POC_MOVWF, popGet(AOP(result),offset));
5831     }
5832
5833     offset++;
5834   }
5835
5836
5837   freeAsmop(left,NULL,ic,TRUE);
5838   freeAsmop(result,NULL,ic,TRUE);
5839 }
5840
5841 /*-----------------------------------------------------------------*/
5842 /* genGetHbit - generates code get highest order bit               */
5843 /*-----------------------------------------------------------------*/
5844 static void genGetHbit (iCode *ic)
5845 {
5846     operand *left, *result;
5847     left = IC_LEFT(ic);
5848     result=IC_RESULT(ic);
5849     aopOp (left,ic,FALSE);
5850     aopOp (result,ic,FALSE);
5851
5852     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5853     /* get the highest order byte into a */
5854     MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
5855     if(AOP_TYPE(result) == AOP_CRY){
5856         pic14_emitcode("rlc","a");
5857         pic14_outBitC(result);
5858     }
5859     else{
5860         pic14_emitcode("rl","a");
5861         pic14_emitcode("anl","a,#0x01");
5862         pic14_outAcc(result);
5863     }
5864
5865
5866     freeAsmop(left,NULL,ic,TRUE);
5867     freeAsmop(result,NULL,ic,TRUE);
5868 }
5869
5870 /*-----------------------------------------------------------------*/
5871 /* AccRol - rotate left accumulator by known count                 */
5872 /*-----------------------------------------------------------------*/
5873 static void AccRol (int shCount)
5874 {
5875     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5876     shCount &= 0x0007;              // shCount : 0..7
5877     switch(shCount){
5878         case 0 :
5879             break;
5880         case 1 :
5881             pic14_emitcode("rl","a");
5882             break;
5883         case 2 :
5884             pic14_emitcode("rl","a");
5885             pic14_emitcode("rl","a");
5886             break;
5887         case 3 :
5888             pic14_emitcode("swap","a");
5889             pic14_emitcode("rr","a");
5890             break;
5891         case 4 :
5892             pic14_emitcode("swap","a");
5893             break;
5894         case 5 :
5895             pic14_emitcode("swap","a");
5896             pic14_emitcode("rl","a");
5897             break;
5898         case 6 :
5899             pic14_emitcode("rr","a");
5900             pic14_emitcode("rr","a");
5901             break;
5902         case 7 :
5903             pic14_emitcode("rr","a");
5904             break;
5905     }
5906 }
5907
5908 /*-----------------------------------------------------------------*/
5909 /* AccLsh - left shift accumulator by known count                  */
5910 /*-----------------------------------------------------------------*/
5911 static void AccLsh (int shCount)
5912 {
5913     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5914     if(shCount != 0){
5915         if(shCount == 1)
5916             pic14_emitcode("add","a,acc");
5917         else 
5918             if(shCount == 2) {
5919             pic14_emitcode("add","a,acc");
5920             pic14_emitcode("add","a,acc");
5921         } else {
5922             /* rotate left accumulator */
5923             AccRol(shCount);
5924             /* and kill the lower order bits */
5925             pic14_emitcode("anl","a,#0x%02x", SLMask[shCount]);
5926         }
5927     }
5928 }
5929
5930 /*-----------------------------------------------------------------*/
5931 /* AccRsh - right shift accumulator by known count                 */
5932 /*-----------------------------------------------------------------*/
5933 static void AccRsh (int shCount)
5934 {
5935     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5936     if(shCount != 0){
5937         if(shCount == 1){
5938             CLRC;
5939             pic14_emitcode("rrc","a");
5940         } else {
5941             /* rotate right accumulator */
5942             AccRol(8 - shCount);
5943             /* and kill the higher order bits */
5944             pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
5945         }
5946     }
5947 }
5948
5949 #if 0
5950 /*-----------------------------------------------------------------*/
5951 /* AccSRsh - signed right shift accumulator by known count                 */
5952 /*-----------------------------------------------------------------*/
5953 static void AccSRsh (int shCount)
5954 {
5955     symbol *tlbl ;
5956     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5957     if(shCount != 0){
5958         if(shCount == 1){
5959             pic14_emitcode("mov","c,acc.7");
5960             pic14_emitcode("rrc","a");
5961         } else if(shCount == 2){
5962             pic14_emitcode("mov","c,acc.7");
5963             pic14_emitcode("rrc","a");
5964             pic14_emitcode("mov","c,acc.7");
5965             pic14_emitcode("rrc","a");
5966         } else {
5967             tlbl = newiTempLabel(NULL);
5968             /* rotate right accumulator */
5969             AccRol(8 - shCount);
5970             /* and kill the higher order bits */
5971             pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
5972             pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
5973             pic14_emitcode("orl","a,#0x%02x",
5974                      (unsigned char)~SRMask[shCount]);
5975             pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5976         }
5977     }
5978 }
5979 #endif
5980 /*-----------------------------------------------------------------*/
5981 /* shiftR1Left2Result - shift right one byte from left to result   */
5982 /*-----------------------------------------------------------------*/
5983 static void shiftR1Left2ResultSigned (operand *left, int offl,
5984                                 operand *result, int offr,
5985                                 int shCount)
5986 {
5987   int same;
5988
5989   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5990
5991   same = (left == result) || (AOP(left) == AOP(result));
5992
5993   switch(shCount) {
5994   case 1:
5995     emitpcode(POC_RLFW, popGet(AOP(left),offl));
5996     if(same) 
5997       emitpcode(POC_RRF, popGet(AOP(result),offr));
5998     else {
5999       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6000       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6001     }
6002
6003     break;
6004
6005   default:
6006     break;
6007   }
6008 }
6009
6010 /*-----------------------------------------------------------------*/
6011 /* shiftR1Left2Result - shift right one byte from left to result   */
6012 /*-----------------------------------------------------------------*/
6013 static void shiftR1Left2Result (operand *left, int offl,
6014                                 operand *result, int offr,
6015                                 int shCount, int sign)
6016 {
6017   int same;
6018
6019   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6020
6021   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6022
6023   /* Copy the msb into the carry if signed. */
6024   if(sign) {
6025     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6026     return;
6027   }
6028
6029
6030
6031   switch(shCount) {
6032   case 1:
6033     emitCLRC;
6034     if(same) 
6035       emitpcode(POC_RRF, popGet(AOP(result),offr));
6036     else {
6037       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6038       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6039     }
6040     break;
6041   case 2:
6042     emitCLRC;
6043     if(same) {
6044       emitpcode(POC_RRF, popGet(AOP(result),offr));
6045     } else {
6046       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6047       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6048     }
6049     emitCLRC;
6050     emitpcode(POC_RRF, popGet(AOP(result),offr));
6051
6052     break;
6053   case 3:
6054     if(same) 
6055       emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6056     else {
6057       emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6058       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6059     }
6060
6061     emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6062     emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6063     emitpcode(POC_ANDLW, popGetLit(0x1f));
6064     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6065     break;
6066       
6067   case 4:
6068     emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6069     emitpcode(POC_ANDLW, popGetLit(0x0f));
6070     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6071     break;
6072
6073   case 5:
6074     emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6075     emitpcode(POC_ANDLW, popGetLit(0x0f));
6076     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6077     emitCLRC;
6078     emitpcode(POC_RRF, popGet(AOP(result),offr));
6079
6080     break;
6081   case 6:
6082
6083     emitpcode(POC_RLFW,  popGet(AOP(left),offl));
6084     emitpcode(POC_ANDLW, popGetLit(0x80));
6085     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6086     emitpcode(POC_RLF,   popGet(AOP(result),offr));
6087     emitpcode(POC_RLF,   popGet(AOP(result),offr));
6088     break;
6089
6090   case 7:
6091
6092     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6093     emitpcode(POC_CLRF, popGet(AOP(result),offr));
6094     emitpcode(POC_RLF,  popGet(AOP(result),offr));
6095
6096     break;
6097
6098   default:
6099     break;
6100   }
6101
6102
6103 #if 0
6104     
6105   MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6106
6107   /* shift right accumulator */
6108   if(sign)
6109     AccSRsh(shCount);
6110   else
6111     AccRsh(shCount);
6112   aopPut(AOP(result),"a",offr);
6113 #endif
6114 }
6115
6116 /*-----------------------------------------------------------------*/
6117 /* shiftL1Left2Result - shift left one byte from left to result    */
6118 /*-----------------------------------------------------------------*/
6119 static void shiftL1Left2Result (operand *left, int offl,
6120                                 operand *result, int offr, int shCount)
6121 {
6122   int same;
6123
6124   //    char *l;
6125   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6126
6127   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6128   DEBUGpic14_emitcode ("; ***","same =  %d",same);
6129     //    l = aopGet(AOP(left),offl,FALSE,FALSE);
6130     //    MOVA(l);
6131     /* shift left accumulator */
6132     //AccLsh(shCount); // don't comment out just yet...
6133   //    aopPut(AOP(result),"a",offr);
6134
6135   switch(shCount) {
6136   case 1:
6137     /* Shift left 1 bit position */
6138     emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6139     if(same) {
6140       emitpcode(POC_ADDWF, popGet(AOP(left),offl));
6141     } else {
6142       emitpcode(POC_ADDFW, popGet(AOP(left),offl));
6143       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6144     }
6145     break;
6146   case 2:
6147     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6148     emitpcode(POC_ANDLW,popGetLit(0x7e));
6149     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6150     emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6151     break;
6152   case 3:
6153     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6154     emitpcode(POC_ANDLW,popGetLit(0x3e));
6155     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6156     emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6157     emitpcode(POC_RLF,  popGet(AOP(result),offr));
6158     break;
6159   case 4:
6160     emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6161     emitpcode(POC_ANDLW, popGetLit(0xf0));
6162     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6163     break;
6164   case 5:
6165     emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6166     emitpcode(POC_ANDLW, popGetLit(0xf0));
6167     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6168     emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6169     break;
6170   case 6:
6171     emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6172     emitpcode(POC_ANDLW, popGetLit(0x30));
6173     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6174     emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6175     emitpcode(POC_RLF,  popGet(AOP(result),offr));
6176     break;
6177   case 7:
6178     emitpcode(POC_RRFW, popGet(AOP(left),offl));
6179     emitpcode(POC_CLRF, popGet(AOP(result),offr));
6180     emitpcode(POC_RRF,  popGet(AOP(result),offr));
6181     break;
6182
6183   default:
6184     DEBUGpic14_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6185   }
6186
6187 }
6188
6189 /*-----------------------------------------------------------------*/
6190 /* movLeft2Result - move byte from left to result                  */
6191 /*-----------------------------------------------------------------*/
6192 static void movLeft2Result (operand *left, int offl,
6193                             operand *result, int offr, int sign)
6194 {
6195     char *l;
6196     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6197     if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6198         l = aopGet(AOP(left),offl,FALSE,FALSE);
6199
6200         if (*l == '@' && (IS_AOP_PREG(result))) {
6201             pic14_emitcode("mov","a,%s",l);
6202             aopPut(AOP(result),"a",offr);
6203         } else {
6204           if(!sign) {
6205             emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6206             emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6207
6208             //aopPut(AOP(result),l,offr);
6209           }else{
6210                 /* MSB sign in acc.7 ! */
6211                 if(pic14_getDataSize(left) == offl+1){
6212                     pic14_emitcode("mov","a,%s",l);
6213                     aopPut(AOP(result),"a",offr);
6214                 }
6215             }
6216         }
6217     }
6218 }
6219
6220 /*-----------------------------------------------------------------*/
6221 /* shiftL2Left2Result - shift left two bytes from left to result   */
6222 /*-----------------------------------------------------------------*/
6223 static void shiftL2Left2Result (operand *left, int offl,
6224                                 operand *result, int offr, int shCount)
6225 {
6226
6227
6228   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6229
6230   if(pic14_sameRegs(AOP(result), AOP(left))) {
6231     switch(shCount) {
6232     case 0:
6233       break;
6234     case 1:
6235     case 2:
6236     case 3:
6237
6238       emitpcode(POC_MOVFW,popGet(AOP(result),offr));
6239       emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6240       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6241
6242       while(--shCount) {
6243         emitCLRC;
6244         emitpcode(POC_RLF, popGet(AOP(result),offr));
6245         emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6246       }
6247
6248       break;
6249     case 4:
6250     case 5:
6251       emitpcode(POC_MOVLW, popGetLit(0x0f));
6252       emitpcode(POC_ANDWF, popGet(AOP(result),offr+MSB16));
6253       emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
6254       emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6255       emitpcode(POC_ANDFW, popGet(AOP(result),offr));
6256       emitpcode(POC_XORWF, popGet(AOP(result),offr));
6257       emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
6258       if(shCount >=5) {
6259         emitpcode(POC_RLF, popGet(AOP(result),offr));
6260         emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6261       }
6262       break;
6263     case 6:
6264       emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
6265       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6266       emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
6267       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6268       emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6269       emitpcode(POC_ANDLW,popGetLit(0xc0));
6270       emitpcode(POC_XORFW,popGet(AOP(result),offr));
6271       emitpcode(POC_XORWF,popGet(AOP(result),offr));
6272       emitpcode(POC_XORFW,popGet(AOP(result),offr));
6273       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6274       break;
6275     case 7:
6276       emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6277       emitpcode(POC_RRFW, popGet(AOP(result),offr));
6278       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6279       emitpcode(POC_CLRF, popGet(AOP(result),offr));
6280       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6281     }
6282
6283   } else {
6284     switch(shCount) {
6285     case 0:
6286       break;
6287     case 1:
6288     case 2:
6289     case 3:
6290       /* note, use a mov/add for the shift since the mov has a
6291          chance of getting optimized out */
6292       emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6293       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6294       emitpcode(POC_ADDWF, popGet(AOP(result),offr));
6295       emitpcode(POC_RLFW,  popGet(AOP(left),offl+MSB16));
6296       emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6297
6298       while(--shCount) {
6299         emitCLRC;
6300         emitpcode(POC_RLF, popGet(AOP(result),offr));
6301         emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6302       }
6303       break;
6304
6305     case 4:
6306     case 5:
6307       emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
6308       emitpcode(POC_ANDLW, popGetLit(0xF0));
6309       emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6310       emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6311       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6312       emitpcode(POC_ANDLW, popGetLit(0xF0));
6313       emitpcode(POC_XORWF, popGet(AOP(result),offr));
6314       emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
6315
6316
6317       if(shCount == 5) {
6318         emitpcode(POC_RLF, popGet(AOP(result),offr));
6319         emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6320       }
6321       break;
6322     case 6:
6323       emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
6324       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6325       emitpcode(POC_RRFW, popGet(AOP(result),offl));
6326       emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6327
6328       emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
6329       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6330       emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6331       emitpcode(POC_ANDLW,popGetLit(0xc0));
6332       emitpcode(POC_XORFW,popGet(AOP(result),offr));
6333       emitpcode(POC_XORWF,popGet(AOP(result),offr));
6334       emitpcode(POC_XORFW,popGet(AOP(result),offr));
6335       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6336       break;
6337     case 7:
6338       emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
6339       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6340       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6341       emitpcode(POC_CLRF, popGet(AOP(result),offr));
6342       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6343     }
6344   }
6345
6346 }
6347 /*-----------------------------------------------------------------*/
6348 /* shiftR2Left2Result - shift right two bytes from left to result  */
6349 /*-----------------------------------------------------------------*/
6350 static void shiftR2Left2Result (operand *left, int offl,
6351                                 operand *result, int offr,
6352                                 int shCount, int sign)
6353 {
6354   int same=0;
6355
6356   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6357   same = pic14_sameRegs(AOP(result), AOP(left));
6358
6359   if(same && ((offl + MSB16) == offr)){
6360     same=1;
6361     /* don't crash result[offr] */
6362     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6363     pic14_emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6364   } else {
6365     movLeft2Result(left,offl, result, offr, 0);
6366     MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6367   }
6368   /* a:x >> shCount (x = lsb(result))*/
6369 /*
6370   if(sign)
6371     AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6372   else {
6373     AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6374 */
6375   switch(shCount) {
6376   case 0:
6377     break;
6378   case 1:
6379   case 2:
6380   case 3:
6381     emitCLRC;
6382     if(same) {
6383       emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
6384       emitpcode(POC_RRF,popGet(AOP(result),offr));
6385     } else {
6386
6387       emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
6388       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6389       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6390       emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6391     }
6392
6393     while(--shCount) {
6394       emitCLRC;
6395       emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
6396       emitpcode(POC_RRF,popGet(AOP(result),offr));
6397     }
6398     break;
6399   case 4:
6400   case 5:
6401     if(same) {
6402
6403       emitpcode(POC_MOVLW, popGetLit(0xf0));
6404       emitpcode(POC_ANDWF, popGet(AOP(result),offr));
6405       emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6406
6407       emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
6408       emitpcode(POC_ANDFW, popGet(AOP(result),offr+MSB16));
6409       emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
6410       emitpcode(POC_ADDWF, popGet(AOP(result),offr));
6411     } else {
6412       emitpcode(POC_SWAPF, popGet(AOP(left),offl));
6413       emitpcode(POC_ANDLW, popGetLit(0x0f));
6414       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6415
6416       emitpcode(POC_SWAPF, popGet(AOP(left),offl+MSB16));
6417       emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6418       emitpcode(POC_ANDLW, popGetLit(0xf0));
6419       emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
6420       emitpcode(POC_ADDWF, popGet(AOP(result),offr));
6421     }
6422
6423     if(shCount >=5) {
6424       emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
6425       emitpcode(POC_RRF, popGet(AOP(result),offr));
6426     }
6427
6428     break;
6429
6430   case 6:
6431     if(same) {
6432
6433       emitpcode(POC_RLF,  popGet(AOP(result),offr));
6434       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6435
6436       emitpcode(POC_RLF,  popGet(AOP(result),offr));
6437       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6438       emitpcode(POC_RLFW, popGet(AOP(result),offr));
6439       emitpcode(POC_ANDLW,popGetLit(0x03));
6440       emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
6441       emitpcode(POC_XORWF,popGet(AOP(result),offr+MSB16));
6442       emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
6443       emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6444     } else {
6445       emitpcode(POC_RLFW, popGet(AOP(left),offl));
6446       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6447       emitpcode(POC_RLFW, popGet(AOP(result),offl+MSB16));
6448       emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6449       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6450       emitpcode(POC_RLF,  popGet(AOP(result),offr));
6451       emitpcode(POC_RLFW, popGet(AOP(result),offr));
6452       emitpcode(POC_ANDLW,popGetLit(0x03));
6453       emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6454     }
6455
6456     break;
6457   case 7:
6458     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6459     emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
6460     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6461     emitpcode(POC_CLRF, popGet(AOP(result),offr+MSB16));
6462     emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6463   }
6464 }
6465
6466
6467 /*-----------------------------------------------------------------*/
6468 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
6469 /*-----------------------------------------------------------------*/
6470 static void shiftLLeftOrResult (operand *left, int offl,
6471                                 operand *result, int offr, int shCount)
6472 {
6473     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6474     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6475     /* shift left accumulator */
6476     AccLsh(shCount);
6477     /* or with result */
6478     pic14_emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
6479     /* back to result */
6480     aopPut(AOP(result),"a",offr);
6481 }
6482
6483 /*-----------------------------------------------------------------*/
6484 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
6485 /*-----------------------------------------------------------------*/
6486 static void shiftRLeftOrResult (operand *left, int offl,
6487                                 operand *result, int offr, int shCount)
6488 {
6489     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6490     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6491     /* shift right accumulator */
6492     AccRsh(shCount);
6493     /* or with result */
6494     pic14_emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
6495     /* back to result */
6496     aopPut(AOP(result),"a",offr);
6497 }
6498
6499 /*-----------------------------------------------------------------*/
6500 /* genlshOne - left shift a one byte quantity by known count       */
6501 /*-----------------------------------------------------------------*/
6502 static void genlshOne (operand *result, operand *left, int shCount)
6503 {       
6504     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6505     shiftL1Left2Result(left, LSB, result, LSB, shCount);
6506 }
6507
6508 /*-----------------------------------------------------------------*/
6509 /* genlshTwo - left shift two bytes by known amount != 0           */
6510 /*-----------------------------------------------------------------*/
6511 static void genlshTwo (operand *result,operand *left, int shCount)
6512 {
6513     int size;
6514     
6515     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6516     size = pic14_getDataSize(result);
6517
6518     /* if shCount >= 8 */
6519     if (shCount >= 8) {
6520         shCount -= 8 ;
6521
6522         if (size > 1){
6523             if (shCount)
6524                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6525             else 
6526                 movLeft2Result(left, LSB, result, MSB16, 0);
6527         }
6528         emitpcode(POC_CLRF,popGet(AOP(result),LSB));
6529     }
6530
6531     /*  1 <= shCount <= 7 */
6532     else {  
6533         if(size == 1)
6534             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
6535         else 
6536             shiftL2Left2Result(left, LSB, result, LSB, shCount);
6537     }
6538 }
6539
6540 /*-----------------------------------------------------------------*/
6541 /* shiftLLong - shift left one long from left to result            */
6542 /* offl = LSB or MSB16                                             */
6543 /*-----------------------------------------------------------------*/
6544 static void shiftLLong (operand *left, operand *result, int offr )
6545 {
6546     char *l;
6547     int size = AOP_SIZE(result);
6548
6549     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6550     if(size >= LSB+offr){
6551         l = aopGet(AOP(left),LSB,FALSE,FALSE);
6552         MOVA(l);
6553         pic14_emitcode("add","a,acc");
6554         if (pic14_sameRegs(AOP(left),AOP(result)) && 
6555             size >= MSB16+offr && offr != LSB )
6556             pic14_emitcode("xch","a,%s",
6557                      aopGet(AOP(left),LSB+offr,FALSE,FALSE));
6558         else        
6559             aopPut(AOP(result),"a",LSB+offr);
6560     }
6561
6562     if(size >= MSB16+offr){
6563         if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
6564             l = aopGet(AOP(left),MSB16,FALSE,FALSE);
6565             MOVA(l);
6566         }
6567         pic14_emitcode("rlc","a");
6568         if (pic14_sameRegs(AOP(left),AOP(result)) && 
6569             size >= MSB24+offr && offr != LSB)
6570             pic14_emitcode("xch","a,%s",
6571                      aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
6572         else        
6573             aopPut(AOP(result),"a",MSB16+offr);
6574     }
6575
6576     if(size >= MSB24+offr){
6577         if (!(pic14_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
6578             l = aopGet(AOP(left),MSB24,FALSE,FALSE);
6579             MOVA(l);
6580         }
6581         pic14_emitcode("rlc","a");
6582         if (pic14_sameRegs(AOP(left),AOP(result)) && 
6583             size >= MSB32+offr && offr != LSB )
6584             pic14_emitcode("xch","a,%s",
6585                      aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
6586         else        
6587             aopPut(AOP(result),"a",MSB24+offr);
6588     }
6589
6590     if(size > MSB32+offr){
6591         if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
6592             l = aopGet(AOP(left),MSB32,FALSE,FALSE);
6593             MOVA(l);    
6594         }
6595         pic14_emitcode("rlc","a");
6596         aopPut(AOP(result),"a",MSB32+offr);
6597     }
6598     if(offr != LSB)
6599         aopPut(AOP(result),zero,LSB);       
6600 }
6601
6602 /*-----------------------------------------------------------------*/
6603 /* genlshFour - shift four byte by a known amount != 0             */
6604 /*-----------------------------------------------------------------*/
6605 static void genlshFour (operand *result, operand *left, int shCount)
6606 {
6607     int size;
6608
6609     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6610     size = AOP_SIZE(result);
6611
6612     /* if shifting more that 3 bytes */
6613     if (shCount >= 24 ) {
6614         shCount -= 24;
6615         if (shCount)
6616             /* lowest order of left goes to the highest
6617             order of the destination */
6618             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
6619         else
6620             movLeft2Result(left, LSB, result, MSB32, 0);
6621         aopPut(AOP(result),zero,LSB);
6622         aopPut(AOP(result),zero,MSB16);
6623         aopPut(AOP(result),zero,MSB32);
6624         return;
6625     }
6626
6627     /* more than two bytes */
6628     else if ( shCount >= 16 ) {
6629         /* lower order two bytes goes to higher order two bytes */
6630         shCount -= 16;
6631         /* if some more remaining */
6632         if (shCount)
6633             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
6634         else {
6635             movLeft2Result(left, MSB16, result, MSB32, 0);
6636             movLeft2Result(left, LSB, result, MSB24, 0);
6637         }
6638         aopPut(AOP(result),zero,MSB16);
6639         aopPut(AOP(result),zero,LSB);
6640         return;
6641     }    
6642
6643     /* if more than 1 byte */
6644     else if ( shCount >= 8 ) {
6645         /* lower order three bytes goes to higher order  three bytes */
6646         shCount -= 8;
6647         if(size == 2){
6648             if(shCount)
6649                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6650             else
6651                 movLeft2Result(left, LSB, result, MSB16, 0);
6652         }
6653         else{   /* size = 4 */
6654             if(shCount == 0){
6655                 movLeft2Result(left, MSB24, result, MSB32, 0);
6656                 movLeft2Result(left, MSB16, result, MSB24, 0);
6657                 movLeft2Result(left, LSB, result, MSB16, 0);
6658                 aopPut(AOP(result),zero,LSB);
6659             }
6660             else if(shCount == 1)
6661                 shiftLLong(left, result, MSB16);
6662             else{
6663                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
6664                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6665                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
6666                 aopPut(AOP(result),zero,LSB);
6667             }
6668         }
6669     }
6670
6671     /* 1 <= shCount <= 7 */
6672     else if(shCount <= 2){
6673         shiftLLong(left, result, LSB);
6674         if(shCount == 2)
6675             shiftLLong(result, result, LSB);
6676     }
6677     /* 3 <= shCount <= 7, optimize */
6678     else{
6679         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
6680         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
6681         shiftL2Left2Result(left, LSB, result, LSB, shCount);
6682     }
6683 }
6684
6685 /*-----------------------------------------------------------------*/
6686 /* genLeftShiftLiteral - left shifting by known count              */
6687 /*-----------------------------------------------------------------*/
6688 static void genLeftShiftLiteral (operand *left,
6689                                  operand *right,
6690                                  operand *result,
6691                                  iCode *ic)
6692 {    
6693     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6694     int size;
6695
6696     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6697     freeAsmop(right,NULL,ic,TRUE);
6698
6699     aopOp(left,ic,FALSE);
6700     aopOp(result,ic,FALSE);
6701
6702     size = getSize(operandType(result));
6703
6704 #if VIEW_SIZE
6705     pic14_emitcode("; shift left ","result %d, left %d",size,
6706              AOP_SIZE(left));
6707 #endif
6708
6709     /* I suppose that the left size >= result size */
6710     if(shCount == 0){
6711         while(size--){
6712             movLeft2Result(left, size, result, size, 0);
6713         }
6714     }
6715
6716     else if(shCount >= (size * 8))
6717         while(size--)
6718             aopPut(AOP(result),zero,size);
6719     else{
6720         switch (size) {
6721             case 1:
6722                 genlshOne (result,left,shCount);
6723                 break;
6724
6725             case 2:
6726             case 3:
6727                 genlshTwo (result,left,shCount);
6728                 break;
6729
6730             case 4:
6731                 genlshFour (result,left,shCount);
6732                 break;
6733         }
6734     }
6735     freeAsmop(left,NULL,ic,TRUE);
6736     freeAsmop(result,NULL,ic,TRUE);
6737 }
6738
6739 /*-----------------------------------------------------------------*
6740  * genMultiAsm - repeat assembly instruction for size of register.
6741  * if endian == 1, then the high byte (i.e base address + size of 
6742  * register) is used first else the low byte is used first;
6743  *-----------------------------------------------------------------*/
6744 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
6745 {
6746
6747   int offset = 0;
6748
6749   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6750
6751   if(!reg)
6752     return;
6753
6754   if(!endian) {
6755     endian = 1;
6756   } else {
6757     endian = -1;
6758     offset = size-1;
6759   }
6760
6761   while(size--) {
6762     emitpcode(poc,    popGet(AOP(reg),offset));
6763     offset += endian;
6764   }
6765
6766 }
6767 /*-----------------------------------------------------------------*/
6768 /* genLeftShift - generates code for left shifting                 */
6769 /*-----------------------------------------------------------------*/
6770 static void genLeftShift (iCode *ic)
6771 {
6772     operand *left,*right, *result;
6773     int size, offset;
6774     char *l;
6775     symbol *tlbl , *tlbl1;
6776
6777     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6778
6779     right = IC_RIGHT(ic);
6780     left  = IC_LEFT(ic);
6781     result = IC_RESULT(ic);
6782
6783     aopOp(right,ic,FALSE);
6784
6785     /* if the shift count is known then do it 
6786     as efficiently as possible */
6787     if (AOP_TYPE(right) == AOP_LIT) {
6788         genLeftShiftLiteral (left,right,result,ic);
6789         return ;
6790     }
6791
6792     /* shift count is unknown then we have to form 
6793     a loop get the loop count in B : Note: we take
6794     only the lower order byte since shifting
6795     more that 32 bits make no sense anyway, ( the
6796     largest size of an object can be only 32 bits ) */  
6797
6798     
6799     aopOp(left,ic,FALSE);
6800     aopOp(result,ic,FALSE);
6801
6802     /* now move the left to the result if they are not the
6803     same */
6804     if (!pic14_sameRegs(AOP(left),AOP(result)) && 
6805         AOP_SIZE(result) > 1) {
6806
6807         size = AOP_SIZE(result);
6808         offset=0;
6809         while (size--) {
6810             l = aopGet(AOP(left),offset,FALSE,TRUE);
6811             if (*l == '@' && (IS_AOP_PREG(result))) {
6812
6813                 pic14_emitcode("mov","a,%s",l);
6814                 aopPut(AOP(result),"a",offset);
6815             } else
6816                 aopPut(AOP(result),l,offset);
6817             offset++;
6818         }
6819     }
6820
6821     size = AOP_SIZE(result);
6822
6823     /* if it is only one byte then */
6824     if (size == 1) {
6825       if(optimized_for_speed) {
6826         emitpcode(POC_SWAPFW, popGet(AOP(left),0));
6827         emitpcode(POC_ANDLW,  popGetLit(0xf0));
6828         emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),2,0));
6829         emitpcode(POC_MOVFW,  popGet(AOP(left),0));
6830         emitpcode(POC_MOVWF,  popGet(AOP(result),0));
6831         emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
6832         emitpcode(POC_ADDWF,  popGet(AOP(result),0));
6833         emitpcode(POC_RLFW,   popGet(AOP(result),0));
6834         emitpcode(POC_ANDLW,  popGetLit(0xfe));
6835         emitpcode(POC_ADDFW,  popGet(AOP(result),0));
6836         emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),1,0));
6837         emitpcode(POC_ADDWF,  popGet(AOP(result),0));
6838       } else {
6839
6840         tlbl = newiTempLabel(NULL);
6841         if (!pic14_sameRegs(AOP(left),AOP(result))) {
6842           emitpcode(POC_MOVFW,  popGet(AOP(left),0));
6843           emitpcode(POC_MOVWF,  popGet(AOP(result),0));
6844         }
6845
6846         emitpcode(POC_COMFW,  popGet(AOP(right),0));
6847         emitpcode(POC_RRF,    popGet(AOP(result),0));
6848         emitpLabel(tlbl->key);
6849         emitpcode(POC_RLF,    popGet(AOP(result),0));
6850         emitpcode(POC_ADDLW,  popGetLit(1));
6851         emitSKPC;
6852         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
6853       }
6854       goto release ;
6855     }
6856     
6857     if (pic14_sameRegs(AOP(left),AOP(result))) {
6858
6859       tlbl = newiTempLabel(NULL);
6860       emitpcode(POC_COMFW,  popGet(AOP(right),0));
6861       genMultiAsm(POC_RRF, result, size,1);
6862       emitpLabel(tlbl->key);
6863       genMultiAsm(POC_RLF, result, size,0);
6864       emitpcode(POC_ADDLW,  popGetLit(1));
6865       emitSKPC;
6866       emitpcode(POC_GOTO,popGetLabel(tlbl->key));
6867       goto release;
6868     }
6869
6870     tlbl = newiTempLabel(NULL);
6871     offset = 0 ;   
6872     tlbl1 = newiTempLabel(NULL);
6873
6874     reAdjustPreg(AOP(result));    
6875     
6876     pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
6877     pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
6878     l = aopGet(AOP(result),offset,FALSE,FALSE);
6879     MOVA(l);
6880     pic14_emitcode("add","a,acc");         
6881     aopPut(AOP(result),"a",offset++);
6882     while (--size) {
6883         l = aopGet(AOP(result),offset,FALSE,FALSE);
6884         MOVA(l);
6885         pic14_emitcode("rlc","a");         
6886         aopPut(AOP(result),"a",offset++);
6887     }
6888     reAdjustPreg(AOP(result));
6889
6890     pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
6891     pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6892 release:
6893     freeAsmop (right,NULL,ic,TRUE);
6894     freeAsmop(left,NULL,ic,TRUE);
6895     freeAsmop(result,NULL,ic,TRUE);
6896 }
6897
6898 /*-----------------------------------------------------------------*/
6899 /* genrshOne - right shift a one byte quantity by known count      */
6900 /*-----------------------------------------------------------------*/
6901 static void genrshOne (operand *result, operand *left,
6902                        int shCount, int sign)
6903 {
6904     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6905     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
6906 }
6907
6908 /*-----------------------------------------------------------------*/
6909 /* genrshTwo - right shift two bytes by known amount != 0          */
6910 /*-----------------------------------------------------------------*/
6911 static void genrshTwo (operand *result,operand *left,
6912                        int shCount, int sign)
6913 {
6914     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6915     /* if shCount >= 8 */
6916     if (shCount >= 8) {
6917         shCount -= 8 ;
6918         if (shCount)
6919             shiftR1Left2Result(left, MSB16, result, LSB,
6920                                shCount, sign);
6921         else 
6922             movLeft2Result(left, MSB16, result, LSB, sign);
6923         if(sign)
6924           addSign(result, MSB16, sign);
6925         else
6926           emitpcode(POC_CLRF,popGet(AOP(result),MSB16));
6927
6928     }
6929
6930     /*  1 <= shCount <= 7 */
6931     else
6932         shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
6933 }
6934
6935 /*-----------------------------------------------------------------*/
6936 /* shiftRLong - shift right one long from left to result           */
6937 /* offl = LSB or MSB16                                             */
6938 /*-----------------------------------------------------------------*/
6939 static void shiftRLong (operand *left, int offl,
6940                         operand *result, int sign)
6941 {
6942     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6943     if(!sign)
6944         pic14_emitcode("clr","c");
6945     MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE));
6946     if(sign)
6947         pic14_emitcode("mov","c,acc.7");
6948     pic14_emitcode("rrc","a");
6949     aopPut(AOP(result),"a",MSB32-offl);
6950     if(offl == MSB16)
6951         /* add sign of "a" */
6952         addSign(result, MSB32, sign);
6953
6954     MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE));
6955     pic14_emitcode("rrc","a");
6956     aopPut(AOP(result),"a",MSB24-offl);
6957
6958     MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE));
6959     pic14_emitcode("rrc","a");
6960     aopPut(AOP(result),"a",MSB16-offl);
6961
6962     if(offl == LSB){
6963         MOVA(aopGet(AOP(left),LSB,FALSE,FALSE));
6964         pic14_emitcode("rrc","a");
6965         aopPut(AOP(result),"a",LSB);
6966     }
6967 }
6968
6969 /*-----------------------------------------------------------------*/
6970 /* genrshFour - shift four byte by a known amount != 0             */
6971 /*-----------------------------------------------------------------*/
6972 static void genrshFour (operand *result, operand *left,
6973                         int shCount, int sign)
6974 {
6975     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6976     /* if shifting more that 3 bytes */
6977     if(shCount >= 24 ) {
6978         shCount -= 24;
6979         if(shCount)
6980             shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
6981         else
6982             movLeft2Result(left, MSB32, result, LSB, sign);
6983         addSign(result, MSB16, sign);
6984     }
6985     else if(shCount >= 16){
6986         shCount -= 16;
6987         if(shCount)
6988             shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
6989         else{
6990             movLeft2Result(left, MSB24, result, LSB, 0);
6991             movLeft2Result(left, MSB32, result, MSB16, sign);
6992         }
6993         addSign(result, MSB24, sign);
6994     }
6995     else if(shCount >= 8){
6996         shCount -= 8;
6997         if(shCount == 1)
6998             shiftRLong(left, MSB16, result, sign);
6999         else if(shCount == 0){
7000             movLeft2Result(left, MSB16, result, LSB, 0);
7001             movLeft2Result(left, MSB24, result, MSB16, 0);
7002             movLeft2Result(left, MSB32, result, MSB24, sign);
7003             addSign(result, MSB32, sign);
7004         }
7005         else{
7006             shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
7007             shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
7008             /* the last shift is signed */
7009             shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
7010             addSign(result, MSB32, sign);
7011         }
7012     }
7013     else{   /* 1 <= shCount <= 7 */
7014         if(shCount <= 2){
7015             shiftRLong(left, LSB, result, sign);
7016             if(shCount == 2)
7017                 shiftRLong(result, LSB, result, sign);
7018         }
7019         else{
7020             shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
7021             shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
7022             shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
7023         }
7024     }
7025 }
7026
7027 /*-----------------------------------------------------------------*/
7028 /* genRightShiftLiteral - right shifting by known count            */
7029 /*-----------------------------------------------------------------*/
7030 static void genRightShiftLiteral (operand *left,
7031                                   operand *right,
7032                                   operand *result,
7033                                   iCode *ic,
7034                                   int sign)
7035 {    
7036     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7037     int size;
7038
7039     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7040     freeAsmop(right,NULL,ic,TRUE);
7041
7042     aopOp(left,ic,FALSE);
7043     aopOp(result,ic,FALSE);
7044
7045 #if VIEW_SIZE
7046     pic14_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
7047              AOP_SIZE(left));
7048 #endif
7049
7050     size = pic14_getDataSize(left);
7051     /* test the LEFT size !!! */
7052
7053     /* I suppose that the left size >= result size */
7054     if(shCount == 0){
7055         size = pic14_getDataSize(result);
7056         while(size--)
7057             movLeft2Result(left, size, result, size, 0);
7058     }
7059
7060     else if(shCount >= (size * 8)){
7061         if(sign)
7062             /* get sign in acc.7 */
7063             MOVA(aopGet(AOP(left),size-1,FALSE,FALSE));
7064         addSign(result, LSB, sign);
7065     } else{
7066         switch (size) {
7067             case 1:
7068                 genrshOne (result,left,shCount,sign);
7069                 break;
7070
7071             case 2:
7072                 genrshTwo (result,left,shCount,sign);
7073                 break;
7074
7075             case 4:
7076                 genrshFour (result,left,shCount,sign);
7077                 break;
7078             default :
7079                 break;
7080         }
7081
7082         freeAsmop(left,NULL,ic,TRUE);
7083         freeAsmop(result,NULL,ic,TRUE);
7084     }
7085 }
7086
7087 /*-----------------------------------------------------------------*/
7088 /* genSignedRightShift - right shift of signed number              */
7089 /*-----------------------------------------------------------------*/
7090 static void genSignedRightShift (iCode *ic)
7091 {
7092     operand *right, *left, *result;
7093     int size, offset;
7094     char *l;
7095     symbol *tlbl, *tlbl1 ;
7096
7097     /* we do it the hard way put the shift count in b
7098     and loop thru preserving the sign */
7099     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7100
7101     right = IC_RIGHT(ic);
7102     left  = IC_LEFT(ic);
7103     result = IC_RESULT(ic);
7104
7105     aopOp(right,ic,FALSE);  
7106
7107
7108     if ( AOP_TYPE(right) == AOP_LIT) {
7109         genRightShiftLiteral (left,right,result,ic,1);
7110         return ;
7111     }
7112         /* shift count is unknown then we have to form 
7113        a loop get the loop count in B : Note: we take
7114        only the lower order byte since shifting
7115        more that 32 bits make no sense anyway, ( the
7116        largest size of an object can be only 32 bits ) */  
7117
7118     pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
7119     pic14_emitcode("inc","b");
7120     freeAsmop (right,NULL,ic,TRUE);
7121     aopOp(left,ic,FALSE);
7122     aopOp(result,ic,FALSE);
7123
7124     /* now move the left to the result if they are not the
7125     same */
7126     if (!pic14_sameRegs(AOP(left),AOP(result)) && 
7127         AOP_SIZE(result) > 1) {
7128
7129         size = AOP_SIZE(result);
7130         offset=0;
7131         while (size--) {
7132             l = aopGet(AOP(left),offset,FALSE,TRUE);
7133             if (*l == '@' && IS_AOP_PREG(result)) {
7134
7135                 pic14_emitcode("mov","a,%s",l);
7136                 aopPut(AOP(result),"a",offset);
7137             } else
7138                 aopPut(AOP(result),l,offset);
7139             offset++;
7140         }
7141     }
7142
7143     /* mov the highest order bit to OVR */    
7144     tlbl = newiTempLabel(NULL);
7145     tlbl1= newiTempLabel(NULL);
7146
7147     size = AOP_SIZE(result);
7148     offset = size - 1;
7149     pic14_emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
7150     pic14_emitcode("rlc","a");
7151     pic14_emitcode("mov","ov,c");
7152     /* if it is only one byte then */
7153     if (size == 1) {
7154         l = aopGet(AOP(left),0,FALSE,FALSE);
7155         MOVA(l);
7156         pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7157         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
7158         pic14_emitcode("mov","c,ov");
7159         pic14_emitcode("rrc","a");
7160         pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7161         pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7162         aopPut(AOP(result),"a",0);
7163         goto release ;
7164     }
7165
7166     reAdjustPreg(AOP(result));
7167     pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7168     pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
7169     pic14_emitcode("mov","c,ov");
7170     while (size--) {
7171         l = aopGet(AOP(result),offset,FALSE,FALSE);
7172         MOVA(l);
7173         pic14_emitcode("rrc","a");         
7174         aopPut(AOP(result),"a",offset--);
7175     }
7176     reAdjustPreg(AOP(result));
7177     pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7178     pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7179
7180 release:
7181     freeAsmop(left,NULL,ic,TRUE);
7182     freeAsmop(result,NULL,ic,TRUE);
7183 }
7184
7185 /*-----------------------------------------------------------------*/
7186 /* genRightShift - generate code for right shifting                */
7187 /*-----------------------------------------------------------------*/
7188 static void genRightShift (iCode *ic)
7189 {
7190     operand *right, *left, *result;
7191     sym_link *retype ;
7192     int size, offset;
7193     char *l;
7194     symbol *tlbl, *tlbl1 ;
7195
7196     /* if signed then we do it the hard way preserve the
7197     sign bit moving it inwards */
7198     retype = getSpec(operandType(IC_RESULT(ic)));
7199     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7200
7201     if (!SPEC_USIGN(retype)) {
7202         genSignedRightShift (ic);
7203         return ;
7204     }
7205
7206     /* signed & unsigned types are treated the same : i.e. the
7207     signed is NOT propagated inwards : quoting from the
7208     ANSI - standard : "for E1 >> E2, is equivalent to division
7209     by 2**E2 if unsigned or if it has a non-negative value,
7210     otherwise the result is implementation defined ", MY definition
7211     is that the sign does not get propagated */
7212
7213     right = IC_RIGHT(ic);
7214     left  = IC_LEFT(ic);
7215     result = IC_RESULT(ic);
7216
7217     aopOp(right,ic,FALSE);
7218
7219     /* if the shift count is known then do it 
7220     as efficiently as possible */
7221     if (AOP_TYPE(right) == AOP_LIT) {
7222         genRightShiftLiteral (left,right,result,ic, 0);
7223         return ;
7224     }
7225
7226     /* shift count is unknown then we have to form 
7227     a loop get the loop count in B : Note: we take
7228     only the lower order byte since shifting
7229     more that 32 bits make no sense anyway, ( the
7230     largest size of an object can be only 32 bits ) */  
7231
7232     pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
7233     pic14_emitcode("inc","b");
7234     aopOp(left,ic,FALSE);
7235     aopOp(result,ic,FALSE);
7236
7237     /* now move the left to the result if they are not the
7238     same */
7239     if (!pic14_sameRegs(AOP(left),AOP(result)) && 
7240         AOP_SIZE(result) > 1) {
7241
7242         size = AOP_SIZE(result);
7243         offset=0;
7244         while (size--) {
7245             l = aopGet(AOP(left),offset,FALSE,TRUE);
7246             if (*l == '@' && IS_AOP_PREG(result)) {
7247
7248                 pic14_emitcode("mov","a,%s",l);
7249                 aopPut(AOP(result),"a",offset);
7250             } else
7251                 aopPut(AOP(result),l,offset);
7252             offset++;
7253         }
7254     }
7255
7256     tlbl = newiTempLabel(NULL);
7257     tlbl1= newiTempLabel(NULL);
7258     size = AOP_SIZE(result);
7259     offset = size - 1;
7260
7261     /* if it is only one byte then */
7262     if (size == 1) {
7263 /*
7264         l = aopGet(AOP(left),0,FALSE,FALSE);
7265         MOVA(l);
7266         pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7267         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
7268         CLRC;
7269         pic14_emitcode("rrc","a");
7270         pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7271         pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7272         aopPut(AOP(result),"a",0);
7273 */
7274         tlbl = newiTempLabel(NULL);
7275         if (!pic14_sameRegs(AOP(left),AOP(result))) {
7276           emitpcode(POC_MOVFW,  popGet(AOP(left),0));
7277           emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7278         }
7279
7280         emitpcode(POC_COMFW,  popGet(AOP(right),0));
7281         emitpcode(POC_RLF,    popGet(AOP(result),0));
7282         emitpLabel(tlbl->key);
7283         emitpcode(POC_RRF,    popGet(AOP(result),0));
7284         emitpcode(POC_ADDLW,  popGetLit(1));
7285         emitSKPC;
7286         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7287
7288         goto release ;
7289     }
7290
7291     reAdjustPreg(AOP(result));
7292     pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7293     pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
7294     CLRC;
7295     while (size--) {
7296         l = aopGet(AOP(result),offset,FALSE,FALSE);
7297         MOVA(l);
7298         pic14_emitcode("rrc","a");         
7299         aopPut(AOP(result),"a",offset--);
7300     }
7301     reAdjustPreg(AOP(result));
7302
7303     pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7304     pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7305
7306 release:
7307     freeAsmop(left,NULL,ic,TRUE);
7308     freeAsmop (right,NULL,ic,TRUE);
7309     freeAsmop(result,NULL,ic,TRUE);
7310 }
7311
7312 /*-----------------------------------------------------------------*/
7313 /* genUnpackBits - generates code for unpacking bits               */
7314 /*-----------------------------------------------------------------*/
7315 static void genUnpackBits (operand *result, char *rname, int ptype)
7316 {    
7317     int shCnt ;
7318     int rlen = 0 ;
7319     sym_link *etype;
7320     int offset = 0 ;
7321
7322     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7323     etype = getSpec(operandType(result));
7324
7325     /* read the first byte  */
7326     switch (ptype) {
7327
7328     case POINTER:
7329     case IPOINTER:
7330         pic14_emitcode("mov","a,@%s",rname);
7331         break;
7332         
7333     case PPOINTER:
7334         pic14_emitcode("movx","a,@%s",rname);
7335         break;
7336         
7337     case FPOINTER:
7338         pic14_emitcode("movx","a,@dptr");
7339         break;
7340
7341     case CPOINTER:
7342         pic14_emitcode("clr","a");
7343         pic14_emitcode("movc","a","@a+dptr");
7344         break;
7345
7346     case GPOINTER:
7347         pic14_emitcode("lcall","__gptrget");
7348         break;
7349     }
7350
7351     /* if we have bitdisplacement then it fits   */
7352     /* into this byte completely or if length is */
7353     /* less than a byte                          */
7354     if ((shCnt = SPEC_BSTR(etype)) || 
7355         (SPEC_BLEN(etype) <= 8))  {
7356
7357         /* shift right acc */
7358         AccRsh(shCnt);
7359
7360         pic14_emitcode("anl","a,#0x%02x",
7361                  ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
7362         aopPut(AOP(result),"a",offset);
7363         return ;
7364     }
7365
7366     /* bit field did not fit in a byte  */
7367     rlen = SPEC_BLEN(etype) - 8;
7368     aopPut(AOP(result),"a",offset++);
7369
7370     while (1)  {
7371
7372         switch (ptype) {
7373         case POINTER:
7374         case IPOINTER:
7375             pic14_emitcode("inc","%s",rname);
7376             pic14_emitcode("mov","a,@%s",rname);
7377             break;
7378             
7379         case PPOINTER:
7380             pic14_emitcode("inc","%s",rname);
7381             pic14_emitcode("movx","a,@%s",rname);
7382             break;
7383
7384         case FPOINTER:
7385             pic14_emitcode("inc","dptr");
7386             pic14_emitcode("movx","a,@dptr");
7387             break;
7388             
7389         case CPOINTER:
7390             pic14_emitcode("clr","a");
7391             pic14_emitcode("inc","dptr");
7392             pic14_emitcode("movc","a","@a+dptr");
7393             break;
7394             
7395         case GPOINTER:
7396             pic14_emitcode("inc","dptr");
7397             pic14_emitcode("lcall","__gptrget");
7398             break;
7399         }
7400
7401         rlen -= 8;            
7402         /* if we are done */
7403         if ( rlen <= 0 )
7404             break ;
7405         
7406         aopPut(AOP(result),"a",offset++);
7407                               
7408     }
7409     
7410     if (rlen) {
7411         pic14_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
7412         aopPut(AOP(result),"a",offset);        
7413     }
7414     
7415     return ;
7416 }
7417
7418
7419 /*-----------------------------------------------------------------*/
7420 /* genDataPointerGet - generates code when ptr offset is known     */
7421 /*-----------------------------------------------------------------*/
7422 static void genDataPointerGet (operand *left, 
7423                                operand *result, 
7424                                iCode *ic)
7425 {
7426   int size , offset = 0;
7427
7428
7429   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7430
7431
7432   /* optimization - most of the time, left and result are the same
7433    * address, but different types. for the pic code, we could omit
7434    * the following
7435    */
7436
7437   aopOp(result,ic,TRUE);
7438
7439   emitpcode(POC_MOVFW, popGet(AOP(left),0));
7440
7441   size = AOP_SIZE(result);
7442
7443   while (size--) {
7444     emitpcode(POC_MOVWF, popGet(AOP(result),offset));
7445     offset++;
7446   }
7447
7448   freeAsmop(left,NULL,ic,TRUE);
7449   freeAsmop(result,NULL,ic,TRUE);
7450 }
7451
7452 /*-----------------------------------------------------------------*/
7453 /* genNearPointerGet - pic14_emitcode for near pointer fetch             */
7454 /*-----------------------------------------------------------------*/
7455 static void genNearPointerGet (operand *left, 
7456                                operand *result, 
7457                                iCode *ic)
7458 {
7459     asmop *aop = NULL;
7460     regs *preg = NULL ;
7461     char *rname ;
7462     sym_link *rtype, *retype;
7463     sym_link *ltype = operandType(left);    
7464     char buffer[80];
7465
7466     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7467
7468     rtype = operandType(result);
7469     retype= getSpec(rtype);
7470     
7471     aopOp(left,ic,FALSE);
7472     
7473     /* if left is rematerialisable and
7474        result is not bit variable type and
7475        the left is pointer to data space i.e
7476        lower 128 bytes of space */
7477     if (AOP_TYPE(left) == AOP_IMMD &&
7478         !IS_BITVAR(retype)         &&
7479         DCL_TYPE(ltype) == POINTER) {
7480         genDataPointerGet (left,result,ic);
7481         return ;
7482     }
7483     
7484     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7485
7486         /* if the value is already in a pointer register
7487        then don't need anything more */
7488     if (!AOP_INPREG(AOP(left))) {
7489         /* otherwise get a free pointer register */
7490     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7491         aop = newAsmop(0);
7492         preg = getFreePtr(ic,&aop,FALSE);
7493         pic14_emitcode("mov","%s,%s",
7494                 preg->name,
7495                 aopGet(AOP(left),0,FALSE,TRUE));
7496         rname = preg->name ;
7497     } else
7498         rname = aopGet(AOP(left),0,FALSE,FALSE);
7499     
7500     freeAsmop(left,NULL,ic,TRUE);
7501     aopOp (result,ic,FALSE);
7502     
7503       /* if bitfield then unpack the bits */
7504     if (IS_BITVAR(retype)) 
7505         genUnpackBits (result,rname,POINTER);
7506     else {
7507         /* we have can just get the values */
7508         int size = AOP_SIZE(result);
7509         int offset = 0 ;        
7510         
7511     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7512         while (size--) {
7513             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
7514
7515                 pic14_emitcode("mov","a,@%s",rname);
7516                 aopPut(AOP(result),"a",offset);
7517             } else {
7518                 sprintf(buffer,"@%s",rname);
7519                 aopPut(AOP(result),buffer,offset);
7520             }
7521             offset++ ;
7522             if (size)
7523                 pic14_emitcode("inc","%s",rname);
7524         }
7525     }
7526
7527     /* now some housekeeping stuff */
7528     if (aop) {
7529         /* we had to allocate for this iCode */
7530     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7531         freeAsmop(NULL,aop,ic,TRUE);
7532     } else { 
7533         /* we did not allocate which means left
7534            already in a pointer register, then
7535            if size > 0 && this could be used again
7536            we have to point it back to where it 
7537            belongs */
7538     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7539         if (AOP_SIZE(result) > 1 &&
7540             !OP_SYMBOL(left)->remat &&
7541             ( OP_SYMBOL(left)->liveTo > ic->seq ||
7542               ic->depth )) {
7543             int size = AOP_SIZE(result) - 1;
7544             while (size--)
7545                 pic14_emitcode("dec","%s",rname);
7546         }
7547     }
7548
7549     /* done */
7550     freeAsmop(result,NULL,ic,TRUE);
7551      
7552 }
7553
7554 /*-----------------------------------------------------------------*/
7555 /* genPagedPointerGet - pic14_emitcode for paged pointer fetch           */
7556 /*-----------------------------------------------------------------*/
7557 static void genPagedPointerGet (operand *left, 
7558                                operand *result, 
7559                                iCode *ic)
7560 {
7561     asmop *aop = NULL;
7562     regs *preg = NULL ;
7563     char *rname ;
7564     sym_link *rtype, *retype;    
7565
7566     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7567
7568     rtype = operandType(result);
7569     retype= getSpec(rtype);
7570     
7571     aopOp(left,ic,FALSE);
7572
7573   /* if the value is already in a pointer register
7574        then don't need anything more */
7575     if (!AOP_INPREG(AOP(left))) {
7576         /* otherwise get a free pointer register */
7577         aop = newAsmop(0);
7578         preg = getFreePtr(ic,&aop,FALSE);
7579         pic14_emitcode("mov","%s,%s",
7580                 preg->name,
7581                 aopGet(AOP(left),0,FALSE,TRUE));
7582         rname = preg->name ;
7583     } else
7584         rname = aopGet(AOP(left),0,FALSE,FALSE);
7585     
7586     freeAsmop(left,NULL,ic,TRUE);
7587     aopOp (result,ic,FALSE);
7588
7589     /* if bitfield then unpack the bits */
7590     if (IS_BITVAR(retype)) 
7591         genUnpackBits (result,rname,PPOINTER);
7592     else {
7593         /* we have can just get the values */
7594         int size = AOP_SIZE(result);
7595         int offset = 0 ;        
7596         
7597         while (size--) {
7598             
7599             pic14_emitcode("movx","a,@%s",rname);
7600             aopPut(AOP(result),"a",offset);
7601             
7602             offset++ ;
7603             
7604             if (size)
7605                 pic14_emitcode("inc","%s",rname);
7606         }
7607     }
7608
7609     /* now some housekeeping stuff */
7610     if (aop) {
7611         /* we had to allocate for this iCode */
7612         freeAsmop(NULL,aop,ic,TRUE);
7613     } else { 
7614         /* we did not allocate which means left
7615            already in a pointer register, then
7616            if size > 0 && this could be used again
7617            we have to point it back to where it 
7618            belongs */
7619         if (AOP_SIZE(result) > 1 &&
7620             !OP_SYMBOL(left)->remat &&
7621             ( OP_SYMBOL(left)->liveTo > ic->seq ||
7622               ic->depth )) {
7623             int size = AOP_SIZE(result) - 1;
7624             while (size--)
7625                 pic14_emitcode("dec","%s",rname);
7626         }
7627     }
7628
7629     /* done */
7630     freeAsmop(result,NULL,ic,TRUE);
7631     
7632         
7633 }
7634
7635 /*-----------------------------------------------------------------*/
7636 /* genFarPointerGet - gget value from far space                    */
7637 /*-----------------------------------------------------------------*/
7638 static void genFarPointerGet (operand *left,
7639                               operand *result, iCode *ic)
7640 {
7641     int size, offset ;
7642     sym_link *retype = getSpec(operandType(result));
7643
7644     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7645
7646     aopOp(left,ic,FALSE);
7647
7648     /* if the operand is already in dptr 
7649     then we do nothing else we move the value to dptr */
7650     if (AOP_TYPE(left) != AOP_STR) {
7651         /* if this is remateriazable */
7652         if (AOP_TYPE(left) == AOP_IMMD)
7653             pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
7654         else { /* we need to get it byte by byte */
7655             pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
7656             pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
7657             if (options.model == MODEL_FLAT24)
7658             {
7659                pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
7660             }
7661         }
7662     }
7663     /* so dptr know contains the address */
7664     freeAsmop(left,NULL,ic,TRUE);
7665     aopOp(result,ic,FALSE);
7666
7667     /* if bit then unpack */
7668     if (IS_BITVAR(retype)) 
7669         genUnpackBits(result,"dptr",FPOINTER);
7670     else {
7671         size = AOP_SIZE(result);
7672         offset = 0 ;
7673
7674         while (size--) {
7675             pic14_emitcode("movx","a,@dptr");
7676             aopPut(AOP(result),"a",offset++);
7677             if (size)
7678                 pic14_emitcode("inc","dptr");
7679         }
7680     }
7681
7682     freeAsmop(result,NULL,ic,TRUE);
7683 }
7684 #if 0
7685 /*-----------------------------------------------------------------*/
7686 /* genCodePointerGet - get value from code space                  */
7687 /*-----------------------------------------------------------------*/
7688 static void genCodePointerGet (operand *left,
7689                                 operand *result, iCode *ic)
7690 {
7691     int size, offset ;
7692     sym_link *retype = getSpec(operandType(result));
7693
7694     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7695
7696     aopOp(left,ic,FALSE);
7697
7698     /* if the operand is already in dptr 
7699     then we do nothing else we move the value to dptr */
7700     if (AOP_TYPE(left) != AOP_STR) {
7701         /* if this is remateriazable */
7702         if (AOP_TYPE(left) == AOP_IMMD)
7703             pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
7704         else { /* we need to get it byte by byte */
7705             pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
7706             pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
7707             if (options.model == MODEL_FLAT24)
7708             {
7709                pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
7710             }
7711         }
7712     }
7713     /* so dptr know contains the address */
7714     freeAsmop(left,NULL,ic,TRUE);
7715     aopOp(result,ic,FALSE);
7716
7717     /* if bit then unpack */
7718     if (IS_BITVAR(retype)) 
7719         genUnpackBits(result,"dptr",CPOINTER);
7720     else {
7721         size = AOP_SIZE(result);
7722         offset = 0 ;
7723
7724         while (size--) {
7725             pic14_emitcode("clr","a");
7726             pic14_emitcode("movc","a,@a+dptr");
7727             aopPut(AOP(result),"a",offset++);
7728             if (size)
7729                 pic14_emitcode("inc","dptr");
7730         }
7731     }
7732
7733     freeAsmop(result,NULL,ic,TRUE);
7734 }
7735 #endif
7736 /*-----------------------------------------------------------------*/
7737 /* genGenPointerGet - gget value from generic pointer space        */
7738 /*-----------------------------------------------------------------*/
7739 static void genGenPointerGet (operand *left,
7740                               operand *result, iCode *ic)
7741 {
7742   int size, offset ;
7743   sym_link *retype = getSpec(operandType(result));
7744
7745   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7746   aopOp(left,ic,FALSE);
7747   aopOp(result,ic,FALSE);
7748
7749
7750   DEBUGpic14_AopType(__LINE__,left,NULL,result);
7751
7752   /* if the operand is already in dptr 
7753      then we do nothing else we move the value to dptr */
7754   //  if (AOP_TYPE(left) != AOP_STR) {
7755     /* if this is remateriazable */
7756     if (AOP_TYPE(left) == AOP_IMMD) {
7757       pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
7758       pic14_emitcode("mov","b,#%d",pointerCode(retype));
7759     }
7760     else { /* we need to get it byte by byte */
7761
7762       emitpcode(POC_MOVFW,popGet(AOP(left),0));
7763       emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
7764
7765       size = AOP_SIZE(result);
7766       offset = 0 ;
7767
7768       while(size--) {
7769         emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
7770         emitpcode(POC_MOVWF,popGet(AOP(result),offset++));
7771         if(size)
7772           emitpcode(POC_INCF,popCopyReg(&pc_fsr));
7773       }
7774       goto release;
7775     }
7776     //}
7777   /* so dptr know contains the address */
7778
7779   /* if bit then unpack */
7780   //if (IS_BITVAR(retype)) 
7781   //  genUnpackBits(result,"dptr",GPOINTER);
7782
7783  release:
7784   freeAsmop(left,NULL,ic,TRUE);
7785   freeAsmop(result,NULL,ic,TRUE);
7786
7787 }
7788
7789 /*-----------------------------------------------------------------*/
7790 /* genConstPointerGet - get value from const generic pointer space */
7791 /*-----------------------------------------------------------------*/
7792 static void genConstPointerGet (operand *left,
7793                                 operand *result, iCode *ic)
7794 {
7795   sym_link *retype = getSpec(operandType(result));
7796   symbol *albl = newiTempLabel(NULL);
7797   symbol *blbl = newiTempLabel(NULL);
7798   PIC_OPCODE poc;
7799
7800   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7801   aopOp(left,ic,FALSE);
7802   aopOp(result,ic,FALSE);
7803
7804
7805   DEBUGpic14_AopType(__LINE__,left,NULL,result);
7806
7807   DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__);
7808
7809   emitpcode(POC_CALL,popGetLabel(albl->key));
7810   emitpcode(POC_GOTO,popGetLabel(blbl->key));
7811   emitpLabel(albl->key);
7812
7813   poc = ( (AOP_TYPE(left) == AOP_IMMD) ? POC_MOVLW : POC_MOVFW);
7814     
7815   emitpcode(poc,popGet(AOP(left),1));
7816   emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
7817   emitpcode(poc,popGet(AOP(left),0));
7818   emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
7819
7820   emitpLabel(blbl->key);
7821
7822   emitpcode(POC_MOVWF,popGet(AOP(result),0));
7823
7824
7825   freeAsmop(left,NULL,ic,TRUE);
7826   freeAsmop(result,NULL,ic,TRUE);
7827
7828 }
7829 /*-----------------------------------------------------------------*/
7830 /* genPointerGet - generate code for pointer get                   */
7831 /*-----------------------------------------------------------------*/
7832 static void genPointerGet (iCode *ic)
7833 {
7834     operand *left, *result ;
7835     sym_link *type, *etype;
7836     int p_type;
7837
7838     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7839
7840     left = IC_LEFT(ic);
7841     result = IC_RESULT(ic) ;
7842
7843     /* depending on the type of pointer we need to
7844     move it to the correct pointer register */
7845     type = operandType(left);
7846     etype = getSpec(type);
7847
7848     if (IS_PTR_CONST(type))
7849       DEBUGpic14_emitcode ("; ***","%d - const pointer",__LINE__);
7850
7851     /* if left is of type of pointer then it is simple */
7852     if (IS_PTR(type) && !IS_FUNC(type->next)) 
7853         p_type = DCL_TYPE(type);
7854     else {
7855         /* we have to go by the storage class */
7856         p_type = PTR_TYPE(SPEC_OCLS(etype));
7857
7858         DEBUGpic14_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
7859
7860         if (SPEC_OCLS(etype)->codesp ) {
7861           DEBUGpic14_emitcode ("; ***","%d - cpointer",__LINE__);
7862           //p_type = CPOINTER ; 
7863         }
7864         else
7865             if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
7866               DEBUGpic14_emitcode ("; ***","%d - fpointer",__LINE__);
7867                /*p_type = FPOINTER ;*/ 
7868             else
7869                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
7870                   DEBUGpic14_emitcode ("; ***","%d - ppointer",__LINE__);
7871 /*                  p_type = PPOINTER; */
7872                 else
7873                     if (SPEC_OCLS(etype) == idata )
7874                       DEBUGpic14_emitcode ("; ***","%d - ipointer",__LINE__);
7875 /*                      p_type = IPOINTER; */
7876                     else
7877                       DEBUGpic14_emitcode ("; ***","%d - pointer",__LINE__);
7878 /*                      p_type = POINTER ; */
7879     }
7880
7881     /* now that we have the pointer type we assign
7882     the pointer values */
7883     switch (p_type) {
7884
7885     case POINTER:       
7886     case IPOINTER:
7887         genNearPointerGet (left,result,ic);
7888         break;
7889
7890     case PPOINTER:
7891         genPagedPointerGet(left,result,ic);
7892         break;
7893
7894     case FPOINTER:
7895         genFarPointerGet (left,result,ic);
7896         break;
7897
7898     case CPOINTER:
7899         genConstPointerGet (left,result,ic);
7900         //pic14_emitcodePointerGet (left,result,ic);
7901         break;
7902
7903     case GPOINTER:
7904       if (IS_PTR_CONST(type))
7905         genConstPointerGet (left,result,ic);
7906       else
7907         genGenPointerGet (left,result,ic);
7908       break;
7909     }
7910
7911 }
7912
7913 /*-----------------------------------------------------------------*/
7914 /* genPackBits - generates code for packed bit storage             */
7915 /*-----------------------------------------------------------------*/
7916 static void genPackBits (sym_link    *etype ,
7917                          operand *right ,
7918                          char *rname, int p_type)
7919 {
7920     int shCount = 0 ;
7921     int offset = 0  ;
7922     int rLen = 0 ;
7923     int blen, bstr ;   
7924     char *l ;
7925
7926     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7927     blen = SPEC_BLEN(etype);
7928     bstr = SPEC_BSTR(etype);
7929
7930     l = aopGet(AOP(right),offset++,FALSE,FALSE);
7931     MOVA(l);   
7932
7933     /* if the bit lenth is less than or    */
7934     /* it exactly fits a byte then         */
7935     if (SPEC_BLEN(etype) <= 8 )  {
7936         shCount = SPEC_BSTR(etype) ;
7937
7938         /* shift left acc */
7939         AccLsh(shCount);
7940
7941         if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
7942
7943
7944             switch (p_type) {
7945                 case POINTER:
7946                     pic14_emitcode ("mov","b,a");
7947                     pic14_emitcode("mov","a,@%s",rname);
7948                     break;
7949
7950                 case FPOINTER:
7951                     pic14_emitcode ("mov","b,a");
7952                     pic14_emitcode("movx","a,@dptr");
7953                     break;
7954
7955                 case GPOINTER:
7956                     pic14_emitcode ("push","b");
7957                     pic14_emitcode ("push","acc");
7958                     pic14_emitcode ("lcall","__gptrget");
7959                     pic14_emitcode ("pop","b");
7960                     break;
7961             }
7962
7963             pic14_emitcode ("anl","a,#0x%02x",(unsigned char)
7964                       ((unsigned char)(0xFF << (blen+bstr)) | 
7965                        (unsigned char)(0xFF >> (8-bstr)) ) );
7966             pic14_emitcode ("orl","a,b");
7967             if (p_type == GPOINTER)
7968                 pic14_emitcode("pop","b");
7969         }
7970     }
7971
7972     switch (p_type) {
7973         case POINTER:
7974             pic14_emitcode("mov","@%s,a",rname);
7975             break;
7976
7977         case FPOINTER:
7978             pic14_emitcode("movx","@dptr,a");
7979             break;
7980
7981         case GPOINTER:
7982             DEBUGpic14_emitcode(";lcall","__gptrput");
7983             break;
7984     }
7985
7986     /* if we r done */
7987     if ( SPEC_BLEN(etype) <= 8 )
7988         return ;
7989
7990     pic14_emitcode("inc","%s",rname);
7991     rLen = SPEC_BLEN(etype) ;     
7992
7993     /* now generate for lengths greater than one byte */
7994     while (1) {
7995
7996         l = aopGet(AOP(right),offset++,FALSE,TRUE);
7997
7998         rLen -= 8 ;
7999         if (rLen <= 0 )
8000             break ;
8001
8002         switch (p_type) {
8003             case POINTER:
8004                 if (*l == '@') {
8005                     MOVA(l);
8006                     pic14_emitcode("mov","@%s,a",rname);
8007                 } else
8008                     pic14_emitcode("mov","@%s,%s",rname,l);
8009                 break;
8010
8011             case FPOINTER:
8012                 MOVA(l);
8013                 pic14_emitcode("movx","@dptr,a");
8014                 break;
8015
8016             case GPOINTER:
8017                 MOVA(l);
8018                 DEBUGpic14_emitcode(";lcall","__gptrput");
8019                 break;  
8020         }   
8021         pic14_emitcode ("inc","%s",rname);
8022     }
8023
8024     MOVA(l);
8025
8026     /* last last was not complete */
8027     if (rLen)   {
8028         /* save the byte & read byte */
8029         switch (p_type) {
8030             case POINTER:
8031                 pic14_emitcode ("mov","b,a");
8032                 pic14_emitcode("mov","a,@%s",rname);
8033                 break;
8034
8035             case FPOINTER:
8036                 pic14_emitcode ("mov","b,a");
8037                 pic14_emitcode("movx","a,@dptr");
8038                 break;
8039
8040             case GPOINTER:
8041                 pic14_emitcode ("push","b");
8042                 pic14_emitcode ("push","acc");
8043                 pic14_emitcode ("lcall","__gptrget");
8044                 pic14_emitcode ("pop","b");
8045                 break;
8046         }
8047
8048         pic14_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
8049         pic14_emitcode ("orl","a,b");
8050     }
8051
8052     if (p_type == GPOINTER)
8053         pic14_emitcode("pop","b");
8054
8055     switch (p_type) {
8056
8057     case POINTER:
8058         pic14_emitcode("mov","@%s,a",rname);
8059         break;
8060         
8061     case FPOINTER:
8062         pic14_emitcode("movx","@dptr,a");
8063         break;
8064         
8065     case GPOINTER:
8066         DEBUGpic14_emitcode(";lcall","__gptrput");
8067         break;                  
8068     }
8069 }
8070 /*-----------------------------------------------------------------*/
8071 /* genDataPointerSet - remat pointer to data space                 */
8072 /*-----------------------------------------------------------------*/
8073 static void genDataPointerSet(operand *right,
8074                               operand *result,
8075                               iCode *ic)
8076 {
8077     int size, offset = 0 ;
8078     char *l, buffer[256];
8079
8080     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8081     aopOp(right,ic,FALSE);
8082     
8083     l = aopGet(AOP(result),0,FALSE,TRUE);
8084     size = AOP_SIZE(right);
8085     // tsd, was l+1 - the underline `_' prefix was being stripped
8086     while (size--) {
8087         if (offset)
8088             sprintf(buffer,"(%s + %d)",l,offset);
8089         else
8090             sprintf(buffer,"%s",l);
8091
8092         if (AOP_TYPE(right) == AOP_LIT) {
8093           unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
8094           lit = lit >> (8*offset);
8095           if(lit&0xff) {
8096             pic14_emitcode("movlw","%d",lit);
8097             pic14_emitcode("movwf","%s",buffer);
8098
8099             emitpcode(POC_MOVLW, popGetLit(lit&0xff));
8100             emitpcode(POC_MOVWF, popRegFromString(buffer));
8101
8102           } else {
8103             pic14_emitcode("clrf","%s",buffer);
8104             //emitpcode(POC_CLRF, popRegFromString(buffer));
8105             emitpcode(POC_CLRF, popGet(AOP(result),offset));
8106           }
8107         }else {
8108           pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
8109           pic14_emitcode("movwf","%s",buffer);
8110
8111           emitpcode(POC_MOVFW, popGet(AOP(right),offset));
8112           emitpcode(POC_MOVWF, popRegFromString(buffer));
8113
8114         }
8115
8116         offset++;
8117     }
8118
8119     freeAsmop(right,NULL,ic,TRUE);
8120     freeAsmop(result,NULL,ic,TRUE);
8121 }
8122
8123 /*-----------------------------------------------------------------*/
8124 /* genNearPointerSet - pic14_emitcode for near pointer put                */
8125 /*-----------------------------------------------------------------*/
8126 static void genNearPointerSet (operand *right,
8127                                operand *result, 
8128                                iCode *ic)
8129 {
8130     asmop *aop = NULL;
8131     char *l;
8132     sym_link *retype;
8133     sym_link *ptype = operandType(result);
8134
8135     
8136     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8137     retype= getSpec(operandType(right));
8138
8139     aopOp(result,ic,FALSE);
8140     
8141     /* if the result is rematerializable &
8142        in data space & not a bit variable */
8143     if (AOP_TYPE(result) == AOP_IMMD &&
8144         DCL_TYPE(ptype) == POINTER   &&
8145         !IS_BITVAR(retype)) {
8146         genDataPointerSet (right,result,ic);
8147         return;
8148     }
8149
8150     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8151
8152     /* if the value is already in a pointer register
8153     then don't need anything more */
8154     if (!AOP_INPREG(AOP(result))) {
8155         /* otherwise get a free pointer register */
8156         //aop = newAsmop(0);
8157         //preg = getFreePtr(ic,&aop,FALSE);
8158         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8159         //pic14_emitcode("mov","%s,%s",
8160         //         preg->name,
8161         //         aopGet(AOP(result),0,FALSE,TRUE));
8162         //rname = preg->name ;
8163         pic14_emitcode("movwf","fsr");
8164     }// else
8165     //   rname = aopGet(AOP(result),0,FALSE,FALSE);
8166
8167     freeAsmop(result,NULL,ic,TRUE);
8168     aopOp (right,ic,FALSE);
8169     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8170
8171     /* if bitfield then unpack the bits */
8172     if (IS_BITVAR(retype)) {
8173       werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8174              "The programmer is obviously confused");
8175       //genPackBits (retype,right,rname,POINTER);
8176       exit(1);
8177     }
8178     else {
8179         /* we have can just get the values */
8180         int size = AOP_SIZE(right);
8181         int offset = 0 ;    
8182
8183     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8184         while (size--) {
8185             l = aopGet(AOP(right),offset,FALSE,TRUE);
8186             if (*l == '@' ) {
8187               //MOVA(l);
8188               //pic14_emitcode("mov","@%s,a",rname);
8189               pic14_emitcode("movf","indf,w ;1");
8190             } else {
8191
8192               if (AOP_TYPE(right) == AOP_LIT) {
8193                 unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
8194                 if(lit) {
8195                   pic14_emitcode("movlw","%s",l);
8196                   pic14_emitcode("movwf","indf ;2");
8197                 } else 
8198                   pic14_emitcode("clrf","indf");
8199               }else {
8200                 pic14_emitcode("movf","%s,w",l);
8201                 pic14_emitcode("movwf","indf ;2");
8202               }
8203             //pic14_emitcode("mov","@%s,%s",rname,l);
8204             }
8205             if (size)
8206               pic14_emitcode("incf","fsr,f ;3");
8207             //pic14_emitcode("inc","%s",rname);
8208             offset++;
8209         }
8210     }
8211
8212     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8213     /* now some housekeeping stuff */
8214     if (aop) {
8215         /* we had to allocate for this iCode */
8216         freeAsmop(NULL,aop,ic,TRUE);
8217     } else { 
8218         /* we did not allocate which means left
8219         already in a pointer register, then
8220         if size > 0 && this could be used again
8221         we have to point it back to where it 
8222         belongs */
8223     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8224         if (AOP_SIZE(right) > 1 &&
8225             !OP_SYMBOL(result)->remat &&
8226             ( OP_SYMBOL(result)->liveTo > ic->seq ||
8227               ic->depth )) {
8228             int size = AOP_SIZE(right) - 1;
8229             while (size--)
8230               pic14_emitcode("decf","fsr,f");
8231               //pic14_emitcode("dec","%s",rname);
8232         }
8233     }
8234
8235     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8236     /* done */
8237     freeAsmop(right,NULL,ic,TRUE);
8238
8239
8240 }
8241
8242 /*-----------------------------------------------------------------*/
8243 /* genPagedPointerSet - pic14_emitcode for Paged pointer put             */
8244 /*-----------------------------------------------------------------*/
8245 static void genPagedPointerSet (operand *right,
8246                                operand *result, 
8247                                iCode *ic)
8248 {
8249     asmop *aop = NULL;
8250     regs *preg = NULL ;
8251     char *rname , *l;
8252     sym_link *retype;
8253        
8254     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8255
8256     retype= getSpec(operandType(right));
8257     
8258     aopOp(result,ic,FALSE);
8259     
8260     /* if the value is already in a pointer register
8261        then don't need anything more */
8262     if (!AOP_INPREG(AOP(result))) {
8263         /* otherwise get a free pointer register */
8264         aop = newAsmop(0);
8265         preg = getFreePtr(ic,&aop,FALSE);
8266         pic14_emitcode("mov","%s,%s",
8267                 preg->name,
8268                 aopGet(AOP(result),0,FALSE,TRUE));
8269         rname = preg->name ;
8270     } else
8271         rname = aopGet(AOP(result),0,FALSE,FALSE);
8272     
8273     freeAsmop(result,NULL,ic,TRUE);
8274     aopOp (right,ic,FALSE);
8275
8276     /* if bitfield then unpack the bits */
8277     if (IS_BITVAR(retype)) 
8278         genPackBits (retype,right,rname,PPOINTER);
8279     else {
8280         /* we have can just get the values */
8281         int size = AOP_SIZE(right);
8282         int offset = 0 ;        
8283         
8284         while (size--) {
8285             l = aopGet(AOP(right),offset,FALSE,TRUE);
8286             
8287             MOVA(l);
8288             pic14_emitcode("movx","@%s,a",rname);
8289
8290             if (size)
8291                 pic14_emitcode("inc","%s",rname);
8292
8293             offset++;
8294         }
8295     }
8296     
8297     /* now some housekeeping stuff */
8298     if (aop) {
8299         /* we had to allocate for this iCode */
8300         freeAsmop(NULL,aop,ic,TRUE);
8301     } else { 
8302         /* we did not allocate which means left
8303            already in a pointer register, then
8304            if size > 0 && this could be used again
8305            we have to point it back to where it 
8306            belongs */
8307         if (AOP_SIZE(right) > 1 &&
8308             !OP_SYMBOL(result)->remat &&
8309             ( OP_SYMBOL(result)->liveTo > ic->seq ||
8310               ic->depth )) {
8311             int size = AOP_SIZE(right) - 1;
8312             while (size--)
8313                 pic14_emitcode("dec","%s",rname);
8314         }
8315     }
8316
8317     /* done */
8318     freeAsmop(right,NULL,ic,TRUE);
8319     
8320         
8321 }
8322
8323 /*-----------------------------------------------------------------*/
8324 /* genFarPointerSet - set value from far space                     */
8325 /*-----------------------------------------------------------------*/
8326 static void genFarPointerSet (operand *right,
8327                               operand *result, iCode *ic)
8328 {
8329     int size, offset ;
8330     sym_link *retype = getSpec(operandType(right));
8331
8332     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8333     aopOp(result,ic,FALSE);
8334
8335     /* if the operand is already in dptr 
8336     then we do nothing else we move the value to dptr */
8337     if (AOP_TYPE(result) != AOP_STR) {
8338         /* if this is remateriazable */
8339         if (AOP_TYPE(result) == AOP_IMMD)
8340             pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
8341         else { /* we need to get it byte by byte */
8342             pic14_emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
8343             pic14_emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
8344             if (options.model == MODEL_FLAT24)
8345             {
8346                pic14_emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
8347             }
8348         }
8349     }
8350     /* so dptr know contains the address */
8351     freeAsmop(result,NULL,ic,TRUE);
8352     aopOp(right,ic,FALSE);
8353
8354     /* if bit then unpack */
8355     if (IS_BITVAR(retype)) 
8356         genPackBits(retype,right,"dptr",FPOINTER);
8357     else {
8358         size = AOP_SIZE(right);
8359         offset = 0 ;
8360
8361         while (size--) {
8362             char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
8363             MOVA(l);
8364             pic14_emitcode("movx","@dptr,a");
8365             if (size)
8366                 pic14_emitcode("inc","dptr");
8367         }
8368     }
8369
8370     freeAsmop(right,NULL,ic,TRUE);
8371 }
8372
8373 /*-----------------------------------------------------------------*/
8374 /* genGenPointerSet - set value from generic pointer space         */
8375 /*-----------------------------------------------------------------*/
8376 static void genGenPointerSet (operand *right,
8377                               operand *result, iCode *ic)
8378 {
8379   int size, offset ;
8380   sym_link *retype = getSpec(operandType(right));
8381
8382   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8383
8384   aopOp(result,ic,FALSE);
8385   aopOp(right,ic,FALSE);
8386   size = AOP_SIZE(right);
8387
8388   DEBUGpic14_AopType(__LINE__,NULL,right,result);
8389
8390   /* if the operand is already in dptr 
8391      then we do nothing else we move the value to dptr */
8392   if (AOP_TYPE(result) != AOP_STR) {
8393     /* if this is remateriazable */
8394     if (AOP_TYPE(result) == AOP_IMMD) {
8395       pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
8396       pic14_emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
8397     }
8398     else { /* we need to get it byte by byte */
8399       //char *l = aopGet(AOP(result),0,FALSE,FALSE);
8400       size = AOP_SIZE(right);
8401       offset = 0 ;
8402
8403       /* hack hack! see if this the FSR. If so don't load W */
8404       if(AOP_TYPE(right) != AOP_ACC) {
8405
8406         emitpcode(POC_MOVFW,popGet(AOP(result),0));
8407         emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
8408
8409         //if(size==2)
8410         //emitpcode(POC_DECF,popCopyReg(&pc_fsr));
8411         //if(size==4) {
8412         //  emitpcode(POC_MOVLW,popGetLit(0xfd));
8413         //  emitpcode(POC_ADDWF,popCopyReg(&pc_fsr));
8414         //}
8415
8416         while(size--) {
8417           emitpcode(POC_MOVFW,popGet(AOP(right),offset++));
8418           emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
8419           
8420           if(size)
8421             emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8422         }
8423
8424
8425         goto release;
8426       } 
8427
8428       if(aopIdx(AOP(result),0) != 4) {
8429
8430         emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
8431         goto release;
8432       }
8433
8434       emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
8435       goto release;
8436
8437     }
8438   }
8439   /* so dptr know contains the address */
8440
8441
8442   /* if bit then unpack */
8443   if (IS_BITVAR(retype)) 
8444     genPackBits(retype,right,"dptr",GPOINTER);
8445   else {
8446     size = AOP_SIZE(right);
8447     offset = 0 ;
8448
8449     while (--size) {
8450       //char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
8451       if(size)
8452         pic14_emitcode("incf","fsr,f");
8453       pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset++,FALSE,FALSE));
8454       pic14_emitcode("movwf","indf");
8455       //MOVA(l);
8456       //DEBUGpic14_emitcode(";lcall","__gptrput");
8457       //if (size)
8458       //    pic14_emitcode("inc","dptr");
8459     }
8460   }
8461
8462  release:
8463   freeAsmop(right,NULL,ic,TRUE);
8464   freeAsmop(result,NULL,ic,TRUE);
8465 }
8466
8467 /*-----------------------------------------------------------------*/
8468 /* genPointerSet - stores the value into a pointer location        */
8469 /*-----------------------------------------------------------------*/
8470 static void genPointerSet (iCode *ic)
8471 {    
8472     operand *right, *result ;
8473     sym_link *type, *etype;
8474     int p_type;
8475
8476     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8477
8478     right = IC_RIGHT(ic);
8479     result = IC_RESULT(ic) ;
8480
8481     /* depending on the type of pointer we need to
8482     move it to the correct pointer register */
8483     type = operandType(result);
8484     etype = getSpec(type);
8485     /* if left is of type of pointer then it is simple */
8486     if (IS_PTR(type) && !IS_FUNC(type->next)) {
8487         p_type = DCL_TYPE(type);
8488     }
8489     else {
8490         /* we have to go by the storage class */
8491         p_type = PTR_TYPE(SPEC_OCLS(etype));
8492
8493 /*      if (SPEC_OCLS(etype)->codesp ) { */
8494 /*          p_type = CPOINTER ;  */
8495 /*      } */
8496 /*      else */
8497 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
8498 /*              p_type = FPOINTER ; */
8499 /*          else */
8500 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
8501 /*                  p_type = PPOINTER ; */
8502 /*              else */
8503 /*                  if (SPEC_OCLS(etype) == idata ) */
8504 /*                      p_type = IPOINTER ; */
8505 /*                  else */
8506 /*                      p_type = POINTER ; */
8507     }
8508
8509     /* now that we have the pointer type we assign
8510     the pointer values */
8511     switch (p_type) {
8512
8513     case POINTER:
8514     case IPOINTER:
8515         genNearPointerSet (right,result,ic);
8516         break;
8517
8518     case PPOINTER:
8519         genPagedPointerSet (right,result,ic);
8520         break;
8521
8522     case FPOINTER:
8523         genFarPointerSet (right,result,ic);
8524         break;
8525
8526     case GPOINTER:
8527         genGenPointerSet (right,result,ic);
8528         break;
8529
8530     default:
8531       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
8532               "genPointerSet: illegal pointer type");
8533     }
8534 }
8535
8536 /*-----------------------------------------------------------------*/
8537 /* genIfx - generate code for Ifx statement                        */
8538 /*-----------------------------------------------------------------*/
8539 static void genIfx (iCode *ic, iCode *popIc)
8540 {
8541   operand *cond = IC_COND(ic);
8542   int isbit =0;
8543
8544   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8545
8546   aopOp(cond,ic,FALSE);
8547
8548   /* get the value into acc */
8549   if (AOP_TYPE(cond) != AOP_CRY)
8550     pic14_toBoolean(cond);
8551   else
8552     isbit = 1;
8553   /* the result is now in the accumulator */
8554   freeAsmop(cond,NULL,ic,TRUE);
8555
8556   /* if there was something to be popped then do it */
8557   if (popIc)
8558     genIpop(popIc);
8559
8560   /* if the condition is  a bit variable */
8561   if (isbit && IS_ITEMP(cond) && 
8562       SPIL_LOC(cond)) {
8563     genIfxJump(ic,SPIL_LOC(cond)->rname);
8564     DEBUGpic14_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
8565   }
8566   else {
8567     if (isbit && !IS_ITEMP(cond))
8568       genIfxJump(ic,OP_SYMBOL(cond)->rname);
8569     else
8570       genIfxJump(ic,"a");
8571   }
8572   ic->generated = 1;
8573
8574 }
8575
8576 /*-----------------------------------------------------------------*/
8577 /* genAddrOf - generates code for address of                       */
8578 /*-----------------------------------------------------------------*/
8579 static void genAddrOf (iCode *ic)
8580 {
8581   //symbol *sym = OP_SYMBOL(IC_LEFT(ic));
8582   operand *right, *result, *left;
8583   //int size, offset ;
8584
8585   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8586
8587
8588   //aopOp(IC_RESULT(ic),ic,FALSE);
8589
8590   aopOp((left=IC_LEFT(ic)),ic,FALSE);
8591   aopOp((right=IC_RIGHT(ic)),ic,FALSE);
8592   aopOp((result=IC_RESULT(ic)),ic,TRUE);
8593
8594   DEBUGpic14_AopType(__LINE__,left,right,result);
8595
8596   emitpcode(POC_MOVLW, popGet(AOP(left),0));
8597   emitpcode(POC_MOVWF, popGet(AOP(result),0));
8598
8599 #if 0
8600   /* object not on stack then we need the name */
8601   size = AOP_SIZE(IC_RESULT(ic));
8602   offset = 0;
8603
8604   while (size--) {
8605     char s[SDCC_NAME_MAX];
8606     if (offset) 
8607       sprintf(s,"#(%s >> %d)",
8608               sym->rname,
8609               offset*8);
8610     else
8611       sprintf(s,"#%s",sym->rname);
8612     aopPut(AOP(IC_RESULT(ic)),s,offset++);
8613   }
8614 #endif
8615
8616
8617   //  freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8618   freeAsmop(left,NULL,ic,FALSE);
8619   freeAsmop(result,NULL,ic,TRUE);
8620
8621 }
8622
8623 #if 0
8624 /*-----------------------------------------------------------------*/
8625 /* genFarFarAssign - assignment when both are in far space         */
8626 /*-----------------------------------------------------------------*/
8627 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
8628 {
8629     int size = AOP_SIZE(right);
8630     int offset = 0;
8631     char *l ;
8632     /* first push the right side on to the stack */
8633     while (size--) {
8634         l = aopGet(AOP(right),offset++,FALSE,FALSE);
8635         MOVA(l);
8636         pic14_emitcode ("push","acc");
8637     }
8638     
8639     freeAsmop(right,NULL,ic,FALSE);
8640     /* now assign DPTR to result */
8641     aopOp(result,ic,FALSE);
8642     size = AOP_SIZE(result);
8643     while (size--) {
8644         pic14_emitcode ("pop","acc");
8645         aopPut(AOP(result),"a",--offset);
8646     }
8647     freeAsmop(result,NULL,ic,FALSE);
8648         
8649 }
8650 #endif
8651
8652 /*-----------------------------------------------------------------*/
8653 /* genAssign - generate code for assignment                        */
8654 /*-----------------------------------------------------------------*/
8655 static void genAssign (iCode *ic)
8656 {
8657   operand *result, *right;
8658   int size, offset,know_W;
8659   unsigned long lit = 0L;
8660
8661   result = IC_RESULT(ic);
8662   right  = IC_RIGHT(ic) ;
8663
8664   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8665
8666   /* if they are the same */
8667   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
8668     return ;
8669
8670   aopOp(right,ic,FALSE);
8671   aopOp(result,ic,TRUE);
8672
8673   DEBUGpic14_AopType(__LINE__,NULL,right,result);
8674
8675   /* if they are the same registers */
8676   if (pic14_sameRegs(AOP(right),AOP(result)))
8677     goto release;
8678
8679   /* if the result is a bit */
8680   if (AOP_TYPE(result) == AOP_CRY) {
8681
8682     /* if the right size is a literal then
8683        we know what the value is */
8684     if (AOP_TYPE(right) == AOP_LIT) {
8685           
8686       emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
8687                   popGet(AOP(result),0));
8688
8689       if (((int) operandLitValue(right))) 
8690         pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
8691                        AOP(result)->aopu.aop_dir,
8692                        AOP(result)->aopu.aop_dir);
8693       else
8694         pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
8695                        AOP(result)->aopu.aop_dir,
8696                        AOP(result)->aopu.aop_dir);
8697       goto release;
8698     }
8699
8700     /* the right is also a bit variable */
8701     if (AOP_TYPE(right) == AOP_CRY) {
8702       emitpcode(POC_BCF,    popGet(AOP(result),0));
8703       emitpcode(POC_BTFSC,  popGet(AOP(right),0));
8704       emitpcode(POC_BSF,    popGet(AOP(result),0));
8705
8706       pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
8707                      AOP(result)->aopu.aop_dir,
8708                      AOP(result)->aopu.aop_dir);
8709       pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
8710                      AOP(right)->aopu.aop_dir,
8711                      AOP(right)->aopu.aop_dir);
8712       pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
8713                      AOP(result)->aopu.aop_dir,
8714                      AOP(result)->aopu.aop_dir);
8715       goto release ;
8716     }
8717
8718     /* we need to or */
8719     emitpcode(POC_BCF,    popGet(AOP(result),0));
8720     pic14_toBoolean(right);
8721     emitSKPZ;
8722     emitpcode(POC_BSF,    popGet(AOP(result),0));
8723     //aopPut(AOP(result),"a",0);
8724     goto release ;
8725   }
8726
8727   /* bit variables done */
8728   /* general case */
8729   size = AOP_SIZE(result);
8730   offset = 0 ;
8731   if(AOP_TYPE(right) == AOP_LIT)
8732     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
8733
8734   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
8735   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8736     if(aopIdx(AOP(result),0) == 4) {
8737   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8738       emitpcode(POC_MOVFW, popGet(AOP(right),offset));
8739       emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8740       goto release;
8741     } else
8742       DEBUGpic14_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
8743   }
8744
8745   know_W=-1;
8746   while (size--) {
8747   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8748     if(AOP_TYPE(right) == AOP_LIT) {
8749       if(lit&0xff) {
8750         if(know_W != (lit&0xff))
8751           emitpcode(POC_MOVLW,popGetLit(lit&0xff));
8752         know_W = lit&0xff;
8753         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8754       } else
8755         emitpcode(POC_CLRF, popGet(AOP(result),offset));
8756
8757       lit >>= 8;
8758
8759     } else if (AOP_TYPE(right) == AOP_CRY) {
8760       emitpcode(POC_CLRF, popGet(AOP(result),offset));
8761       if(offset == 0) {
8762         emitpcode(POC_BTFSS, popGet(AOP(right),0));
8763         emitpcode(POC_INCF, popGet(AOP(result),0));
8764       }
8765     } else {
8766   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8767       emitpcode(POC_MOVFW, popGet(AOP(right),offset));
8768       emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8769     }
8770             
8771     offset++;
8772   }
8773
8774     
8775  release:
8776   freeAsmop (right,NULL,ic,FALSE);
8777   freeAsmop (result,NULL,ic,TRUE);
8778 }   
8779
8780 /*-----------------------------------------------------------------*/
8781 /* genJumpTab - genrates code for jump table                       */
8782 /*-----------------------------------------------------------------*/
8783 static void genJumpTab (iCode *ic)
8784 {
8785     symbol *jtab;
8786     char *l;
8787
8788     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8789
8790     aopOp(IC_JTCOND(ic),ic,FALSE);
8791     /* get the condition into accumulator */
8792     l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
8793     MOVA(l);
8794     /* multiply by three */
8795     pic14_emitcode("add","a,acc");
8796     pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
8797
8798     jtab = newiTempLabel(NULL);
8799     pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
8800     pic14_emitcode("jmp","@a+dptr");
8801     pic14_emitcode("","%05d_DS_:",jtab->key+100);
8802
8803     emitpcode(POC_MOVLW, popGetLabel(jtab->key));
8804     emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
8805     emitSKPNC;
8806     emitpcode(POC_INCF, popCopyReg(&pc_pclath));
8807     emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
8808     emitpLabel(jtab->key);
8809
8810     freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
8811
8812     /* now generate the jump labels */
8813     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
8814          jtab = setNextItem(IC_JTLABELS(ic))) {
8815         pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
8816         emitpcode(POC_GOTO,popGetLabel(jtab->key));
8817         
8818     }
8819
8820 }
8821
8822 /*-----------------------------------------------------------------*/
8823 /* genMixedOperation - gen code for operators between mixed types  */
8824 /*-----------------------------------------------------------------*/
8825 /*
8826   TSD - Written for the PIC port - but this unfortunately is buggy.
8827   This routine is good in that it is able to efficiently promote 
8828   types to different (larger) sizes. Unfortunately, the temporary
8829   variables that are optimized out by this routine are sometimes
8830   used in other places. So until I know how to really parse the 
8831   iCode tree, I'm going to not be using this routine :(.
8832 */
8833 static int genMixedOperation (iCode *ic)
8834 {
8835 #if 0
8836   operand *result = IC_RESULT(ic);
8837   sym_link *ctype = operandType(IC_LEFT(ic));
8838   operand *right = IC_RIGHT(ic);
8839   int ret = 0;
8840   int big,small;
8841   int offset;
8842
8843   iCode *nextic;
8844   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
8845
8846   pic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
8847
8848   nextic = ic->next;
8849   if(!nextic)
8850     return 0;
8851
8852   nextright = IC_RIGHT(nextic);
8853   nextleft  = IC_LEFT(nextic);
8854   nextresult = IC_RESULT(nextic);
8855
8856   aopOp(right,ic,FALSE);
8857   aopOp(result,ic,FALSE);
8858   aopOp(nextright,  nextic, FALSE);
8859   aopOp(nextleft,   nextic, FALSE);
8860   aopOp(nextresult, nextic, FALSE);
8861
8862   if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
8863
8864     operand *t = right;
8865     right = nextright;
8866     nextright = t; 
8867
8868     pic14_emitcode(";remove right +","");
8869
8870   } else   if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
8871 /*
8872     operand *t = right;
8873     right = nextleft;
8874     nextleft = t; 
8875 */
8876     pic14_emitcode(";remove left +","");
8877   } else
8878     return 0;
8879
8880   big = AOP_SIZE(nextleft);
8881   small = AOP_SIZE(nextright);
8882
8883   switch(nextic->op) {
8884
8885   case '+':
8886     pic14_emitcode(";optimize a +","");
8887     /* if unsigned or not an integral type */
8888     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
8889       pic14_emitcode(";add a bit to something","");
8890     } else {
8891
8892       pic14_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
8893
8894       if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
8895         pic14_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
8896         pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
8897       } else
8898         pic14_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
8899
8900       offset = 0;
8901       while(--big) {
8902
8903         offset++;
8904
8905         if(--small) {
8906           if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
8907             pic14_emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8908             pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
8909           }
8910
8911           pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8912           emitSKPNC;
8913           pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
8914                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
8915                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
8916           pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8917           pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
8918
8919         } else {
8920           pic14_emitcode("rlf","known_zero,w");
8921
8922           /*
8923             if right is signed
8924               btfsc  right,7
8925                addlw ff
8926           */
8927           if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
8928             pic14_emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8929             pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
8930           } else {
8931             pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
8932           }
8933         }
8934       }
8935       ret = 1;
8936     }
8937   }
8938   ret = 1;
8939
8940 release:
8941   freeAsmop(right,NULL,ic,TRUE);
8942   freeAsmop(result,NULL,ic,TRUE);
8943   freeAsmop(nextright,NULL,ic,TRUE);
8944   freeAsmop(nextleft,NULL,ic,TRUE);
8945   if(ret)
8946     nextic->generated = 1;
8947
8948   return ret;
8949 #else
8950   return 0;
8951 #endif
8952 }
8953 /*-----------------------------------------------------------------*/
8954 /* genCast - gen code for casting                                  */
8955 /*-----------------------------------------------------------------*/
8956 static void genCast (iCode *ic)
8957 {
8958     operand *result = IC_RESULT(ic);
8959     sym_link *ctype = operandType(IC_LEFT(ic));
8960     sym_link *rtype = operandType(IC_RIGHT(ic));
8961     operand *right = IC_RIGHT(ic);
8962     int size, offset ;
8963
8964     DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
8965     /* if they are equivalent then do nothing */
8966     if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
8967         return ;
8968
8969     aopOp(right,ic,FALSE) ;
8970     aopOp(result,ic,FALSE);
8971
8972     DEBUGpic14_AopType(__LINE__,NULL,right,result);
8973
8974     /* if the result is a bit */
8975     if (AOP_TYPE(result) == AOP_CRY) {
8976         /* if the right size is a literal then
8977         we know what the value is */
8978       DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
8979         if (AOP_TYPE(right) == AOP_LIT) {
8980
8981           emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
8982                       popGet(AOP(result),0));
8983
8984             if (((int) operandLitValue(right))) 
8985               pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
8986                        AOP(result)->aopu.aop_dir,
8987                        AOP(result)->aopu.aop_dir);
8988             else
8989               pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
8990                        AOP(result)->aopu.aop_dir,
8991                        AOP(result)->aopu.aop_dir);
8992
8993             goto release;
8994         }
8995
8996         /* the right is also a bit variable */
8997         if (AOP_TYPE(right) == AOP_CRY) {
8998
8999           emitCLRC;
9000           emitpcode(POC_BTFSC,  popGet(AOP(right),0));
9001
9002           pic14_emitcode("clrc","");
9003           pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
9004                    AOP(right)->aopu.aop_dir,
9005                    AOP(right)->aopu.aop_dir);
9006             aopPut(AOP(result),"c",0);
9007             goto release ;
9008         }
9009
9010         /* we need to or */
9011         if (AOP_TYPE(right) == AOP_REG) {
9012           emitpcode(POC_BCF,    popGet(AOP(result),0));
9013           emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
9014           emitpcode(POC_BSF,    popGet(AOP(result),0));
9015         }
9016         pic14_toBoolean(right);
9017         aopPut(AOP(result),"a",0);
9018         goto release ;
9019     }
9020
9021     if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
9022       int offset = 1;
9023       size = AOP_SIZE(result);
9024
9025       DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9026
9027       emitpcode(POC_CLRF,   popGet(AOP(result),0));
9028       emitpcode(POC_BTFSC,  popGet(AOP(right),0));
9029       emitpcode(POC_INCF,   popGet(AOP(result),0));
9030
9031       while (size--)
9032         emitpcode(POC_CLRF,   popGet(AOP(result),offset++));
9033
9034       goto release;
9035     }
9036
9037     /* if they are the same size : or less */
9038     if (AOP_SIZE(result) <= AOP_SIZE(right)) {
9039
9040         /* if they are in the same place */
9041       if (pic14_sameRegs(AOP(right),AOP(result)))
9042         goto release;
9043
9044       DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9045       if (IS_PTR_CONST(rtype))
9046         DEBUGpic14_emitcode ("; ***","%d - right is const pointer",__LINE__);
9047       if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
9048         DEBUGpic14_emitcode ("; ***","%d - result is const pointer",__LINE__);
9049
9050         /* if they in different places then copy */
9051         size = AOP_SIZE(result);
9052         offset = 0 ;
9053         while (size--) {
9054           if(AOP_TYPE(right) == AOP_IMMD)
9055             emitpcode(POC_MOVLW, popGetImmd(AOP(right)->aopu.aop_dir,offset));
9056           else
9057             emitpcode(POC_MOVFW,   popGet(AOP(right),offset));
9058           emitpcode(POC_MOVWF,   popGet(AOP(result),offset));
9059
9060           //aopPut(AOP(result),
9061           // aopGet(AOP(right),offset,FALSE,FALSE),
9062           // offset);
9063
9064           offset++;
9065         }
9066         goto release;
9067     }
9068
9069
9070     /* if the result is of type pointer */
9071     if (IS_PTR(ctype)) {
9072
9073         int p_type;
9074         sym_link *type = operandType(right);
9075         sym_link *etype = getSpec(type);
9076       DEBUGpic14_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
9077
9078         /* pointer to generic pointer */
9079         if (IS_GENPTR(ctype)) {
9080             char *l = zero;
9081             
9082             if (IS_PTR(type)) 
9083                 p_type = DCL_TYPE(type);
9084             else {
9085                 /* we have to go by the storage class */
9086                 p_type = PTR_TYPE(SPEC_OCLS(etype));
9087
9088 /*              if (SPEC_OCLS(etype)->codesp )  */
9089 /*                  p_type = CPOINTER ;  */
9090 /*              else */
9091 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9092 /*                      p_type = FPOINTER ; */
9093 /*                  else */
9094 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9095 /*                          p_type = PPOINTER; */
9096 /*                      else */
9097 /*                          if (SPEC_OCLS(etype) == idata ) */
9098 /*                              p_type = IPOINTER ; */
9099 /*                          else */
9100 /*                              p_type = POINTER ; */
9101             }
9102                 
9103             /* the first two bytes are known */
9104             size = GPTRSIZE - 1; 
9105             offset = 0 ;
9106             while (size--) {
9107               if(offset < AOP_SIZE(right))
9108                 aopPut(AOP(result),
9109                        aopGet(AOP(right),offset,FALSE,FALSE),
9110                        offset);
9111               else
9112                 emitpcode(POC_CLRF,popGet(AOP(result),offset));
9113               offset++;
9114             }
9115             /* the last byte depending on type */
9116             switch (p_type) {
9117             case IPOINTER:
9118             case POINTER:
9119                 emitpcode(POC_CLRF,popGet(AOP(result),GPTRSIZE - 1));
9120                 break;
9121             case FPOINTER:
9122               pic14_emitcode(";BUG!? ","%d",__LINE__);
9123                 l = one;
9124                 break;
9125             case CPOINTER:
9126               pic14_emitcode(";BUG!? ","%d",__LINE__);
9127                 l = "#0x02";
9128                 break;                          
9129             case PPOINTER:
9130               pic14_emitcode(";BUG!? ","%d",__LINE__);
9131                 l = "#0x03";
9132                 break;
9133                 
9134             default:
9135                 /* this should never happen */
9136                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
9137                        "got unknown pointer type");
9138                 exit(1);
9139             }
9140             //aopPut(AOP(result),l, GPTRSIZE - 1);          
9141             goto release ;
9142         }
9143         
9144         /* just copy the pointers */
9145         size = AOP_SIZE(result);
9146         offset = 0 ;
9147         while (size--) {
9148             aopPut(AOP(result),
9149                    aopGet(AOP(right),offset,FALSE,FALSE),
9150                    offset);
9151             offset++;
9152         }
9153         goto release ;
9154     }
9155     
9156
9157
9158     /* so we now know that the size of destination is greater
9159     than the size of the source.
9160     Now, if the next iCode is an operator then we might be
9161     able to optimize the operation without performing a cast.
9162     */
9163     if(genMixedOperation(ic))
9164       goto release;
9165
9166     DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9167     
9168     /* we move to result for the size of source */
9169     size = AOP_SIZE(right);
9170     offset = 0 ;
9171     while (size--) {
9172       emitpcode(POC_MOVFW,   popGet(AOP(right),offset));
9173       emitpcode(POC_MOVWF,   popGet(AOP(result),offset));
9174       offset++;
9175     }
9176
9177     /* now depending on the sign of the destination */
9178     size = AOP_SIZE(result) - AOP_SIZE(right);
9179     /* if unsigned or not an integral type */
9180     if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
9181       while (size--)
9182         emitpcode(POC_CLRF,   popGet(AOP(result),offset++));
9183     } else {
9184       /* we need to extend the sign :{ */
9185
9186       if(size == 1) {
9187         /* Save one instruction of casting char to int */
9188         emitpcode(POC_CLRF,   popGet(AOP(result),offset));
9189         emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
9190         emitpcode(POC_DECF,   popGet(AOP(result),offset));
9191       } else {
9192         emitpcodeNULLop(POC_CLRW);
9193
9194         if(offset)
9195           emitpcode(POC_BTFSC,   newpCodeOpBit(aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
9196         else
9197           emitpcode(POC_BTFSC,   newpCodeOpBit(aopGet(AOP(right),offset,FALSE,FALSE),7,0));
9198         
9199         emitpcode(POC_MOVLW,   popGetLit(0xff));
9200
9201         while (size--)
9202           emitpcode(POC_MOVWF,   popGet(AOP(result),offset++));
9203       }
9204     }
9205
9206 release:
9207     freeAsmop(right,NULL,ic,TRUE);
9208     freeAsmop(result,NULL,ic,TRUE);
9209
9210 }
9211
9212 /*-----------------------------------------------------------------*/
9213 /* genDjnz - generate decrement & jump if not zero instrucion      */
9214 /*-----------------------------------------------------------------*/
9215 static int genDjnz (iCode *ic, iCode *ifx)
9216 {
9217     symbol *lbl, *lbl1;
9218     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9219
9220     if (!ifx)
9221         return 0;
9222     
9223     /* if the if condition has a false label
9224        then we cannot save */
9225     if (IC_FALSE(ifx))
9226         return 0;
9227
9228     /* if the minus is not of the form 
9229        a = a - 1 */
9230     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
9231         !IS_OP_LITERAL(IC_RIGHT(ic)))
9232         return 0;
9233
9234     if (operandLitValue(IC_RIGHT(ic)) != 1)
9235         return 0;
9236
9237     /* if the size of this greater than one then no
9238        saving */
9239     if (getSize(operandType(IC_RESULT(ic))) > 1)
9240         return 0;
9241
9242     /* otherwise we can save BIG */
9243     lbl = newiTempLabel(NULL);
9244     lbl1= newiTempLabel(NULL);
9245
9246     aopOp(IC_RESULT(ic),ic,FALSE);
9247     
9248     if (IS_AOP_PREG(IC_RESULT(ic))) {
9249         pic14_emitcode("dec","%s",
9250                  aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
9251         pic14_emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
9252         pic14_emitcode("jnz","%05d_DS_",lbl->key+100);
9253     } else {    
9254
9255
9256       emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0));
9257       emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
9258
9259       pic14_emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
9260       pic14_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
9261
9262     }
9263 /*     pic14_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
9264 /*     pic14_emitcode ("","%05d_DS_:",lbl->key+100); */
9265 /*     pic14_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
9266 /*     pic14_emitcode ("","%05d_DS_:",lbl1->key+100); */
9267
9268     
9269     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
9270     ifx->generated = 1;
9271     return 1;
9272 }
9273
9274 /*-----------------------------------------------------------------*/
9275 /* genReceive - generate code for a receive iCode                  */
9276 /*-----------------------------------------------------------------*/
9277 static void genReceive (iCode *ic)
9278 {    
9279   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9280
9281   if (isOperandInFarSpace(IC_RESULT(ic)) && 
9282       ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
9283         IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
9284
9285     int size = getSize(operandType(IC_RESULT(ic)));
9286     int offset =  fReturnSizePic - size;
9287     while (size--) {
9288       pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
9289                                     fReturn[fReturnSizePic - offset - 1] : "acc"));
9290       offset++;
9291     }
9292     aopOp(IC_RESULT(ic),ic,FALSE);  
9293     size = AOP_SIZE(IC_RESULT(ic));
9294     offset = 0;
9295     while (size--) {
9296       pic14_emitcode ("pop","acc");
9297       aopPut (AOP(IC_RESULT(ic)),"a",offset++);
9298     }
9299         
9300   } else {
9301     _G.accInUse++;
9302     aopOp(IC_RESULT(ic),ic,FALSE);  
9303     _G.accInUse--;
9304     assignResultValue(IC_RESULT(ic));   
9305   }
9306
9307   freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
9308 }
9309
9310 /*-----------------------------------------------------------------*/
9311 /* genpic14Code - generate code for pic14 based controllers        */
9312 /*-----------------------------------------------------------------*/
9313 /*
9314  * At this point, ralloc.c has gone through the iCode and attempted
9315  * to optimize in a way suitable for a PIC. Now we've got to generate
9316  * PIC instructions that correspond to the iCode.
9317  *
9318  * Once the instructions are generated, we'll pass through both the
9319  * peep hole optimizer and the pCode optimizer.
9320  *-----------------------------------------------------------------*/
9321
9322 void genpic14Code (iCode *lic)
9323 {
9324     iCode *ic;
9325     int cln = 0;
9326
9327     lineHead = lineCurr = NULL;
9328
9329     pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
9330     addpBlock(pb);
9331
9332     /* if debug information required */
9333     if (options.debug && currFunc) { 
9334       if (currFunc) {
9335         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
9336         _G.debugLine = 1;
9337         if (IS_STATIC(currFunc->etype)) {
9338           pic14_emitcode("",";F%s$%s$0$0     %d",moduleName,currFunc->name,__LINE__);
9339           //addpCode2pBlock(pb,newpCodeLabel(moduleName,currFunc->name));
9340         } else {
9341           pic14_emitcode("",";G$%s$0$0   %d",currFunc->name,__LINE__);
9342           //addpCode2pBlock(pb,newpCodeLabel(NULL,currFunc->name));
9343         }
9344         _G.debugLine = 0;
9345       }
9346     }
9347
9348
9349     for (ic = lic ; ic ; ic = ic->next ) {
9350
9351       DEBUGpic14_emitcode(";ic","");
9352         if ( cln != ic->lineno ) {
9353             if ( options.debug ) {
9354                 _G.debugLine = 1;
9355                 pic14_emitcode("",";C$%s$%d$%d$%d ==.",
9356                          FileBaseName(ic->filename),ic->lineno,
9357                          ic->level,ic->block);
9358                 _G.debugLine = 0;
9359             }
9360             pic14_emitcode("#CSRC","%s %d",FileBaseName(ic->filename),ic->lineno);
9361             cln = ic->lineno ;
9362         }
9363         /* if the result is marked as
9364            spilt and rematerializable or code for
9365            this has already been generated then
9366            do nothing */
9367         if (resultRemat(ic) || ic->generated ) 
9368             continue ;
9369         
9370         /* depending on the operation */
9371         switch (ic->op) {
9372         case '!' :
9373             genNot(ic);
9374             break;
9375             
9376         case '~' :
9377             genCpl(ic);
9378             break;
9379             
9380         case UNARYMINUS:
9381             genUminus (ic);
9382             break;
9383             
9384         case IPUSH:
9385             genIpush (ic);
9386             break;
9387             
9388         case IPOP:
9389             /* IPOP happens only when trying to restore a 
9390                spilt live range, if there is an ifx statement
9391                following this pop then the if statement might
9392                be using some of the registers being popped which
9393                would destory the contents of the register so
9394                we need to check for this condition and handle it */
9395             if (ic->next            && 
9396                 ic->next->op == IFX &&
9397                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
9398                 genIfx (ic->next,ic);
9399             else
9400                 genIpop (ic);
9401             break; 
9402             
9403         case CALL:
9404             genCall (ic);
9405             break;
9406             
9407         case PCALL:
9408             genPcall (ic);
9409             break;
9410             
9411         case FUNCTION:
9412             genFunction (ic);
9413             break;
9414             
9415         case ENDFUNCTION:
9416             genEndFunction (ic);
9417             break;
9418             
9419         case RETURN:
9420             genRet (ic);
9421             break;
9422             
9423         case LABEL:
9424             genLabel (ic);
9425             break;
9426             
9427         case GOTO:
9428             genGoto (ic);
9429             break;
9430             
9431         case '+' :
9432             genPlus (ic) ;
9433             break;
9434             
9435         case '-' :
9436             if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
9437                 genMinus (ic);
9438             break;
9439             
9440         case '*' :
9441             genMult (ic);
9442             break;
9443             
9444         case '/' :
9445             genDiv (ic) ;
9446             break;
9447             
9448         case '%' :
9449             genMod (ic);
9450             break;
9451             
9452         case '>' :
9453             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
9454             break;
9455             
9456         case '<' :
9457             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
9458             break;
9459             
9460         case LE_OP:
9461         case GE_OP:
9462         case NE_OP:
9463             
9464             /* note these two are xlated by algebraic equivalence
9465                during parsing SDCC.y */
9466             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
9467                    "got '>=' or '<=' shouldn't have come here");
9468             break;      
9469             
9470         case EQ_OP:
9471             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
9472             break;          
9473             
9474         case AND_OP:
9475             genAndOp (ic);
9476             break;
9477             
9478         case OR_OP:
9479             genOrOp (ic);
9480             break;
9481             
9482         case '^' :
9483             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
9484             break;
9485             
9486         case '|' :
9487                 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
9488             break;
9489             
9490         case BITWISEAND:
9491             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
9492             break;
9493             
9494         case INLINEASM:
9495             genInline (ic);
9496             break;
9497             
9498         case RRC:
9499             genRRC (ic);
9500             break;
9501             
9502         case RLC:
9503             genRLC (ic);
9504             break;
9505             
9506         case GETHBIT:
9507             genGetHbit (ic);
9508             break;
9509             
9510         case LEFT_OP:
9511             genLeftShift (ic);
9512             break;
9513             
9514         case RIGHT_OP:
9515             genRightShift (ic);
9516             break;
9517             
9518         case GET_VALUE_AT_ADDRESS:
9519             genPointerGet(ic);
9520             break;
9521             
9522         case '=' :
9523             if (POINTER_SET(ic))
9524                 genPointerSet(ic);
9525             else
9526                 genAssign(ic);
9527             break;
9528             
9529         case IFX:
9530             genIfx (ic,NULL);
9531             break;
9532             
9533         case ADDRESS_OF:
9534             genAddrOf (ic);
9535             break;
9536             
9537         case JUMPTABLE:
9538             genJumpTab (ic);
9539             break;
9540             
9541         case CAST:
9542             genCast (ic);
9543             break;
9544             
9545         case RECEIVE:
9546             genReceive(ic);
9547             break;
9548             
9549         case SEND:
9550             addSet(&_G.sendSet,ic);
9551             break;
9552
9553         default :
9554             ic = ic;
9555         }
9556     }
9557     
9558
9559     /* now we are ready to call the 
9560        peep hole optimizer */
9561     if (!options.nopeep) {
9562       peepHole (&lineHead);
9563     }
9564     /* now do the actual printing */
9565     printLine (lineHead,codeOutFile);
9566
9567 #ifdef PCODE_DEBUG
9568     DFPRINTF((stderr,"printing pBlock\n\n"));
9569     printpBlock(stdout,pb);
9570 #endif
9571
9572     return;
9573 }