- Parameter passing now works
[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   if(IC_RESULT(ic) && AOP(IC_RESULT(ic)))
64     DEBUGpic14_emitcode ("; ","result %s",
65                          AopType(AOP_TYPE(IC_RESULT(ic))));
66
67   if(IC_LEFT(ic) && AOP(IC_LEFT(ic)))
68     DEBUGpic14_emitcode ("; ","left %s",
69                        AopType(AOP_TYPE(IC_LEFT(ic))));
70
71   if(IC_RIGHT(ic) && AOP(IC_RIGHT(ic)))
72     DEBUGpic14_emitcode ("; ","right %s",
73                        AopType(AOP_TYPE(IC_RIGHT(ic))));
74 */
75
76
77 static int labelOffset=0;
78 static int debug_verbose=1;
79 static int optimized_for_speed = 0;
80
81 /* max_key keeps track of the largest label number used in 
82    a function. This is then used to adjust the label offset
83    for the next function.
84 */
85 static int max_key=0;
86 static int GpsuedoStkPtr=0;
87
88 unsigned int pic14aopLiteral (value *val, int offset);
89 const char *AopType(short type);
90
91 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
92
93 /* this is the down and dirty file with all kinds of 
94    kludgy & hacky stuff. This is what it is all about
95    CODE GENERATION for a specific MCU . some of the
96    routines may be reusable, will have to see */
97
98 static char *zero = "#0x00";
99 static char *one  = "#0x01";
100 static char *spname = "sp";
101
102 char *fReturnpic14[] = {"FSR","dph","b","a" };
103 //char *fReturn390[] = {"dpl","dph","dpx", "b","a" };
104 unsigned fReturnSizePic = 4; /* shared with ralloc.c */
105 static char **fReturn = fReturnpic14;
106
107 static char *accUse[] = {"a","b"};
108
109 //static short rbank = -1;
110
111 static struct {
112     short r0Pushed;
113     short r1Pushed;
114     short accInUse;
115     short inLine;
116     short debugLine;
117     short nRegsSaved;
118     set *sendSet;
119 } _G;
120
121 /* Resolved ifx structure. This structure stores information
122    about an iCode ifx that makes it easier to generate code.
123 */
124 typedef struct resolvedIfx {
125   symbol *lbl;     /* pointer to a label */
126   int condition;   /* true or false ifx */
127   int generated;   /* set true when the code associated with the ifx
128                     * is generated */
129 } resolvedIfx;
130
131 extern int pic14_ptrRegReq ;
132 extern int pic14_nRegs;
133 extern FILE *codeOutFile;
134 static void saverbank (int, iCode *,bool);
135
136 static lineNode *lineHead = NULL;
137 static lineNode *lineCurr = NULL;
138
139 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
140 0xE0, 0xC0, 0x80, 0x00};
141 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
142 0x07, 0x03, 0x01, 0x00};
143
144 static  pBlock *pb;
145
146 /*-----------------------------------------------------------------*/
147 /*  my_powof2(n) - If `n' is an integaer power of 2, then the      */
148 /*                 exponent of 2 is returned, otherwise -1 is      */
149 /*                 returned.                                       */
150 /* note that this is similar to the function `powof2' in SDCCsymt  */
151 /* if(n == 2^y)                                                    */
152 /*   return y;                                                     */
153 /* return -1;                                                      */
154 /*-----------------------------------------------------------------*/
155 static int my_powof2 (unsigned long num)
156 {
157   if(num) {
158     if( (num & (num-1)) == 0) {
159       int nshifts = -1;
160       while(num) {
161         num>>=1;
162         nshifts++;
163       }
164       return nshifts;
165     }
166   }
167
168   return -1;
169 }
170
171 void DEBUGpic14_emitcode (char *inst,char *fmt, ...)
172 {
173     va_list ap;
174     char lb[INITIAL_INLINEASM];  
175     char *lbp = lb;
176
177     if(!debug_verbose)
178       return;
179
180     va_start(ap,fmt);   
181
182     if (inst && *inst) {
183         if (fmt && *fmt)
184             sprintf(lb,"%s\t",inst);
185         else
186             sprintf(lb,"%s",inst);
187         vsprintf(lb+(strlen(lb)),fmt,ap);
188     }  else
189         vsprintf(lb,fmt,ap);
190
191     while (isspace(*lbp)) lbp++;
192
193     if (lbp && *lbp) 
194         lineCurr = (lineCurr ?
195                     connectLine(lineCurr,newLineNode(lb)) :
196                     (lineHead = newLineNode(lb)));
197     lineCurr->isInline = _G.inLine;
198     lineCurr->isDebug  = _G.debugLine;
199
200     addpCode2pBlock(pb,newpCodeCharP(lb));
201
202     va_end(ap);
203 }
204
205
206 static void emitpLabel(int key)
207 {
208   addpCode2pBlock(pb,newpCodeLabel(key+100+labelOffset));
209 }
210
211 void emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
212 {
213
214   if(pcop)
215     addpCode2pBlock(pb,newpCode(poc,pcop));
216   else
217     DEBUGpic14_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
218 }
219
220 void emitpcodeNULLop(PIC_OPCODE poc)
221 {
222
223   addpCode2pBlock(pb,newpCode(poc,NULL));
224
225 }
226
227 /*-----------------------------------------------------------------*/
228 /* pic14_emitcode - writes the code into a file : for now it is simple    */
229 /*-----------------------------------------------------------------*/
230 void pic14_emitcode (char *inst,char *fmt, ...)
231 {
232     va_list ap;
233     char lb[INITIAL_INLINEASM];  
234     char *lbp = lb;
235
236     va_start(ap,fmt);   
237
238     if (inst && *inst) {
239         if (fmt && *fmt)
240             sprintf(lb,"%s\t",inst);
241         else
242             sprintf(lb,"%s",inst);
243         vsprintf(lb+(strlen(lb)),fmt,ap);
244     }  else
245         vsprintf(lb,fmt,ap);
246
247     while (isspace(*lbp)) lbp++;
248
249     if (lbp && *lbp) 
250         lineCurr = (lineCurr ?
251                     connectLine(lineCurr,newLineNode(lb)) :
252                     (lineHead = newLineNode(lb)));
253     lineCurr->isInline = _G.inLine;
254     lineCurr->isDebug  = _G.debugLine;
255
256     if(debug_verbose)
257       addpCode2pBlock(pb,newpCodeCharP(lb));
258
259     va_end(ap);
260 }
261
262
263 /*-----------------------------------------------------------------*/
264 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
265 /*-----------------------------------------------------------------*/
266 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
267 {
268     bool r0iu = FALSE , r1iu = FALSE;
269     bool r0ou = FALSE , r1ou = FALSE;
270
271     /* the logic: if r0 & r1 used in the instruction
272     then we are in trouble otherwise */
273
274     /* first check if r0 & r1 are used by this
275     instruction, in which case we are in trouble */
276     if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
277         (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
278     {
279         goto endOfWorld;      
280     }
281
282     r0ou = bitVectBitValue(ic->rMask,R0_IDX);
283     r1ou = bitVectBitValue(ic->rMask,R1_IDX);
284
285     /* if no usage of r0 then return it */
286     if (!r0iu && !r0ou) {
287         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
288         (*aopp)->type = AOP_R0;
289         
290         return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
291     }
292
293     /* if no usage of r1 then return it */
294     if (!r1iu && !r1ou) {
295         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
296         (*aopp)->type = AOP_R1;
297
298         return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R1_IDX);
299     }    
300
301     /* now we know they both have usage */
302     /* if r0 not used in this instruction */
303     if (!r0iu) {
304         /* push it if not already pushed */
305         if (!_G.r0Pushed) {
306             pic14_emitcode ("push","%s",
307                       pic14_regWithIdx(R0_IDX)->dname);
308             _G.r0Pushed++ ;
309         }
310         
311         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
312         (*aopp)->type = AOP_R0;
313
314         return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
315     }
316
317     /* if r1 not used then */
318
319     if (!r1iu) {
320         /* push it if not already pushed */
321         if (!_G.r1Pushed) {
322             pic14_emitcode ("push","%s",
323                       pic14_regWithIdx(R1_IDX)->dname);
324             _G.r1Pushed++ ;
325         }
326         
327         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
328         (*aopp)->type = AOP_R1;
329         return pic14_regWithIdx(R1_IDX);
330     }
331
332 endOfWorld :
333     /* I said end of world but not quite end of world yet */
334     /* if this is a result then we can push it on the stack*/
335     if (result) {
336         (*aopp)->type = AOP_STK;    
337         return NULL;
338     }
339
340     /* other wise this is true end of the world */
341     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
342            "getFreePtr should never reach here");
343     exit(0);
344 }
345
346 /*-----------------------------------------------------------------*/
347 /* newAsmop - creates a new asmOp                                  */
348 /*-----------------------------------------------------------------*/
349 asmop *newAsmop (short type)
350 {
351     asmop *aop;
352
353     aop = Safe_calloc(1,sizeof(asmop));
354     aop->type = type;
355     return aop;
356 }
357
358 static void genSetDPTR(int n)
359 {
360     if (!n)
361     {
362         pic14_emitcode(";", "Select standard DPTR");
363         pic14_emitcode("mov", "dps, #0x00");
364     }
365     else
366     {
367         pic14_emitcode(";", "Select alternate DPTR");
368         pic14_emitcode("mov", "dps, #0x01");
369     }
370 }
371
372 /*-----------------------------------------------------------------*/
373 /* resolveIfx - converts an iCode ifx into a form more useful for  */
374 /*              generating code                                    */
375 /*-----------------------------------------------------------------*/
376 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
377 {
378   if(!resIfx) 
379     return;
380
381   DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
382
383   resIfx->condition = 1;    /* assume that the ifx is true */
384   resIfx->generated = 0;    /* indicate that the ifx has not been used */
385
386   if(!ifx) {
387     resIfx->lbl = newiTempLabel(NULL);  /* oops, there is no ifx. so create a label */
388     DEBUGpic14_emitcode("; ***","%s %d null ifx creating new label key =%d",
389                         __FUNCTION__,__LINE__,resIfx->lbl->key);
390   } else {
391     if(IC_TRUE(ifx)) {
392       resIfx->lbl = IC_TRUE(ifx);
393     } else {
394       resIfx->lbl = IC_FALSE(ifx);
395       resIfx->condition = 0;
396     }
397     if(IC_TRUE(ifx)) 
398       DEBUGpic14_emitcode("; ***","ifx true is non-null");
399     if(IC_FALSE(ifx)) 
400       DEBUGpic14_emitcode("; ***","ifx false is non-null");
401   }
402
403   DEBUGpic14_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,labelOffset);
404
405 }
406 /*-----------------------------------------------------------------*/
407 /* pointerCode - returns the code for a pointer type               */
408 /*-----------------------------------------------------------------*/
409 static int pointerCode (sym_link *etype)
410 {
411
412     return PTR_TYPE(SPEC_OCLS(etype));
413
414 }
415
416 /*-----------------------------------------------------------------*/
417 /* aopForSym - for a true symbol                                   */
418 /*-----------------------------------------------------------------*/
419 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
420 {
421     asmop *aop;
422     memmap *space= SPEC_OCLS(sym->etype);
423
424     DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
425     /* if already has one */
426     if (sym->aop)
427         return sym->aop;
428
429     /* assign depending on the storage class */
430     /* if it is on the stack or indirectly addressable */
431     /* space we need to assign either r0 or r1 to it   */    
432     if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
433         sym->aop = aop = newAsmop(0);
434         aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
435         aop->size = getSize(sym->type);
436
437         /* now assign the address of the variable to 
438         the pointer register */
439         if (aop->type != AOP_STK) {
440
441             if (sym->onStack) {
442                     if ( _G.accInUse )
443                         pic14_emitcode("push","acc");
444
445                     pic14_emitcode("mov","a,_bp");
446                     pic14_emitcode("add","a,#0x%02x",
447                              ((sym->stack < 0) ?
448                               ((char)(sym->stack - _G.nRegsSaved )) :
449                               ((char)sym->stack)) & 0xff);
450                     pic14_emitcode("mov","%s,a",
451                              aop->aopu.aop_ptr->name);
452
453                     if ( _G.accInUse )
454                         pic14_emitcode("pop","acc");
455             } else
456                 pic14_emitcode("mov","%s,#%s",
457                          aop->aopu.aop_ptr->name,
458                          sym->rname);
459             aop->paged = space->paged;
460         } else
461             aop->aopu.aop_stk = sym->stack;
462         return aop;
463     }
464     
465     if (sym->onStack && options.stack10bit)
466     {
467         /* It's on the 10 bit stack, which is located in
468          * far data space.
469          */
470          
471       //DEBUGpic14_emitcode(";","%d",__LINE__);
472
473         if ( _G.accInUse )
474                 pic14_emitcode("push","acc");
475
476         pic14_emitcode("mov","a,_bp");
477         pic14_emitcode("add","a,#0x%02x",
478                  ((sym->stack < 0) ?
479                    ((char)(sym->stack - _G.nRegsSaved )) :
480                    ((char)sym->stack)) & 0xff);
481         
482         genSetDPTR(1);
483         pic14_emitcode ("mov","dpx1,#0x40");
484         pic14_emitcode ("mov","dph1,#0x00");
485         pic14_emitcode ("mov","dpl1, a");
486         genSetDPTR(0);
487         
488         if ( _G.accInUse )
489             pic14_emitcode("pop","acc");
490             
491         sym->aop = aop = newAsmop(AOP_DPTR2);
492         aop->size = getSize(sym->type); 
493         return aop;
494     }
495
496     //DEBUGpic14_emitcode(";","%d",__LINE__);
497     /* if in bit space */
498     if (IN_BITSPACE(space)) {
499         sym->aop = aop = newAsmop (AOP_CRY);
500         aop->aopu.aop_dir = sym->rname ;
501         aop->size = getSize(sym->type);
502         DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
503         return aop;
504     }
505     /* if it is in direct space */
506     if (IN_DIRSPACE(space)) {
507         sym->aop = aop = newAsmop (AOP_DIR);
508         aop->aopu.aop_dir = sym->rname ;
509         aop->size = getSize(sym->type);
510         DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
511         return aop;
512     }
513
514     /* special case for a function */
515     if (IS_FUNC(sym->type)) {   
516         sym->aop = aop = newAsmop(AOP_IMMD);    
517         //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
518         aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
519         strcpy(aop->aopu.aop_immd,sym->rname);
520         aop->size = FPTRSIZE; 
521         return aop;
522     }
523
524
525     /* only remaining is far space */
526     /* in which case DPTR gets the address */
527     sym->aop = aop = newAsmop(AOP_DPTR);
528     pic14_emitcode ("mov","dptr,#%s", sym->rname);
529     aop->size = getSize(sym->type);
530
531     DEBUGpic14_emitcode(";","%d size = %d",__LINE__,aop->size);
532     /* if it is in code space */
533     if (IN_CODESPACE(space))
534         aop->code = 1;
535
536     return aop;     
537 }
538
539 /*-----------------------------------------------------------------*/
540 /* aopForRemat - rematerialzes an object                           */
541 /*-----------------------------------------------------------------*/
542 static asmop *aopForRemat (symbol *sym)
543 {
544     iCode *ic = sym->rematiCode;
545     asmop *aop = newAsmop(AOP_IMMD);
546     int val = 0;
547     DEBUGpic14_emitcode(";","%s %d",__FUNCTION__,__LINE__);
548     for (;;) {
549         if (ic->op == '+')
550             val += (int) operandLitValue(IC_RIGHT(ic));
551         else if (ic->op == '-')
552             val -= (int) operandLitValue(IC_RIGHT(ic));
553         else
554             break;
555         
556         ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
557     }
558
559     if (val)
560         sprintf(buffer,"(%s %c 0x%04x)",
561                 OP_SYMBOL(IC_LEFT(ic))->rname, 
562                 val >= 0 ? '+' : '-',
563                 abs(val) & 0xffff);
564     else
565         strcpy(buffer,OP_SYMBOL(IC_LEFT(ic))->rname);
566
567     //DEBUGpic14_emitcode(";","%s",buffer);
568     aop->aopu.aop_immd = Safe_calloc(1,strlen(buffer)+1);
569     strcpy(aop->aopu.aop_immd,buffer);    
570     return aop;        
571 }
572
573 int aopIdx (asmop *aop, int offset)
574 {
575   if(!aop)
576     return -1;
577
578   if(aop->type !=  AOP_REG)
579     return -2;
580         
581   return aop->aopu.aop_reg[offset]->rIdx;
582
583 }
584 /*-----------------------------------------------------------------*/
585 /* regsInCommon - two operands have some registers in common       */
586 /*-----------------------------------------------------------------*/
587 static bool regsInCommon (operand *op1, operand *op2)
588 {
589     symbol *sym1, *sym2;
590     int i;
591
592     /* if they have registers in common */
593     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
594         return FALSE ;
595
596     sym1 = OP_SYMBOL(op1);
597     sym2 = OP_SYMBOL(op2);
598
599     if (sym1->nRegs == 0 || sym2->nRegs == 0)
600         return FALSE ;
601
602     for (i = 0 ; i < sym1->nRegs ; i++) {
603         int j;
604         if (!sym1->regs[i])
605             continue ;
606
607         for (j = 0 ; j < sym2->nRegs ;j++ ) {
608             if (!sym2->regs[j])
609                 continue ;
610
611             if (sym2->regs[j] == sym1->regs[i])
612                 return TRUE ;
613         }
614     }
615
616     return FALSE ;
617 }
618
619 /*-----------------------------------------------------------------*/
620 /* operandsEqu - equivalent                                        */
621 /*-----------------------------------------------------------------*/
622 static bool operandsEqu ( operand *op1, operand *op2)
623 {
624     symbol *sym1, *sym2;
625
626     /* if they not symbols */
627     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
628         return FALSE;
629
630     sym1 = OP_SYMBOL(op1);
631     sym2 = OP_SYMBOL(op2);
632
633     /* if both are itemps & one is spilt
634        and the other is not then false */
635     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
636         sym1->isspilt != sym2->isspilt )
637         return FALSE ;
638
639     /* if they are the same */
640     if (sym1 == sym2)
641         return TRUE ;
642
643     if (strcmp(sym1->rname,sym2->rname) == 0)
644         return TRUE;
645
646
647     /* if left is a tmp & right is not */
648     if (IS_ITEMP(op1)  && 
649         !IS_ITEMP(op2) &&
650         sym1->isspilt  &&
651         (sym1->usl.spillLoc == sym2))
652         return TRUE;
653
654     if (IS_ITEMP(op2)  && 
655         !IS_ITEMP(op1) &&
656         sym2->isspilt  &&
657         sym1->level > 0 &&
658         (sym2->usl.spillLoc == sym1))
659         return TRUE ;
660
661     return FALSE ;
662 }
663
664 /*-----------------------------------------------------------------*/
665 /* pic14_sameRegs - two asmops have the same registers                   */
666 /*-----------------------------------------------------------------*/
667 bool pic14_sameRegs (asmop *aop1, asmop *aop2 )
668 {
669     int i;
670
671     if (aop1 == aop2)
672         return TRUE ;
673
674     if (aop1->type != AOP_REG ||
675         aop2->type != AOP_REG )
676         return FALSE ;
677
678     if (aop1->size != aop2->size )
679         return FALSE ;
680
681     for (i = 0 ; i < aop1->size ; i++ )
682         if (aop1->aopu.aop_reg[i] !=
683             aop2->aopu.aop_reg[i] )
684             return FALSE ;
685
686     return TRUE ;
687 }
688
689 /*-----------------------------------------------------------------*/
690 /* aopOp - allocates an asmop for an operand  :                    */
691 /*-----------------------------------------------------------------*/
692 void aopOp (operand *op, iCode *ic, bool result)
693 {
694     asmop *aop;
695     symbol *sym;
696     int i;
697
698     if (!op)
699         return ;
700
701     DEBUGpic14_emitcode(";","%d",__LINE__);
702     /* if this a literal */
703     if (IS_OP_LITERAL(op)) {
704         op->aop = aop = newAsmop(AOP_LIT);
705         aop->aopu.aop_lit = op->operand.valOperand;
706         aop->size = getSize(operandType(op));
707       DEBUGpic14_emitcode(";","%d, lit = %d",__LINE__,aop->aopu.aop_lit);
708         return;
709     }
710
711     /* if already has a asmop then continue */
712     if (op->aop)
713         return ;
714
715     /* if the underlying symbol has a aop */
716     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
717       DEBUGpic14_emitcode(";","%d",__LINE__);
718         op->aop = OP_SYMBOL(op)->aop;
719         return;
720     }
721
722     /* if this is a true symbol */
723     if (IS_TRUE_SYMOP(op)) {    
724       DEBUGpic14_emitcode(";","%d - true symop",__LINE__);
725         op->aop = aopForSym(ic,OP_SYMBOL(op),result);
726         return ;
727     }
728
729     /* this is a temporary : this has
730     only four choices :
731     a) register
732     b) spillocation
733     c) rematerialize 
734     d) conditional   
735     e) can be a return use only */
736
737     sym = OP_SYMBOL(op);
738
739
740     /* if the type is a conditional */
741     if (sym->regType == REG_CND) {
742       DEBUGpic14_emitcode(";","%d",__LINE__);
743         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
744         aop->size = 0;
745         return;
746     }
747
748     /* if it is spilt then two situations
749     a) is rematerialize 
750     b) has a spill location */
751     if (sym->isspilt || sym->nRegs == 0) {
752
753       DEBUGpic14_emitcode(";","%d",__LINE__);
754         /* rematerialize it NOW */
755         if (sym->remat) {
756             sym->aop = op->aop = aop =
757                                       aopForRemat (sym);
758             aop->size = getSize(sym->type);
759             DEBUGpic14_emitcode(";","%d",__LINE__);
760             return;
761         }
762
763         if (sym->accuse) {
764             int i;
765             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
766             aop->size = getSize(sym->type);
767             for ( i = 0 ; i < 2 ; i++ )
768                 aop->aopu.aop_str[i] = accUse[i];
769             DEBUGpic14_emitcode(";","%d",__LINE__);
770             return;  
771         }
772
773         if (sym->ruonly ) {
774             unsigned i;
775             aop = op->aop = sym->aop = newAsmop(AOP_STR);
776             aop->size = getSize(sym->type);
777             for ( i = 0 ; i < fReturnSizePic ; i++ )
778               aop->aopu.aop_str[i] = fReturn[i];
779             DEBUGpic14_emitcode(";","%d",__LINE__);
780             return;
781         }
782
783         /* else spill location  */
784         DEBUGpic14_emitcode(";","%s %d %s",__FUNCTION__,__LINE__,sym->usl.spillLoc->rname);
785         sym->aop = op->aop = aop = 
786                                   aopForSym(ic,sym->usl.spillLoc,result);
787         aop->size = getSize(sym->type);
788         return;
789     }
790
791     /* must be in a register */
792     sym->aop = op->aop = aop = newAsmop(AOP_REG);
793     aop->size = sym->nRegs;
794     for ( i = 0 ; i < sym->nRegs ;i++)
795         aop->aopu.aop_reg[i] = sym->regs[i];
796 }
797
798 /*-----------------------------------------------------------------*/
799 /* freeAsmop - free up the asmop given to an operand               */
800 /*----------------------------------------------------------------*/
801 void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
802 {   
803     asmop *aop ;
804
805     if (!op)
806         aop = aaop;
807     else 
808         aop = op->aop;
809
810     if (!aop)
811         return ;
812
813     if (aop->freed)
814         goto dealloc; 
815
816     aop->freed = 1;
817
818     /* depending on the asmop type only three cases need work AOP_RO
819        , AOP_R1 && AOP_STK */
820     switch (aop->type) {
821         case AOP_R0 :
822             if (_G.r0Pushed ) {
823                 if (pop) {
824                     pic14_emitcode ("pop","ar0");     
825                     _G.r0Pushed--;
826                 }
827             }
828             bitVectUnSetBit(ic->rUsed,R0_IDX);
829             break;
830
831         case AOP_R1 :
832             if (_G.r1Pushed ) {
833                 if (pop) {
834                     pic14_emitcode ("pop","ar1");
835                     _G.r1Pushed--;
836                 }
837             }
838             bitVectUnSetBit(ic->rUsed,R1_IDX);          
839             break;
840
841         case AOP_STK :
842         {
843             int sz = aop->size;    
844             int stk = aop->aopu.aop_stk + aop->size;
845             bitVectUnSetBit(ic->rUsed,R0_IDX);
846             bitVectUnSetBit(ic->rUsed,R1_IDX);          
847
848             getFreePtr(ic,&aop,FALSE);
849             
850             if (options.stack10bit)
851             {
852                 /* I'm not sure what to do here yet... */
853                 /* #STUB */
854                 fprintf(stderr, 
855                         "*** Warning: probably generating bad code for "
856                         "10 bit stack mode.\n");
857             }
858             
859             if (stk) {
860                 pic14_emitcode ("mov","a,_bp");
861                 pic14_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
862                 pic14_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
863             } else {
864                 pic14_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
865             }
866
867             while (sz--) {
868                 pic14_emitcode("pop","acc");
869                 pic14_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
870                 if (!sz) break;
871                 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
872             }
873             op->aop = aop;
874             freeAsmop(op,NULL,ic,TRUE);
875             if (_G.r0Pushed) {
876                 pic14_emitcode("pop","ar0");
877                 _G.r0Pushed--;
878             }
879
880             if (_G.r1Pushed) {
881                 pic14_emitcode("pop","ar1");
882                 _G.r1Pushed--;
883             }       
884         }
885     }
886
887 dealloc:
888     /* all other cases just dealloc */
889     if (op ) {
890         op->aop = NULL;
891         if (IS_SYMOP(op)) {
892             OP_SYMBOL(op)->aop = NULL;    
893             /* if the symbol has a spill */
894             if (SPIL_LOC(op))
895                 SPIL_LOC(op)->aop = NULL;
896         }
897     }
898 }
899
900 /*-----------------------------------------------------------------*/
901 /* aopGet - for fetching value of the aop                          */
902 /*-----------------------------------------------------------------*/
903 char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
904 {
905     char *s = buffer ;
906     char *rs;
907
908     //DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
909     /* offset is greater than
910     size then zero */
911     if (offset > (aop->size - 1) &&
912         aop->type != AOP_LIT)
913         return zero;
914
915     /* depending on type */
916     switch (aop->type) {
917         
918     case AOP_R0:
919     case AOP_R1:
920         DEBUGpic14_emitcode(";","%d",__LINE__);
921         /* if we need to increment it */       
922         while (offset > aop->coff) {        
923             pic14_emitcode ("inc","%s",aop->aopu.aop_ptr->name);  
924             aop->coff++;
925         }
926         
927         while (offset < aop->coff) {
928             pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
929             aop->coff--;
930         }
931         
932         aop->coff = offset ;
933         if (aop->paged) {
934             pic14_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
935             return (dname ? "acc" : "a");
936         }       
937         sprintf(s,"@%s",aop->aopu.aop_ptr->name);
938         rs = Safe_calloc(1,strlen(s)+1);
939         strcpy(rs,s);   
940         return rs;
941         
942     case AOP_DPTR:
943     case AOP_DPTR2:
944         DEBUGpic14_emitcode(";","%d",__LINE__);
945     if (aop->type == AOP_DPTR2)
946     {
947         genSetDPTR(1);
948     }
949     
950         while (offset > aop->coff) {
951             pic14_emitcode ("inc","dptr");
952             aop->coff++;
953         }
954         
955         while (offset < aop->coff) {        
956             pic14_emitcode("lcall","__decdptr");
957             aop->coff--;
958         }
959         
960         aop->coff = offset;
961         if (aop->code) {
962             pic14_emitcode("clr","a");
963             pic14_emitcode("movc","a,@a+dptr");
964         }
965     else {
966             pic14_emitcode("movx","a,@dptr");
967     }
968             
969     if (aop->type == AOP_DPTR2)
970     {
971         genSetDPTR(0);
972     }
973             
974     return (dname ? "acc" : "a");
975         
976         
977     case AOP_IMMD:
978       DEBUGpic14_emitcode(";","%d",__LINE__);
979         if (bit16) 
980             sprintf (s,"%s",aop->aopu.aop_immd);
981         else
982             if (offset) 
983                 sprintf(s,"(%s >> %d)",
984                         aop->aopu.aop_immd,
985                         offset*8);
986             else
987                 sprintf(s,"%s",
988                         aop->aopu.aop_immd);
989         rs = Safe_calloc(1,strlen(s)+1);
990         strcpy(rs,s);   
991         return rs;
992         
993     case AOP_DIR:
994         if (offset)
995             sprintf(s,"(%s + %d)",
996                     aop->aopu.aop_dir,
997                     offset);
998         else
999             sprintf(s,"%s",aop->aopu.aop_dir);
1000         rs = Safe_calloc(1,strlen(s)+1);
1001         strcpy(rs,s);   
1002         return rs;
1003         
1004     case AOP_REG:
1005       DEBUGpic14_emitcode(";","%d",__LINE__);
1006         if (dname) 
1007             return aop->aopu.aop_reg[offset]->dname;
1008         else
1009             return aop->aopu.aop_reg[offset]->name;
1010         
1011     case AOP_CRY:
1012       pic14_emitcode(";","%d",__LINE__);
1013       //pic14_emitcode("clr","a");
1014       //pic14_emitcode("mov","c,%s",aop->aopu.aop_dir);
1015       //pic14_emitcode("rlc","a") ;
1016       //return (dname ? "acc" : "a");
1017       return aop->aopu.aop_dir;
1018         
1019     case AOP_ACC:
1020         DEBUGpic14_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1021         //if (!offset && dname)
1022         //    return "acc";
1023         //return aop->aopu.aop_str[offset];
1024         return "AOP_accumulator_bug";
1025
1026     case AOP_LIT:
1027         DEBUGpic14_emitcode(";","%d",__LINE__);
1028         sprintf(s,"0x%02x", pic14aopLiteral (aop->aopu.aop_lit,offset));
1029         rs = Safe_calloc(1,strlen(s)+1);
1030         strcpy(rs,s);   
1031         return rs;
1032         
1033     case AOP_STR:
1034         DEBUGpic14_emitcode(";","%d",__LINE__);
1035         aop->coff = offset ;
1036         if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1037             dname)
1038             return "acc";
1039         
1040         return aop->aopu.aop_str[offset];
1041         
1042     }
1043
1044     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1045            "aopget got unsupported aop->type");
1046     exit(0);
1047 }
1048
1049 /*-----------------------------------------------------------------*/
1050 /* popGetLabel - create a new pCodeOp of type PO_LABEL             */
1051 /*-----------------------------------------------------------------*/
1052 pCodeOp *popGetLabel(unsigned int key)
1053 {
1054
1055   DEBUGpic14_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1056
1057   if(key>max_key)
1058     max_key = key;
1059
1060   return newpCodeOpLabel(key+100+labelOffset);
1061 }
1062
1063 /*-----------------------------------------------------------------*/
1064 /* popCopyReg - copy a pcode operator                              */
1065 /*-----------------------------------------------------------------*/
1066 pCodeOp *popCopyReg(pCodeOpReg *pc)
1067 {
1068   pCodeOpReg *pcor;
1069
1070   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1071   pcor->pcop.type = pc->pcop.type;
1072   if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1073     fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1074   pcor->r = pc->r;
1075   pcor->rIdx = pc->rIdx;
1076
1077
1078   return PCOP(pcor);
1079 }
1080
1081 /*-----------------------------------------------------------------*/
1082 /* popCopy - copy a pcode operator                                 */
1083 /*-----------------------------------------------------------------*/
1084 pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval)
1085 {
1086   pCodeOp *pcop;
1087
1088   pcop = Safe_calloc(1,sizeof(pCodeOpBit) );
1089   pcop->type = PO_BIT;
1090   if(!(pcop->name = Safe_strdup(pc->name)))
1091     fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1092   ((pCodeOpBit *)pcop)->bit = bitval;
1093
1094   ((pCodeOpBit *)pcop)->inBitSpace = 0; //(pc->type == PO_BIT) ? 1 : 0;
1095
1096   return pcop;
1097 }
1098
1099 /*-----------------------------------------------------------------*/
1100 /* popGet - asm operator to pcode operator conversion              */
1101 /*-----------------------------------------------------------------*/
1102 pCodeOp *popGetLit(unsigned int lit)
1103 {
1104
1105   return newpCodeOpLit(lit);
1106 }
1107
1108
1109 /*-----------------------------------------------------------------*/
1110 /* popGet - asm operator to pcode operator conversion              */
1111 /*-----------------------------------------------------------------*/
1112 pCodeOp *popGetWithString(char *str)
1113 {
1114   pCodeOp *pcop;
1115
1116
1117   if(!str) {
1118     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1119     exit (1);
1120   }
1121
1122   pcop = newpCodeOp(str,PO_STR);
1123
1124   return pcop;
1125 }
1126
1127 pCodeOp *popRegFromString(char *str)
1128 {
1129
1130   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1131   pcop->type = PO_GPR_REGISTER;
1132
1133   PCOR(pcop)->rIdx = -1;
1134   PCOR(pcop)->r = NULL;
1135
1136   DEBUGpic14_emitcode(";","%d",__LINE__);
1137   pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1138
1139   return pcop;
1140 }
1141
1142 pCodeOp *popRegFromIdx(int rIdx)
1143 {
1144   pCodeOp *pcop;
1145
1146   DEBUGpic14_emitcode ("; ***","%s,%d  , rIdx=0x%x",
1147                        __FUNCTION__,__LINE__,rIdx);
1148
1149   pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1150
1151   PCOR(pcop)->rIdx = rIdx;
1152   PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1153   PCOR(pcop)->r->isFree = 0;
1154   PCOR(pcop)->r->wasUsed = 1;
1155
1156   pcop->type = PCOR(pcop)->r->pc_type;
1157
1158
1159   return pcop;
1160 }
1161 /*-----------------------------------------------------------------*/
1162 /* popGet - asm operator to pcode operator conversion              */
1163 /*-----------------------------------------------------------------*/
1164 pCodeOp *popGet (asmop *aop, int offset, bool bit16, bool dname)
1165 {
1166     char *s = buffer ;
1167     char *rs;
1168
1169     pCodeOp *pcop;
1170
1171     //DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1172     /* offset is greater than
1173     size then zero */
1174
1175     if (offset > (aop->size - 1) &&
1176         aop->type != AOP_LIT)
1177       return NULL;  //zero;
1178
1179     /* depending on type */
1180     switch (aop->type) {
1181         
1182     case AOP_R0:
1183     case AOP_R1:
1184     case AOP_DPTR:
1185     case AOP_DPTR2:
1186     case AOP_ACC:
1187         DEBUGpic14_emitcode(";8051 legacy","%d type = %s",__LINE__,AopType(aop->type));
1188         //pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1189         //pcop->type = PO_SFR_REGISTER;
1190
1191         //PCOR(pcop)->rIdx = -1;
1192         //PCOR(pcop)->r = NULL;
1193         // Really nasty hack to check for temporary registers
1194
1195         //pcop->name = Safe_strdup("BAD_REGISTER");
1196
1197         return NULL;
1198         
1199     case AOP_IMMD:
1200       DEBUGpic14_emitcode(";","%d",__LINE__);
1201         pcop = Safe_calloc(1,sizeof(pCodeOp) );
1202         pcop->type = PO_IMMEDIATE;
1203         if (bit16) 
1204             sprintf (s,"%s",aop->aopu.aop_immd);
1205         else
1206             if (offset) 
1207                 sprintf(s,"(%s >> %d)",
1208                         aop->aopu.aop_immd,
1209                         offset*8);
1210             else
1211                 sprintf(s,"%s",
1212                         aop->aopu.aop_immd);
1213         pcop->name = Safe_calloc(1,strlen(s)+1);
1214         strcpy(pcop->name,s);   
1215         return pcop;
1216         
1217     case AOP_DIR:
1218         pcop = Safe_calloc(1,sizeof(pCodeOp) );
1219         pcop->type = PO_DIR;
1220         if (offset)
1221             sprintf(s,"(%s + %d)",
1222                     aop->aopu.aop_dir,
1223                     offset);
1224         else
1225             sprintf(s,"%s",aop->aopu.aop_dir);
1226         pcop->name = Safe_calloc(1,strlen(s)+1);
1227         strcpy(pcop->name,s);   
1228         return pcop;
1229         
1230     case AOP_REG:
1231       {
1232         int rIdx = aop->aopu.aop_reg[offset]->rIdx;
1233
1234         DEBUGpic14_emitcode(";","%d, rIdx=0x%x",__LINE__,rIdx);
1235         if(bit16)
1236           pcop = Safe_calloc(1,sizeof(pCodeOpRegBit) );
1237         else
1238           pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1239         //pcop->type = PO_GPR_REGISTER;
1240         PCOR(pcop)->rIdx = rIdx;
1241         PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1242         pcop->type = PCOR(pcop)->r->pc_type;
1243
1244         if (dname)
1245           rs = aop->aopu.aop_reg[offset]->dname;
1246         else 
1247           rs = aop->aopu.aop_reg[offset]->name;
1248
1249         DEBUGpic14_emitcode(";","%d  %s",__LINE__,rs);
1250
1251         return pcop;
1252       }
1253
1254     case AOP_CRY:
1255       pcop = newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1256       return pcop;
1257         
1258     case AOP_LIT:
1259       DEBUGpic14_emitcode(";","%d",__LINE__);
1260       return newpCodeOpLit(pic14aopLiteral (aop->aopu.aop_lit,offset));
1261
1262     case AOP_STR:
1263       DEBUGpic14_emitcode(";","%d",__LINE__);
1264
1265       pcop = Safe_calloc(1,sizeof(pCodeOp) );
1266       pcop->type = PO_STR;
1267
1268       //aop->coff = offset ;
1269         if (strcmp(aop->aopu.aop_str[offset],"a") == 0 && dname)
1270           sprintf(s,"%s","acc");
1271         else
1272           sprintf(s,"%s",aop->aopu.aop_str[offset]);
1273         pcop->name = Safe_calloc(1,strlen(s)+1);
1274         strcpy(pcop->name,s);   
1275         return pcop;
1276         
1277     }
1278
1279     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1280            "popGet got unsupported aop->type");
1281     exit(0);
1282 }
1283 /*-----------------------------------------------------------------*/
1284 /* aopPut - puts a string for a aop                                */
1285 /*-----------------------------------------------------------------*/
1286 void aopPut (asmop *aop, char *s, int offset)
1287 {
1288     char *d = buffer ;
1289     symbol *lbl ;
1290
1291     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1292
1293     if (aop->size && offset > ( aop->size - 1)) {
1294         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1295                "aopPut got offset > aop->size");
1296         exit(0);
1297     }
1298
1299     /* will assign value to value */
1300     /* depending on where it is ofcourse */
1301     switch (aop->type) {
1302     case AOP_DIR:
1303         if (offset)
1304             sprintf(d,"(%s + %d)",
1305                     aop->aopu.aop_dir,offset);
1306         else
1307             sprintf(d,"%s",aop->aopu.aop_dir);
1308         
1309         if (strcmp(d,s)) {
1310           DEBUGpic14_emitcode(";","%d",__LINE__);
1311           if(strcmp(s,"W"))
1312             pic14_emitcode("movf","%s,w",s);
1313           pic14_emitcode("movwf","%s",d);
1314
1315           if(strcmp(s,"W"))
1316             pic14_emitcode(";BUG! should have this:movf","%s,w   %d",s,__LINE__);
1317           emitpcode(POC_MOVWF,popGet(aop,offset,FALSE,FALSE));
1318
1319
1320         }
1321         break;
1322         
1323     case AOP_REG:
1324         if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0 &&
1325             strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1326           /*
1327             if (*s == '@'           ||
1328                 strcmp(s,"r0") == 0 ||
1329                 strcmp(s,"r1") == 0 ||
1330                 strcmp(s,"r2") == 0 ||
1331                 strcmp(s,"r3") == 0 ||
1332                 strcmp(s,"r4") == 0 ||
1333                 strcmp(s,"r5") == 0 ||
1334                 strcmp(s,"r6") == 0 || 
1335                 strcmp(s,"r7") == 0 )
1336                 pic14_emitcode("mov","%s,%s  ; %d",
1337                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1338             else
1339           */
1340
1341           if(strcmp(s,"W"))
1342             pic14_emitcode("movf","%s,w  ; %d",s,__LINE__);
1343
1344           pic14_emitcode("movwf","%s",
1345                    aop->aopu.aop_reg[offset]->name);
1346
1347           if(strcmp(s,"W")) {
1348             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1349             pcop->type = PO_GPR_REGISTER;
1350
1351             PCOR(pcop)->rIdx = -1;
1352             PCOR(pcop)->r = NULL;
1353
1354             DEBUGpic14_emitcode(";","%d",__LINE__);
1355             pcop->name = Safe_strdup(s);
1356             emitpcode(POC_MOVFW,pcop);
1357           }
1358           emitpcode(POC_MOVWF,popGet(aop,offset,FALSE,FALSE));
1359
1360         }
1361         break;
1362         
1363     case AOP_DPTR:
1364     case AOP_DPTR2:
1365     
1366     if (aop->type == AOP_DPTR2)
1367     {
1368         genSetDPTR(1);
1369     }
1370     
1371         if (aop->code) {
1372             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1373                    "aopPut writting to code space");
1374             exit(0);
1375         }
1376         
1377         while (offset > aop->coff) {
1378             aop->coff++;
1379             pic14_emitcode ("inc","dptr");
1380         }
1381         
1382         while (offset < aop->coff) {
1383             aop->coff-- ;
1384             pic14_emitcode("lcall","__decdptr");
1385         }
1386         
1387         aop->coff = offset;
1388         
1389         /* if not in accumulater */
1390         MOVA(s);        
1391         
1392         pic14_emitcode ("movx","@dptr,a");
1393         
1394     if (aop->type == AOP_DPTR2)
1395     {
1396         genSetDPTR(0);
1397     }
1398         break;
1399         
1400     case AOP_R0:
1401     case AOP_R1:
1402         while (offset > aop->coff) {
1403             aop->coff++;
1404             pic14_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1405         }
1406         while (offset < aop->coff) {
1407             aop->coff-- ;
1408             pic14_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1409         }
1410         aop->coff = offset;
1411         
1412         if (aop->paged) {
1413             MOVA(s);           
1414             pic14_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1415             
1416         } else
1417             if (*s == '@') {
1418                 MOVA(s);
1419                 pic14_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1420             } else
1421                 if (strcmp(s,"r0") == 0 ||
1422                     strcmp(s,"r1") == 0 ||
1423                     strcmp(s,"r2") == 0 ||
1424                     strcmp(s,"r3") == 0 ||
1425                     strcmp(s,"r4") == 0 ||
1426                     strcmp(s,"r5") == 0 ||
1427                     strcmp(s,"r6") == 0 || 
1428                     strcmp(s,"r7") == 0 ) {
1429                     char buffer[10];
1430                     sprintf(buffer,"a%s",s);
1431                     pic14_emitcode("mov","@%s,%s",
1432                              aop->aopu.aop_ptr->name,buffer);
1433                 } else
1434                     pic14_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1435         
1436         break;
1437         
1438     case AOP_STK:
1439         if (strcmp(s,"a") == 0)
1440             pic14_emitcode("push","acc");
1441         else
1442             pic14_emitcode("push","%s",s);
1443         
1444         break;
1445         
1446     case AOP_CRY:
1447         /* if bit variable */
1448         if (!aop->aopu.aop_dir) {
1449             pic14_emitcode("clr","a");
1450             pic14_emitcode("rlc","a");
1451         } else {
1452             if (s == zero) 
1453                 pic14_emitcode("clr","%s",aop->aopu.aop_dir);
1454             else
1455                 if (s == one)
1456                     pic14_emitcode("setb","%s",aop->aopu.aop_dir);
1457                 else
1458                     if (!strcmp(s,"c"))
1459                         pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1460                     else {
1461                         lbl = newiTempLabel(NULL);
1462                         
1463                         if (strcmp(s,"a")) {
1464                             MOVA(s);
1465                         }
1466                         pic14_emitcode("clr","c");
1467                         pic14_emitcode("jz","%05d_DS_",lbl->key+100);
1468                         pic14_emitcode("cpl","c");
1469                         pic14_emitcode("","%05d_DS_:",lbl->key+100);
1470                         pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1471                     }
1472         }
1473         break;
1474         
1475     case AOP_STR:
1476         aop->coff = offset;
1477         if (strcmp(aop->aopu.aop_str[offset],s))
1478             pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1479         break;
1480         
1481     case AOP_ACC:
1482         aop->coff = offset;
1483         if (!offset && (strcmp(s,"acc") == 0))
1484             break;
1485         
1486         if (strcmp(aop->aopu.aop_str[offset],s))
1487             pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1488         break;
1489
1490     default :
1491         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1492                "aopPut got unsupported aop->type");
1493         exit(0);    
1494     }    
1495
1496 }
1497
1498 /*-----------------------------------------------------------------*/
1499 /* reAdjustPreg - points a register back to where it should        */
1500 /*-----------------------------------------------------------------*/
1501 static void reAdjustPreg (asmop *aop)
1502 {
1503     int size ;
1504
1505     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1506     aop->coff = 0;
1507     if ((size = aop->size) <= 1)
1508         return ;
1509     size-- ;
1510     switch (aop->type) {
1511         case AOP_R0 :
1512         case AOP_R1 :
1513             while (size--)
1514                 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1515             break;          
1516         case AOP_DPTR :
1517         case AOP_DPTR2:
1518             if (aop->type == AOP_DPTR2)
1519             {
1520                 genSetDPTR(1);
1521             } 
1522             while (size--)
1523             {
1524                 pic14_emitcode("lcall","__decdptr");
1525             }
1526                 
1527             if (aop->type == AOP_DPTR2)
1528             {
1529                 genSetDPTR(0);
1530             }                
1531             break;  
1532
1533     }   
1534
1535 }
1536
1537 /*-----------------------------------------------------------------*/
1538 /* genNotFloat - generates not for float operations              */
1539 /*-----------------------------------------------------------------*/
1540 static void genNotFloat (operand *op, operand *res)
1541 {
1542     int size, offset;
1543     char *l;
1544     symbol *tlbl ;
1545
1546     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1547     /* we will put 127 in the first byte of 
1548     the result */
1549     aopPut(AOP(res),"#127",0);
1550     size = AOP_SIZE(op) - 1;
1551     offset = 1;
1552
1553     l = aopGet(op->aop,offset++,FALSE,FALSE);
1554     MOVA(l);    
1555
1556     while(size--) {
1557         pic14_emitcode("orl","a,%s",
1558                  aopGet(op->aop,
1559                         offset++,FALSE,FALSE));
1560     }
1561     tlbl = newiTempLabel(NULL);
1562
1563     tlbl = newiTempLabel(NULL);
1564     aopPut(res->aop,one,1);
1565     pic14_emitcode("jz","%05d_DS_",(tlbl->key+100));
1566     aopPut(res->aop,zero,1);
1567     pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
1568
1569     size = res->aop->size - 2;
1570     offset = 2;    
1571     /* put zeros in the rest */
1572     while (size--) 
1573         aopPut(res->aop,zero,offset++);
1574 }
1575
1576 #if 0
1577 /*-----------------------------------------------------------------*/
1578 /* opIsGptr: returns non-zero if the passed operand is             */   
1579 /* a generic pointer type.                                         */
1580 /*-----------------------------------------------------------------*/ 
1581 static int opIsGptr(operand *op)
1582 {
1583     sym_link *type = operandType(op);
1584     
1585     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1586     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1587     {
1588         return 1;
1589     }
1590     return 0;        
1591 }
1592 #endif
1593
1594 /*-----------------------------------------------------------------*/
1595 /* pic14_getDataSize - get the operand data size                         */
1596 /*-----------------------------------------------------------------*/
1597 int pic14_getDataSize(operand *op)
1598 {
1599     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1600
1601
1602     return AOP_SIZE(op);
1603
1604     // tsd- in the pic port, the genptr size is 1, so this code here
1605     // fails. ( in the 8051 port, the size was 4).
1606 #if 0
1607     int size;
1608     size = AOP_SIZE(op);
1609     if (size == GPTRSIZE)
1610     {
1611         sym_link *type = operandType(op);
1612         if (IS_GENPTR(type))
1613         {
1614             /* generic pointer; arithmetic operations
1615              * should ignore the high byte (pointer type).
1616              */
1617             size--;
1618     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1619         }
1620     }
1621     return size;
1622 #endif
1623 }
1624
1625 /*-----------------------------------------------------------------*/
1626 /* pic14_outAcc - output Acc                                             */
1627 /*-----------------------------------------------------------------*/
1628 void pic14_outAcc(operand *result)
1629 {
1630
1631     DEBUGpic14_emitcode ("; ***","%s  %d - Warning no code will be generated here",__FUNCTION__,__LINE__);
1632
1633 #if 0
1634     size = pic14_getDataSize(result);
1635     if(size){
1636         aopPut(AOP(result),"a",0);
1637         size--;
1638         offset = 1;
1639         /* unsigned or positive */
1640         while(size--){
1641             aopPut(AOP(result),zero,offset++);
1642         }
1643     }
1644 #endif
1645 }
1646
1647 /*-----------------------------------------------------------------*/
1648 /* pic14_outBitC - output a bit C                                        */
1649 /*-----------------------------------------------------------------*/
1650 void pic14_outBitC(operand *result)
1651 {
1652
1653     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1654     /* if the result is bit */
1655     if (AOP_TYPE(result) == AOP_CRY) 
1656         aopPut(AOP(result),"c",0);
1657     else {
1658         pic14_emitcode("clr","a  ; %d", __LINE__);
1659         pic14_emitcode("rlc","a");
1660         pic14_outAcc(result);
1661     }
1662 }
1663
1664 /*-----------------------------------------------------------------*/
1665 /* pic14_toBoolean - emit code for orl a,operator(sizeop)                */
1666 /*-----------------------------------------------------------------*/
1667 void pic14_toBoolean(operand *oper)
1668 {
1669     int size = AOP_SIZE(oper) - 1;
1670     int offset = 1;
1671
1672     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1673
1674     if ( AOP_TYPE(oper) != AOP_ACC) {
1675       emitpcode(POC_MOVFW,popGet(AOP(oper),0,FALSE,FALSE));
1676       pic14_emitcode("movf","%s,w",aopGet(AOP(oper),0,FALSE,FALSE));
1677     }
1678     while (size--) {
1679       pic14_emitcode("iorwf","%s,w",aopGet(AOP(oper),offset,FALSE,FALSE));
1680       emitpcode(POC_IORFW, popGet(AOP(oper),offset++,FALSE,FALSE));
1681     }
1682 }
1683
1684
1685 /*-----------------------------------------------------------------*/
1686 /* genNot - generate code for ! operation                          */
1687 /*-----------------------------------------------------------------*/
1688 static void genNot (iCode *ic)
1689 {
1690     symbol *tlbl;
1691     sym_link *optype = operandType(IC_LEFT(ic));
1692
1693     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1694     /* assign asmOps to operand & result */
1695     aopOp (IC_LEFT(ic),ic,FALSE);
1696     aopOp (IC_RESULT(ic),ic,TRUE);
1697
1698     /* if in bit space then a special case */
1699     if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1700       pic14_emitcode("movlw","1<<%s");
1701       //pic14_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
1702       //pic14_emitcode("cpl","c"); 
1703       //pic14_outBitC(IC_RESULT(ic));
1704       goto release;
1705     }
1706
1707     /* if type float then do float */
1708     if (IS_FLOAT(optype)) {
1709         genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
1710         goto release;
1711     }
1712
1713     pic14_toBoolean(IC_LEFT(ic));
1714
1715     tlbl = newiTempLabel(NULL);
1716     pic14_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
1717     pic14_emitcode("","%05d_DS_:",tlbl->key+100);
1718     pic14_outBitC(IC_RESULT(ic));
1719
1720 release:    
1721     /* release the aops */
1722     freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1723     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1724 }
1725
1726
1727 /*-----------------------------------------------------------------*/
1728 /* genCpl - generate code for complement                           */
1729 /*-----------------------------------------------------------------*/
1730 static void genCpl (iCode *ic)
1731 {
1732     int offset = 0;
1733     int size ;
1734
1735
1736     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1737     /* assign asmOps to operand & result */
1738     aopOp (IC_LEFT(ic),ic,FALSE);
1739     aopOp (IC_RESULT(ic),ic,TRUE);
1740
1741     /* if both are in bit space then 
1742     a special case */
1743     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1744         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
1745
1746         pic14_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
1747         pic14_emitcode("cpl","c"); 
1748         pic14_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
1749         goto release; 
1750     } 
1751
1752     size = AOP_SIZE(IC_RESULT(ic));
1753     while (size--) {
1754         char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1755         MOVA(l);       
1756         pic14_emitcode("cpl","a");
1757         aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1758     }
1759
1760
1761 release:
1762     /* release the aops */
1763     freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1764     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1765 }
1766
1767 /*-----------------------------------------------------------------*/
1768 /* genUminusFloat - unary minus for floating points                */
1769 /*-----------------------------------------------------------------*/
1770 static void genUminusFloat(operand *op,operand *result)
1771 {
1772     int size ,offset =0 ;
1773     char *l;
1774
1775     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1776     /* for this we just need to flip the 
1777     first it then copy the rest in place */
1778     size = AOP_SIZE(op) - 1;
1779     l = aopGet(AOP(op),3,FALSE,FALSE);
1780
1781     MOVA(l);    
1782
1783     pic14_emitcode("cpl","acc.7");
1784     aopPut(AOP(result),"a",3);    
1785
1786     while(size--) {
1787         aopPut(AOP(result),
1788                aopGet(AOP(op),offset,FALSE,FALSE),
1789                offset);
1790         offset++;
1791     }          
1792 }
1793
1794 /*-----------------------------------------------------------------*/
1795 /* genUminus - unary minus code generation                         */
1796 /*-----------------------------------------------------------------*/
1797 static void genUminus (iCode *ic)
1798 {
1799     int offset ,size ;
1800     sym_link *optype, *rtype;
1801
1802
1803     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1804     /* assign asmops */
1805     aopOp(IC_LEFT(ic),ic,FALSE);
1806     aopOp(IC_RESULT(ic),ic,TRUE);
1807
1808     /* if both in bit space then special
1809     case */
1810     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1811         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
1812
1813         pic14_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
1814         pic14_emitcode("cpl","c"); 
1815         pic14_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
1816         goto release; 
1817     } 
1818
1819     optype = operandType(IC_LEFT(ic));
1820     rtype = operandType(IC_RESULT(ic));
1821
1822     /* if float then do float stuff */
1823     if (IS_FLOAT(optype)) {
1824         genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1825         goto release;
1826     }
1827
1828     /* otherwise subtract from zero */
1829     size = AOP_SIZE(IC_LEFT(ic));
1830     offset = 0 ;
1831     CLRC ;
1832     while(size--) {
1833         char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1834         if (!strcmp(l,"a")) {
1835             pic14_emitcode("cpl","a");
1836             pic14_emitcode("inc","a");
1837         } else {
1838             pic14_emitcode("clr","a");
1839             pic14_emitcode("subb","a,%s",l);
1840         }       
1841         aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1842     }
1843
1844     /* if any remaining bytes in the result */
1845     /* we just need to propagate the sign   */
1846     if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1847         pic14_emitcode("rlc","a");
1848         pic14_emitcode("subb","a,acc");
1849         while (size--) 
1850             aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1851     }       
1852
1853 release:
1854     /* release the aops */
1855     freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1856     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
1857 }
1858
1859 /*-----------------------------------------------------------------*/
1860 /* saveRegisters - will look for a call and save the registers     */
1861 /*-----------------------------------------------------------------*/
1862 static void saveRegisters(iCode *lic) 
1863 {
1864     int i;
1865     iCode *ic;
1866     bitVect *rsave;
1867     sym_link *dtype;
1868
1869     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1870     /* look for call */
1871     for (ic = lic ; ic ; ic = ic->next) 
1872         if (ic->op == CALL || ic->op == PCALL)
1873             break;
1874
1875     if (!ic) {
1876         fprintf(stderr,"found parameter push with no function call\n");
1877         return ;
1878     }
1879
1880     /* if the registers have been saved already then
1881     do nothing */
1882     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
1883         return ;
1884
1885     /* find the registers in use at this time 
1886     and push them away to safety */
1887     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1888                           ic->rUsed);
1889
1890     ic->regsSaved = 1;
1891     if (options.useXstack) {
1892         if (bitVectBitValue(rsave,R0_IDX))
1893             pic14_emitcode("mov","b,r0");
1894         pic14_emitcode("mov","r0,%s",spname);
1895         for (i = 0 ; i < pic14_nRegs ; i++) {
1896             if (bitVectBitValue(rsave,i)) {
1897                 if (i == R0_IDX)
1898                     pic14_emitcode("mov","a,b");
1899                 else
1900                     pic14_emitcode("mov","a,%s",pic14_regWithIdx(i)->name);
1901                 pic14_emitcode("movx","@r0,a");
1902                 pic14_emitcode("inc","r0");
1903             }
1904         }
1905         pic14_emitcode("mov","%s,r0",spname);
1906         if (bitVectBitValue(rsave,R0_IDX))
1907             pic14_emitcode("mov","r0,b");           
1908     } else
1909         for (i = 0 ; i < pic14_nRegs ; i++) {
1910             if (bitVectBitValue(rsave,i))
1911                 pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
1912         }
1913
1914     dtype = operandType(IC_LEFT(ic));
1915     if (dtype        && 
1916         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
1917         IFFUNC_ISISR(currFunc->type) &&
1918         !ic->bankSaved) 
1919
1920         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
1921
1922 }
1923 /*-----------------------------------------------------------------*/
1924 /* unsaveRegisters - pop the pushed registers                      */
1925 /*-----------------------------------------------------------------*/
1926 static void unsaveRegisters (iCode *ic)
1927 {
1928     int i;
1929     bitVect *rsave;
1930
1931     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1932     /* find the registers in use at this time 
1933     and push them away to safety */
1934     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1935                           ic->rUsed);
1936     
1937     if (options.useXstack) {
1938         pic14_emitcode("mov","r0,%s",spname);   
1939         for (i =  pic14_nRegs ; i >= 0 ; i--) {
1940             if (bitVectBitValue(rsave,i)) {
1941                 pic14_emitcode("dec","r0");
1942                 pic14_emitcode("movx","a,@r0");
1943                 if (i == R0_IDX)
1944                     pic14_emitcode("mov","b,a");
1945                 else
1946                     pic14_emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
1947             }       
1948
1949         }
1950         pic14_emitcode("mov","%s,r0",spname);
1951         if (bitVectBitValue(rsave,R0_IDX))
1952             pic14_emitcode("mov","r0,b");
1953     } else
1954         for (i =  pic14_nRegs ; i >= 0 ; i--) {
1955             if (bitVectBitValue(rsave,i))
1956                 pic14_emitcode("pop","%s",pic14_regWithIdx(i)->dname);
1957         }
1958
1959 }  
1960
1961
1962 /*-----------------------------------------------------------------*/
1963 /* pushSide -                                                      */
1964 /*-----------------------------------------------------------------*/
1965 static void pushSide(operand * oper, int size)
1966 {
1967 #if 0
1968         int offset = 0;
1969     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1970         while (size--) {
1971                 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
1972                 if (AOP_TYPE(oper) != AOP_REG &&
1973                     AOP_TYPE(oper) != AOP_DIR &&
1974                     strcmp(l,"a") ) {
1975                         pic14_emitcode("mov","a,%s",l);
1976                         pic14_emitcode("push","acc");
1977                 } else
1978                         pic14_emitcode("push","%s",l);
1979         }
1980 #endif
1981 }
1982
1983 /*-----------------------------------------------------------------*/
1984 /* assignResultValue -                                             */
1985 /*-----------------------------------------------------------------*/
1986 static void assignResultValue(operand * oper)
1987 {
1988   int offset = 0;
1989   int size = AOP_SIZE(oper);
1990
1991   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1992
1993   if(!GpsuedoStkPtr) {
1994     /* The last byte in the assignment is in W */
1995     //aopPut(AOP(oper),"W",size-1);
1996     emitpcode(POC_MOVWF, popGet(AOP(oper),0,FALSE,FALSE));
1997     GpsuedoStkPtr++;
1998     if(size == 1)
1999       return;
2000     size--;
2001     offset++;
2002   }
2003
2004   while (size--) {
2005     emitpcode(POC_MOVFW,popRegFromIdx(GpsuedoStkPtr-1 + Gstack_base_addr));
2006     emitpcode(POC_MOVWF, popGet(AOP(oper),offset,FALSE,FALSE));
2007     offset++;
2008     GpsuedoStkPtr++;
2009
2010   }
2011 }
2012
2013
2014 /*-----------------------------------------------------------------*/
2015 /* genXpush - pushes onto the external stack                       */
2016 /*-----------------------------------------------------------------*/
2017 static void genXpush (iCode *ic)
2018 {
2019     asmop *aop = newAsmop(0);
2020     regs *r ;
2021     int size,offset = 0;
2022
2023     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2024     aopOp(IC_LEFT(ic),ic,FALSE);
2025     r = getFreePtr(ic,&aop,FALSE);
2026
2027     
2028     pic14_emitcode("mov","%s,_spx",r->name);
2029
2030     size = AOP_SIZE(IC_LEFT(ic));
2031     while(size--) {
2032
2033         char *l = aopGet(AOP(IC_LEFT(ic)),
2034                          offset++,FALSE,FALSE); 
2035         MOVA(l);            
2036         pic14_emitcode("movx","@%s,a",r->name); 
2037         pic14_emitcode("inc","%s",r->name);
2038
2039     }
2040
2041         
2042     pic14_emitcode("mov","_spx,%s",r->name);
2043
2044     freeAsmop(NULL,aop,ic,TRUE);
2045     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2046 }
2047
2048 /*-----------------------------------------------------------------*/
2049 /* genIpush - genrate code for pushing this gets a little complex  */
2050 /*-----------------------------------------------------------------*/
2051 static void genIpush (iCode *ic)
2052 {
2053     int size, offset = 0 ;
2054     char *l;
2055
2056
2057     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2058     /* if this is not a parm push : ie. it is spill push 
2059     and spill push is always done on the local stack */
2060     if (!ic->parmPush) {
2061
2062         /* and the item is spilt then do nothing */
2063         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2064             return ;
2065
2066         aopOp(IC_LEFT(ic),ic,FALSE);
2067         size = AOP_SIZE(IC_LEFT(ic));
2068         /* push it on the stack */
2069         while(size--) {
2070             l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2071             if (*l == '#') {
2072                 MOVA(l);
2073                 l = "acc";
2074             }
2075             pic14_emitcode("push","%s",l);
2076         }
2077         return ;        
2078     }
2079
2080     /* this is a paramter push: in this case we call
2081     the routine to find the call and save those
2082     registers that need to be saved */   
2083     saveRegisters(ic);
2084
2085     /* if use external stack then call the external
2086     stack pushing routine */
2087     if (options.useXstack) {
2088         genXpush(ic);
2089         return ;
2090     }
2091
2092     /* then do the push */
2093     aopOp(IC_LEFT(ic),ic,FALSE);
2094
2095
2096         // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2097     size = AOP_SIZE(IC_LEFT(ic));
2098
2099     while (size--) {
2100         l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2101         if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && 
2102             AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2103             strcmp(l,"a") ) {
2104             pic14_emitcode("mov","a,%s",l);
2105             pic14_emitcode("push","acc");
2106         } else
2107             pic14_emitcode("push","%s",l);
2108     }       
2109
2110     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2111 }
2112
2113 /*-----------------------------------------------------------------*/
2114 /* genIpop - recover the registers: can happen only for spilling   */
2115 /*-----------------------------------------------------------------*/
2116 static void genIpop (iCode *ic)
2117 {
2118     int size,offset ;
2119
2120
2121     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2122     /* if the temp was not pushed then */
2123     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2124         return ;
2125
2126     aopOp(IC_LEFT(ic),ic,FALSE);
2127     size = AOP_SIZE(IC_LEFT(ic));
2128     offset = (size-1);
2129     while (size--) 
2130         pic14_emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
2131                                    FALSE,TRUE));
2132
2133     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2134 }
2135
2136 /*-----------------------------------------------------------------*/
2137 /* unsaverbank - restores the resgister bank from stack            */
2138 /*-----------------------------------------------------------------*/
2139 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2140 {
2141     int i;
2142     asmop *aop ;
2143     regs *r = NULL;
2144
2145     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2146     if (popPsw) {
2147         if (options.useXstack) {
2148             aop = newAsmop(0);
2149             r = getFreePtr(ic,&aop,FALSE);
2150             
2151             
2152             pic14_emitcode("mov","%s,_spx",r->name);
2153             pic14_emitcode("movx","a,@%s",r->name);
2154             pic14_emitcode("mov","psw,a");
2155             pic14_emitcode("dec","%s",r->name);
2156             
2157         }else
2158             pic14_emitcode ("pop","psw");
2159     }
2160
2161     for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
2162         if (options.useXstack) {       
2163             pic14_emitcode("movx","a,@%s",r->name);
2164             //pic14_emitcode("mov","(%s+%d),a",
2165             //       regspic14[i].base,8*bank+regspic14[i].offset);
2166             pic14_emitcode("dec","%s",r->name);
2167
2168         } else 
2169           pic14_emitcode("pop",""); //"(%s+%d)",
2170         //regspic14[i].base,8*bank); //+regspic14[i].offset);
2171     }
2172
2173     if (options.useXstack) {
2174
2175         pic14_emitcode("mov","_spx,%s",r->name);
2176         freeAsmop(NULL,aop,ic,TRUE);
2177
2178     } 
2179 }
2180
2181 /*-----------------------------------------------------------------*/
2182 /* saverbank - saves an entire register bank on the stack          */
2183 /*-----------------------------------------------------------------*/
2184 static void saverbank (int bank, iCode *ic, bool pushPsw)
2185 {
2186     int i;
2187     asmop *aop ;
2188     regs *r = NULL;
2189
2190     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2191     if (options.useXstack) {
2192
2193         aop = newAsmop(0);
2194         r = getFreePtr(ic,&aop,FALSE);  
2195         pic14_emitcode("mov","%s,_spx",r->name);
2196
2197     }
2198
2199     for (i = 0 ; i < pic14_nRegs ;i++) {
2200         if (options.useXstack) {
2201             pic14_emitcode("inc","%s",r->name);
2202             //pic14_emitcode("mov","a,(%s+%d)",
2203             //         regspic14[i].base,8*bank+regspic14[i].offset);
2204             pic14_emitcode("movx","@%s,a",r->name);           
2205         } else 
2206           pic14_emitcode("push","");// "(%s+%d)",
2207                      //regspic14[i].base,8*bank+regspic14[i].offset);
2208     }
2209     
2210     if (pushPsw) {
2211         if (options.useXstack) {
2212             pic14_emitcode("mov","a,psw");
2213             pic14_emitcode("movx","@%s,a",r->name);     
2214             pic14_emitcode("inc","%s",r->name);
2215             pic14_emitcode("mov","_spx,%s",r->name);       
2216             freeAsmop (NULL,aop,ic,TRUE);
2217             
2218         } else
2219             pic14_emitcode("push","psw");
2220         
2221         pic14_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2222     }
2223     ic->bankSaved = 1;
2224
2225 }
2226
2227 /*-----------------------------------------------------------------*/
2228 /* genCall - generates a call statement                            */
2229 /*-----------------------------------------------------------------*/
2230 static void genCall (iCode *ic)
2231 {
2232   sym_link *dtype;   
2233
2234   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2235
2236   /* if caller saves & we have not saved then */
2237   if (!ic->regsSaved)
2238     saveRegisters(ic);
2239
2240   /* if we are calling a function that is not using
2241      the same register bank then we need to save the
2242      destination registers on the stack */
2243   dtype = operandType(IC_LEFT(ic));
2244   if (dtype        && 
2245       (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2246       IFFUNC_ISISR(currFunc->type) &&
2247       !ic->bankSaved) 
2248
2249     saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2250
2251   /* if send set is not empty the assign */
2252   if (_G.sendSet) {
2253     iCode *sic;
2254     /* For the Pic port, there is no data stack.
2255      * So parameters passed to functions are stored
2256      * in registers. (The pCode optimizer will get
2257      * rid of most of these :).
2258      */
2259     int psuedoStkPtr=0; 
2260     int firstTimeThruLoop = 1;
2261
2262     for (sic = setFirstItem(_G.sendSet) ; sic ; 
2263          sic = setNextItem(_G.sendSet)) {
2264       int size, offset = 0;
2265
2266       aopOp(IC_LEFT(sic),sic,FALSE);
2267       size = AOP_SIZE(IC_LEFT(sic));
2268
2269
2270       while (size--) {
2271         char *l = aopGet(AOP(IC_LEFT(sic)),offset,
2272                          FALSE,FALSE);
2273         DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2274                              AopType(AOP_TYPE(IC_LEFT(sic))));
2275
2276         if(!firstTimeThruLoop) {
2277           /* If is not the first time we've been through the loop
2278            * then we need to save the parameter in a temporary
2279            * register. The last byte of the last parameter is
2280            * passed in W. */
2281           pic14_emitcode("movwf","%s",fReturn[offset]);
2282           emitpcode(POC_MOVWF,popRegFromIdx(psuedoStkPtr + Gstack_base_addr));
2283           psuedoStkPtr++;
2284           DEBUGpic14_emitcode ("; ","%d save param in %d",__LINE__,
2285                                psuedoStkPtr+Gstack_base_addr);
2286         }
2287         firstTimeThruLoop=0;
2288
2289         if (strcmp(l,fReturn[offset])) {
2290
2291           if ( ((AOP(IC_LEFT(sic))->type) == AOP_IMMD) ||
2292                ((AOP(IC_LEFT(sic))->type) == AOP_LIT) )
2293             emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(sic)),size,FALSE,FALSE));
2294           //pic14_emitcode("movlw","%s",l);
2295           else
2296             emitpcode(POC_MOVFW,popGet(AOP(IC_LEFT(sic)),size,FALSE,FALSE));
2297           //pic14_emitcode("movf","%s,w",l);
2298
2299           /* The last one is passed in W but all others are passed on 
2300              the psuedo stack */
2301           /*
2302           if(size) {
2303             pic14_emitcode("movwf","%s",fReturn[offset]);
2304             emitpcode(POC_MOVWF,popRegFromIdx(offset + Gstack_base_addr));
2305           }
2306           */
2307         }
2308         offset++;
2309       }
2310       freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2311     }
2312     _G.sendSet = NULL;
2313   }
2314   /* make the call */
2315   emitpcode(POC_CALL,popGetWithString(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2316                                       OP_SYMBOL(IC_LEFT(ic))->rname :
2317                                       OP_SYMBOL(IC_LEFT(ic))->name));
2318
2319   GpsuedoStkPtr=0;
2320   /* if we need assign a result value */
2321   if ((IS_ITEMP(IC_RESULT(ic)) && 
2322        (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2323         OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2324       IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2325
2326     _G.accInUse++;
2327     aopOp(IC_RESULT(ic),ic,FALSE);
2328     _G.accInUse--;
2329
2330     assignResultValue(IC_RESULT(ic));
2331
2332     DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2333                          AopType(AOP_TYPE(IC_RESULT(ic))));
2334                 
2335     freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2336   }
2337
2338   /* adjust the stack for parameters if 
2339      required */
2340   if (ic->parmBytes) {
2341     int i;
2342     if (ic->parmBytes > 3) {
2343       pic14_emitcode("mov","a,%s",spname);
2344       pic14_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2345       pic14_emitcode("mov","%s,a",spname);
2346     } else 
2347       for ( i = 0 ; i <  ic->parmBytes ;i++)
2348         pic14_emitcode("dec","%s",spname);
2349
2350   }
2351
2352   /* if register bank was saved then pop them */
2353   if (ic->bankSaved)
2354     unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2355
2356   /* if we hade saved some registers then unsave them */
2357   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2358     unsaveRegisters (ic);
2359
2360
2361 }
2362
2363 /*-----------------------------------------------------------------*/
2364 /* genPcall - generates a call by pointer statement                */
2365 /*-----------------------------------------------------------------*/
2366 static void genPcall (iCode *ic)
2367 {
2368     sym_link *dtype;
2369     symbol *rlbl = newiTempLabel(NULL);
2370
2371
2372     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2373     /* if caller saves & we have not saved then */
2374     if (!ic->regsSaved)
2375         saveRegisters(ic);
2376
2377     /* if we are calling a function that is not using
2378     the same register bank then we need to save the
2379     destination registers on the stack */
2380     dtype = operandType(IC_LEFT(ic));
2381     if (dtype        && 
2382         IFFUNC_ISISR(currFunc->type) &&
2383         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2384         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2385
2386
2387     /* push the return address on to the stack */
2388     pic14_emitcode("mov","a,#%05d_DS_",(rlbl->key+100));
2389     pic14_emitcode("push","acc");    
2390     pic14_emitcode("mov","a,#(%05d_DS_ >> 8)",(rlbl->key+100));
2391     pic14_emitcode("push","acc");
2392     
2393     if (options.model == MODEL_FLAT24)
2394     {
2395         pic14_emitcode("mov","a,#(%05d_DS_ >> 16)",(rlbl->key+100));
2396         pic14_emitcode("push","acc");    
2397     }
2398
2399     /* now push the calling address */
2400     aopOp(IC_LEFT(ic),ic,FALSE);
2401
2402     pushSide(IC_LEFT(ic), FPTRSIZE);
2403
2404     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
2405
2406     /* if send set is not empty the assign */
2407     if (_G.sendSet) {
2408         iCode *sic ;
2409
2410         for (sic = setFirstItem(_G.sendSet) ; sic ; 
2411              sic = setNextItem(_G.sendSet)) {
2412             int size, offset = 0;
2413             aopOp(IC_LEFT(sic),sic,FALSE);
2414             size = AOP_SIZE(IC_LEFT(sic));
2415             while (size--) {
2416                 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
2417                                 FALSE,FALSE);
2418                 if (strcmp(l,fReturn[offset]))
2419                     pic14_emitcode("mov","%s,%s",
2420                              fReturn[offset],
2421                              l);
2422                 offset++;
2423             }
2424             freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2425         }
2426         _G.sendSet = NULL;
2427     }
2428
2429     pic14_emitcode("ret","");
2430     pic14_emitcode("","%05d_DS_:",(rlbl->key+100));
2431
2432
2433     /* if we need assign a result value */
2434     if ((IS_ITEMP(IC_RESULT(ic)) &&
2435          (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2436           OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2437         IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2438
2439         _G.accInUse++;
2440         aopOp(IC_RESULT(ic),ic,FALSE);
2441         _G.accInUse--;
2442         
2443         assignResultValue(IC_RESULT(ic));
2444
2445         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2446     }
2447
2448     /* adjust the stack for parameters if 
2449     required */
2450     if (ic->parmBytes) {
2451         int i;
2452         if (ic->parmBytes > 3) {
2453             pic14_emitcode("mov","a,%s",spname);
2454             pic14_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2455             pic14_emitcode("mov","%s,a",spname);
2456         } else 
2457             for ( i = 0 ; i <  ic->parmBytes ;i++)
2458                 pic14_emitcode("dec","%s",spname);
2459
2460     }
2461
2462     /* if register bank was saved then unsave them */
2463     if (dtype        && 
2464         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2465         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2466
2467     /* if we hade saved some registers then
2468     unsave them */
2469     if (ic->regsSaved)
2470         unsaveRegisters (ic);
2471
2472 }
2473
2474 /*-----------------------------------------------------------------*/
2475 /* resultRemat - result  is rematerializable                       */
2476 /*-----------------------------------------------------------------*/
2477 static int resultRemat (iCode *ic)
2478 {
2479     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2480     if (SKIP_IC(ic) || ic->op == IFX)
2481         return 0;
2482
2483     if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2484         symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2485         if (sym->remat && !POINTER_SET(ic)) 
2486             return 1;
2487     }
2488
2489     return 0;
2490 }
2491
2492 #if defined(__BORLANDC__) || defined(_MSC_VER)
2493 #define STRCASECMP stricmp
2494 #else
2495 #define STRCASECMP strcasecmp
2496 #endif
2497
2498 /*-----------------------------------------------------------------*/
2499 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2500 /*-----------------------------------------------------------------*/
2501 static bool inExcludeList(char *s)
2502 {
2503     int i =0;
2504     
2505     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2506     if (options.excludeRegs[i] &&
2507     STRCASECMP(options.excludeRegs[i],"none") == 0)
2508         return FALSE ;
2509
2510     for ( i = 0 ; options.excludeRegs[i]; i++) {
2511         if (options.excludeRegs[i] &&
2512         STRCASECMP(s,options.excludeRegs[i]) == 0)
2513             return TRUE;
2514     }
2515     return FALSE ;
2516 }
2517
2518 /*-----------------------------------------------------------------*/
2519 /* genFunction - generated code for function entry                 */
2520 /*-----------------------------------------------------------------*/
2521 static void genFunction (iCode *ic)
2522 {
2523     symbol *sym;
2524     sym_link *ftype;
2525
2526     DEBUGpic14_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2527
2528     labelOffset += (max_key+4);
2529     max_key=0;
2530     GpsuedoStkPtr=0;
2531     _G.nRegsSaved = 0;
2532     /* create the function header */
2533     pic14_emitcode(";","-----------------------------------------");
2534     pic14_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2535     pic14_emitcode(";","-----------------------------------------");
2536
2537     pic14_emitcode("","%s:",sym->rname);
2538     addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname));
2539
2540     ftype = operandType(IC_LEFT(ic));
2541
2542     /* if critical function then turn interrupts off */
2543     if (IFFUNC_ISCRITICAL(ftype))
2544         pic14_emitcode("clr","ea");
2545
2546     /* here we need to generate the equates for the
2547        register bank if required */
2548 #if 0
2549     if (FUNC_REGBANK(ftype) != rbank) {
2550         int i ;
2551
2552         rbank = FUNC_REGBANK(ftype);
2553         for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2554             if (strcmp(regspic14[i].base,"0") == 0)
2555                 pic14_emitcode("","%s = 0x%02x",
2556                          regspic14[i].dname,
2557                          8*rbank+regspic14[i].offset);
2558             else
2559                 pic14_emitcode ("","%s = %s + 0x%02x",
2560                           regspic14[i].dname,
2561                           regspic14[i].base,
2562                           8*rbank+regspic14[i].offset);
2563         }
2564     }
2565 #endif
2566
2567     /* if this is an interrupt service routine then
2568     save acc, b, dpl, dph  */
2569     if (IFFUNC_ISISR(sym->type)) {
2570         
2571         if (!inExcludeList("acc"))          
2572             pic14_emitcode ("push","acc");      
2573         if (!inExcludeList("b"))
2574             pic14_emitcode ("push","b");
2575         if (!inExcludeList("dpl"))
2576             pic14_emitcode ("push","dpl");
2577         if (!inExcludeList("dph"))
2578             pic14_emitcode ("push","dph");
2579         if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2580         {
2581             pic14_emitcode ("push", "dpx");
2582             /* Make sure we're using standard DPTR */
2583             pic14_emitcode ("push", "dps");
2584             pic14_emitcode ("mov", "dps, #0x00");
2585             if (options.stack10bit)
2586             {   
2587                 /* This ISR could conceivably use DPTR2. Better save it. */
2588                 pic14_emitcode ("push", "dpl1");
2589                 pic14_emitcode ("push", "dph1");
2590                 pic14_emitcode ("push", "dpx1");
2591             }
2592         }
2593         /* if this isr has no bank i.e. is going to
2594            run with bank 0 , then we need to save more
2595            registers :-) */
2596         if (!FUNC_REGBANK(sym->type)) {
2597
2598             /* if this function does not call any other
2599                function then we can be economical and
2600                save only those registers that are used */
2601             if (! IFFUNC_HASFCALL(sym->type)) {
2602                 int i;
2603
2604                 /* if any registers used */
2605                 if (sym->regsUsed) {
2606                     /* save the registers used */
2607                     for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2608                         if (bitVectBitValue(sym->regsUsed,i) ||
2609                           (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2610                             pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);                         
2611                     }
2612                 }
2613                 
2614             } else {
2615                 /* this function has  a function call cannot
2616                    determines register usage so we will have the
2617                    entire bank */
2618                 saverbank(0,ic,FALSE);
2619             }       
2620         }
2621     } else {
2622         /* if callee-save to be used for this function
2623            then save the registers being used in this function */
2624         if (IFFUNC_CALLEESAVES(sym->type)) {
2625             int i;
2626             
2627             /* if any registers used */
2628             if (sym->regsUsed) {
2629                 /* save the registers used */
2630                 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2631                     if (bitVectBitValue(sym->regsUsed,i) ||
2632                       (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2633                         pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2634                         _G.nRegsSaved++;
2635                     }
2636                 }
2637             }
2638         }
2639     }
2640
2641     /* set the register bank to the desired value */
2642     if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type)) {
2643         pic14_emitcode("push","psw");
2644         pic14_emitcode("mov","psw,#0x%02x",(FUNC_REGBANK(sym->type) << 3)&0x00ff);   
2645     }
2646
2647     if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
2648
2649         if (options.useXstack) {
2650             pic14_emitcode("mov","r0,%s",spname);
2651             pic14_emitcode("mov","a,_bp");
2652             pic14_emitcode("movx","@r0,a");
2653             pic14_emitcode("inc","%s",spname);
2654         }
2655         else
2656         {
2657             /* set up the stack */
2658             pic14_emitcode ("push","_bp");     /* save the callers stack  */
2659         }
2660         pic14_emitcode ("mov","_bp,%s",spname);
2661     }
2662
2663     /* adjust the stack for the function */
2664     if (sym->stack) {
2665
2666         int i = sym->stack;
2667         if (i > 256 ) 
2668             werror(W_STACK_OVERFLOW,sym->name);
2669
2670         if (i > 3 && sym->recvSize < 4) {              
2671
2672             pic14_emitcode ("mov","a,sp");
2673             pic14_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2674             pic14_emitcode ("mov","sp,a");
2675            
2676         }
2677         else
2678             while(i--)
2679                 pic14_emitcode("inc","sp");
2680     }
2681
2682      if (sym->xstack) {
2683
2684         pic14_emitcode ("mov","a,_spx");
2685         pic14_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2686         pic14_emitcode ("mov","_spx,a");
2687     }    
2688
2689 }
2690
2691 /*-----------------------------------------------------------------*/
2692 /* genEndFunction - generates epilogue for functions               */
2693 /*-----------------------------------------------------------------*/
2694 static void genEndFunction (iCode *ic)
2695 {
2696     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2697
2698     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2699
2700     if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
2701     {
2702         pic14_emitcode ("mov","%s,_bp",spname);
2703     }
2704
2705     /* if use external stack but some variables were
2706     added to the local stack then decrement the
2707     local stack */
2708     if (options.useXstack && sym->stack) {      
2709         pic14_emitcode("mov","a,sp");
2710         pic14_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2711         pic14_emitcode("mov","sp,a");
2712     }
2713
2714
2715     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
2716         if (options.useXstack) {
2717             pic14_emitcode("mov","r0,%s",spname);
2718             pic14_emitcode("movx","a,@r0");
2719             pic14_emitcode("mov","_bp,a");
2720             pic14_emitcode("dec","%s",spname);
2721         }
2722         else
2723         {
2724             pic14_emitcode ("pop","_bp");
2725         }
2726     }
2727
2728     /* restore the register bank  */    
2729     if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
2730         pic14_emitcode ("pop","psw");
2731
2732     if (IFFUNC_ISISR(sym->type)) {
2733
2734         /* now we need to restore the registers */
2735         /* if this isr has no bank i.e. is going to
2736            run with bank 0 , then we need to save more
2737            registers :-) */
2738         if (!FUNC_REGBANK(sym->type)) {
2739             
2740             /* if this function does not call any other
2741                function then we can be economical and
2742                save only those registers that are used */
2743             if (! IFFUNC_HASFCALL(sym->type)) {
2744                 int i;
2745                 
2746                 /* if any registers used */
2747                 if (sym->regsUsed) {
2748                     /* save the registers used */
2749                     for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2750                         if (bitVectBitValue(sym->regsUsed,i) ||
2751                           (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2752                             pic14_emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2753                     }
2754                 }
2755                 
2756             } else {
2757                 /* this function has  a function call cannot
2758                    determines register usage so we will have the
2759                    entire bank */
2760                 unsaverbank(0,ic,FALSE);
2761             }       
2762         }
2763
2764         if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2765         {
2766             if (options.stack10bit)
2767             {
2768                 pic14_emitcode ("pop", "dpx1");
2769                 pic14_emitcode ("pop", "dph1");
2770                 pic14_emitcode ("pop", "dpl1");
2771             }   
2772             pic14_emitcode ("pop", "dps");
2773             pic14_emitcode ("pop", "dpx");
2774         }
2775         if (!inExcludeList("dph"))
2776             pic14_emitcode ("pop","dph");
2777         if (!inExcludeList("dpl"))
2778             pic14_emitcode ("pop","dpl");
2779         if (!inExcludeList("b"))
2780             pic14_emitcode ("pop","b");
2781         if (!inExcludeList("acc"))
2782             pic14_emitcode ("pop","acc");
2783
2784         if (IFFUNC_ISCRITICAL(sym->type))
2785             pic14_emitcode("setb","ea");
2786
2787         /* if debug then send end of function */
2788 /*      if (options.debug && currFunc) { */
2789         if (currFunc) {
2790             _G.debugLine = 1;
2791             pic14_emitcode(";","C$%s$%d$%d$%d ==.",
2792                      FileBaseName(ic->filename),currFunc->lastLine,
2793                      ic->level,ic->block); 
2794             if (IS_STATIC(currFunc->etype))         
2795                 pic14_emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
2796             else
2797                 pic14_emitcode(";","XG$%s$0$0 ==.",currFunc->name);
2798             _G.debugLine = 0;
2799         }
2800         
2801         pic14_emitcode ("reti","");
2802     }
2803     else {
2804         if (IFFUNC_ISCRITICAL(sym->type))
2805             pic14_emitcode("setb","ea");
2806         
2807         if (IFFUNC_CALLEESAVES(sym->type)) {
2808             int i;
2809             
2810             /* if any registers used */
2811             if (sym->regsUsed) {
2812                 /* save the registers used */
2813                 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2814                     if (bitVectBitValue(sym->regsUsed,i) ||
2815                       (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2816                         pic14_emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2817                 }
2818             }
2819             
2820         }
2821
2822         /* if debug then send end of function */
2823         if (currFunc) {
2824             _G.debugLine = 1;
2825             pic14_emitcode(";","C$%s$%d$%d$%d ==.",
2826                      FileBaseName(ic->filename),currFunc->lastLine,
2827                      ic->level,ic->block); 
2828             if (IS_STATIC(currFunc->etype))         
2829                 pic14_emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
2830             else
2831                 pic14_emitcode(";","XG$%s$0$0 ==.",currFunc->name);
2832             _G.debugLine = 0;
2833         }
2834
2835         pic14_emitcode ("return","");
2836         emitpcodeNULLop(POC_RETURN);
2837
2838         /* Mark the end of a function */
2839         addpCode2pBlock(pb,newpCodeFunction(NULL,NULL));
2840     }
2841
2842 }
2843
2844 /*-----------------------------------------------------------------*/
2845 /* genRet - generate code for return statement                     */
2846 /*-----------------------------------------------------------------*/
2847 static void genRet (iCode *ic)
2848 {
2849   int size,offset = 0 , pushed = 0;
2850     
2851   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2852   /* if we have no return value then
2853      just generate the "ret" */
2854   if (!IC_LEFT(ic)) 
2855     goto jumpret;       
2856     
2857   /* we have something to return then
2858      move the return value into place */
2859   aopOp(IC_LEFT(ic),ic,FALSE);
2860   size = AOP_SIZE(IC_LEFT(ic));
2861     
2862   while (size--) {
2863     char *l ;
2864     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
2865       /* #NOCHANGE */
2866       l = aopGet(AOP(IC_LEFT(ic)),offset++,
2867                  FALSE,TRUE);
2868       pic14_emitcode("push","%s",l);
2869       pushed++;
2870     } else {
2871       l = aopGet(AOP(IC_LEFT(ic)),offset,
2872                  FALSE,FALSE);
2873       if (strcmp(fReturn[offset],l)) {
2874         if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD) ||
2875             ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
2876           emitpcode(POC_MOVLW, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2877           pic14_emitcode("movlw","%s",l);
2878         }else {
2879           emitpcode(POC_MOVFW, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2880           pic14_emitcode("movf","%s,w",l);
2881         }
2882         if(size) {
2883           emitpcode(POC_MOVWF,popRegFromIdx(offset + Gstack_base_addr));
2884           pic14_emitcode("movwf","%s",fReturn[offset]);
2885         }
2886         offset++;
2887       }
2888     }
2889   }    
2890
2891   if (pushed) {
2892     while(pushed) {
2893       pushed--;
2894       if (strcmp(fReturn[pushed],"a"))
2895         pic14_emitcode("pop",fReturn[pushed]);
2896       else
2897         pic14_emitcode("pop","acc");
2898     }
2899   }
2900   freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2901     
2902  jumpret:
2903   /* generate a jump to the return label
2904      if the next is not the return statement */
2905   if (!(ic->next && ic->next->op == LABEL &&
2906         IC_LABEL(ic->next) == returnLabel)) {
2907         
2908     emitpcode(POC_GOTO,popGetLabel(returnLabel->key));
2909     pic14_emitcode("goto","_%05d_DS_",returnLabel->key+100 + labelOffset);
2910   }
2911     
2912 }
2913
2914 /*-----------------------------------------------------------------*/
2915 /* genLabel - generates a label                                    */
2916 /*-----------------------------------------------------------------*/
2917 static void genLabel (iCode *ic)
2918 {
2919     /* special case never generate */
2920     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2921     if (IC_LABEL(ic) == entryLabel)
2922         return ;
2923
2924     emitpLabel(IC_LABEL(ic)->key);
2925     pic14_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
2926 }
2927
2928 /*-----------------------------------------------------------------*/
2929 /* genGoto - generates a goto                                      */
2930 /*-----------------------------------------------------------------*/
2931 //tsd
2932 static void genGoto (iCode *ic)
2933 {
2934   emitpcode(POC_GOTO,popGetLabel(IC_LABEL(ic)->key));
2935   pic14_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
2936 }
2937
2938 /*-----------------------------------------------------------------*/
2939 /* findLabelBackwards: walks back through the iCode chain looking  */
2940 /* for the given label. Returns number of iCode instructions       */
2941 /* between that label and given ic.                                */
2942 /* Returns zero if label not found.                                */
2943 /*-----------------------------------------------------------------*/
2944 #if 0
2945 static int findLabelBackwards(iCode *ic, int key)
2946 {
2947     int count = 0;
2948     
2949     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2950     while (ic->prev)
2951     {
2952         ic = ic->prev;
2953         count++;
2954         
2955         if (ic->op == LABEL && IC_LABEL(ic)->key == key)
2956         {
2957             /* printf("findLabelBackwards = %d\n", count); */
2958             return count;
2959         }
2960     }
2961     
2962     return 0;
2963 }
2964 #endif
2965
2966 /*-----------------------------------------------------------------*/
2967 /* genMultbits :- multiplication of bits                           */
2968 /*-----------------------------------------------------------------*/
2969 static void genMultbits (operand *left, 
2970                          operand *right, 
2971                          operand *result)
2972 {
2973     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2974
2975     pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
2976     pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
2977     pic14_outBitC(result);
2978 }
2979
2980
2981 /*-----------------------------------------------------------------*/
2982 /* genMultOneByte : 8 bit multiplication & division                */
2983 /*-----------------------------------------------------------------*/
2984 static void genMultOneByte (operand *left,
2985                             operand *right,
2986                             operand *result)
2987 {
2988     sym_link *opetype = operandType(result);
2989     char *l ;
2990     symbol *lbl ;
2991     int size,offset;
2992
2993     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2994     /* (if two literals, the value is computed before) */
2995     /* if one literal, literal on the right */
2996     if (AOP_TYPE(left) == AOP_LIT){
2997         operand *t = right;
2998         right = left;
2999         left = t;
3000     }
3001
3002     size = AOP_SIZE(result);
3003     /* signed or unsigned */
3004     pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3005     l = aopGet(AOP(left),0,FALSE,FALSE);
3006     MOVA(l);       
3007     pic14_emitcode("mul","ab");
3008     /* if result size = 1, mul signed = mul unsigned */
3009     aopPut(AOP(result),"a",0);
3010     if (size > 1){
3011         if (SPEC_USIGN(opetype)){
3012             aopPut(AOP(result),"b",1);
3013             if (size > 2)
3014                 /* for filling the MSBs */
3015                 pic14_emitcode("clr","a");
3016         }
3017         else{
3018             pic14_emitcode("mov","a,b");
3019
3020             /* adjust the MSB if left or right neg */
3021
3022             /* if one literal */
3023             if (AOP_TYPE(right) == AOP_LIT){
3024                 /* AND literal negative */
3025                 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3026                     /* adjust MSB (c==0 after mul) */
3027                     pic14_emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
3028                 }
3029             }
3030             else{
3031                 lbl = newiTempLabel(NULL);
3032                 pic14_emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3033                 pic14_emitcode("cjne","a,#0x80,%05d_DS_", (lbl->key+100));
3034                 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3035                 pic14_emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3036                 lbl = newiTempLabel(NULL);      
3037                 pic14_emitcode("jc","%05d_DS_",(lbl->key+100));          
3038                 pic14_emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
3039                 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3040             }
3041
3042             lbl = newiTempLabel(NULL);
3043             pic14_emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
3044             pic14_emitcode("cjne","a,#0x80,%05d_DS_", (lbl->key+100));
3045             pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3046             pic14_emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
3047             lbl = newiTempLabel(NULL);      
3048             pic14_emitcode("jc","%05d_DS_",(lbl->key+100));          
3049             pic14_emitcode("subb","a,%s", aopGet(AOP(right),0,FALSE,FALSE));
3050             pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3051
3052             aopPut(AOP(result),"a",1);
3053             if(size > 2){
3054                 /* get the sign */
3055                 pic14_emitcode("rlc","a");
3056                 pic14_emitcode("subb","a,acc");
3057             }
3058         }
3059         size -= 2;   
3060         offset = 2;
3061         if (size > 0)
3062             while (size--)
3063                 aopPut(AOP(result),"a",offset++);
3064     }
3065 }
3066
3067 /*-----------------------------------------------------------------*/
3068 /* genMult - generates code for multiplication                     */
3069 /*-----------------------------------------------------------------*/
3070 static void genMult (iCode *ic)
3071 {
3072     operand *left = IC_LEFT(ic);
3073     operand *right = IC_RIGHT(ic);
3074     operand *result= IC_RESULT(ic);   
3075
3076     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3077     /* assign the amsops */
3078     aopOp (left,ic,FALSE);
3079     aopOp (right,ic,FALSE);
3080     aopOp (result,ic,TRUE);
3081
3082     /* special cases first */
3083     /* both are bits */
3084     if (AOP_TYPE(left) == AOP_CRY &&
3085         AOP_TYPE(right)== AOP_CRY) {
3086         genMultbits(left,right,result);
3087         goto release ;
3088     }
3089
3090     /* if both are of size == 1 */
3091     if (AOP_SIZE(left) == 1 &&
3092         AOP_SIZE(right) == 1 ) {
3093         genMultOneByte(left,right,result);
3094         goto release ;
3095     }
3096
3097     /* should have been converted to function call */       
3098     assert(0) ;
3099
3100 release :
3101     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3102     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3103     freeAsmop(result,NULL,ic,TRUE); 
3104 }
3105
3106 /*-----------------------------------------------------------------*/
3107 /* genDivbits :- division of bits                                  */
3108 /*-----------------------------------------------------------------*/
3109 static void genDivbits (operand *left, 
3110                         operand *right, 
3111                         operand *result)
3112 {
3113
3114     char *l;
3115
3116     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3117     /* the result must be bit */    
3118     pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3119     l = aopGet(AOP(left),0,FALSE,FALSE);
3120
3121     MOVA(l);    
3122
3123     pic14_emitcode("div","ab");
3124     pic14_emitcode("rrc","a");
3125     aopPut(AOP(result),"c",0);
3126 }
3127
3128 /*-----------------------------------------------------------------*/
3129 /* genDivOneByte : 8 bit division                                  */
3130 /*-----------------------------------------------------------------*/
3131 static void genDivOneByte (operand *left,
3132                            operand *right,
3133                            operand *result)
3134 {
3135     sym_link *opetype = operandType(result);
3136     char *l ;
3137     symbol *lbl ;
3138     int size,offset;
3139
3140     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3141     size = AOP_SIZE(result) - 1;
3142     offset = 1;
3143     /* signed or unsigned */
3144     if (SPEC_USIGN(opetype)) {
3145         /* unsigned is easy */
3146         pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3147         l = aopGet(AOP(left),0,FALSE,FALSE);
3148         MOVA(l);        
3149         pic14_emitcode("div","ab");
3150         aopPut(AOP(result),"a",0);
3151         while (size--)
3152             aopPut(AOP(result),zero,offset++);
3153         return ;
3154     }
3155
3156     /* signed is a little bit more difficult */
3157
3158     /* save the signs of the operands */
3159     l = aopGet(AOP(left),0,FALSE,FALSE);    
3160     MOVA(l);    
3161     pic14_emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE));
3162     pic14_emitcode("push","acc"); /* save it on the stack */
3163
3164     /* now sign adjust for both left & right */
3165     l =  aopGet(AOP(right),0,FALSE,FALSE);    
3166     MOVA(l);       
3167     lbl = newiTempLabel(NULL);
3168     pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
3169     pic14_emitcode("cpl","a");   
3170     pic14_emitcode("inc","a");
3171     pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3172     pic14_emitcode("mov","b,a");
3173
3174     /* sign adjust left side */
3175     l =  aopGet(AOP(left),0,FALSE,FALSE);    
3176     MOVA(l);
3177
3178     lbl = newiTempLabel(NULL);
3179     pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3180     pic14_emitcode("cpl","a");
3181     pic14_emitcode("inc","a");
3182     pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3183
3184     /* now the division */
3185     pic14_emitcode("div","ab");
3186     /* we are interested in the lower order
3187     only */
3188     pic14_emitcode("mov","b,a");
3189     lbl = newiTempLabel(NULL);
3190     pic14_emitcode("pop","acc");   
3191     /* if there was an over flow we don't 
3192     adjust the sign of the result */
3193     pic14_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3194     pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3195     CLRC;
3196     pic14_emitcode("clr","a");
3197     pic14_emitcode("subb","a,b");
3198     pic14_emitcode("mov","b,a");
3199     pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3200
3201     /* now we are done */
3202     aopPut(AOP(result),"b",0);
3203     if(size > 0){
3204         pic14_emitcode("mov","c,b.7");
3205         pic14_emitcode("subb","a,acc");   
3206     }
3207     while (size--)
3208         aopPut(AOP(result),"a",offset++);
3209
3210 }
3211
3212 /*-----------------------------------------------------------------*/
3213 /* genDiv - generates code for division                            */
3214 /*-----------------------------------------------------------------*/
3215 static void genDiv (iCode *ic)
3216 {
3217     operand *left = IC_LEFT(ic);
3218     operand *right = IC_RIGHT(ic);
3219     operand *result= IC_RESULT(ic);   
3220
3221     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3222     /* assign the amsops */
3223     aopOp (left,ic,FALSE);
3224     aopOp (right,ic,FALSE);
3225     aopOp (result,ic,TRUE);
3226
3227     /* special cases first */
3228     /* both are bits */
3229     if (AOP_TYPE(left) == AOP_CRY &&
3230         AOP_TYPE(right)== AOP_CRY) {
3231         genDivbits(left,right,result);
3232         goto release ;
3233     }
3234
3235     /* if both are of size == 1 */
3236     if (AOP_SIZE(left) == 1 &&
3237         AOP_SIZE(right) == 1 ) {
3238         genDivOneByte(left,right,result);
3239         goto release ;
3240     }
3241
3242     /* should have been converted to function call */
3243     assert(0);
3244 release :
3245     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3246     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3247     freeAsmop(result,NULL,ic,TRUE); 
3248 }
3249
3250 /*-----------------------------------------------------------------*/
3251 /* genModbits :- modulus of bits                                   */
3252 /*-----------------------------------------------------------------*/
3253 static void genModbits (operand *left, 
3254                         operand *right, 
3255                         operand *result)
3256 {
3257
3258     char *l;
3259
3260     /* the result must be bit */    
3261     pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3262     l = aopGet(AOP(left),0,FALSE,FALSE);
3263
3264     MOVA(l);       
3265
3266     pic14_emitcode("div","ab");
3267     pic14_emitcode("mov","a,b");
3268     pic14_emitcode("rrc","a");
3269     aopPut(AOP(result),"c",0);
3270 }
3271
3272 /*-----------------------------------------------------------------*/
3273 /* genModOneByte : 8 bit modulus                                   */
3274 /*-----------------------------------------------------------------*/
3275 static void genModOneByte (operand *left,
3276                            operand *right,
3277                            operand *result)
3278 {
3279     sym_link *opetype = operandType(result);
3280     char *l ;
3281     symbol *lbl ;
3282
3283     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3284     /* signed or unsigned */
3285     if (SPEC_USIGN(opetype)) {
3286         /* unsigned is easy */
3287         pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3288         l = aopGet(AOP(left),0,FALSE,FALSE);
3289         MOVA(l);    
3290         pic14_emitcode("div","ab");
3291         aopPut(AOP(result),"b",0);
3292         return ;
3293     }
3294
3295     /* signed is a little bit more difficult */
3296
3297     /* save the signs of the operands */
3298     l = aopGet(AOP(left),0,FALSE,FALSE);    
3299     MOVA(l);
3300
3301     pic14_emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3302     pic14_emitcode("push","acc"); /* save it on the stack */
3303
3304     /* now sign adjust for both left & right */
3305     l =  aopGet(AOP(right),0,FALSE,FALSE);    
3306     MOVA(l);
3307
3308     lbl = newiTempLabel(NULL);
3309     pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
3310     pic14_emitcode("cpl","a");   
3311     pic14_emitcode("inc","a");
3312     pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3313     pic14_emitcode("mov","b,a"); 
3314
3315     /* sign adjust left side */
3316     l =  aopGet(AOP(left),0,FALSE,FALSE);    
3317     MOVA(l);
3318
3319     lbl = newiTempLabel(NULL);
3320     pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3321     pic14_emitcode("cpl","a");   
3322     pic14_emitcode("inc","a");
3323     pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3324
3325     /* now the multiplication */
3326     pic14_emitcode("div","ab");
3327     /* we are interested in the lower order
3328     only */
3329     lbl = newiTempLabel(NULL);
3330     pic14_emitcode("pop","acc");   
3331     /* if there was an over flow we don't 
3332     adjust the sign of the result */
3333     pic14_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3334     pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3335     CLRC ;
3336     pic14_emitcode("clr","a");
3337     pic14_emitcode("subb","a,b");
3338     pic14_emitcode("mov","b,a");
3339     pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3340
3341     /* now we are done */
3342     aopPut(AOP(result),"b",0);
3343
3344 }
3345
3346 /*-----------------------------------------------------------------*/
3347 /* genMod - generates code for division                            */
3348 /*-----------------------------------------------------------------*/
3349 static void genMod (iCode *ic)
3350 {
3351     operand *left = IC_LEFT(ic);
3352     operand *right = IC_RIGHT(ic);
3353     operand *result= IC_RESULT(ic);  
3354
3355     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3356     /* assign the amsops */
3357     aopOp (left,ic,FALSE);
3358     aopOp (right,ic,FALSE);
3359     aopOp (result,ic,TRUE);
3360
3361     /* special cases first */
3362     /* both are bits */
3363     if (AOP_TYPE(left) == AOP_CRY &&
3364         AOP_TYPE(right)== AOP_CRY) {
3365         genModbits(left,right,result);
3366         goto release ;
3367     }
3368
3369     /* if both are of size == 1 */
3370     if (AOP_SIZE(left) == 1 &&
3371         AOP_SIZE(right) == 1 ) {
3372         genModOneByte(left,right,result);
3373         goto release ;
3374     }
3375
3376     /* should have been converted to function call */
3377     assert(0);
3378
3379 release :
3380     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3381     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3382     freeAsmop(result,NULL,ic,TRUE); 
3383 }
3384
3385 /*-----------------------------------------------------------------*/
3386 /* genIfxJump :- will create a jump depending on the ifx           */
3387 /*-----------------------------------------------------------------*/
3388 /*
3389   note: May need to add parameter to indicate when a variable is in bit space.
3390 */
3391 static void genIfxJump (iCode *ic, char *jval)
3392 {
3393
3394     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3395     /* if true label then we jump if condition
3396     supplied is true */
3397     if ( IC_TRUE(ic) ) {
3398
3399         if(strcmp(jval,"a") == 0)
3400           emitSKPZ;
3401         else if (strcmp(jval,"c") == 0)
3402           emitSKPC;
3403         else {
3404           DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
3405           emitpcode(POC_BTFSC,  newpCodeOpBit(jval,-1,1));
3406         }
3407
3408         emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3409         pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3410
3411     }
3412     else {
3413         /* false label is present */
3414         if(strcmp(jval,"a") == 0)
3415           emitSKPNZ;
3416         else if (strcmp(jval,"c") == 0)
3417           emitSKPNC;
3418         else {
3419           DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
3420           emitpcode(POC_BTFSS,  newpCodeOpBit(jval,-1,1));
3421         }
3422
3423         emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
3424         pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3425
3426     }
3427
3428
3429     /* mark the icode as generated */
3430     ic->generated = 1;
3431 }
3432
3433 /*-----------------------------------------------------------------*/
3434 /* genSkip                                                         */
3435 /*-----------------------------------------------------------------*/
3436 static void genSkip(iCode *ifx,int status_bit)
3437 {
3438   if(!ifx)
3439     return;
3440
3441   if ( IC_TRUE(ifx) ) {
3442     switch(status_bit) {
3443     case 'z':
3444       emitSKPNZ;
3445       break;
3446
3447     case 'c':
3448       emitSKPNC;
3449       break;
3450
3451     case 'd':
3452       emitSKPDC;
3453       break;
3454
3455     }
3456
3457     emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3458     pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3459
3460   } else {
3461
3462     switch(status_bit) {
3463
3464     case 'z':
3465       emitSKPZ;
3466       break;
3467
3468     case 'c':
3469       emitSKPC;
3470       break;
3471
3472     case 'd':
3473       emitSKPDC;
3474       break;
3475     }
3476     emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3477     pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3478
3479   }
3480
3481 }
3482
3483 /*-----------------------------------------------------------------*/
3484 /* genSkipc                                                        */
3485 /*-----------------------------------------------------------------*/
3486 static void genSkipc(resolvedIfx *rifx)
3487 {
3488   if(!rifx)
3489     return;
3490
3491   if(rifx->condition)
3492     emitSKPC;
3493   else
3494     emitSKPNC;
3495
3496   emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3497   rifx->generated = 1;
3498 }
3499
3500 /*-----------------------------------------------------------------*/
3501 /* genSkipz                                                        */
3502 /*-----------------------------------------------------------------*/
3503 static void genSkipz(iCode *ifx, int condition)
3504 {
3505   if(!ifx)
3506     return;
3507
3508   if(condition)
3509     emitSKPNZ;
3510   else
3511     emitSKPZ;
3512
3513   if ( IC_TRUE(ifx) )
3514     emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3515   else
3516     emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3517
3518   if ( IC_TRUE(ifx) )
3519     pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3520   else
3521     pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3522
3523 }
3524 /*-----------------------------------------------------------------*/
3525 /* genCmp :- greater or less than comparison                       */
3526 /*-----------------------------------------------------------------*/
3527 static void genCmp (operand *left,operand *right,
3528                     operand *result, iCode *ifx, int sign)
3529 {
3530   int size, offset = 0 ;
3531   unsigned long lit = 0L,i = 0;
3532   resolvedIfx rIfx;
3533
3534   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3535   if(ifx) {
3536   DEBUGpic14_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
3537   DEBUGpic14_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
3538   }
3539
3540   resolveIfx(&rIfx,ifx);
3541
3542   /* if left & right are bit variables */
3543   if (AOP_TYPE(left) == AOP_CRY &&
3544       AOP_TYPE(right) == AOP_CRY ) {
3545     pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3546     pic14_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3547   } else {
3548     /* subtract right from left if at the
3549        end the carry flag is set then we know that
3550        left is greater than right */
3551     size = max(AOP_SIZE(left),AOP_SIZE(right));
3552
3553     /* if unsigned char cmp with lit, do cjne left,#right,zz */
3554     if((size == 1) && !sign &&
3555        (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
3556       symbol *lbl  = newiTempLabel(NULL);
3557       pic14_emitcode("cjne","%s,%s,%05d_DS_",
3558                aopGet(AOP(left),offset,FALSE,FALSE),
3559                aopGet(AOP(right),offset,FALSE,FALSE),
3560                lbl->key+100);
3561       pic14_emitcode("","%05d_DS_:",lbl->key+100);
3562     } else {
3563
3564       if(AOP_TYPE(right) == AOP_LIT) {
3565         symbol *lbl = newiTempLabel(NULL);
3566
3567         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3568
3569         DEBUGpic14_emitcode(";right lit","lit = %d,sign=%d",lit,sign);
3570
3571         size--;
3572         i = (lit >> (size*8)) & 0xff;
3573         if(sign) {
3574           if(i & 0x80) {
3575             emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
3576           } else {
3577             emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
3578           }
3579           emitpcode(POC_GOTO,popGetLabel(lbl->key));
3580         }
3581
3582         emitpcode(POC_MOVLW, popGetLit(i));
3583         emitpcode(POC_SUBFW, popGet(AOP(left),size,FALSE,FALSE));
3584         while(size--) {
3585           i = (lit >> (size*8)) & 0xff;
3586           emitpcode(POC_MOVLW, popGetLit(i));
3587           emitSKPNC;
3588           emitpcode(POC_SUBFW, popGet(AOP(left),size,FALSE,FALSE));
3589         }
3590
3591         if(ifx) {
3592           DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3593           //genSkipc(ifx,0,1); //IC_TRUE(ifx) == NULL);
3594           genSkipc(&rIfx);
3595           //if(sign)
3596             emitpLabel(lbl->key);
3597
3598           ifx->generated = 1;
3599         }
3600         return;
3601       }
3602
3603       if(AOP_TYPE(left) == AOP_LIT) {
3604         //symbol *lbl = newiTempLabel(NULL);
3605
3606         lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
3607
3608         DEBUGpic14_emitcode(";left lit","lit = %d,sign=%d",lit,sign);
3609
3610         if(size==1) {
3611           if(sign) {
3612             if(lit & 0x80) {
3613               emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),7,0));
3614             } else {
3615               emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),7,0));
3616             }
3617             if(ifx) {
3618               if(IC_TRUE(ifx) != NULL)
3619                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3620               else
3621                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3622             }
3623           }
3624           emitpcode(POC_MOVLW, popGetLit((lit+1) & 0xff));
3625           emitpcode(POC_SUBFW, popGet(AOP(right),0,FALSE,FALSE));
3626           DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3627           rIfx.condition ^= 1;
3628           genSkipc(&rIfx);//      if(ifx) genSkipc(ifx,1,1);//IC_TRUE(ifx)!=NULL);
3629         } else {
3630           size--;
3631           //lit++;
3632           i = (lit >> (size*8)) & 0xff;
3633
3634           if(sign) {
3635             if(i & 0x80) {
3636               emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
3637             } else {
3638               emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
3639             }
3640             if(ifx) {
3641               if(IC_TRUE(ifx) != NULL)
3642                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3643               else
3644                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3645             }
3646           }
3647
3648           emitpcode(POC_MOVFW, popGet(AOP(right),size,FALSE,FALSE));
3649           emitpcode(POC_SUBLW, popGetLit((i)&0xff));
3650           while(size--) {
3651             i = (lit >> (size*8)) & 0xff;
3652             emitpcode(POC_MOVFW, popGet(AOP(right),size,FALSE,FALSE));
3653             emitSKPNC;
3654             emitpcode(POC_SUBLW, popGetLit((i)&0xff));
3655           }
3656   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3657           genSkipc(&rIfx);//      if(ifx) genSkipc(ifx,0,1);  //IC_TRUE(ifx) == NULL);
3658
3659         }
3660 /*
3661         if(sign)
3662           emitpLabel(lbl->key);
3663 */
3664         if(ifx) ifx->generated = 1;
3665         return;
3666       }
3667
3668
3669       // CLRC;
3670       DEBUGpic14_emitcode(";sign","%d",sign);
3671
3672       pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
3673       pic14_emitcode("subwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));//++
3674
3675       emitpcode(POC_MOVFW, popGet(AOP(right),offset,FALSE,FALSE));
3676       emitpcode(POC_SUBFW, popGet(AOP(left),offset++,FALSE,FALSE));
3677
3678       size--;
3679       while (size--) {
3680
3681         emitpcode(POC_MOVFW,   popGet(AOP(right),offset,FALSE,FALSE));
3682         emitSKPC;
3683         emitpcode(POC_INCFSZW, popGet(AOP(right),offset,FALSE,FALSE));
3684         emitpcode(POC_SUBFW,   popGet(AOP(left),offset,FALSE,FALSE));
3685
3686 /*
3687         pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
3688         emitSKPC;
3689         pic14_emitcode("incfsz","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
3690         pic14_emitcode("subwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
3691 */
3692         offset++;
3693       }
3694     }
3695   }
3696
3697   //release:
3698   if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
3699     pic14_outBitC(result);
3700   } else {
3701     /* if the result is used in the next
3702        ifx conditional branch then generate
3703        code a little differently */
3704     if (ifx )
3705       genIfxJump (ifx,"c");
3706     else
3707       pic14_outBitC(result);
3708     /* leave the result in acc */
3709   }
3710
3711 }
3712
3713 /*-----------------------------------------------------------------*/
3714 /* genCmpGt :- greater than comparison                             */
3715 /*-----------------------------------------------------------------*/
3716 static void genCmpGt (iCode *ic, iCode *ifx)
3717 {
3718     operand *left, *right, *result;
3719     sym_link *letype , *retype;
3720     int sign ;
3721
3722     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3723     left = IC_LEFT(ic);
3724     right= IC_RIGHT(ic);
3725     result = IC_RESULT(ic);
3726
3727     letype = getSpec(operandType(left));
3728     retype =getSpec(operandType(right));
3729     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3730     /* assign the amsops */
3731     aopOp (left,ic,FALSE);
3732     aopOp (right,ic,FALSE);
3733     aopOp (result,ic,TRUE);
3734
3735     genCmp(right, left, result, ifx, sign);
3736
3737     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3738     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3739     freeAsmop(result,NULL,ic,TRUE); 
3740 }
3741
3742 /*-----------------------------------------------------------------*/
3743 /* genCmpLt - less than comparisons                                */
3744 /*-----------------------------------------------------------------*/
3745 static void genCmpLt (iCode *ic, iCode *ifx)
3746 {
3747     operand *left, *right, *result;
3748     sym_link *letype , *retype;
3749     int sign ;
3750
3751     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3752     left = IC_LEFT(ic);
3753     right= IC_RIGHT(ic);
3754     result = IC_RESULT(ic);
3755
3756     letype = getSpec(operandType(left));
3757     retype =getSpec(operandType(right));
3758     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3759
3760     /* assign the amsops */
3761     aopOp (left,ic,FALSE);
3762     aopOp (right,ic,FALSE);
3763     aopOp (result,ic,TRUE);
3764
3765     genCmp(left, right, result, ifx, sign);
3766
3767     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3768     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3769     freeAsmop(result,NULL,ic,TRUE); 
3770 }
3771
3772 /*-----------------------------------------------------------------*/
3773 /* genc16bit2lit - compare a 16 bit value to a literal             */
3774 /*-----------------------------------------------------------------*/
3775 static void genc16bit2lit(operand *op, int lit, int offset)
3776 {
3777   int i;
3778
3779   DEBUGpic14_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
3780   if( (lit&0xff) == 0) 
3781     i=1;
3782   else
3783     i=0;
3784
3785   switch( BYTEofLONG(lit,i)) { 
3786   case 0:
3787     emitpcode(POC_MOVFW,popGet(AOP(op),offset+i,FALSE,FALSE));
3788     break;
3789   case 1:
3790     emitpcode(POC_DECFW,popGet(AOP(op),offset+i,FALSE,FALSE));
3791     break;
3792   case 0xff:
3793     emitpcode(POC_INCFW,popGet(AOP(op),offset+i,FALSE,FALSE));
3794     break;
3795   default:
3796     emitpcode(POC_MOVFW,popGet(AOP(op),offset+i,FALSE,FALSE));
3797     emitpcode(POC_XORLW,popGetLit(BYTEofLONG(lit,i)));
3798   }
3799
3800   i ^= 1;
3801
3802   switch( BYTEofLONG(lit,i)) { 
3803   case 0:
3804     emitpcode(POC_IORFW,popGet(AOP(op),offset+i,FALSE,FALSE));
3805     break;
3806   case 1:
3807     emitSKPNZ;
3808     emitpcode(POC_DECFW,popGet(AOP(op),offset+i,FALSE,FALSE));
3809     break;
3810   case 0xff:
3811     emitSKPNZ;
3812     emitpcode(POC_INCFW,popGet(AOP(op),offset+i,FALSE,FALSE));
3813     break;
3814   default:
3815     emitpcode(POC_MOVLW,popGetLit(BYTEofLONG(lit,i)));
3816     emitSKPNZ;
3817     emitpcode(POC_XORFW,popGet(AOP(op),offset+i,FALSE,FALSE));
3818
3819   }
3820
3821 }
3822
3823 /*-----------------------------------------------------------------*/
3824 /* gencjneshort - compare and jump if not equal                    */
3825 /*-----------------------------------------------------------------*/
3826 static void gencjne(operand *left, operand *right, iCode *ifx)
3827 {
3828   int size = max(AOP_SIZE(left),AOP_SIZE(right));
3829   int offset = 0;
3830   resolvedIfx rIfx;
3831   symbol *lbl;
3832
3833   unsigned long lit = 0L;
3834   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3835   DEBUGpic14_emitcode ("; ","left %s=%s, right %s=%s, size = %d",
3836                        AopType(AOP_TYPE(left)),
3837                        aopGet(AOP(left),0,TRUE,FALSE),
3838                        AopType(AOP_TYPE(right)),
3839                        aopGet(AOP(right),0,FALSE,FALSE),
3840                        size);
3841
3842   resolveIfx(&rIfx,ifx);
3843   lbl =  newiTempLabel(NULL);
3844
3845
3846   /* if the left side is a literal or 
3847      if the right is in a pointer register and left 
3848      is not */
3849   if ((AOP_TYPE(left) == AOP_LIT) || 
3850       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
3851     operand *t = right;
3852     right = left;
3853     left = t;
3854   }
3855   if(AOP_TYPE(right) == AOP_LIT)
3856     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3857
3858   /* if the right side is a literal then anything goes */
3859   if (AOP_TYPE(right) == AOP_LIT &&
3860       AOP_TYPE(left) != AOP_DIR ) {
3861     switch(size) {
3862     case 2:
3863       genc16bit2lit(left, lit, 0);
3864       emitSKPNZ;
3865       pic14_emitcode("goto","_%05d_DS_",lbl->key+100+labelOffset);
3866       emitpcode(POC_GOTO,popGetLabel(lbl->key));
3867       break;
3868     default:
3869       while (size--) {
3870         if(lit & 0xff) {
3871           emitpcode(POC_MOVFW,popGet(AOP(left),offset,FALSE,FALSE));
3872           emitpcode(POC_XORLW,popGetLit(lit & 0xff));
3873           pic14_emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
3874           pic14_emitcode("xorlw","0x%x",lit & 0xff);
3875         } else {
3876           emitpcode(POC_MOVF,popGet(AOP(left),offset,FALSE,FALSE));
3877           pic14_emitcode("movf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
3878         }
3879
3880         emitSKPNZ;
3881         pic14_emitcode("goto","_%05d_DS_",lbl->key+100+labelOffset);
3882         emitpcode(POC_GOTO,popGetLabel(lbl->key));
3883         offset++;
3884         lit >>= 8;
3885       }
3886       break;
3887     }
3888   }
3889
3890   /* if the right side is in a register or in direct space or
3891      if the left is a pointer register & right is not */    
3892   else if (AOP_TYPE(right) == AOP_REG ||
3893            AOP_TYPE(right) == AOP_DIR || 
3894            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
3895            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
3896     switch(size) {
3897     case 2:
3898       genc16bit2lit(left, lit, 0);
3899       emitSKPNZ;
3900       pic14_emitcode("goto","_%05d_DS_",lbl->key+100+labelOffset);
3901       emitpcode(POC_GOTO,popGetLabel(lbl->key));
3902       break;
3903     default:
3904       while (size--) {
3905         int emit_skip=1;
3906         if((AOP_TYPE(left) == AOP_DIR) && 
3907            ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
3908
3909           emitpcode(POC_MOVFW,popGet(AOP(left),offset,FALSE,FALSE));
3910           emitpcode(POC_XORFW,popGet(AOP(right),offset,FALSE,FALSE));
3911
3912         } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
3913             
3914           switch (lit & 0xff) {
3915           case 0:
3916             emitpcode(POC_MOVFW,popGet(AOP(left),offset,FALSE,FALSE));
3917             break;
3918           case 1:
3919             emitpcode(POC_DECFSZ,popGet(AOP(left),offset,FALSE,FALSE));
3920             emitpcode(POC_GOTO,popGetLabel(lbl->key));
3921             emit_skip=0;
3922             break;
3923           case 0xff:
3924             emitpcode(POC_INCFSZ,popGet(AOP(left),offset,FALSE,FALSE));
3925             emitpcode(POC_GOTO,popGetLabel(lbl->key));
3926             emit_skip=0;
3927             break;
3928           default:
3929             emitpcode(POC_MOVFW,popGet(AOP(left),offset,FALSE,FALSE));
3930             emitpcode(POC_XORLW,popGetLit(lit & 0xff));
3931           }
3932           lit >>= 8;
3933
3934         } else {
3935           emitpcode(POC_MOVF,popGet(AOP(left),offset,FALSE,FALSE));
3936           pic14_emitcode("movf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
3937         }
3938         if(emit_skip) {
3939           pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
3940           if(rIfx.condition)
3941             emitSKPNZ;
3942           else
3943             emitSKPZ;
3944           emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
3945           if(ifx)
3946             ifx->generated=1;
3947         }
3948         emit_skip++;
3949         offset++;
3950       }
3951       break;
3952     }
3953   } else if(AOP_TYPE(right) == AOP_REG &&
3954             AOP_TYPE(left) != AOP_DIR){
3955
3956     while(size--) {
3957       emitpcode(POC_MOVFW,popGet(AOP(left),offset,FALSE,FALSE));
3958       emitpcode(POC_XORFW,popGet(AOP(right),offset,FALSE,FALSE));
3959       pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
3960       if(rIfx.condition)
3961         emitSKPNZ;
3962       else
3963         emitSKPZ;
3964       emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
3965       offset++;
3966     }
3967       
3968   }else{
3969     /* right is a pointer reg need both a & b */
3970     while(size--) {
3971       char *l = aopGet(AOP(left),offset,FALSE,FALSE);
3972       if(strcmp(l,"b"))
3973         pic14_emitcode("mov","b,%s",l);
3974       MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3975       pic14_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
3976       offset++;
3977     }
3978   }
3979   emitpLabel(lbl->key);
3980
3981   if(ifx)
3982     ifx->generated = 1;
3983 }
3984
3985 #if 0
3986 /*-----------------------------------------------------------------*/
3987 /* gencjne - compare and jump if not equal                         */
3988 /*-----------------------------------------------------------------*/
3989 static void gencjne(operand *left, operand *right, iCode *ifx)
3990 {
3991     symbol *tlbl  = newiTempLabel(NULL);
3992
3993     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3994     gencjneshort(left, right, lbl);
3995
3996     pic14_emitcode("mov","a,%s",one);
3997     pic14_emitcode("sjmp","%05d_DS_",tlbl->key+100);
3998     pic14_emitcode("","%05d_DS_:",lbl->key+100);
3999     pic14_emitcode("clr","a");
4000     pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4001
4002     emitpLabel(lbl->key);
4003     emitpLabel(tlbl->key);
4004
4005 }
4006 #endif
4007
4008 /*-----------------------------------------------------------------*/
4009 /* genCmpEq - generates code for equal to                          */
4010 /*-----------------------------------------------------------------*/
4011 static void genCmpEq (iCode *ic, iCode *ifx)
4012 {
4013     operand *left, *right, *result;
4014     unsigned long lit = 0L;
4015     int size,offset=0;
4016
4017     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4018
4019     if(ifx)
4020       DEBUGpic14_emitcode ("; ifx is non-null","");
4021     else
4022       DEBUGpic14_emitcode ("; ifx is null","");
4023
4024     aopOp((left=IC_LEFT(ic)),ic,FALSE);
4025     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4026     aopOp((result=IC_RESULT(ic)),ic,TRUE);
4027
4028 /*
4029     DEBUGpic14_emitcode ("; ","result %s, left %s, right %s",
4030                          AopType(AOP_TYPE(IC_RESULT(ic))),
4031                          AopType(AOP_TYPE(IC_LEFT(ic))),
4032                          AopType(AOP_TYPE(IC_RIGHT(ic))));
4033 */
4034     size = max(AOP_SIZE(left),AOP_SIZE(right));
4035     DEBUGpic14_emitcode ("; ","result %s=%s, left %s=%s, right %s=%s, size = %d",
4036                          AopType(AOP_TYPE(result)),
4037                          aopGet(AOP(result),0,TRUE,FALSE),
4038                          AopType(AOP_TYPE(left)),
4039                          aopGet(AOP(left),0,TRUE,FALSE),
4040                          AopType(AOP_TYPE(right)),
4041                          aopGet(AOP(right),0,FALSE,FALSE),
4042                          size);
4043
4044
4045     /* if literal, literal on the right or 
4046     if the right is in a pointer register and left 
4047     is not */
4048     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
4049         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4050         operand *t = IC_RIGHT(ic);
4051         IC_RIGHT(ic) = IC_LEFT(ic);
4052         IC_LEFT(ic) = t;
4053     }
4054
4055     if(ifx && !AOP_SIZE(result)){
4056         symbol *tlbl;
4057         /* if they are both bit variables */
4058         if (AOP_TYPE(left) == AOP_CRY &&
4059             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4060             if(AOP_TYPE(right) == AOP_LIT){
4061                 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4062                 if(lit == 0L){
4063                     pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4064                     pic14_emitcode("cpl","c");
4065                 } else if(lit == 1L) {
4066                     pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4067                 } else {
4068                     pic14_emitcode("clr","c");
4069                 }
4070                 /* AOP_TYPE(right) == AOP_CRY */
4071             } else {
4072                 symbol *lbl = newiTempLabel(NULL);
4073                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4074                 pic14_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4075                 pic14_emitcode("cpl","c");
4076                 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
4077             }
4078             /* if true label then we jump if condition
4079             supplied is true */
4080             tlbl = newiTempLabel(NULL);
4081             if ( IC_TRUE(ifx) ) {
4082                 pic14_emitcode("jnc","%05d_DS_",tlbl->key+100);
4083                 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
4084             } else {
4085                 pic14_emitcode("jc","%05d_DS_",tlbl->key+100);
4086                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
4087             }
4088             pic14_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
4089         } else {
4090
4091           /* They're not both bit variables. Is the right a literal? */
4092           if(AOP_TYPE(right) == AOP_LIT) {
4093             lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4094             
4095
4096             switch(size) {
4097
4098             case 1:
4099               switch(lit & 0xff) {
4100               case 1:
4101                 if ( IC_TRUE(ifx) ) {
4102                   emitpcode(POC_DECFW,popGet(AOP(left),offset,FALSE,FALSE));
4103                   emitSKPNZ;
4104                   emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4105                 } else {
4106                   emitpcode(POC_DECFSZW,popGet(AOP(left),offset,FALSE,FALSE));
4107                   emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4108                 }
4109                 break;
4110               case 0xff:
4111                 if ( IC_TRUE(ifx) ) {
4112                   emitpcode(POC_INCFW,popGet(AOP(left),offset,FALSE,FALSE));
4113                   emitSKPNZ;
4114                   emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4115                 } else {
4116                   emitpcode(POC_INCFSZW,popGet(AOP(left),offset,FALSE,FALSE));
4117                   emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4118                 }
4119                 break;
4120               default:
4121                 emitpcode(POC_MOVFW,popGet(AOP(left),offset,FALSE,FALSE));
4122                 if(lit)
4123                   emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4124                 genSkip(ifx,'z');
4125               }
4126
4127
4128               /* end of size == 1 */
4129               break;
4130               
4131             case 2:
4132               genc16bit2lit(left,lit,offset);
4133               genSkip(ifx,'z');
4134               break;
4135               /* end of size == 2 */
4136
4137             default:
4138               /* size is 4 */
4139               if(lit==0) {
4140                 emitpcode(POC_MOVFW,popGet(AOP(left),0,FALSE,FALSE));
4141                 emitpcode(POC_IORFW,popGet(AOP(left),1,FALSE,FALSE));
4142                 emitpcode(POC_IORFW,popGet(AOP(left),2,FALSE,FALSE));
4143                 emitpcode(POC_IORFW,popGet(AOP(left),3,FALSE,FALSE));
4144
4145               } else {
4146
4147                 /* search for patterns that can be optimized */
4148
4149                 genc16bit2lit(left,lit,0);
4150                 lit >>= 16;
4151                 if(lit) {
4152                   genSkipz(ifx,IC_TRUE(ifx) == NULL);
4153                   //genSkip(ifx,'z');
4154                   genc16bit2lit(left,lit,2);
4155                 } else {
4156                   emitpcode(POC_IORFW,popGet(AOP(left),2,FALSE,FALSE));
4157                   emitpcode(POC_IORFW,popGet(AOP(left),3,FALSE,FALSE));
4158
4159                 }
4160                 
4161               }
4162
4163               genSkip(ifx,'z');
4164             }
4165           
4166             ifx->generated = 1;
4167             goto release ;
4168             
4169
4170           } else if(AOP_TYPE(right) == AOP_CRY ) {
4171             /* we know the left is not a bit, but that the right is */
4172             emitpcode(POC_MOVFW,popGet(AOP(left),offset,FALSE,FALSE));
4173             emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
4174                       popGet(AOP(right),offset,FALSE,FALSE));
4175             emitpcode(POC_XORLW,popGetLit(1));
4176
4177             pic14_emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4178             if ( IC_TRUE(ifx) )
4179               pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
4180                        AOP(right)->aopu.aop_dir,
4181                        AOP(right)->aopu.aop_dir);
4182             else
4183               pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
4184                        AOP(right)->aopu.aop_dir,
4185                        AOP(right)->aopu.aop_dir);
4186
4187             pic14_emitcode("xorlw","1");
4188
4189             /* if the two are equal, then W will be 0 and the Z bit is set
4190              * we could test Z now, or go ahead and check the high order bytes if
4191              * the variable we're comparing is larger than a byte. */
4192
4193             while(--size)
4194               emitpcode(POC_IORFW,popGet(AOP(left),offset,FALSE,FALSE));
4195             //pic14_emitcode("iorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4196
4197             if ( IC_TRUE(ifx) ) {
4198               emitSKPNZ;
4199               emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4200               pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4201             } else {
4202               emitSKPZ;
4203               emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4204               pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4205             }
4206
4207           } else {
4208             /* They're both variables that are larger than bits */
4209             int s = size;
4210
4211             tlbl = newiTempLabel(NULL);
4212
4213             while(size--) {
4214               emitpcode(POC_MOVFW,popGet(AOP(left),offset,FALSE,FALSE));
4215               emitpcode(POC_XORFW,popGet(AOP(right),offset,FALSE,FALSE));
4216
4217               pic14_emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4218               pic14_emitcode("xorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4219
4220               if ( IC_TRUE(ifx) ) {
4221                 if(size) {
4222                   emitSKPZ;
4223                   emitpcode(POC_GOTO,popGetLabel(tlbl->key));
4224                   pic14_emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset);
4225                 } else {
4226                   emitSKPNZ;
4227                   emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4228                   pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4229                 }
4230               } else {
4231                 emitSKPZ;
4232                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4233                 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4234               }
4235               offset++;
4236             }
4237             if(s>1 && IC_TRUE(ifx)) {
4238               emitpLabel(tlbl->key);
4239               pic14_emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);                
4240             }
4241           }
4242         }
4243         /* mark the icode as generated */
4244         ifx->generated = 1;
4245         goto release ;
4246     }
4247
4248     /* if they are both bit variables */
4249     if (AOP_TYPE(left) == AOP_CRY &&
4250         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4251         if(AOP_TYPE(right) == AOP_LIT){
4252             unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4253             if(lit == 0L){
4254                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4255                 pic14_emitcode("cpl","c");
4256             } else if(lit == 1L) {
4257                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4258             } else {
4259                 pic14_emitcode("clr","c");
4260             }
4261             /* AOP_TYPE(right) == AOP_CRY */
4262         } else {
4263             symbol *lbl = newiTempLabel(NULL);
4264             pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4265             pic14_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4266             pic14_emitcode("cpl","c");
4267             pic14_emitcode("","%05d_DS_:",(lbl->key+100));
4268         }
4269         /* c = 1 if egal */
4270         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
4271             pic14_outBitC(result);
4272             goto release ;
4273         }
4274         if (ifx) {
4275             genIfxJump (ifx,"c");
4276             goto release ;
4277         }
4278         /* if the result is used in an arithmetic operation
4279         then put the result in place */
4280         pic14_outBitC(result);
4281     } else {
4282       
4283       gencjne(left,right,ifx);
4284 /*
4285       if(ifx) 
4286         gencjne(left,right,newiTempLabel(NULL));
4287       else {
4288         if(IC_TRUE(ifx)->key)
4289           gencjne(left,right,IC_TRUE(ifx)->key);
4290         else
4291           gencjne(left,right,IC_FALSE(ifx)->key);
4292         ifx->generated = 1;
4293         goto release ;
4294       }
4295       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4296         aopPut(AOP(result),"a",0);
4297         goto release ;
4298       }
4299
4300       if (ifx) {
4301         genIfxJump (ifx,"a");
4302         goto release ;
4303       }
4304 */
4305       /* if the result is used in an arithmetic operation
4306          then put the result in place */
4307       if (AOP_TYPE(result) != AOP_CRY) 
4308         pic14_outAcc(result);
4309       /* leave the result in acc */
4310     }
4311
4312 release:
4313     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4314     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4315     freeAsmop(result,NULL,ic,TRUE);
4316 }
4317
4318 /*-----------------------------------------------------------------*/
4319 /* ifxForOp - returns the icode containing the ifx for operand     */
4320 /*-----------------------------------------------------------------*/
4321 static iCode *ifxForOp ( operand *op, iCode *ic )
4322 {
4323     /* if true symbol then needs to be assigned */
4324     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4325     if (IS_TRUE_SYMOP(op))
4326         return NULL ;
4327
4328     /* if this has register type condition and
4329     the next instruction is ifx with the same operand
4330     and live to of the operand is upto the ifx only then */
4331     if (ic->next &&
4332         ic->next->op == IFX &&
4333         IC_COND(ic->next)->key == op->key &&
4334         OP_SYMBOL(op)->liveTo <= ic->next->seq )
4335         return ic->next;
4336
4337     if (ic->next &&
4338         ic->next->op == IFX &&
4339         IC_COND(ic->next)->key == op->key) {
4340       DEBUGpic14_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
4341       return ic->next;
4342     }
4343
4344     DEBUGpic14_emitcode ("; NULL :(","%d",__LINE__);
4345     if (ic->next &&
4346         ic->next->op == IFX)
4347       DEBUGpic14_emitcode ("; ic-next"," is an IFX");
4348
4349     if (ic->next &&
4350         ic->next->op == IFX &&
4351         IC_COND(ic->next)->key == op->key) {
4352       DEBUGpic14_emitcode ("; "," key is okay");
4353       DEBUGpic14_emitcode ("; "," key liveTo %d, next->seq = %d",
4354                            OP_SYMBOL(op)->liveTo,
4355                            ic->next->seq);
4356     }
4357
4358
4359     return NULL;
4360 }
4361 /*-----------------------------------------------------------------*/
4362 /* genAndOp - for && operation                                     */
4363 /*-----------------------------------------------------------------*/
4364 static void genAndOp (iCode *ic)
4365 {
4366     operand *left,*right, *result;
4367     symbol *tlbl;
4368
4369     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4370     /* note here that && operations that are in an
4371     if statement are taken away by backPatchLabels
4372     only those used in arthmetic operations remain */
4373     aopOp((left=IC_LEFT(ic)),ic,FALSE);
4374     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4375     aopOp((result=IC_RESULT(ic)),ic,FALSE);
4376
4377     /* if both are bit variables */
4378     if (AOP_TYPE(left) == AOP_CRY &&
4379         AOP_TYPE(right) == AOP_CRY ) {
4380         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4381         pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
4382         pic14_outBitC(result);
4383     } else {
4384         tlbl = newiTempLabel(NULL);
4385         pic14_toBoolean(left);    
4386         pic14_emitcode("jz","%05d_DS_",tlbl->key+100);
4387         pic14_toBoolean(right);
4388         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4389         pic14_outBitAcc(result);
4390     }
4391
4392     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4393     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4394     freeAsmop(result,NULL,ic,TRUE);
4395 }
4396
4397
4398 /*-----------------------------------------------------------------*/
4399 /* genOrOp - for || operation                                      */
4400 /*-----------------------------------------------------------------*/
4401 /*
4402   tsd pic port -
4403   modified this code, but it doesn't appear to ever get called
4404 */
4405
4406 static void genOrOp (iCode *ic)
4407 {
4408     operand *left,*right, *result;
4409     symbol *tlbl;
4410
4411     /* note here that || operations that are in an
4412     if statement are taken away by backPatchLabels
4413     only those used in arthmetic operations remain */
4414     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4415     aopOp((left=IC_LEFT(ic)),ic,FALSE);
4416     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4417     aopOp((result=IC_RESULT(ic)),ic,FALSE);
4418
4419     /* if both are bit variables */
4420     if (AOP_TYPE(left) == AOP_CRY &&
4421         AOP_TYPE(right) == AOP_CRY ) {
4422       pic14_emitcode("clrc","");
4423       pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
4424                AOP(left)->aopu.aop_dir,
4425                AOP(left)->aopu.aop_dir);
4426       pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
4427                AOP(right)->aopu.aop_dir,
4428                AOP(right)->aopu.aop_dir);
4429       pic14_emitcode("setc","");
4430
4431     } else {
4432         tlbl = newiTempLabel(NULL);
4433         pic14_toBoolean(left);
4434         emitSKPZ;
4435         pic14_emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
4436         pic14_toBoolean(right);
4437         pic14_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
4438
4439         pic14_outBitAcc(result);
4440     }
4441
4442     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4443     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4444     freeAsmop(result,NULL,ic,TRUE);            
4445 }
4446
4447 /*-----------------------------------------------------------------*/
4448 /* isLiteralBit - test if lit == 2^n                               */
4449 /*-----------------------------------------------------------------*/
4450 static int isLiteralBit(unsigned long lit)
4451 {
4452     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
4453     0x100L,0x200L,0x400L,0x800L,
4454     0x1000L,0x2000L,0x4000L,0x8000L,
4455     0x10000L,0x20000L,0x40000L,0x80000L,
4456     0x100000L,0x200000L,0x400000L,0x800000L,
4457     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
4458     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
4459     int idx;
4460     
4461     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4462     for(idx = 0; idx < 32; idx++)
4463         if(lit == pw[idx])
4464             return idx+1;
4465     return 0;
4466 }
4467
4468 /*-----------------------------------------------------------------*/
4469 /* continueIfTrue -                                                */
4470 /*-----------------------------------------------------------------*/
4471 static void continueIfTrue (iCode *ic)
4472 {
4473     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4474     if(IC_TRUE(ic))
4475         pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
4476     ic->generated = 1;
4477 }
4478
4479 /*-----------------------------------------------------------------*/
4480 /* jmpIfTrue -                                                     */
4481 /*-----------------------------------------------------------------*/
4482 static void jumpIfTrue (iCode *ic)
4483 {
4484     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4485     if(!IC_TRUE(ic))
4486         pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
4487     ic->generated = 1;
4488 }
4489
4490 /*-----------------------------------------------------------------*/
4491 /* jmpTrueOrFalse -                                                */
4492 /*-----------------------------------------------------------------*/
4493 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
4494 {
4495     // ugly but optimized by peephole
4496     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4497     if(IC_TRUE(ic)){
4498         symbol *nlbl = newiTempLabel(NULL);
4499         pic14_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
4500         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4501         pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
4502         pic14_emitcode("","%05d_DS_:",nlbl->key+100);
4503     }
4504     else{
4505         pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
4506         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4507     }
4508     ic->generated = 1;
4509 }
4510
4511 /*-----------------------------------------------------------------*/
4512 /* genAnd  - code for and                                          */
4513 /*-----------------------------------------------------------------*/
4514 static void genAnd (iCode *ic, iCode *ifx)
4515 {
4516   operand *left, *right, *result;
4517   int size, offset=0;  
4518   unsigned long lit = 0L;
4519   int bytelit = 0;
4520   resolvedIfx rIfx;
4521
4522
4523   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4524   aopOp((left = IC_LEFT(ic)),ic,FALSE);
4525   aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4526   aopOp((result=IC_RESULT(ic)),ic,TRUE);
4527
4528   resolveIfx(&rIfx,ifx);
4529
4530   /* if left is a literal & right is not then exchange them */
4531   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4532       AOP_NEEDSACC(left)) {
4533     operand *tmp = right ;
4534     right = left;
4535     left = tmp;
4536   }
4537
4538   /* if result = right then exchange them */
4539   if(pic14_sameRegs(AOP(result),AOP(right))){
4540     operand *tmp = right ;
4541     right = left;
4542     left = tmp;
4543   }
4544
4545   /* if right is bit then exchange them */
4546   if (AOP_TYPE(right) == AOP_CRY &&
4547       AOP_TYPE(left) != AOP_CRY){
4548     operand *tmp = right ;
4549     right = left;
4550     left = tmp;
4551   }
4552   if(AOP_TYPE(right) == AOP_LIT)
4553     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4554
4555   size = AOP_SIZE(result);
4556
4557   DEBUGpic14_emitcode ("; ","result %s=%s, left %s=%s, right %s=%s, size = %d",
4558                        AopType(AOP_TYPE(result)),
4559                        aopGet(AOP(result),0,TRUE,FALSE),
4560                        AopType(AOP_TYPE(left)),
4561                        aopGet(AOP(left),0,TRUE,FALSE),
4562                        AopType(AOP_TYPE(right)),
4563                        aopGet(AOP(right),0,FALSE,FALSE),
4564                        size);
4565   // if(bit & yy)
4566   // result = bit & yy;
4567   if (AOP_TYPE(left) == AOP_CRY){
4568     // c = bit & literal;
4569     if(AOP_TYPE(right) == AOP_LIT){
4570       if(lit & 1) {
4571         if(size && pic14_sameRegs(AOP(result),AOP(left)))
4572           // no change
4573           goto release;
4574         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4575       } else {
4576         // bit(result) = 0;
4577         if(size && (AOP_TYPE(result) == AOP_CRY)){
4578           pic14_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
4579           goto release;
4580         }
4581         if((AOP_TYPE(result) == AOP_CRY) && ifx){
4582           jumpIfTrue(ifx);
4583           goto release;
4584         }
4585         pic14_emitcode("clr","c");
4586       }
4587     } else {
4588       if (AOP_TYPE(right) == AOP_CRY){
4589         // c = bit & bit;
4590         pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4591         pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4592       } else {
4593         // c = bit & val;
4594         MOVA(aopGet(AOP(right),0,FALSE,FALSE));
4595         // c = lsb
4596         pic14_emitcode("rrc","a");
4597         pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4598       }
4599     }
4600     // bit = c
4601     // val = c
4602     if(size)
4603       pic14_outBitC(result);
4604     // if(bit & ...)
4605     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4606       genIfxJump(ifx, "c");           
4607     goto release ;
4608   }
4609
4610   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
4611   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
4612   if((AOP_TYPE(right) == AOP_LIT) &&
4613      (AOP_TYPE(result) == AOP_CRY) &&
4614      (AOP_TYPE(left) != AOP_CRY)){
4615     int posbit = isLiteralBit(lit);
4616     /* left &  2^n */
4617     if(posbit){
4618       posbit--;
4619       //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
4620       // bit = left & 2^n
4621       if(size)
4622         pic14_emitcode("mov","c,acc.%d",posbit&0x07);
4623       // if(left &  2^n)
4624       else{
4625         if(ifx){
4626 /*
4627           if(IC_TRUE(ifx)) {
4628             emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
4629             emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
4630           } else {
4631             emitpcode(POC_BTFSS,newpCodeOpBit(aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
4632             emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
4633           }
4634 */
4635           emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
4636                     newpCodeOpBit(aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
4637           emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4638           
4639           ifx->generated = 1;
4640         }
4641         goto release;
4642       }
4643     } else {
4644       symbol *tlbl = newiTempLabel(NULL);
4645       int sizel = AOP_SIZE(left);
4646       if(size)
4647         pic14_emitcode("setb","c");
4648       while(sizel--){
4649         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
4650           MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
4651           // byte ==  2^n ?
4652           if((posbit = isLiteralBit(bytelit)) != 0)
4653             pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
4654           else{
4655             if(bytelit != 0x0FFL)
4656               pic14_emitcode("anl","a,%s",
4657                              aopGet(AOP(right),offset,FALSE,TRUE));
4658             pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
4659           }
4660         }
4661         offset++;
4662       }
4663       // bit = left & literal
4664       if(size){
4665         pic14_emitcode("clr","c");
4666         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4667       }
4668       // if(left & literal)
4669       else{
4670         if(ifx)
4671           jmpTrueOrFalse(ifx, tlbl);
4672         goto release ;
4673       }
4674     }
4675     pic14_outBitC(result);
4676     goto release ;
4677   }
4678
4679   /* if left is same as result */
4680   if(pic14_sameRegs(AOP(result),AOP(left))){
4681     int know_W = -1;
4682     for(;size--; offset++,lit>>=8) {
4683       if(AOP_TYPE(right) == AOP_LIT){
4684         switch(lit & 0xff) {
4685         case 0x00:
4686           /*  and'ing with 0 has clears the result */
4687           pic14_emitcode("clrf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
4688           emitpcode(POC_CLRF,popGet(AOP(result),offset,FALSE,FALSE));
4689           break;
4690         case 0xff:
4691           /* and'ing with 0xff is a nop when the result and left are the same */
4692           break;
4693
4694         default:
4695           {
4696             int p = my_powof2( (~lit) & 0xff );
4697             if(p>=0) {
4698               /* only one bit is set in the literal, so use a bcf instruction */
4699               pic14_emitcode("bcf","%s,%d",aopGet(AOP(left),offset,FALSE,TRUE),p);
4700               //emitpcode(POC_BCF,popGet(AOP(left),offset,FALSE,TRUE));
4701               emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
4702
4703             } else {
4704               pic14_emitcode("movlw","0x%x", (lit & 0xff));
4705               pic14_emitcode("andwf","%s,f",aopGet(AOP(left),offset,FALSE,TRUE));
4706               if(know_W != (lit&0xff))
4707                 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
4708               know_W = lit &0xff;
4709               emitpcode(POC_ANDWF,popGet(AOP(left),offset,FALSE,TRUE));
4710             }
4711           }    
4712         }
4713       } else {
4714         if (AOP_TYPE(left) == AOP_ACC) {
4715           emitpcode(POC_ANDFW,popGet(AOP(right),offset,FALSE,FALSE));
4716         } else {                    
4717           emitpcode(POC_MOVFW,popGet(AOP(right),offset,FALSE,FALSE));
4718           emitpcode(POC_ANDWF,popGet(AOP(left),offset,FALSE,FALSE));
4719
4720         }
4721       }
4722     }
4723
4724   } else {
4725     // left & result in different registers
4726     if(AOP_TYPE(result) == AOP_CRY){
4727       // result = bit
4728       // if(size), result in bit
4729       // if(!size && ifx), conditional oper: if(left & right)
4730       symbol *tlbl = newiTempLabel(NULL);
4731       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
4732       if(size)
4733         pic14_emitcode("setb","c");
4734       while(sizer--){
4735         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4736         pic14_emitcode("anl","a,%s",
4737                        aopGet(AOP(left),offset,FALSE,FALSE));
4738         pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
4739         offset++;
4740       }
4741       if(size){
4742         CLRC;
4743         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4744         pic14_outBitC(result);
4745       } else if(ifx)
4746         jmpTrueOrFalse(ifx, tlbl);
4747     } else {
4748       for(;(size--);offset++) {
4749         // normal case
4750         // result = left & right
4751         if(AOP_TYPE(right) == AOP_LIT){
4752           int t = (lit >> (offset*8)) & 0x0FFL;
4753           switch(t) { 
4754           case 0x00:
4755             pic14_emitcode("clrf","%s",
4756                            aopGet(AOP(result),offset,FALSE,FALSE));
4757             emitpcode(POC_CLRF,popGet(AOP(result),offset,FALSE,FALSE));
4758             break;
4759           case 0xff:
4760             pic14_emitcode("movf","%s,w",
4761                            aopGet(AOP(left),offset,FALSE,FALSE));
4762             pic14_emitcode("movwf","%s",
4763                            aopGet(AOP(result),offset,FALSE,FALSE));
4764             emitpcode(POC_MOVFW,popGet(AOP(left),offset,FALSE,FALSE));
4765             emitpcode(POC_MOVWF,popGet(AOP(result),offset,FALSE,FALSE));
4766             break;
4767           default:
4768             pic14_emitcode("movlw","0x%x",t);
4769             pic14_emitcode("andwf","%s,w",
4770                            aopGet(AOP(left),offset,FALSE,FALSE));
4771             pic14_emitcode("movwf","%s",
4772                            aopGet(AOP(result),offset,FALSE,FALSE));
4773               
4774             emitpcode(POC_MOVLW, popGetLit(t));
4775             emitpcode(POC_ANDFW,popGet(AOP(left),offset,FALSE,FALSE));
4776             emitpcode(POC_MOVWF,popGet(AOP(result),offset,FALSE,FALSE));
4777           }
4778           continue;
4779         }
4780
4781         if (AOP_TYPE(left) == AOP_ACC) {
4782           pic14_emitcode("andwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4783           emitpcode(POC_ANDFW,popGet(AOP(right),offset,FALSE,FALSE));
4784         } else {
4785           pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4786           pic14_emitcode("andwf","%s,w",
4787                          aopGet(AOP(left),offset,FALSE,FALSE));
4788           emitpcode(POC_MOVFW,popGet(AOP(right),offset,FALSE,FALSE));
4789           emitpcode(POC_ANDFW,popGet(AOP(left),offset,FALSE,FALSE));
4790         }
4791         pic14_emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
4792         emitpcode(POC_MOVWF,popGet(AOP(result),offset,FALSE,FALSE));
4793       }
4794     }
4795   }
4796
4797   release :
4798     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4799   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4800   freeAsmop(result,NULL,ic,TRUE);     
4801 }
4802
4803 /*-----------------------------------------------------------------*/
4804 /* genOr  - code for or                                            */
4805 /*-----------------------------------------------------------------*/
4806 static void genOr (iCode *ic, iCode *ifx)
4807 {
4808     operand *left, *right, *result;
4809     int size, offset=0;
4810     unsigned long lit = 0L;
4811
4812     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4813
4814     aopOp((left = IC_LEFT(ic)),ic,FALSE);
4815     aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4816     aopOp((result=IC_RESULT(ic)),ic,TRUE);
4817
4818
4819     /* if left is a literal & right is not then exchange them */
4820     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4821         AOP_NEEDSACC(left)) {
4822         operand *tmp = right ;
4823         right = left;
4824         left = tmp;
4825     }
4826
4827     /* if result = right then exchange them */
4828     if(pic14_sameRegs(AOP(result),AOP(right))){
4829         operand *tmp = right ;
4830         right = left;
4831         left = tmp;
4832     }
4833
4834     /* if right is bit then exchange them */
4835     if (AOP_TYPE(right) == AOP_CRY &&
4836         AOP_TYPE(left) != AOP_CRY){
4837         operand *tmp = right ;
4838         right = left;
4839         left = tmp;
4840     }
4841
4842     DEBUGpic14_emitcode ("; ","result %s, left %s, right %s",
4843                          AopType(AOP_TYPE(result)),
4844                          AopType(AOP_TYPE(left)),
4845                          AopType(AOP_TYPE(right)));
4846
4847     if(AOP_TYPE(right) == AOP_LIT)
4848         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4849
4850     size = AOP_SIZE(result);
4851
4852     // if(bit | yy)
4853     // xx = bit | yy;
4854     if (AOP_TYPE(left) == AOP_CRY){
4855         if(AOP_TYPE(right) == AOP_LIT){
4856             // c = bit & literal;
4857             if(lit){
4858                 // lit != 0 => result = 1
4859                 if(AOP_TYPE(result) == AOP_CRY){
4860                   if(size)
4861                     emitpcode(POC_BSF, popGet(AOP(result),0,FALSE,FALSE));
4862                   //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
4863                   //     AOP(result)->aopu.aop_dir,
4864                   //     AOP(result)->aopu.aop_dir);
4865                     else if(ifx)
4866                         continueIfTrue(ifx);
4867                     goto release;
4868                 }
4869             } else {
4870                 // lit == 0 => result = left
4871                 if(size && pic14_sameRegs(AOP(result),AOP(left)))
4872                     goto release;
4873                 pic14_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
4874             }
4875         } else {
4876             if (AOP_TYPE(right) == AOP_CRY){
4877               if(pic14_sameRegs(AOP(result),AOP(left))){
4878                 // c = bit | bit;
4879                 emitpcode(POC_BCF,   popGet(AOP(result),0,FALSE,FALSE));
4880                 emitpcode(POC_BTFSC, popGet(AOP(right),0,FALSE,FALSE));
4881                 emitpcode(POC_BSF,   popGet(AOP(result),0,FALSE,FALSE));
4882
4883                 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
4884                          AOP(result)->aopu.aop_dir,
4885                          AOP(result)->aopu.aop_dir);
4886                 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
4887                          AOP(right)->aopu.aop_dir,
4888                          AOP(right)->aopu.aop_dir);
4889                 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
4890                          AOP(result)->aopu.aop_dir,
4891                          AOP(result)->aopu.aop_dir);
4892               } else {
4893                 if( AOP_TYPE(result) == AOP_ACC) {
4894                   emitpcode(POC_MOVLW, popGetLit(0));
4895                   emitpcode(POC_BTFSS, popGet(AOP(right),0,FALSE,FALSE));
4896                   emitpcode(POC_BTFSC, popGet(AOP(left),0,FALSE,FALSE));
4897                   emitpcode(POC_MOVLW, popGetLit(1));
4898
4899                 } else {
4900
4901                   emitpcode(POC_BCF,   popGet(AOP(result),0,FALSE,FALSE));
4902                   emitpcode(POC_BTFSS, popGet(AOP(right),0,FALSE,FALSE));
4903                   emitpcode(POC_BTFSC, popGet(AOP(left),0,FALSE,FALSE));
4904                   emitpcode(POC_BSF,   popGet(AOP(result),0,FALSE,FALSE));
4905
4906                   pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
4907                                  AOP(result)->aopu.aop_dir,
4908                                  AOP(result)->aopu.aop_dir);
4909                   pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
4910                                  AOP(right)->aopu.aop_dir,
4911                                  AOP(right)->aopu.aop_dir);
4912                   pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
4913                                  AOP(left)->aopu.aop_dir,
4914                                  AOP(left)->aopu.aop_dir);
4915                   pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
4916                                  AOP(result)->aopu.aop_dir,
4917                                  AOP(result)->aopu.aop_dir);
4918                 }
4919               }
4920             } else {
4921                 // c = bit | val;
4922                 symbol *tlbl = newiTempLabel(NULL);
4923                 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
4924
4925
4926                 emitpcode(POC_BCF,   popGet(AOP(result),0,FALSE,FALSE));
4927                 if( AOP_TYPE(right) == AOP_ACC) {
4928                   emitpcode(POC_IORLW, popGetLit(0));
4929                   emitSKPNZ;
4930                   emitpcode(POC_BTFSC, popGet(AOP(left),0,FALSE,FALSE));
4931                   emitpcode(POC_BSF,   popGet(AOP(result),0,FALSE,FALSE));
4932                 }
4933
4934
4935
4936                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
4937                     pic14_emitcode(";XXX setb","c");
4938                 pic14_emitcode(";XXX jb","%s,%05d_DS_",
4939                          AOP(left)->aopu.aop_dir,tlbl->key+100);
4940                 pic14_toBoolean(right);
4941                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
4942                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4943                     jmpTrueOrFalse(ifx, tlbl);
4944                     goto release;
4945                 } else {
4946                     CLRC;
4947                     pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4948                 }
4949             }
4950         }
4951         // bit = c
4952         // val = c
4953         if(size)
4954             pic14_outBitC(result);
4955         // if(bit | ...)
4956         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4957             genIfxJump(ifx, "c");           
4958         goto release ;
4959     }
4960
4961     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
4962     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
4963     if((AOP_TYPE(right) == AOP_LIT) &&
4964        (AOP_TYPE(result) == AOP_CRY) &&
4965        (AOP_TYPE(left) != AOP_CRY)){
4966         if(lit){
4967           pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
4968             // result = 1
4969             if(size)
4970                 pic14_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
4971             else 
4972                 continueIfTrue(ifx);
4973             goto release;
4974         } else {
4975           pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
4976             // lit = 0, result = boolean(left)
4977             if(size)
4978                 pic14_emitcode(";XXX setb","c");
4979             pic14_toBoolean(right);
4980             if(size){
4981                 symbol *tlbl = newiTempLabel(NULL);
4982                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
4983                 CLRC;
4984                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4985             } else {
4986                 genIfxJump (ifx,"a");
4987                 goto release;
4988             }
4989         }
4990         pic14_outBitC(result);
4991         goto release ;
4992     }
4993
4994     /* if left is same as result */
4995     if(pic14_sameRegs(AOP(result),AOP(left))){
4996       int know_W = -1;
4997       for(;size--; offset++,lit>>=8) {
4998         if(AOP_TYPE(right) == AOP_LIT){
4999           if((lit & 0xff) == 0)
5000             /*  or'ing with 0 has no effect */
5001             continue;
5002           else {
5003             int p = my_powof2(lit & 0xff);
5004             if(p>=0) {
5005               /* only one bit is set in the literal, so use a bsf instruction */
5006               emitpcode(POC_BSF,
5007                         newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5008             } else {
5009               if(know_W != (lit & 0xff))
5010                 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5011               know_W = lit & 0xff;
5012               emitpcode(POC_IORWF, popGet(AOP(left),offset,FALSE,FALSE));
5013             }
5014                     
5015           }
5016         } else {
5017           if (AOP_TYPE(left) == AOP_ACC) {
5018             emitpcode(POC_IORFW,  popGet(AOP(right),offset,FALSE,FALSE));
5019             pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5020           } else {                  
5021             emitpcode(POC_MOVFW,  popGet(AOP(right),offset,FALSE,FALSE));
5022             emitpcode(POC_IORWF,  popGet(AOP(left),offset,FALSE,FALSE));
5023
5024             pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5025             pic14_emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
5026
5027           }
5028         }
5029       }
5030     } else {
5031         // left & result in different registers
5032         if(AOP_TYPE(result) == AOP_CRY){
5033             // result = bit
5034             // if(size), result in bit
5035             // if(!size && ifx), conditional oper: if(left | right)
5036             symbol *tlbl = newiTempLabel(NULL);
5037             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5038             pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5039
5040
5041             if(size)
5042                 pic14_emitcode(";XXX setb","c");
5043             while(sizer--){
5044                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5045                 pic14_emitcode(";XXX orl","a,%s",
5046                          aopGet(AOP(left),offset,FALSE,FALSE));
5047                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5048                 offset++;
5049             }
5050             if(size){
5051                 CLRC;
5052                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5053                 pic14_outBitC(result);
5054             } else if(ifx)
5055                 jmpTrueOrFalse(ifx, tlbl);
5056         } else for(;(size--);offset++){
5057           // normal case
5058           // result = left & right
5059           if(AOP_TYPE(right) == AOP_LIT){
5060             int t = (lit >> (offset*8)) & 0x0FFL;
5061             switch(t) { 
5062             case 0x00:
5063               emitpcode(POC_MOVFW,  popGet(AOP(left),offset,FALSE,FALSE));
5064               emitpcode(POC_MOVWF,  popGet(AOP(result),offset,FALSE,FALSE));
5065
5066               pic14_emitcode("movf","%s,w",
5067                        aopGet(AOP(left),offset,FALSE,FALSE));
5068               pic14_emitcode("movwf","%s",
5069                        aopGet(AOP(result),offset,FALSE,FALSE));
5070               break;
5071             default:
5072               emitpcode(POC_MOVLW,  popGetLit(t));
5073               emitpcode(POC_IORFW,  popGet(AOP(left),offset,FALSE,FALSE));
5074               emitpcode(POC_MOVWF,  popGet(AOP(result),offset,FALSE,FALSE));
5075
5076               pic14_emitcode("movlw","0x%x",t);
5077               pic14_emitcode("iorwf","%s,w",
5078                        aopGet(AOP(left),offset,FALSE,FALSE));
5079               pic14_emitcode("movwf","%s",
5080                        aopGet(AOP(result),offset,FALSE,FALSE));
5081               
5082             }
5083             continue;
5084           }
5085
5086           // faster than result <- left, anl result,right
5087           // and better if result is SFR
5088           if (AOP_TYPE(left) == AOP_ACC) {
5089             emitpcode(POC_IORWF,  popGet(AOP(right),offset,FALSE,FALSE));
5090             pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5091           } else {
5092             emitpcode(POC_MOVFW,  popGet(AOP(right),offset,FALSE,FALSE));
5093             emitpcode(POC_IORFW,  popGet(AOP(left),offset,FALSE,FALSE));
5094
5095             pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5096             pic14_emitcode("iorwf","%s,w",
5097                      aopGet(AOP(left),offset,FALSE,FALSE));
5098           }
5099           emitpcode(POC_MOVWF,  popGet(AOP(result),offset,FALSE,FALSE));
5100           pic14_emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5101         }
5102     }
5103
5104 release :
5105     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5106     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5107     freeAsmop(result,NULL,ic,TRUE);     
5108 }
5109
5110 /*-----------------------------------------------------------------*/
5111 /* genXor - code for xclusive or                                   */
5112 /*-----------------------------------------------------------------*/
5113 static void genXor (iCode *ic, iCode *ifx)
5114 {
5115     operand *left, *right, *result;
5116     int size, offset=0;
5117     unsigned long lit = 0L;
5118
5119     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5120
5121     aopOp((left = IC_LEFT(ic)),ic,FALSE);
5122     aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5123     aopOp((result=IC_RESULT(ic)),ic,TRUE);
5124
5125     /* if left is a literal & right is not ||
5126        if left needs acc & right does not */
5127     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5128         (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
5129         operand *tmp = right ;
5130         right = left;
5131         left = tmp;
5132     }
5133
5134     /* if result = right then exchange them */
5135     if(pic14_sameRegs(AOP(result),AOP(right))){
5136         operand *tmp = right ;
5137         right = left;
5138         left = tmp;
5139     }
5140
5141     /* if right is bit then exchange them */
5142     if (AOP_TYPE(right) == AOP_CRY &&
5143         AOP_TYPE(left) != AOP_CRY){
5144         operand *tmp = right ;
5145         right = left;
5146         left = tmp;
5147     }
5148     if(AOP_TYPE(right) == AOP_LIT)
5149         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5150
5151     size = AOP_SIZE(result);
5152
5153     // if(bit ^ yy)
5154     // xx = bit ^ yy;
5155     if (AOP_TYPE(left) == AOP_CRY){
5156         if(AOP_TYPE(right) == AOP_LIT){
5157             // c = bit & literal;
5158             if(lit>>1){
5159                 // lit>>1  != 0 => result = 1
5160                 if(AOP_TYPE(result) == AOP_CRY){
5161                     if(size)
5162                         pic14_emitcode("setb","%s",AOP(result)->aopu.aop_dir);
5163                     else if(ifx)
5164                         continueIfTrue(ifx);
5165                     goto release;
5166                 }
5167                 pic14_emitcode("setb","c");
5168             } else{
5169                 // lit == (0 or 1)
5170                 if(lit == 0){
5171                     // lit == 0, result = left
5172                     if(size && pic14_sameRegs(AOP(result),AOP(left)))
5173                         goto release;
5174                     pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5175                 } else{
5176                     // lit == 1, result = not(left)
5177                     if(size && pic14_sameRegs(AOP(result),AOP(left))){
5178                         pic14_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
5179                         goto release;
5180                     } else {
5181                         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5182                         pic14_emitcode("cpl","c");
5183                     }
5184                 }
5185             }
5186
5187         } else {
5188             // right != literal
5189             symbol *tlbl = newiTempLabel(NULL);
5190             if (AOP_TYPE(right) == AOP_CRY){
5191                 // c = bit ^ bit;
5192                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5193             }
5194             else{
5195                 int sizer = AOP_SIZE(right);
5196                 // c = bit ^ val
5197                 // if val>>1 != 0, result = 1
5198                 pic14_emitcode("setb","c");
5199                 while(sizer){
5200                     MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
5201                     if(sizer == 1)
5202                         // test the msb of the lsb
5203                         pic14_emitcode("anl","a,#0xfe");
5204                     pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5205                     sizer--;
5206                 }
5207                 // val = (0,1)
5208                 pic14_emitcode("rrc","a");
5209             }
5210             pic14_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
5211             pic14_emitcode("cpl","c");
5212             pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
5213         }
5214         // bit = c
5215         // val = c
5216         if(size)
5217             pic14_outBitC(result);
5218         // if(bit | ...)
5219         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5220             genIfxJump(ifx, "c");           
5221         goto release ;
5222     }
5223
5224     if(pic14_sameRegs(AOP(result),AOP(left))){
5225         /* if left is same as result */
5226         for(;size--; offset++) {
5227             if(AOP_TYPE(right) == AOP_LIT){
5228               int t  = (lit >> (offset*8)) & 0x0FFL;
5229                 if(t == 0x00L)
5230                     continue;
5231                 else
5232                     if (IS_AOP_PREG(left)) {
5233                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5234                         pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
5235                         aopPut(AOP(result),"a",offset);
5236                     } else {
5237                       emitpcode(POC_MOVLW, popGetLit(t));
5238                       emitpcode(POC_XORWF,popGet(AOP(left),offset,FALSE,FALSE));
5239                       pic14_emitcode("xrl","%s,%s",
5240                                      aopGet(AOP(left),offset,FALSE,TRUE),
5241                                      aopGet(AOP(right),offset,FALSE,FALSE));
5242                     }
5243             } else {
5244                 if (AOP_TYPE(left) == AOP_ACC)
5245                     pic14_emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
5246                 else {
5247                     MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5248                     if (IS_AOP_PREG(left)) {
5249                         pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
5250                         aopPut(AOP(result),"a",offset);
5251                     } else
5252                         pic14_emitcode("xrl","%s,a",
5253                                  aopGet(AOP(left),offset,FALSE,TRUE));
5254                 }
5255             }
5256         }
5257     } else {
5258         // left & result in different registers
5259         if(AOP_TYPE(result) == AOP_CRY){
5260             // result = bit
5261             // if(size), result in bit
5262             // if(!size && ifx), conditional oper: if(left ^ right)
5263             symbol *tlbl = newiTempLabel(NULL);
5264             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5265             if(size)
5266                 pic14_emitcode("setb","c");
5267             while(sizer--){
5268                 if((AOP_TYPE(right) == AOP_LIT) &&
5269                    (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
5270                     MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
5271                 } else {
5272                     MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5273                     pic14_emitcode("xrl","a,%s",
5274                              aopGet(AOP(left),offset,FALSE,FALSE));
5275                 }
5276                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5277                 offset++;
5278             }
5279             if(size){
5280                 CLRC;
5281                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5282                 pic14_outBitC(result);
5283             } else if(ifx)
5284                 jmpTrueOrFalse(ifx, tlbl);
5285         } else for(;(size--);offset++){
5286             // normal case
5287             // result = left & right
5288             if(AOP_TYPE(right) == AOP_LIT){
5289               int t = (lit >> (offset*8)) & 0x0FFL;
5290               switch(t) { 
5291               case 0x00:
5292                 emitpcode(POC_MOVFW,popGet(AOP(left),offset,FALSE,FALSE));
5293                 emitpcode(POC_MOVWF,popGet(AOP(result),offset,FALSE,FALSE));
5294                 pic14_emitcode("movf","%s,w",
5295                          aopGet(AOP(left),offset,FALSE,FALSE));
5296                 pic14_emitcode("movwf","%s",
5297                          aopGet(AOP(result),offset,FALSE,FALSE));
5298                 break;
5299               case 0xff:
5300                 emitpcode(POC_COMFW,popGet(AOP(left),offset,FALSE,FALSE));
5301                 emitpcode(POC_MOVWF,popGet(AOP(result),offset,FALSE,FALSE));
5302                 pic14_emitcode("comf","%s,w",
5303                          aopGet(AOP(left),offset,FALSE,FALSE));
5304                 pic14_emitcode("movwf","%s",
5305                          aopGet(AOP(result),offset,FALSE,FALSE));
5306                 break;
5307               default:
5308                 emitpcode(POC_MOVLW, popGetLit(t));
5309                 emitpcode(POC_XORFW,popGet(AOP(left),offset,FALSE,FALSE));
5310                 emitpcode(POC_MOVWF,popGet(AOP(result),offset,FALSE,FALSE));
5311                 pic14_emitcode("movlw","0x%x",t);
5312                 pic14_emitcode("xorwf","%s,w",
5313                          aopGet(AOP(left),offset,FALSE,FALSE));
5314                 pic14_emitcode("movwf","%s",
5315                          aopGet(AOP(result),offset,FALSE,FALSE));
5316
5317               }
5318               continue;
5319             }
5320
5321             // faster than result <- left, anl result,right
5322             // and better if result is SFR
5323             if (AOP_TYPE(left) == AOP_ACC) {
5324                 emitpcode(POC_XORFW,popGet(AOP(right),offset,FALSE,FALSE));
5325                 pic14_emitcode("xorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5326             } else {
5327                 emitpcode(POC_MOVFW,popGet(AOP(right),offset,FALSE,FALSE));
5328                 emitpcode(POC_XORFW,popGet(AOP(left),offset,FALSE,FALSE));
5329                 pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5330                 pic14_emitcode("xorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
5331             }
5332             if ( AOP_TYPE(result) != AOP_ACC){
5333                 emitpcode(POC_MOVWF,popGet(AOP(result),offset,FALSE,FALSE));
5334               pic14_emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5335             }
5336         }
5337     }
5338
5339 release :
5340     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5341     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5342     freeAsmop(result,NULL,ic,TRUE);     
5343 }
5344
5345 /*-----------------------------------------------------------------*/
5346 /* genInline - write the inline code out                           */
5347 /*-----------------------------------------------------------------*/
5348 static void genInline (iCode *ic)
5349 {
5350     char *buffer, *bp, *bp1;
5351     
5352     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5353
5354     _G.inLine += (!options.asmpeep);
5355
5356     buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5357     strcpy(buffer,IC_INLINE(ic));
5358
5359     /* emit each line as a code */
5360     while (*bp) {
5361         if (*bp == '\n') {
5362             *bp++ = '\0';
5363             pic14_emitcode(bp1,"");
5364             bp1 = bp;
5365         } else {
5366             if (*bp == ':') {
5367                 bp++;
5368                 *bp = '\0';
5369                 bp++;
5370                 pic14_emitcode(bp1,"");
5371                 bp1 = bp;
5372             } else
5373                 bp++;
5374         }
5375     }
5376     if (bp1 != bp)
5377         pic14_emitcode(bp1,"");
5378     /*     pic14_emitcode("",buffer); */
5379     _G.inLine -= (!options.asmpeep);
5380 }
5381
5382 /*-----------------------------------------------------------------*/
5383 /* genRRC - rotate right with carry                                */
5384 /*-----------------------------------------------------------------*/
5385 static void genRRC (iCode *ic)
5386 {
5387     operand *left , *result ;
5388     int size, offset = 0;
5389     char *l;    
5390
5391     /* rotate right with carry */
5392     left = IC_LEFT(ic);
5393     result=IC_RESULT(ic);
5394     aopOp (left,ic,FALSE);
5395     aopOp (result,ic,FALSE);
5396
5397     /* move it to the result */
5398     size = AOP_SIZE(result);    
5399     offset = size - 1 ;
5400     CLRC;
5401     while (size--) {
5402         l = aopGet(AOP(left),offset,FALSE,FALSE);
5403         MOVA(l);
5404         pic14_emitcode("rrc","a");
5405         if (AOP_SIZE(result) > 1)
5406             aopPut(AOP(result),"a",offset--);
5407     }
5408     /* now we need to put the carry into the
5409     highest order byte of the result */
5410     if (AOP_SIZE(result) > 1) {
5411         l = aopGet(AOP(result),AOP_SIZE(result)-1,FALSE,FALSE);
5412         MOVA(l);
5413     }
5414     pic14_emitcode("mov","acc.7,c");
5415     aopPut(AOP(result),"a",AOP_SIZE(result)-1);
5416     freeAsmop(left,NULL,ic,TRUE);
5417     freeAsmop(result,NULL,ic,TRUE);
5418 }
5419
5420 /*-----------------------------------------------------------------*/
5421 /* genRLC - generate code for rotate left with carry               */
5422 /*-----------------------------------------------------------------*/
5423 static void genRLC (iCode *ic)
5424 {    
5425     operand *left , *result ;
5426     int size, offset = 0;
5427     char *l;    
5428
5429     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5430     /* rotate right with carry */
5431     left = IC_LEFT(ic);
5432     result=IC_RESULT(ic);
5433     aopOp (left,ic,FALSE);
5434     aopOp (result,ic,FALSE);
5435
5436     /* move it to the result */
5437     size = AOP_SIZE(result);    
5438     offset = 0 ;
5439     if (size--) {
5440         l = aopGet(AOP(left),offset,FALSE,FALSE);
5441         MOVA(l);
5442         pic14_emitcode("add","a,acc");
5443         if (AOP_SIZE(result) > 1)
5444             aopPut(AOP(result),"a",offset++);
5445         while (size--) {
5446             l = aopGet(AOP(left),offset,FALSE,FALSE);
5447             MOVA(l);
5448             pic14_emitcode("rlc","a");
5449             if (AOP_SIZE(result) > 1)
5450                 aopPut(AOP(result),"a",offset++);
5451         }
5452     }
5453     /* now we need to put the carry into the
5454     highest order byte of the result */
5455     if (AOP_SIZE(result) > 1) {
5456         l = aopGet(AOP(result),0,FALSE,FALSE);
5457         MOVA(l);
5458     }
5459     pic14_emitcode("mov","acc.0,c");
5460     aopPut(AOP(result),"a",0);
5461     freeAsmop(left,NULL,ic,TRUE);
5462     freeAsmop(result,NULL,ic,TRUE);
5463 }
5464
5465 /*-----------------------------------------------------------------*/
5466 /* genGetHbit - generates code get highest order bit               */
5467 /*-----------------------------------------------------------------*/
5468 static void genGetHbit (iCode *ic)
5469 {
5470     operand *left, *result;
5471     left = IC_LEFT(ic);
5472     result=IC_RESULT(ic);
5473     aopOp (left,ic,FALSE);
5474     aopOp (result,ic,FALSE);
5475
5476     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5477     /* get the highest order byte into a */
5478     MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
5479     if(AOP_TYPE(result) == AOP_CRY){
5480         pic14_emitcode("rlc","a");
5481         pic14_outBitC(result);
5482     }
5483     else{
5484         pic14_emitcode("rl","a");
5485         pic14_emitcode("anl","a,#0x01");
5486         pic14_outAcc(result);
5487     }
5488
5489
5490     freeAsmop(left,NULL,ic,TRUE);
5491     freeAsmop(result,NULL,ic,TRUE);
5492 }
5493
5494 /*-----------------------------------------------------------------*/
5495 /* AccRol - rotate left accumulator by known count                 */
5496 /*-----------------------------------------------------------------*/
5497 static void AccRol (int shCount)
5498 {
5499     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5500     shCount &= 0x0007;              // shCount : 0..7
5501     switch(shCount){
5502         case 0 :
5503             break;
5504         case 1 :
5505             pic14_emitcode("rl","a");
5506             break;
5507         case 2 :
5508             pic14_emitcode("rl","a");
5509             pic14_emitcode("rl","a");
5510             break;
5511         case 3 :
5512             pic14_emitcode("swap","a");
5513             pic14_emitcode("rr","a");
5514             break;
5515         case 4 :
5516             pic14_emitcode("swap","a");
5517             break;
5518         case 5 :
5519             pic14_emitcode("swap","a");
5520             pic14_emitcode("rl","a");
5521             break;
5522         case 6 :
5523             pic14_emitcode("rr","a");
5524             pic14_emitcode("rr","a");
5525             break;
5526         case 7 :
5527             pic14_emitcode("rr","a");
5528             break;
5529     }
5530 }
5531
5532 /*-----------------------------------------------------------------*/
5533 /* AccLsh - left shift accumulator by known count                  */
5534 /*-----------------------------------------------------------------*/
5535 static void AccLsh (int shCount)
5536 {
5537     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5538     if(shCount != 0){
5539         if(shCount == 1)
5540             pic14_emitcode("add","a,acc");
5541         else 
5542             if(shCount == 2) {
5543             pic14_emitcode("add","a,acc");
5544             pic14_emitcode("add","a,acc");
5545         } else {
5546             /* rotate left accumulator */
5547             AccRol(shCount);
5548             /* and kill the lower order bits */
5549             pic14_emitcode("anl","a,#0x%02x", SLMask[shCount]);
5550         }
5551     }
5552 }
5553
5554 /*-----------------------------------------------------------------*/
5555 /* AccRsh - right shift accumulator by known count                 */
5556 /*-----------------------------------------------------------------*/
5557 static void AccRsh (int shCount)
5558 {
5559     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5560     if(shCount != 0){
5561         if(shCount == 1){
5562             CLRC;
5563             pic14_emitcode("rrc","a");
5564         } else {
5565             /* rotate right accumulator */
5566             AccRol(8 - shCount);
5567             /* and kill the higher order bits */
5568             pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
5569         }
5570     }
5571 }
5572
5573 #if 0
5574 /*-----------------------------------------------------------------*/
5575 /* AccSRsh - signed right shift accumulator by known count                 */
5576 /*-----------------------------------------------------------------*/
5577 static void AccSRsh (int shCount)
5578 {
5579     symbol *tlbl ;
5580     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5581     if(shCount != 0){
5582         if(shCount == 1){
5583             pic14_emitcode("mov","c,acc.7");
5584             pic14_emitcode("rrc","a");
5585         } else if(shCount == 2){
5586             pic14_emitcode("mov","c,acc.7");
5587             pic14_emitcode("rrc","a");
5588             pic14_emitcode("mov","c,acc.7");
5589             pic14_emitcode("rrc","a");
5590         } else {
5591             tlbl = newiTempLabel(NULL);
5592             /* rotate right accumulator */
5593             AccRol(8 - shCount);
5594             /* and kill the higher order bits */
5595             pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
5596             pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
5597             pic14_emitcode("orl","a,#0x%02x",
5598                      (unsigned char)~SRMask[shCount]);
5599             pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5600         }
5601     }
5602 }
5603 #endif
5604 /*-----------------------------------------------------------------*/
5605 /* shiftR1Left2Result - shift right one byte from left to result   */
5606 /*-----------------------------------------------------------------*/
5607 static void shiftR1Left2ResultSigned (operand *left, int offl,
5608                                 operand *result, int offr,
5609                                 int shCount)
5610 {
5611   int same;
5612
5613   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5614
5615   same = (left == result) || (AOP(left) == AOP(result));
5616
5617   switch(shCount) {
5618   case 1:
5619     emitpcode(POC_RLFW, popGet(AOP(left),offl,FALSE,FALSE));
5620     if(same) 
5621       emitpcode(POC_RRF, popGet(AOP(result),offr,FALSE,FALSE));
5622     else {
5623       emitpcode(POC_RRFW, popGet(AOP(left),offl,FALSE,FALSE));
5624       emitpcode(POC_MOVWF, popGet(AOP(result),offr,FALSE,FALSE));
5625     }
5626
5627     break;
5628
5629   default:
5630     break;
5631   }
5632 }
5633
5634 /*-----------------------------------------------------------------*/
5635 /* shiftR1Left2Result - shift right one byte from left to result   */
5636 /*-----------------------------------------------------------------*/
5637 static void shiftR1Left2Result (operand *left, int offl,
5638                                 operand *result, int offr,
5639                                 int shCount, int sign)
5640 {
5641   int same;
5642
5643   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5644
5645   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
5646
5647   /* Copy the msb into the carry if signed. */
5648   if(sign) {
5649     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
5650     return;
5651   }
5652
5653
5654
5655   switch(shCount) {
5656   case 1:
5657     emitCLRC;
5658     if(same) 
5659       emitpcode(POC_RRF, popGet(AOP(result),offr,FALSE,FALSE));
5660     else {
5661       emitpcode(POC_RRFW, popGet(AOP(left),offl,FALSE,FALSE));
5662       emitpcode(POC_MOVWF, popGet(AOP(result),offr,FALSE,FALSE));
5663     }
5664     break;
5665   case 2:
5666     emitCLRC;
5667     if(same) {
5668       emitpcode(POC_RRF, popGet(AOP(result),offr,FALSE,FALSE));
5669     } else {
5670       emitpcode(POC_RRFW, popGet(AOP(left),offl,FALSE,FALSE));
5671       emitpcode(POC_MOVWF, popGet(AOP(result),offr,FALSE,FALSE));
5672     }
5673     emitCLRC;
5674     emitpcode(POC_RRF, popGet(AOP(result),offr,FALSE,FALSE));
5675
5676     break;
5677   case 3:
5678     if(same) 
5679       emitpcode(POC_SWAPF, popGet(AOP(result),offr,FALSE,FALSE));
5680     else {
5681       emitpcode(POC_SWAPFW, popGet(AOP(left),offl,FALSE,FALSE));
5682       emitpcode(POC_MOVWF, popGet(AOP(result),offr,FALSE,FALSE));
5683     }
5684
5685     emitpcode(POC_RLFW,  popGet(AOP(result),offr,FALSE,FALSE));
5686     emitpcode(POC_RLFW,  popGet(AOP(result),offr,FALSE,FALSE));
5687     emitpcode(POC_ANDLW, popGetLit(0x1f));
5688     emitpcode(POC_MOVWF, popGet(AOP(result),offr,FALSE,FALSE));
5689     break;
5690       
5691   case 4:
5692     emitpcode(POC_SWAPFW, popGet(AOP(left),offl,FALSE,FALSE));
5693     emitpcode(POC_ANDLW, popGetLit(0x0f));
5694     emitpcode(POC_MOVWF, popGet(AOP(result),offr,FALSE,FALSE));
5695     break;
5696
5697   case 5:
5698     emitpcode(POC_SWAPFW, popGet(AOP(left),offl,FALSE,FALSE));
5699     emitpcode(POC_ANDLW, popGetLit(0x0f));
5700     emitpcode(POC_MOVWF, popGet(AOP(result),offr,FALSE,FALSE));
5701     emitCLRC;
5702     emitpcode(POC_RRF, popGet(AOP(result),offr,FALSE,FALSE));
5703
5704     break;
5705   case 6:
5706
5707     emitpcode(POC_RLFW,  popGet(AOP(left),offl,FALSE,FALSE));
5708     emitpcode(POC_ANDLW, popGetLit(0x80));
5709     emitpcode(POC_MOVWF, popGet(AOP(result),offr,FALSE,FALSE));
5710     emitpcode(POC_RLF,   popGet(AOP(result),offr,FALSE,FALSE));
5711     emitpcode(POC_RLF,   popGet(AOP(result),offr,FALSE,FALSE));
5712     break;
5713
5714   case 7:
5715
5716     emitpcode(POC_RLFW, popGet(AOP(left),offl,FALSE,FALSE));
5717     emitpcode(POC_CLRF, popGet(AOP(result),offr,FALSE,FALSE));
5718     emitpcode(POC_RLF,  popGet(AOP(result),offr,FALSE,FALSE));
5719
5720     break;
5721
5722   default:
5723     break;
5724   }
5725
5726
5727 #if 0
5728     
5729   MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5730
5731   /* shift right accumulator */
5732   if(sign)
5733     AccSRsh(shCount);
5734   else
5735     AccRsh(shCount);
5736   aopPut(AOP(result),"a",offr);
5737 #endif
5738 }
5739
5740 /*-----------------------------------------------------------------*/
5741 /* shiftL1Left2Result - shift left one byte from left to result    */
5742 /*-----------------------------------------------------------------*/
5743 static void shiftL1Left2Result (operand *left, int offl,
5744                                 operand *result, int offr, int shCount)
5745 {
5746   int same;
5747
5748   //    char *l;
5749   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5750
5751   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
5752   DEBUGpic14_emitcode ("; ***","same =  %d",same);
5753     //    l = aopGet(AOP(left),offl,FALSE,FALSE);
5754     //    MOVA(l);
5755     /* shift left accumulator */
5756     //AccLsh(shCount); // don't comment out just yet...
5757   //    aopPut(AOP(result),"a",offr);
5758
5759   switch(shCount) {
5760   case 1:
5761     /* Shift left 1 bit position */
5762     emitpcode(POC_MOVFW, popGet(AOP(left),offl,FALSE,FALSE));
5763     if(same) {
5764       emitpcode(POC_ADDWF, popGet(AOP(left),offl,FALSE,FALSE));
5765     } else {
5766       emitpcode(POC_ADDFW, popGet(AOP(left),offl,FALSE,FALSE));
5767       emitpcode(POC_MOVWF, popGet(AOP(result),offr,FALSE,FALSE));
5768     }
5769     break;
5770   case 2:
5771     emitpcode(POC_RLFW, popGet(AOP(left),offl,FALSE,FALSE));
5772     emitpcode(POC_ANDLW,popGetLit(0x7e));
5773     emitpcode(POC_MOVWF,popGet(AOP(result),offr,FALSE,FALSE));
5774     emitpcode(POC_ADDWF,popGet(AOP(result),offr,FALSE,FALSE));
5775     break;
5776   case 3:
5777     emitpcode(POC_RLFW, popGet(AOP(left),offl,FALSE,FALSE));
5778     emitpcode(POC_ANDLW,popGetLit(0x3e));
5779     emitpcode(POC_MOVWF,popGet(AOP(result),offr,FALSE,FALSE));
5780     emitpcode(POC_ADDWF,popGet(AOP(result),offr,FALSE,FALSE));
5781     emitpcode(POC_RLF,  popGet(AOP(result),offr,FALSE,FALSE));
5782     break;
5783   case 4:
5784     emitpcode(POC_SWAPFW,popGet(AOP(left),offl,FALSE,FALSE));
5785     emitpcode(POC_ANDLW, popGetLit(0xf0));
5786     emitpcode(POC_MOVWF,popGet(AOP(result),offr,FALSE,FALSE));
5787     break;
5788   case 5:
5789     emitpcode(POC_SWAPFW,popGet(AOP(left),offl,FALSE,FALSE));
5790     emitpcode(POC_ANDLW, popGetLit(0xf0));
5791     emitpcode(POC_MOVWF,popGet(AOP(result),offr,FALSE,FALSE));
5792     emitpcode(POC_ADDWF,popGet(AOP(result),offr,FALSE,FALSE));
5793     break;
5794   case 6:
5795     emitpcode(POC_SWAPFW,popGet(AOP(left),offl,FALSE,FALSE));
5796     emitpcode(POC_ANDLW, popGetLit(0x30));
5797     emitpcode(POC_MOVWF,popGet(AOP(result),offr,FALSE,FALSE));
5798     emitpcode(POC_ADDWF,popGet(AOP(result),offr,FALSE,FALSE));
5799     emitpcode(POC_RLF,  popGet(AOP(result),offr,FALSE,FALSE));
5800     break;
5801   case 7:
5802     emitpcode(POC_RRFW, popGet(AOP(left),offl,FALSE,FALSE));
5803     emitpcode(POC_CLRF, popGet(AOP(result),offr,FALSE,FALSE));
5804     emitpcode(POC_RRF,  popGet(AOP(result),offr,FALSE,FALSE));
5805     break;
5806
5807   default:
5808     DEBUGpic14_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
5809   }
5810
5811 }
5812
5813 /*-----------------------------------------------------------------*/
5814 /* movLeft2Result - move byte from left to result                  */
5815 /*-----------------------------------------------------------------*/
5816 static void movLeft2Result (operand *left, int offl,
5817                             operand *result, int offr, int sign)
5818 {
5819     char *l;
5820     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5821     if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
5822         l = aopGet(AOP(left),offl,FALSE,FALSE);
5823
5824         if (*l == '@' && (IS_AOP_PREG(result))) {
5825             pic14_emitcode("mov","a,%s",l);
5826             aopPut(AOP(result),"a",offr);
5827         } else {
5828           if(!sign) {
5829             emitpcode(POC_MOVFW, popGet(AOP(left),offl,FALSE,FALSE));
5830             emitpcode(POC_MOVWF, popGet(AOP(result),offr,FALSE,FALSE));
5831
5832             //aopPut(AOP(result),l,offr);
5833           }else{
5834                 /* MSB sign in acc.7 ! */
5835                 if(pic14_getDataSize(left) == offl+1){
5836                     pic14_emitcode("mov","a,%s",l);
5837                     aopPut(AOP(result),"a",offr);
5838                 }
5839             }
5840         }
5841     }
5842 }
5843
5844 /*-----------------------------------------------------------------*/
5845 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
5846 /*-----------------------------------------------------------------*/
5847 static void AccAXRrl1 (char *x)
5848 {
5849     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5850     pic14_emitcode("rrc","a");
5851     pic14_emitcode("xch","a,%s", x);
5852     pic14_emitcode("rrc","a");
5853     pic14_emitcode("xch","a,%s", x);
5854 }
5855
5856 /*-----------------------------------------------------------------*/
5857 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
5858 /*-----------------------------------------------------------------*/
5859 static void AccAXLrl1 (char *x)
5860 {
5861     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5862     pic14_emitcode("xch","a,%s",x);
5863     pic14_emitcode("rlc","a");
5864     pic14_emitcode("xch","a,%s",x);
5865     pic14_emitcode("rlc","a");
5866 }
5867 #if 0
5868 /*-----------------------------------------------------------------*/
5869 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
5870 /*-----------------------------------------------------------------*/
5871 static void AccAXLsh1 (char *x)
5872 {
5873     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5874     pic14_emitcode("xch","a,%s",x);
5875     pic14_emitcode("add","a,acc");
5876     pic14_emitcode("xch","a,%s",x);
5877     pic14_emitcode("rlc","a");
5878 }
5879 #endif
5880 #if 0
5881 /*-----------------------------------------------------------------*/
5882 /* AccAXLsh - left shift a:x by known count (0..7)                 */
5883 /*-----------------------------------------------------------------*/
5884 static void AccAXLsh (char *x, int shCount)
5885 {
5886     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5887     switch(shCount){
5888         case 0 :
5889             break;
5890         case 1 :
5891             AccAXLsh1(x);
5892             break;
5893         case 2 :
5894             AccAXLsh1(x);
5895             AccAXLsh1(x);
5896             break;
5897         case 3 :
5898         case 4 :
5899         case 5 :                        // AAAAABBB:CCCCCDDD
5900             AccRol(shCount);            // BBBAAAAA:CCCCCDDD
5901             pic14_emitcode("anl","a,#0x%02x",
5902                      SLMask[shCount]);  // BBB00000:CCCCCDDD
5903             pic14_emitcode("xch","a,%s",x);   // CCCCCDDD:BBB00000
5904             AccRol(shCount);            // DDDCCCCC:BBB00000
5905             pic14_emitcode("xch","a,%s",x);   // BBB00000:DDDCCCCC
5906             pic14_emitcode("xrl","a,%s",x);   // (BBB^DDD)CCCCC:DDDCCCCC
5907             pic14_emitcode("xch","a,%s",x);   // DDDCCCCC:(BBB^DDD)CCCCC
5908             pic14_emitcode("anl","a,#0x%02x",
5909                      SLMask[shCount]);  // DDD00000:(BBB^DDD)CCCCC
5910             pic14_emitcode("xch","a,%s",x);   // (BBB^DDD)CCCCC:DDD00000
5911             pic14_emitcode("xrl","a,%s",x);   // BBBCCCCC:DDD00000            
5912             break;
5913         case 6 :                        // AAAAAABB:CCCCCCDD
5914             pic14_emitcode("anl","a,#0x%02x",
5915                      SRMask[shCount]);  // 000000BB:CCCCCCDD
5916             pic14_emitcode("mov","c,acc.0");  // c = B
5917             pic14_emitcode("xch","a,%s",x);   // CCCCCCDD:000000BB
5918             AccAXRrl1(x);               // BCCCCCCD:D000000B
5919             AccAXRrl1(x);               // BBCCCCCC:DD000000
5920             break;
5921         case 7 :                        // a:x <<= 7
5922             pic14_emitcode("anl","a,#0x%02x",
5923                      SRMask[shCount]);  // 0000000B:CCCCCCCD
5924             pic14_emitcode("mov","c,acc.0");  // c = B
5925             pic14_emitcode("xch","a,%s",x);   // CCCCCCCD:0000000B
5926             AccAXRrl1(x);               // BCCCCCCC:D0000000
5927             break;
5928         default :
5929             break;
5930     }
5931 }
5932 #endif
5933 #if 0
5934 /*-----------------------------------------------------------------*/
5935 /* AccAXRsh - right shift a:x known count (0..7)                   */
5936 /*-----------------------------------------------------------------*/
5937 static void AccAXRsh (char *x, int shCount)
5938 {   
5939     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5940     switch(shCount){
5941         case 0 :
5942             break;
5943         case 1 :
5944             CLRC;
5945             AccAXRrl1(x);               // 0->a:x
5946             break;
5947         case 2 :
5948             CLRC;
5949             AccAXRrl1(x);               // 0->a:x
5950             CLRC;
5951             AccAXRrl1(x);               // 0->a:x
5952             break;
5953         case 3 :
5954         case 4 :
5955         case 5 :                        // AAAAABBB:CCCCCDDD = a:x
5956             AccRol(8 - shCount);        // BBBAAAAA:DDDCCCCC
5957             pic14_emitcode("xch","a,%s",x);   // CCCCCDDD:BBBAAAAA
5958             AccRol(8 - shCount);        // DDDCCCCC:BBBAAAAA
5959             pic14_emitcode("anl","a,#0x%02x",
5960                      SRMask[shCount]);  // 000CCCCC:BBBAAAAA
5961             pic14_emitcode("xrl","a,%s",x);   // BBB(CCCCC^AAAAA):BBBAAAAA
5962             pic14_emitcode("xch","a,%s",x);   // BBBAAAAA:BBB(CCCCC^AAAAA)
5963             pic14_emitcode("anl","a,#0x%02x",
5964                      SRMask[shCount]);  // 000AAAAA:BBB(CCCCC^AAAAA)
5965             pic14_emitcode("xch","a,%s",x);   // BBB(CCCCC^AAAAA):000AAAAA
5966             pic14_emitcode("xrl","a,%s",x);   // BBBCCCCC:000AAAAA
5967             pic14_emitcode("xch","a,%s",x);   // 000AAAAA:BBBCCCCC
5968             break;
5969         case 6 :                        // AABBBBBB:CCDDDDDD
5970             pic14_emitcode("mov","c,acc.7");
5971             AccAXLrl1(x);               // ABBBBBBC:CDDDDDDA
5972             AccAXLrl1(x);               // BBBBBBCC:DDDDDDAA
5973             pic14_emitcode("xch","a,%s",x);   // DDDDDDAA:BBBBBBCC
5974             pic14_emitcode("anl","a,#0x%02x",
5975                      SRMask[shCount]);  // 000000AA:BBBBBBCC
5976             break;
5977         case 7 :                        // ABBBBBBB:CDDDDDDD
5978             pic14_emitcode("mov","c,acc.7");  // c = A
5979             AccAXLrl1(x);               // BBBBBBBC:DDDDDDDA
5980             pic14_emitcode("xch","a,%s",x);   // DDDDDDDA:BBBBBBCC
5981             pic14_emitcode("anl","a,#0x%02x",
5982                      SRMask[shCount]);  // 0000000A:BBBBBBBC
5983             break;
5984         default :
5985             break;
5986     }
5987 }
5988 #endif
5989 /*-----------------------------------------------------------------*/
5990 /* AccAXRshS - right shift signed a:x known count (0..7)           */
5991 /*-----------------------------------------------------------------*/
5992 static void AccAXRshS (char *x, int shCount)
5993 {   
5994     symbol *tlbl ;
5995     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5996     switch(shCount){
5997         case 0 :
5998             break;
5999         case 1 :
6000             pic14_emitcode("mov","c,acc.7");
6001             AccAXRrl1(x);               // s->a:x
6002             break;
6003         case 2 :
6004             pic14_emitcode("mov","c,acc.7");
6005             AccAXRrl1(x);               // s->a:x
6006             pic14_emitcode("mov","c,acc.7");
6007             AccAXRrl1(x);               // s->a:x
6008             break;
6009         case 3 :
6010         case 4 :
6011         case 5 :                        // AAAAABBB:CCCCCDDD = a:x
6012             tlbl = newiTempLabel(NULL);
6013             AccRol(8 - shCount);        // BBBAAAAA:CCCCCDDD
6014             pic14_emitcode("xch","a,%s",x);   // CCCCCDDD:BBBAAAAA
6015             AccRol(8 - shCount);        // DDDCCCCC:BBBAAAAA
6016             pic14_emitcode("anl","a,#0x%02x",
6017                      SRMask[shCount]);  // 000CCCCC:BBBAAAAA
6018             pic14_emitcode("xrl","a,%s",x);   // BBB(CCCCC^AAAAA):BBBAAAAA
6019             pic14_emitcode("xch","a,%s",x);   // BBBAAAAA:BBB(CCCCC^AAAAA)
6020             pic14_emitcode("anl","a,#0x%02x",
6021                      SRMask[shCount]);  // 000AAAAA:BBB(CCCCC^AAAAA)
6022             pic14_emitcode("xch","a,%s",x);   // BBB(CCCCC^AAAAA):000AAAAA
6023             pic14_emitcode("xrl","a,%s",x);   // BBBCCCCC:000AAAAA
6024             pic14_emitcode("xch","a,%s",x);   // 000SAAAA:BBBCCCCC
6025             pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100); 
6026             pic14_emitcode("orl","a,#0x%02x",
6027                      (unsigned char)~SRMask[shCount]);  // 111AAAAA:BBBCCCCC
6028             pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6029             break;                      // SSSSAAAA:BBBCCCCC
6030         case 6 :                        // AABBBBBB:CCDDDDDD
6031             tlbl = newiTempLabel(NULL);
6032             pic14_emitcode("mov","c,acc.7");
6033             AccAXLrl1(x);               // ABBBBBBC:CDDDDDDA
6034             AccAXLrl1(x);               // BBBBBBCC:DDDDDDAA
6035             pic14_emitcode("xch","a,%s",x);   // DDDDDDAA:BBBBBBCC
6036             pic14_emitcode("anl","a,#0x%02x",
6037                      SRMask[shCount]);  // 000000AA:BBBBBBCC
6038             pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100); 
6039             pic14_emitcode("orl","a,#0x%02x",
6040                      (unsigned char)~SRMask[shCount]);  // 111111AA:BBBBBBCC
6041             pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6042             break;
6043         case 7 :                        // ABBBBBBB:CDDDDDDD
6044             tlbl = newiTempLabel(NULL);
6045             pic14_emitcode("mov","c,acc.7");  // c = A
6046             AccAXLrl1(x);               // BBBBBBBC:DDDDDDDA
6047             pic14_emitcode("xch","a,%s",x);   // DDDDDDDA:BBBBBBCC
6048             pic14_emitcode("anl","a,#0x%02x",
6049                      SRMask[shCount]);  // 0000000A:BBBBBBBC
6050             pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100); 
6051             pic14_emitcode("orl","a,#0x%02x",
6052                      (unsigned char)~SRMask[shCount]);  // 1111111A:BBBBBBBC
6053             pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6054             break;
6055         default :
6056             break;
6057     }
6058 }
6059
6060 /*-----------------------------------------------------------------*/
6061 /* shiftL2Left2Result - shift left two bytes from left to result   */
6062 /*-----------------------------------------------------------------*/
6063 static void shiftL2Left2Result (operand *left, int offl,
6064                                 operand *result, int offr, int shCount)
6065 {
6066
6067
6068   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6069
6070   if(pic14_sameRegs(AOP(result), AOP(left))) {
6071     switch(shCount) {
6072     case 0:
6073       break;
6074     case 1:
6075     case 2:
6076     case 3:
6077
6078       emitpcode(POC_MOVFW,popGet(AOP(result),offr,FALSE,FALSE));
6079       emitpcode(POC_ADDWF,popGet(AOP(result),offr,FALSE,FALSE));
6080       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16,FALSE,FALSE));
6081
6082       while(--shCount) {
6083         emitCLRC;
6084         emitpcode(POC_RLF, popGet(AOP(result),offr,FALSE,FALSE));
6085         emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16,FALSE,FALSE));
6086       }
6087
6088       break;
6089     case 4:
6090     case 5:
6091       emitpcode(POC_MOVLW, popGetLit(0x0f));
6092       emitpcode(POC_ANDWF, popGet(AOP(result),offr+MSB16,FALSE,FALSE));
6093       emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16,FALSE,FALSE));
6094       emitpcode(POC_SWAPF, popGet(AOP(result),offr,FALSE,FALSE));
6095       emitpcode(POC_ANDFW, popGet(AOP(result),offr,FALSE,FALSE));
6096       emitpcode(POC_XORWF, popGet(AOP(result),offr,FALSE,FALSE));
6097       emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16,FALSE,FALSE));
6098       if(shCount >=5) {
6099         emitpcode(POC_RLF, popGet(AOP(result),offr,FALSE,FALSE));
6100         emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16,FALSE,FALSE));
6101       }
6102       break;
6103     case 6:
6104       emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16,FALSE,FALSE));
6105       emitpcode(POC_RRF,  popGet(AOP(result),offr,FALSE,FALSE));
6106       emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16,FALSE,FALSE));
6107       emitpcode(POC_RRF,  popGet(AOP(result),offr,FALSE,FALSE));
6108       emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16,FALSE,FALSE));
6109       emitpcode(POC_ANDLW,popGetLit(0xc0));
6110       emitpcode(POC_XORFW,popGet(AOP(result),offr,FALSE,FALSE));
6111       emitpcode(POC_XORWF,popGet(AOP(result),offr,FALSE,FALSE));
6112       emitpcode(POC_XORFW,popGet(AOP(result),offr,FALSE,FALSE));
6113       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16,FALSE,FALSE));
6114       break;
6115     case 7:
6116       emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16,FALSE,FALSE));
6117       emitpcode(POC_RRFW, popGet(AOP(result),offr,FALSE,FALSE));
6118       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16,FALSE,FALSE));
6119       emitpcode(POC_CLRF, popGet(AOP(result),offr,FALSE,FALSE));
6120       emitpcode(POC_RRF,  popGet(AOP(result),offr,FALSE,FALSE));
6121     }
6122
6123   } else {
6124     switch(shCount) {
6125     case 0:
6126       break;
6127     case 1:
6128     case 2:
6129     case 3:
6130       /* note, use a mov/add for the shift since the mov has a
6131          chance of getting optimized out */
6132       emitpcode(POC_MOVFW, popGet(AOP(left),offl,FALSE,FALSE));
6133       emitpcode(POC_MOVWF, popGet(AOP(result),offr,FALSE,FALSE));
6134       emitpcode(POC_ADDWF, popGet(AOP(result),offr,FALSE,FALSE));
6135       emitpcode(POC_RLFW,  popGet(AOP(left),offl+MSB16,FALSE,FALSE));
6136       emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16,FALSE,FALSE));
6137
6138       while(--shCount) {
6139         emitCLRC;
6140         emitpcode(POC_RLF, popGet(AOP(result),offr,FALSE,FALSE));
6141         emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16,FALSE,FALSE));
6142       }
6143       break;
6144
6145     case 4:
6146     case 5:
6147       emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16,FALSE,FALSE));
6148       emitpcode(POC_ANDLW, popGetLit(0xF0));
6149       emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16,FALSE,FALSE));
6150       emitpcode(POC_SWAPFW,popGet(AOP(left),offl,FALSE,FALSE));
6151       emitpcode(POC_MOVWF, popGet(AOP(result),offr,FALSE,FALSE));
6152       emitpcode(POC_ANDLW, popGetLit(0xF0));
6153       emitpcode(POC_XORWF, popGet(AOP(result),offr,FALSE,FALSE));
6154       emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16,FALSE,FALSE));
6155
6156
6157       if(shCount == 5) {
6158         emitpcode(POC_RLF, popGet(AOP(result),offr,FALSE,FALSE));
6159         emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16,FALSE,FALSE));
6160       }
6161       break;
6162     case 6:
6163       emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16,FALSE,FALSE));
6164       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16,FALSE,FALSE));
6165       emitpcode(POC_RRFW, popGet(AOP(result),offl,FALSE,FALSE));
6166       emitpcode(POC_MOVWF,  popGet(AOP(result),offr,FALSE,FALSE));
6167
6168       emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16,FALSE,FALSE));
6169       emitpcode(POC_RRF,  popGet(AOP(result),offr,FALSE,FALSE));
6170       emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16,FALSE,FALSE));
6171       emitpcode(POC_ANDLW,popGetLit(0xc0));
6172       emitpcode(POC_XORFW,popGet(AOP(result),offr,FALSE,FALSE));
6173       emitpcode(POC_XORWF,popGet(AOP(result),offr,FALSE,FALSE));
6174       emitpcode(POC_XORFW,popGet(AOP(result),offr,FALSE,FALSE));
6175       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16,FALSE,FALSE));
6176       break;
6177     case 7:
6178       emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16,FALSE,FALSE));
6179       emitpcode(POC_RRFW, popGet(AOP(left),offl,FALSE,FALSE));
6180       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16,FALSE,FALSE));
6181       emitpcode(POC_CLRF, popGet(AOP(result),offr,FALSE,FALSE));
6182       emitpcode(POC_RRF,  popGet(AOP(result),offr,FALSE,FALSE));
6183     }
6184   }
6185
6186 }
6187 /*-----------------------------------------------------------------*/
6188 /* shiftR2Left2Result - shift right two bytes from left to result  */
6189 /*-----------------------------------------------------------------*/
6190 static void shiftR2Left2Result (operand *left, int offl,
6191                                 operand *result, int offr,
6192                                 int shCount, int sign)
6193 {
6194   int same=0;
6195
6196   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6197   same = pic14_sameRegs(AOP(result), AOP(left));
6198
6199   if(same && ((offl + MSB16) == offr)){
6200     same=1;
6201     /* don't crash result[offr] */
6202     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6203     pic14_emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6204   } else {
6205     movLeft2Result(left,offl, result, offr, 0);
6206     MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6207   }
6208   /* a:x >> shCount (x = lsb(result))*/
6209   if(sign)
6210     AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6211   else {
6212     //AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6213     
6214     switch(shCount) {
6215     case 0:
6216       break;
6217     case 1:
6218     case 2:
6219     case 3:
6220       emitCLRC;
6221       if(same) {
6222         emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16,FALSE,FALSE));
6223         emitpcode(POC_RRF,popGet(AOP(result),offr,FALSE,FALSE));
6224       } else {
6225
6226         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16,FALSE,FALSE));
6227         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16,FALSE,FALSE));
6228         emitpcode(POC_RRFW, popGet(AOP(left),offl,FALSE,FALSE));
6229         emitpcode(POC_MOVWF,popGet(AOP(result),offr,FALSE,FALSE));
6230       }
6231
6232       while(--shCount) {
6233         emitCLRC;
6234         emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16,FALSE,FALSE));
6235         emitpcode(POC_RRF,popGet(AOP(result),offr,FALSE,FALSE));
6236       }
6237       break;
6238     case 4:
6239     case 5:
6240       if(same) {
6241
6242         emitpcode(POC_MOVLW, popGetLit(0xf0));
6243         emitpcode(POC_ANDWF, popGet(AOP(result),offr,FALSE,FALSE));
6244         emitpcode(POC_SWAPF, popGet(AOP(result),offr,FALSE,FALSE));
6245
6246         emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16,FALSE,FALSE));
6247         emitpcode(POC_ANDFW, popGet(AOP(result),offr+MSB16,FALSE,FALSE));
6248         emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16,FALSE,FALSE));
6249         emitpcode(POC_ADDWF, popGet(AOP(result),offr,FALSE,FALSE));
6250       } else {
6251         emitpcode(POC_SWAPF, popGet(AOP(left),offl,FALSE,FALSE));
6252         emitpcode(POC_ANDLW, popGetLit(0x0f));
6253         emitpcode(POC_MOVWF, popGet(AOP(result),offr,FALSE,FALSE));
6254
6255         emitpcode(POC_SWAPF, popGet(AOP(left),offl+MSB16,FALSE,FALSE));
6256         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16,FALSE,FALSE));
6257         emitpcode(POC_ANDLW, popGetLit(0xf0));
6258         emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16,FALSE,FALSE));
6259         emitpcode(POC_ADDWF, popGet(AOP(result),offr,FALSE,FALSE));
6260       }
6261
6262       if(shCount >=5) {
6263         emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16,FALSE,FALSE));
6264         emitpcode(POC_RRF, popGet(AOP(result),offr,FALSE,FALSE));
6265       }
6266
6267       break;
6268
6269     case 6:
6270       if(same) {
6271
6272         emitpcode(POC_RLF,  popGet(AOP(result),offr,FALSE,FALSE));
6273         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16,FALSE,FALSE));
6274
6275         emitpcode(POC_RLF,  popGet(AOP(result),offr,FALSE,FALSE));
6276         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16,FALSE,FALSE));
6277         emitpcode(POC_RLFW, popGet(AOP(result),offr,FALSE,FALSE));
6278         emitpcode(POC_ANDLW,popGetLit(0x03));
6279         emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16,FALSE,FALSE));
6280         emitpcode(POC_XORWF,popGet(AOP(result),offr+MSB16,FALSE,FALSE));
6281         emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16,FALSE,FALSE));
6282         emitpcode(POC_MOVWF,popGet(AOP(result),offr,FALSE,FALSE));
6283       } else {
6284         emitpcode(POC_RLFW, popGet(AOP(left),offl,FALSE,FALSE));
6285         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16,FALSE,FALSE));
6286         emitpcode(POC_RLFW, popGet(AOP(result),offl+MSB16,FALSE,FALSE));
6287         emitpcode(POC_MOVWF,popGet(AOP(result),offr,FALSE,FALSE));
6288         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16,FALSE,FALSE));
6289         emitpcode(POC_RLF,  popGet(AOP(result),offr,FALSE,FALSE));
6290         emitpcode(POC_RLFW, popGet(AOP(result),offr,FALSE,FALSE));
6291         emitpcode(POC_ANDLW,popGetLit(0x03));
6292         emitpcode(POC_MOVWF,popGet(AOP(result),offr,FALSE,FALSE));
6293       }
6294
6295       break;
6296     case 7:
6297       emitpcode(POC_RLFW, popGet(AOP(left),offl,FALSE,FALSE));
6298       emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16,FALSE,FALSE));
6299       emitpcode(POC_MOVWF,popGet(AOP(result),offr,FALSE,FALSE));
6300       emitpcode(POC_CLRF, popGet(AOP(result),offr+MSB16,FALSE,FALSE));
6301       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16,FALSE,FALSE));
6302     }
6303   }
6304 }
6305
6306 /*-----------------------------------------------------------------*/
6307 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
6308 /*-----------------------------------------------------------------*/
6309 static void shiftLLeftOrResult (operand *left, int offl,
6310                                 operand *result, int offr, int shCount)
6311 {
6312     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6313     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6314     /* shift left accumulator */
6315     AccLsh(shCount);
6316     /* or with result */
6317     pic14_emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
6318     /* back to result */
6319     aopPut(AOP(result),"a",offr);
6320 }
6321
6322 /*-----------------------------------------------------------------*/
6323 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
6324 /*-----------------------------------------------------------------*/
6325 static void shiftRLeftOrResult (operand *left, int offl,
6326                                 operand *result, int offr, int shCount)
6327 {
6328     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6329     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6330     /* shift right accumulator */
6331     AccRsh(shCount);
6332     /* or with result */
6333     pic14_emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
6334     /* back to result */
6335     aopPut(AOP(result),"a",offr);
6336 }
6337
6338 /*-----------------------------------------------------------------*/
6339 /* genlshOne - left shift a one byte quantity by known count       */
6340 /*-----------------------------------------------------------------*/
6341 static void genlshOne (operand *result, operand *left, int shCount)
6342 {       
6343     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6344     shiftL1Left2Result(left, LSB, result, LSB, shCount);
6345 }
6346
6347 /*-----------------------------------------------------------------*/
6348 /* genlshTwo - left shift two bytes by known amount != 0           */
6349 /*-----------------------------------------------------------------*/
6350 static void genlshTwo (operand *result,operand *left, int shCount)
6351 {
6352     int size;
6353     
6354     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6355     size = pic14_getDataSize(result);
6356
6357     /* if shCount >= 8 */
6358     if (shCount >= 8) {
6359         shCount -= 8 ;
6360
6361         if (size > 1){
6362             if (shCount)
6363                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6364             else 
6365                 movLeft2Result(left, LSB, result, MSB16, 0);
6366         }
6367         emitpcode(POC_CLRF,popGet(AOP(result),LSB,FALSE,FALSE));
6368     }
6369
6370     /*  1 <= shCount <= 7 */
6371     else {  
6372         if(size == 1)
6373             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
6374         else 
6375             shiftL2Left2Result(left, LSB, result, LSB, shCount);
6376     }
6377 }
6378
6379 /*-----------------------------------------------------------------*/
6380 /* shiftLLong - shift left one long from left to result            */
6381 /* offl = LSB or MSB16                                             */
6382 /*-----------------------------------------------------------------*/
6383 static void shiftLLong (operand *left, operand *result, int offr )
6384 {
6385     char *l;
6386     int size = AOP_SIZE(result);
6387
6388     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6389     if(size >= LSB+offr){
6390         l = aopGet(AOP(left),LSB,FALSE,FALSE);
6391         MOVA(l);
6392         pic14_emitcode("add","a,acc");
6393         if (pic14_sameRegs(AOP(left),AOP(result)) && 
6394             size >= MSB16+offr && offr != LSB )
6395             pic14_emitcode("xch","a,%s",
6396                      aopGet(AOP(left),LSB+offr,FALSE,FALSE));
6397         else        
6398             aopPut(AOP(result),"a",LSB+offr);
6399     }
6400
6401     if(size >= MSB16+offr){
6402         if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
6403             l = aopGet(AOP(left),MSB16,FALSE,FALSE);
6404             MOVA(l);
6405         }
6406         pic14_emitcode("rlc","a");
6407         if (pic14_sameRegs(AOP(left),AOP(result)) && 
6408             size >= MSB24+offr && offr != LSB)
6409             pic14_emitcode("xch","a,%s",
6410                      aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
6411         else        
6412             aopPut(AOP(result),"a",MSB16+offr);
6413     }
6414
6415     if(size >= MSB24+offr){
6416         if (!(pic14_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
6417             l = aopGet(AOP(left),MSB24,FALSE,FALSE);
6418             MOVA(l);
6419         }
6420         pic14_emitcode("rlc","a");
6421         if (pic14_sameRegs(AOP(left),AOP(result)) && 
6422             size >= MSB32+offr && offr != LSB )
6423             pic14_emitcode("xch","a,%s",
6424                      aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
6425         else        
6426             aopPut(AOP(result),"a",MSB24+offr);
6427     }
6428
6429     if(size > MSB32+offr){
6430         if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
6431             l = aopGet(AOP(left),MSB32,FALSE,FALSE);
6432             MOVA(l);    
6433         }
6434         pic14_emitcode("rlc","a");
6435         aopPut(AOP(result),"a",MSB32+offr);
6436     }
6437     if(offr != LSB)
6438         aopPut(AOP(result),zero,LSB);       
6439 }
6440
6441 /*-----------------------------------------------------------------*/
6442 /* genlshFour - shift four byte by a known amount != 0             */
6443 /*-----------------------------------------------------------------*/
6444 static void genlshFour (operand *result, operand *left, int shCount)
6445 {
6446     int size;
6447
6448     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6449     size = AOP_SIZE(result);
6450
6451     /* if shifting more that 3 bytes */
6452     if (shCount >= 24 ) {
6453         shCount -= 24;
6454         if (shCount)
6455             /* lowest order of left goes to the highest
6456             order of the destination */
6457             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
6458         else
6459             movLeft2Result(left, LSB, result, MSB32, 0);
6460         aopPut(AOP(result),zero,LSB);
6461         aopPut(AOP(result),zero,MSB16);
6462         aopPut(AOP(result),zero,MSB32);
6463         return;
6464     }
6465
6466     /* more than two bytes */
6467     else if ( shCount >= 16 ) {
6468         /* lower order two bytes goes to higher order two bytes */
6469         shCount -= 16;
6470         /* if some more remaining */
6471         if (shCount)
6472             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
6473         else {
6474             movLeft2Result(left, MSB16, result, MSB32, 0);
6475             movLeft2Result(left, LSB, result, MSB24, 0);
6476         }
6477         aopPut(AOP(result),zero,MSB16);
6478         aopPut(AOP(result),zero,LSB);
6479         return;
6480     }    
6481
6482     /* if more than 1 byte */
6483     else if ( shCount >= 8 ) {
6484         /* lower order three bytes goes to higher order  three bytes */
6485         shCount -= 8;
6486         if(size == 2){
6487             if(shCount)
6488                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6489             else
6490                 movLeft2Result(left, LSB, result, MSB16, 0);
6491         }
6492         else{   /* size = 4 */
6493             if(shCount == 0){
6494                 movLeft2Result(left, MSB24, result, MSB32, 0);
6495                 movLeft2Result(left, MSB16, result, MSB24, 0);
6496                 movLeft2Result(left, LSB, result, MSB16, 0);
6497                 aopPut(AOP(result),zero,LSB);
6498             }
6499             else if(shCount == 1)
6500                 shiftLLong(left, result, MSB16);
6501             else{
6502                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
6503                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6504                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
6505                 aopPut(AOP(result),zero,LSB);
6506             }
6507         }
6508     }
6509
6510     /* 1 <= shCount <= 7 */
6511     else if(shCount <= 2){
6512         shiftLLong(left, result, LSB);
6513         if(shCount == 2)
6514             shiftLLong(result, result, LSB);
6515     }
6516     /* 3 <= shCount <= 7, optimize */
6517     else{
6518         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
6519         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
6520         shiftL2Left2Result(left, LSB, result, LSB, shCount);
6521     }
6522 }
6523
6524 /*-----------------------------------------------------------------*/
6525 /* genLeftShiftLiteral - left shifting by known count              */
6526 /*-----------------------------------------------------------------*/
6527 static void genLeftShiftLiteral (operand *left,
6528                                  operand *right,
6529                                  operand *result,
6530                                  iCode *ic)
6531 {    
6532     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6533     int size;
6534
6535     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6536     freeAsmop(right,NULL,ic,TRUE);
6537
6538     aopOp(left,ic,FALSE);
6539     aopOp(result,ic,FALSE);
6540
6541     size = getSize(operandType(result));
6542
6543 #if VIEW_SIZE
6544     pic14_emitcode("; shift left ","result %d, left %d",size,
6545              AOP_SIZE(left));
6546 #endif
6547
6548     /* I suppose that the left size >= result size */
6549     if(shCount == 0){
6550         while(size--){
6551             movLeft2Result(left, size, result, size, 0);
6552         }
6553     }
6554
6555     else if(shCount >= (size * 8))
6556         while(size--)
6557             aopPut(AOP(result),zero,size);
6558     else{
6559         switch (size) {
6560             case 1:
6561                 genlshOne (result,left,shCount);
6562                 break;
6563
6564             case 2:
6565             case 3:
6566                 genlshTwo (result,left,shCount);
6567                 break;
6568
6569             case 4:
6570                 genlshFour (result,left,shCount);
6571                 break;
6572         }
6573     }
6574     freeAsmop(left,NULL,ic,TRUE);
6575     freeAsmop(result,NULL,ic,TRUE);
6576 }
6577
6578 /*-----------------------------------------------------------------*/
6579 /* genLeftShift - generates code for left shifting                 */
6580 /*-----------------------------------------------------------------*/
6581 static void genLeftShift (iCode *ic)
6582 {
6583     operand *left,*right, *result;
6584     int size, offset;
6585     char *l;
6586     symbol *tlbl , *tlbl1;
6587
6588     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6589
6590     right = IC_RIGHT(ic);
6591     left  = IC_LEFT(ic);
6592     result = IC_RESULT(ic);
6593
6594     aopOp(right,ic,FALSE);
6595
6596     /* if the shift count is known then do it 
6597     as efficiently as possible */
6598     if (AOP_TYPE(right) == AOP_LIT) {
6599         genLeftShiftLiteral (left,right,result,ic);
6600         return ;
6601     }
6602
6603     /* shift count is unknown then we have to form 
6604     a loop get the loop count in B : Note: we take
6605     only the lower order byte since shifting
6606     more that 32 bits make no sense anyway, ( the
6607     largest size of an object can be only 32 bits ) */  
6608
6609     
6610     aopOp(left,ic,FALSE);
6611     aopOp(result,ic,FALSE);
6612
6613     /* now move the left to the result if they are not the
6614     same */
6615     if (!pic14_sameRegs(AOP(left),AOP(result)) && 
6616         AOP_SIZE(result) > 1) {
6617
6618         size = AOP_SIZE(result);
6619         offset=0;
6620         while (size--) {
6621             l = aopGet(AOP(left),offset,FALSE,TRUE);
6622             if (*l == '@' && (IS_AOP_PREG(result))) {
6623
6624                 pic14_emitcode("mov","a,%s",l);
6625                 aopPut(AOP(result),"a",offset);
6626             } else
6627                 aopPut(AOP(result),l,offset);
6628             offset++;
6629         }
6630     }
6631
6632     size = AOP_SIZE(result);
6633
6634     /* if it is only one byte then */
6635     if (size == 1) {
6636       if(optimized_for_speed) {
6637         emitpcode(POC_SWAPFW, popGet(AOP(left),0,FALSE,FALSE));
6638         emitpcode(POC_ANDLW,  popGetLit(0xf0));
6639         emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),2,0));
6640         emitpcode(POC_MOVFW,  popGet(AOP(left),0,FALSE,FALSE));
6641         emitpcode(POC_MOVWF,  popGet(AOP(result),0,FALSE,FALSE));
6642         emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
6643         emitpcode(POC_ADDWF,  popGet(AOP(result),0,FALSE,FALSE));
6644         emitpcode(POC_RLFW,   popGet(AOP(result),0,FALSE,FALSE));
6645         emitpcode(POC_ANDLW,  popGetLit(0xfe));
6646         emitpcode(POC_ADDFW,  popGet(AOP(result),0,FALSE,FALSE));
6647         emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),1,0));
6648         emitpcode(POC_ADDWF,  popGet(AOP(result),0,FALSE,FALSE));
6649       } else {
6650
6651         tlbl = newiTempLabel(NULL);
6652         if (!pic14_sameRegs(AOP(left),AOP(result))) {
6653           emitpcode(POC_MOVFW,  popGet(AOP(left),0,FALSE,FALSE));
6654           emitpcode(POC_MOVWF,  popGet(AOP(result),0,FALSE,FALSE));
6655         }
6656
6657         emitpcode(POC_COMFW,  popGet(AOP(right),0,FALSE,FALSE));
6658         emitpcode(POC_RRF,    popGet(AOP(result),0,FALSE,FALSE));
6659         emitpLabel(tlbl->key);
6660         emitpcode(POC_RLF,    popGet(AOP(result),0,FALSE,FALSE));
6661         emitpcode(POC_ADDLW,  popGetLit(1));
6662         emitSKPC;
6663         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
6664       }
6665       goto release ;
6666     }
6667     
6668
6669     tlbl = newiTempLabel(NULL);
6670     offset = 0 ;   
6671     tlbl1 = newiTempLabel(NULL);
6672
6673     reAdjustPreg(AOP(result));    
6674     
6675     pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
6676     pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
6677     l = aopGet(AOP(result),offset,FALSE,FALSE);
6678     MOVA(l);
6679     pic14_emitcode("add","a,acc");         
6680     aopPut(AOP(result),"a",offset++);
6681     while (--size) {
6682         l = aopGet(AOP(result),offset,FALSE,FALSE);
6683         MOVA(l);
6684         pic14_emitcode("rlc","a");         
6685         aopPut(AOP(result),"a",offset++);
6686     }
6687     reAdjustPreg(AOP(result));
6688
6689     pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
6690     pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6691 release:
6692     freeAsmop (right,NULL,ic,TRUE);
6693     freeAsmop(left,NULL,ic,TRUE);
6694     freeAsmop(result,NULL,ic,TRUE);
6695 }
6696
6697 /*-----------------------------------------------------------------*/
6698 /* genrshOne - right shift a one byte quantity by known count      */
6699 /*-----------------------------------------------------------------*/
6700 static void genrshOne (operand *result, operand *left,
6701                        int shCount, int sign)
6702 {
6703     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6704     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
6705 }
6706
6707 /*-----------------------------------------------------------------*/
6708 /* genrshTwo - right shift two bytes by known amount != 0          */
6709 /*-----------------------------------------------------------------*/
6710 static void genrshTwo (operand *result,operand *left,
6711                        int shCount, int sign)
6712 {
6713     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6714     /* if shCount >= 8 */
6715     if (shCount >= 8) {
6716         shCount -= 8 ;
6717         if (shCount)
6718             shiftR1Left2Result(left, MSB16, result, LSB,
6719                                shCount, sign);
6720         else 
6721             movLeft2Result(left, MSB16, result, LSB, sign);
6722         if(sign)
6723           addSign(result, MSB16, sign);
6724         else
6725           emitpcode(POC_CLRF,popGet(AOP(result),MSB16,FALSE,FALSE));
6726
6727     }
6728
6729     /*  1 <= shCount <= 7 */
6730     else
6731         shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
6732 }
6733
6734 /*-----------------------------------------------------------------*/
6735 /* shiftRLong - shift right one long from left to result           */
6736 /* offl = LSB or MSB16                                             */
6737 /*-----------------------------------------------------------------*/
6738 static void shiftRLong (operand *left, int offl,
6739                         operand *result, int sign)
6740 {
6741     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6742     if(!sign)
6743         pic14_emitcode("clr","c");
6744     MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE));
6745     if(sign)
6746         pic14_emitcode("mov","c,acc.7");
6747     pic14_emitcode("rrc","a");
6748     aopPut(AOP(result),"a",MSB32-offl);
6749     if(offl == MSB16)
6750         /* add sign of "a" */
6751         addSign(result, MSB32, sign);
6752
6753     MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE));
6754     pic14_emitcode("rrc","a");
6755     aopPut(AOP(result),"a",MSB24-offl);
6756
6757     MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE));
6758     pic14_emitcode("rrc","a");
6759     aopPut(AOP(result),"a",MSB16-offl);
6760
6761     if(offl == LSB){
6762         MOVA(aopGet(AOP(left),LSB,FALSE,FALSE));
6763         pic14_emitcode("rrc","a");
6764         aopPut(AOP(result),"a",LSB);
6765     }
6766 }
6767
6768 /*-----------------------------------------------------------------*/
6769 /* genrshFour - shift four byte by a known amount != 0             */
6770 /*-----------------------------------------------------------------*/
6771 static void genrshFour (operand *result, operand *left,
6772                         int shCount, int sign)
6773 {
6774     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6775     /* if shifting more that 3 bytes */
6776     if(shCount >= 24 ) {
6777         shCount -= 24;
6778         if(shCount)
6779             shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
6780         else
6781             movLeft2Result(left, MSB32, result, LSB, sign);
6782         addSign(result, MSB16, sign);
6783     }
6784     else if(shCount >= 16){
6785         shCount -= 16;
6786         if(shCount)
6787             shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
6788         else{
6789             movLeft2Result(left, MSB24, result, LSB, 0);
6790             movLeft2Result(left, MSB32, result, MSB16, sign);
6791         }
6792         addSign(result, MSB24, sign);
6793     }
6794     else if(shCount >= 8){
6795         shCount -= 8;
6796         if(shCount == 1)
6797             shiftRLong(left, MSB16, result, sign);
6798         else if(shCount == 0){
6799             movLeft2Result(left, MSB16, result, LSB, 0);
6800             movLeft2Result(left, MSB24, result, MSB16, 0);
6801             movLeft2Result(left, MSB32, result, MSB24, sign);
6802             addSign(result, MSB32, sign);
6803         }
6804         else{
6805             shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
6806             shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
6807             /* the last shift is signed */
6808             shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
6809             addSign(result, MSB32, sign);
6810         }
6811     }
6812     else{   /* 1 <= shCount <= 7 */
6813         if(shCount <= 2){
6814             shiftRLong(left, LSB, result, sign);
6815             if(shCount == 2)
6816                 shiftRLong(result, LSB, result, sign);
6817         }
6818         else{
6819             shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
6820             shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
6821             shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
6822         }
6823     }
6824 }
6825
6826 /*-----------------------------------------------------------------*/
6827 /* genRightShiftLiteral - right shifting by known count            */
6828 /*-----------------------------------------------------------------*/
6829 static void genRightShiftLiteral (operand *left,
6830                                   operand *right,
6831                                   operand *result,
6832                                   iCode *ic,
6833                                   int sign)
6834 {    
6835     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6836     int size;
6837
6838     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6839     freeAsmop(right,NULL,ic,TRUE);
6840
6841     aopOp(left,ic,FALSE);
6842     aopOp(result,ic,FALSE);
6843
6844 #if VIEW_SIZE
6845     pic14_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
6846              AOP_SIZE(left));
6847 #endif
6848
6849     size = pic14_getDataSize(left);
6850     /* test the LEFT size !!! */
6851
6852     /* I suppose that the left size >= result size */
6853     if(shCount == 0){
6854         size = pic14_getDataSize(result);
6855         while(size--)
6856             movLeft2Result(left, size, result, size, 0);
6857     }
6858
6859     else if(shCount >= (size * 8)){
6860         if(sign)
6861             /* get sign in acc.7 */
6862             MOVA(aopGet(AOP(left),size-1,FALSE,FALSE));
6863         addSign(result, LSB, sign);
6864     } else{
6865         switch (size) {
6866             case 1:
6867                 genrshOne (result,left,shCount,sign);
6868                 break;
6869
6870             case 2:
6871                 genrshTwo (result,left,shCount,sign);
6872                 break;
6873
6874             case 4:
6875                 genrshFour (result,left,shCount,sign);
6876                 break;
6877             default :
6878                 break;
6879         }
6880
6881         freeAsmop(left,NULL,ic,TRUE);
6882         freeAsmop(result,NULL,ic,TRUE);
6883     }
6884 }
6885
6886 /*-----------------------------------------------------------------*/
6887 /* genSignedRightShift - right shift of signed number              */
6888 /*-----------------------------------------------------------------*/
6889 static void genSignedRightShift (iCode *ic)
6890 {
6891     operand *right, *left, *result;
6892     int size, offset;
6893     char *l;
6894     symbol *tlbl, *tlbl1 ;
6895
6896     /* we do it the hard way put the shift count in b
6897     and loop thru preserving the sign */
6898     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6899
6900     right = IC_RIGHT(ic);
6901     left  = IC_LEFT(ic);
6902     result = IC_RESULT(ic);
6903
6904     aopOp(right,ic,FALSE);  
6905
6906
6907     if ( AOP_TYPE(right) == AOP_LIT) {
6908         genRightShiftLiteral (left,right,result,ic,1);
6909         return ;
6910     }
6911         /* shift count is unknown then we have to form 
6912        a loop get the loop count in B : Note: we take
6913        only the lower order byte since shifting
6914        more that 32 bits make no sense anyway, ( the
6915        largest size of an object can be only 32 bits ) */  
6916
6917     pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
6918     pic14_emitcode("inc","b");
6919     freeAsmop (right,NULL,ic,TRUE);
6920     aopOp(left,ic,FALSE);
6921     aopOp(result,ic,FALSE);
6922
6923     /* now move the left to the result if they are not the
6924     same */
6925     if (!pic14_sameRegs(AOP(left),AOP(result)) && 
6926         AOP_SIZE(result) > 1) {
6927
6928         size = AOP_SIZE(result);
6929         offset=0;
6930         while (size--) {
6931             l = aopGet(AOP(left),offset,FALSE,TRUE);
6932             if (*l == '@' && IS_AOP_PREG(result)) {
6933
6934                 pic14_emitcode("mov","a,%s",l);
6935                 aopPut(AOP(result),"a",offset);
6936             } else
6937                 aopPut(AOP(result),l,offset);
6938             offset++;
6939         }
6940     }
6941
6942     /* mov the highest order bit to OVR */    
6943     tlbl = newiTempLabel(NULL);
6944     tlbl1= newiTempLabel(NULL);
6945
6946     size = AOP_SIZE(result);
6947     offset = size - 1;
6948     pic14_emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
6949     pic14_emitcode("rlc","a");
6950     pic14_emitcode("mov","ov,c");
6951     /* if it is only one byte then */
6952     if (size == 1) {
6953         l = aopGet(AOP(left),0,FALSE,FALSE);
6954         MOVA(l);
6955         pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
6956         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6957         pic14_emitcode("mov","c,ov");
6958         pic14_emitcode("rrc","a");
6959         pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
6960         pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6961         aopPut(AOP(result),"a",0);
6962         goto release ;
6963     }
6964
6965     reAdjustPreg(AOP(result));
6966     pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
6967     pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
6968     pic14_emitcode("mov","c,ov");
6969     while (size--) {
6970         l = aopGet(AOP(result),offset,FALSE,FALSE);
6971         MOVA(l);
6972         pic14_emitcode("rrc","a");         
6973         aopPut(AOP(result),"a",offset--);
6974     }
6975     reAdjustPreg(AOP(result));
6976     pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
6977     pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6978
6979 release:
6980     freeAsmop(left,NULL,ic,TRUE);
6981     freeAsmop(result,NULL,ic,TRUE);
6982 }
6983
6984 /*-----------------------------------------------------------------*/
6985 /* genRightShift - generate code for right shifting                */
6986 /*-----------------------------------------------------------------*/
6987 static void genRightShift (iCode *ic)
6988 {
6989     operand *right, *left, *result;
6990     sym_link *retype ;
6991     int size, offset;
6992     char *l;
6993     symbol *tlbl, *tlbl1 ;
6994
6995     /* if signed then we do it the hard way preserve the
6996     sign bit moving it inwards */
6997     retype = getSpec(operandType(IC_RESULT(ic)));
6998     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6999
7000     if (!SPEC_USIGN(retype)) {
7001         genSignedRightShift (ic);
7002         return ;
7003     }
7004
7005     /* signed & unsigned types are treated the same : i.e. the
7006     signed is NOT propagated inwards : quoting from the
7007     ANSI - standard : "for E1 >> E2, is equivalent to division
7008     by 2**E2 if unsigned or if it has a non-negative value,
7009     otherwise the result is implementation defined ", MY definition
7010     is that the sign does not get propagated */
7011
7012     right = IC_RIGHT(ic);
7013     left  = IC_LEFT(ic);
7014     result = IC_RESULT(ic);
7015
7016     aopOp(right,ic,FALSE);
7017
7018     /* if the shift count is known then do it 
7019     as efficiently as possible */
7020     if (AOP_TYPE(right) == AOP_LIT) {
7021         genRightShiftLiteral (left,right,result,ic, 0);
7022         return ;
7023     }
7024
7025     /* shift count is unknown then we have to form 
7026     a loop get the loop count in B : Note: we take
7027     only the lower order byte since shifting
7028     more that 32 bits make no sense anyway, ( the
7029     largest size of an object can be only 32 bits ) */  
7030
7031     pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
7032     pic14_emitcode("inc","b");
7033     aopOp(left,ic,FALSE);
7034     aopOp(result,ic,FALSE);
7035
7036     /* now move the left to the result if they are not the
7037     same */
7038     if (!pic14_sameRegs(AOP(left),AOP(result)) && 
7039         AOP_SIZE(result) > 1) {
7040
7041         size = AOP_SIZE(result);
7042         offset=0;
7043         while (size--) {
7044             l = aopGet(AOP(left),offset,FALSE,TRUE);
7045             if (*l == '@' && IS_AOP_PREG(result)) {
7046
7047                 pic14_emitcode("mov","a,%s",l);
7048                 aopPut(AOP(result),"a",offset);
7049             } else
7050                 aopPut(AOP(result),l,offset);
7051             offset++;
7052         }
7053     }
7054
7055     tlbl = newiTempLabel(NULL);
7056     tlbl1= newiTempLabel(NULL);
7057     size = AOP_SIZE(result);
7058     offset = size - 1;
7059
7060     /* if it is only one byte then */
7061     if (size == 1) {
7062 /*
7063         l = aopGet(AOP(left),0,FALSE,FALSE);
7064         MOVA(l);
7065         pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7066         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
7067         CLRC;
7068         pic14_emitcode("rrc","a");
7069         pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7070         pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7071         aopPut(AOP(result),"a",0);
7072 */
7073         tlbl = newiTempLabel(NULL);
7074         if (!pic14_sameRegs(AOP(left),AOP(result))) {
7075           emitpcode(POC_MOVFW,  popGet(AOP(left),0,FALSE,FALSE));
7076           emitpcode(POC_MOVWF,  popGet(AOP(result),0,FALSE,FALSE));
7077         }
7078
7079         emitpcode(POC_COMFW,  popGet(AOP(right),0,FALSE,FALSE));
7080         emitpcode(POC_RLF,    popGet(AOP(result),0,FALSE,FALSE));
7081         emitpLabel(tlbl->key);
7082         emitpcode(POC_RRF,    popGet(AOP(result),0,FALSE,FALSE));
7083         emitpcode(POC_ADDLW,  popGetLit(1));
7084         emitSKPC;
7085         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7086
7087         goto release ;
7088     }
7089
7090     reAdjustPreg(AOP(result));
7091     pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7092     pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
7093     CLRC;
7094     while (size--) {
7095         l = aopGet(AOP(result),offset,FALSE,FALSE);
7096         MOVA(l);
7097         pic14_emitcode("rrc","a");         
7098         aopPut(AOP(result),"a",offset--);
7099     }
7100     reAdjustPreg(AOP(result));
7101
7102     pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7103     pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7104
7105 release:
7106     freeAsmop(left,NULL,ic,TRUE);
7107     freeAsmop (right,NULL,ic,TRUE);
7108     freeAsmop(result,NULL,ic,TRUE);
7109 }
7110
7111 /*-----------------------------------------------------------------*/
7112 /* genUnpackBits - generates code for unpacking bits               */
7113 /*-----------------------------------------------------------------*/
7114 static void genUnpackBits (operand *result, char *rname, int ptype)
7115 {    
7116     int shCnt ;
7117     int rlen = 0 ;
7118     sym_link *etype;
7119     int offset = 0 ;
7120
7121     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7122     etype = getSpec(operandType(result));
7123
7124     /* read the first byte  */
7125     switch (ptype) {
7126
7127     case POINTER:
7128     case IPOINTER:
7129         pic14_emitcode("mov","a,@%s",rname);
7130         break;
7131         
7132     case PPOINTER:
7133         pic14_emitcode("movx","a,@%s",rname);
7134         break;
7135         
7136     case FPOINTER:
7137         pic14_emitcode("movx","a,@dptr");
7138         break;
7139
7140     case CPOINTER:
7141         pic14_emitcode("clr","a");
7142         pic14_emitcode("movc","a","@a+dptr");
7143         break;
7144
7145     case GPOINTER:
7146         pic14_emitcode("lcall","__gptrget");
7147         break;
7148     }
7149
7150     /* if we have bitdisplacement then it fits   */
7151     /* into this byte completely or if length is */
7152     /* less than a byte                          */
7153     if ((shCnt = SPEC_BSTR(etype)) || 
7154         (SPEC_BLEN(etype) <= 8))  {
7155
7156         /* shift right acc */
7157         AccRsh(shCnt);
7158
7159         pic14_emitcode("anl","a,#0x%02x",
7160                  ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
7161         aopPut(AOP(result),"a",offset);
7162         return ;
7163     }
7164
7165     /* bit field did not fit in a byte  */
7166     rlen = SPEC_BLEN(etype) - 8;
7167     aopPut(AOP(result),"a",offset++);
7168
7169     while (1)  {
7170
7171         switch (ptype) {
7172         case POINTER:
7173         case IPOINTER:
7174             pic14_emitcode("inc","%s",rname);
7175             pic14_emitcode("mov","a,@%s",rname);
7176             break;
7177             
7178         case PPOINTER:
7179             pic14_emitcode("inc","%s",rname);
7180             pic14_emitcode("movx","a,@%s",rname);
7181             break;
7182
7183         case FPOINTER:
7184             pic14_emitcode("inc","dptr");
7185             pic14_emitcode("movx","a,@dptr");
7186             break;
7187             
7188         case CPOINTER:
7189             pic14_emitcode("clr","a");
7190             pic14_emitcode("inc","dptr");
7191             pic14_emitcode("movc","a","@a+dptr");
7192             break;
7193             
7194         case GPOINTER:
7195             pic14_emitcode("inc","dptr");
7196             pic14_emitcode("lcall","__gptrget");
7197             break;
7198         }
7199
7200         rlen -= 8;            
7201         /* if we are done */
7202         if ( rlen <= 0 )
7203             break ;
7204         
7205         aopPut(AOP(result),"a",offset++);
7206                               
7207     }
7208     
7209     if (rlen) {
7210         pic14_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
7211         aopPut(AOP(result),"a",offset);        
7212     }
7213     
7214     return ;
7215 }
7216
7217
7218 /*-----------------------------------------------------------------*/
7219 /* genDataPointerGet - generates code when ptr offset is known     */
7220 /*-----------------------------------------------------------------*/
7221 static void genDataPointerGet (operand *left, 
7222                                operand *result, 
7223                                iCode *ic)
7224 {
7225   int size , offset = 0;
7226
7227
7228   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7229
7230
7231   /* optimization - most of the time, left and result are the same
7232    * address, but different types. for the pic code, we could omit
7233    * the following
7234    */
7235
7236   aopOp(result,ic,TRUE);
7237
7238   emitpcode(POC_MOVFW, popGet(AOP(left),0,FALSE,TRUE));
7239
7240   size = AOP_SIZE(result);
7241
7242   while (size--) {
7243     emitpcode(POC_MOVWF, popGet(AOP(result),offset,FALSE,TRUE));
7244     offset++;
7245   }
7246
7247   freeAsmop(left,NULL,ic,TRUE);
7248   freeAsmop(result,NULL,ic,TRUE);
7249 }
7250
7251 /*-----------------------------------------------------------------*/
7252 /* genNearPointerGet - pic14_emitcode for near pointer fetch             */
7253 /*-----------------------------------------------------------------*/
7254 static void genNearPointerGet (operand *left, 
7255                                operand *result, 
7256                                iCode *ic)
7257 {
7258     asmop *aop = NULL;
7259     regs *preg = NULL ;
7260     char *rname ;
7261     sym_link *rtype, *retype;
7262     sym_link *ltype = operandType(left);    
7263     char buffer[80];
7264
7265     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7266
7267     rtype = operandType(result);
7268     retype= getSpec(rtype);
7269     
7270     aopOp(left,ic,FALSE);
7271     
7272     /* if left is rematerialisable and
7273        result is not bit variable type and
7274        the left is pointer to data space i.e
7275        lower 128 bytes of space */
7276     if (AOP_TYPE(left) == AOP_IMMD &&
7277         !IS_BITVAR(retype)         &&
7278         DCL_TYPE(ltype) == POINTER) {
7279         genDataPointerGet (left,result,ic);
7280         return ;
7281     }
7282     
7283     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7284
7285         /* if the value is already in a pointer register
7286        then don't need anything more */
7287     if (!AOP_INPREG(AOP(left))) {
7288         /* otherwise get a free pointer register */
7289     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7290         aop = newAsmop(0);
7291         preg = getFreePtr(ic,&aop,FALSE);
7292         pic14_emitcode("mov","%s,%s",
7293                 preg->name,
7294                 aopGet(AOP(left),0,FALSE,TRUE));
7295         rname = preg->name ;
7296     } else
7297         rname = aopGet(AOP(left),0,FALSE,FALSE);
7298     
7299     freeAsmop(left,NULL,ic,TRUE);
7300     aopOp (result,ic,FALSE);
7301     
7302       /* if bitfield then unpack the bits */
7303     if (IS_BITVAR(retype)) 
7304         genUnpackBits (result,rname,POINTER);
7305     else {
7306         /* we have can just get the values */
7307         int size = AOP_SIZE(result);
7308         int offset = 0 ;        
7309         
7310     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7311         while (size--) {
7312             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
7313
7314                 pic14_emitcode("mov","a,@%s",rname);
7315                 aopPut(AOP(result),"a",offset);
7316             } else {
7317                 sprintf(buffer,"@%s",rname);
7318                 aopPut(AOP(result),buffer,offset);
7319             }
7320             offset++ ;
7321             if (size)
7322                 pic14_emitcode("inc","%s",rname);
7323         }
7324     }
7325
7326     /* now some housekeeping stuff */
7327     if (aop) {
7328         /* we had to allocate for this iCode */
7329     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7330         freeAsmop(NULL,aop,ic,TRUE);
7331     } else { 
7332         /* we did not allocate which means left
7333            already in a pointer register, then
7334            if size > 0 && this could be used again
7335            we have to point it back to where it 
7336            belongs */
7337     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7338         if (AOP_SIZE(result) > 1 &&
7339             !OP_SYMBOL(left)->remat &&
7340             ( OP_SYMBOL(left)->liveTo > ic->seq ||
7341               ic->depth )) {
7342             int size = AOP_SIZE(result) - 1;
7343             while (size--)
7344                 pic14_emitcode("dec","%s",rname);
7345         }
7346     }
7347
7348     /* done */
7349     freeAsmop(result,NULL,ic,TRUE);
7350      
7351 }
7352
7353 /*-----------------------------------------------------------------*/
7354 /* genPagedPointerGet - pic14_emitcode for paged pointer fetch           */
7355 /*-----------------------------------------------------------------*/
7356 static void genPagedPointerGet (operand *left, 
7357                                operand *result, 
7358                                iCode *ic)
7359 {
7360     asmop *aop = NULL;
7361     regs *preg = NULL ;
7362     char *rname ;
7363     sym_link *rtype, *retype;    
7364
7365     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7366
7367     rtype = operandType(result);
7368     retype= getSpec(rtype);
7369     
7370     aopOp(left,ic,FALSE);
7371
7372   /* if the value is already in a pointer register
7373        then don't need anything more */
7374     if (!AOP_INPREG(AOP(left))) {
7375         /* otherwise get a free pointer register */
7376         aop = newAsmop(0);
7377         preg = getFreePtr(ic,&aop,FALSE);
7378         pic14_emitcode("mov","%s,%s",
7379                 preg->name,
7380                 aopGet(AOP(left),0,FALSE,TRUE));
7381         rname = preg->name ;
7382     } else
7383         rname = aopGet(AOP(left),0,FALSE,FALSE);
7384     
7385     freeAsmop(left,NULL,ic,TRUE);
7386     aopOp (result,ic,FALSE);
7387
7388     /* if bitfield then unpack the bits */
7389     if (IS_BITVAR(retype)) 
7390         genUnpackBits (result,rname,PPOINTER);
7391     else {
7392         /* we have can just get the values */
7393         int size = AOP_SIZE(result);
7394         int offset = 0 ;        
7395         
7396         while (size--) {
7397             
7398             pic14_emitcode("movx","a,@%s",rname);
7399             aopPut(AOP(result),"a",offset);
7400             
7401             offset++ ;
7402             
7403             if (size)
7404                 pic14_emitcode("inc","%s",rname);
7405         }
7406     }
7407
7408     /* now some housekeeping stuff */
7409     if (aop) {
7410         /* we had to allocate for this iCode */
7411         freeAsmop(NULL,aop,ic,TRUE);
7412     } else { 
7413         /* we did not allocate which means left
7414            already in a pointer register, then
7415            if size > 0 && this could be used again
7416            we have to point it back to where it 
7417            belongs */
7418         if (AOP_SIZE(result) > 1 &&
7419             !OP_SYMBOL(left)->remat &&
7420             ( OP_SYMBOL(left)->liveTo > ic->seq ||
7421               ic->depth )) {
7422             int size = AOP_SIZE(result) - 1;
7423             while (size--)
7424                 pic14_emitcode("dec","%s",rname);
7425         }
7426     }
7427
7428     /* done */
7429     freeAsmop(result,NULL,ic,TRUE);
7430     
7431         
7432 }
7433
7434 /*-----------------------------------------------------------------*/
7435 /* genFarPointerGet - gget value from far space                    */
7436 /*-----------------------------------------------------------------*/
7437 static void genFarPointerGet (operand *left,
7438                               operand *result, iCode *ic)
7439 {
7440     int size, offset ;
7441     sym_link *retype = getSpec(operandType(result));
7442
7443     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7444
7445     aopOp(left,ic,FALSE);
7446
7447     /* if the operand is already in dptr 
7448     then we do nothing else we move the value to dptr */
7449     if (AOP_TYPE(left) != AOP_STR) {
7450         /* if this is remateriazable */
7451         if (AOP_TYPE(left) == AOP_IMMD)
7452             pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
7453         else { /* we need to get it byte by byte */
7454             pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
7455             pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
7456             if (options.model == MODEL_FLAT24)
7457             {
7458                pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
7459             }
7460         }
7461     }
7462     /* so dptr know contains the address */
7463     freeAsmop(left,NULL,ic,TRUE);
7464     aopOp(result,ic,FALSE);
7465
7466     /* if bit then unpack */
7467     if (IS_BITVAR(retype)) 
7468         genUnpackBits(result,"dptr",FPOINTER);
7469     else {
7470         size = AOP_SIZE(result);
7471         offset = 0 ;
7472
7473         while (size--) {
7474             pic14_emitcode("movx","a,@dptr");
7475             aopPut(AOP(result),"a",offset++);
7476             if (size)
7477                 pic14_emitcode("inc","dptr");
7478         }
7479     }
7480
7481     freeAsmop(result,NULL,ic,TRUE);
7482 }
7483
7484 /*-----------------------------------------------------------------*/
7485 /* pic14_emitcodePointerGet - gget value from code space                  */
7486 /*-----------------------------------------------------------------*/
7487 static void pic14_emitcodePointerGet (operand *left,
7488                                 operand *result, iCode *ic)
7489 {
7490     int size, offset ;
7491     sym_link *retype = getSpec(operandType(result));
7492
7493     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7494
7495     aopOp(left,ic,FALSE);
7496
7497     /* if the operand is already in dptr 
7498     then we do nothing else we move the value to dptr */
7499     if (AOP_TYPE(left) != AOP_STR) {
7500         /* if this is remateriazable */
7501         if (AOP_TYPE(left) == AOP_IMMD)
7502             pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
7503         else { /* we need to get it byte by byte */
7504             pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
7505             pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
7506             if (options.model == MODEL_FLAT24)
7507             {
7508                pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
7509             }
7510         }
7511     }
7512     /* so dptr know contains the address */
7513     freeAsmop(left,NULL,ic,TRUE);
7514     aopOp(result,ic,FALSE);
7515
7516     /* if bit then unpack */
7517     if (IS_BITVAR(retype)) 
7518         genUnpackBits(result,"dptr",CPOINTER);
7519     else {
7520         size = AOP_SIZE(result);
7521         offset = 0 ;
7522
7523         while (size--) {
7524             pic14_emitcode("clr","a");
7525             pic14_emitcode("movc","a,@a+dptr");
7526             aopPut(AOP(result),"a",offset++);
7527             if (size)
7528                 pic14_emitcode("inc","dptr");
7529         }
7530     }
7531
7532     freeAsmop(result,NULL,ic,TRUE);
7533 }
7534
7535 /*-----------------------------------------------------------------*/
7536 /* genGenPointerGet - gget value from generic pointer space        */
7537 /*-----------------------------------------------------------------*/
7538 static void genGenPointerGet (operand *left,
7539                               operand *result, iCode *ic)
7540 {
7541   int size, offset ;
7542   sym_link *retype = getSpec(operandType(result));
7543
7544   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7545   aopOp(left,ic,FALSE);
7546   aopOp(result,ic,FALSE);
7547
7548
7549   DEBUGpic14_emitcode ("; ","result %s, left %s",
7550                          AopType(AOP_TYPE(result)),
7551                          AopType(AOP_TYPE(left)));
7552
7553   /* if the operand is already in dptr 
7554      then we do nothing else we move the value to dptr */
7555   if (AOP_TYPE(left) != AOP_STR) {
7556     /* if this is remateriazable */
7557     if (AOP_TYPE(left) == AOP_IMMD) {
7558       pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
7559       pic14_emitcode("mov","b,#%d",pointerCode(retype));
7560     }
7561     else { /* we need to get it byte by byte */
7562
7563       size = AOP_SIZE(result);
7564       offset = 0 ;
7565
7566       while(size--) {
7567         emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
7568         emitpcode(POC_MOVWF,popGet(AOP(result),offset++,FALSE,FALSE));
7569         if(size)
7570           emitpcode(POC_INCF,popCopyReg(&pc_fsr));
7571       }
7572       goto release;
7573     }
7574   }
7575   /* so dptr know contains the address */
7576
7577   /* if bit then unpack */
7578   if (IS_BITVAR(retype)) 
7579     genUnpackBits(result,"dptr",GPOINTER);
7580
7581  release:
7582   freeAsmop(left,NULL,ic,TRUE);
7583   freeAsmop(result,NULL,ic,TRUE);
7584
7585 }
7586
7587 /*-----------------------------------------------------------------*/
7588 /* genPointerGet - generate code for pointer get                   */
7589 /*-----------------------------------------------------------------*/
7590 static void genPointerGet (iCode *ic)
7591 {
7592     operand *left, *result ;
7593     sym_link *type, *etype;
7594     int p_type;
7595
7596     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7597
7598     left = IC_LEFT(ic);
7599     result = IC_RESULT(ic) ;
7600
7601     /* depending on the type of pointer we need to
7602     move it to the correct pointer register */
7603     type = operandType(left);
7604     etype = getSpec(type);
7605     /* if left is of type of pointer then it is simple */
7606     if (IS_PTR(type) && !IS_FUNC(type->next)) 
7607         p_type = DCL_TYPE(type);
7608     else {
7609         /* we have to go by the storage class */
7610         p_type = PTR_TYPE(SPEC_OCLS(etype));
7611
7612 /*      if (SPEC_OCLS(etype)->codesp ) { */
7613 /*          p_type = CPOINTER ;  */
7614 /*      } */
7615 /*      else */
7616 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
7617 /*              p_type = FPOINTER ; */
7618 /*          else */
7619 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
7620 /*                  p_type = PPOINTER; */
7621 /*              else */
7622 /*                  if (SPEC_OCLS(etype) == idata ) */
7623 /*                      p_type = IPOINTER; */
7624 /*                  else */
7625 /*                      p_type = POINTER ; */
7626     }
7627
7628     /* now that we have the pointer type we assign
7629     the pointer values */
7630     switch (p_type) {
7631
7632     case POINTER:       
7633     case IPOINTER:
7634         genNearPointerGet (left,result,ic);
7635         break;
7636
7637     case PPOINTER:
7638         genPagedPointerGet(left,result,ic);
7639         break;
7640
7641     case FPOINTER:
7642         genFarPointerGet (left,result,ic);
7643         break;
7644
7645     case CPOINTER:
7646         pic14_emitcodePointerGet (left,result,ic);
7647         break;
7648
7649     case GPOINTER:
7650         genGenPointerGet (left,result,ic);
7651         break;
7652     }
7653
7654 }
7655
7656 /*-----------------------------------------------------------------*/
7657 /* genPackBits - generates code for packed bit storage             */
7658 /*-----------------------------------------------------------------*/
7659 static void genPackBits (sym_link    *etype ,
7660                          operand *right ,
7661                          char *rname, int p_type)
7662 {
7663     int shCount = 0 ;
7664     int offset = 0  ;
7665     int rLen = 0 ;
7666     int blen, bstr ;   
7667     char *l ;
7668
7669     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7670     blen = SPEC_BLEN(etype);
7671     bstr = SPEC_BSTR(etype);
7672
7673     l = aopGet(AOP(right),offset++,FALSE,FALSE);
7674     MOVA(l);   
7675
7676     /* if the bit lenth is less than or    */
7677     /* it exactly fits a byte then         */
7678     if (SPEC_BLEN(etype) <= 8 )  {
7679         shCount = SPEC_BSTR(etype) ;
7680
7681         /* shift left acc */
7682         AccLsh(shCount);
7683
7684         if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
7685
7686
7687             switch (p_type) {
7688                 case POINTER:
7689                     pic14_emitcode ("mov","b,a");
7690                     pic14_emitcode("mov","a,@%s",rname);
7691                     break;
7692
7693                 case FPOINTER:
7694                     pic14_emitcode ("mov","b,a");
7695                     pic14_emitcode("movx","a,@dptr");
7696                     break;
7697
7698                 case GPOINTER:
7699                     pic14_emitcode ("push","b");
7700                     pic14_emitcode ("push","acc");
7701                     pic14_emitcode ("lcall","__gptrget");
7702                     pic14_emitcode ("pop","b");
7703                     break;
7704             }
7705
7706             pic14_emitcode ("anl","a,#0x%02x",(unsigned char)
7707                       ((unsigned char)(0xFF << (blen+bstr)) | 
7708                        (unsigned char)(0xFF >> (8-bstr)) ) );
7709             pic14_emitcode ("orl","a,b");
7710             if (p_type == GPOINTER)
7711                 pic14_emitcode("pop","b");
7712         }
7713     }
7714
7715     switch (p_type) {
7716         case POINTER:
7717             pic14_emitcode("mov","@%s,a",rname);
7718             break;
7719
7720         case FPOINTER:
7721             pic14_emitcode("movx","@dptr,a");
7722             break;
7723
7724         case GPOINTER:
7725             DEBUGpic14_emitcode(";lcall","__gptrput");
7726             break;
7727     }
7728
7729     /* if we r done */
7730     if ( SPEC_BLEN(etype) <= 8 )
7731         return ;
7732
7733     pic14_emitcode("inc","%s",rname);
7734     rLen = SPEC_BLEN(etype) ;     
7735
7736     /* now generate for lengths greater than one byte */
7737     while (1) {
7738
7739         l = aopGet(AOP(right),offset++,FALSE,TRUE);
7740
7741         rLen -= 8 ;
7742         if (rLen <= 0 )
7743             break ;
7744
7745         switch (p_type) {
7746             case POINTER:
7747                 if (*l == '@') {
7748                     MOVA(l);
7749                     pic14_emitcode("mov","@%s,a",rname);
7750                 } else
7751                     pic14_emitcode("mov","@%s,%s",rname,l);
7752                 break;
7753
7754             case FPOINTER:
7755                 MOVA(l);
7756                 pic14_emitcode("movx","@dptr,a");
7757                 break;
7758
7759             case GPOINTER:
7760                 MOVA(l);
7761                 DEBUGpic14_emitcode(";lcall","__gptrput");
7762                 break;  
7763         }   
7764         pic14_emitcode ("inc","%s",rname);
7765     }
7766
7767     MOVA(l);
7768
7769     /* last last was not complete */
7770     if (rLen)   {
7771         /* save the byte & read byte */
7772         switch (p_type) {
7773             case POINTER:
7774                 pic14_emitcode ("mov","b,a");
7775                 pic14_emitcode("mov","a,@%s",rname);
7776                 break;
7777
7778             case FPOINTER:
7779                 pic14_emitcode ("mov","b,a");
7780                 pic14_emitcode("movx","a,@dptr");
7781                 break;
7782
7783             case GPOINTER:
7784                 pic14_emitcode ("push","b");
7785                 pic14_emitcode ("push","acc");
7786                 pic14_emitcode ("lcall","__gptrget");
7787                 pic14_emitcode ("pop","b");
7788                 break;
7789         }
7790
7791         pic14_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
7792         pic14_emitcode ("orl","a,b");
7793     }
7794
7795     if (p_type == GPOINTER)
7796         pic14_emitcode("pop","b");
7797
7798     switch (p_type) {
7799
7800     case POINTER:
7801         pic14_emitcode("mov","@%s,a",rname);
7802         break;
7803         
7804     case FPOINTER:
7805         pic14_emitcode("movx","@dptr,a");
7806         break;
7807         
7808     case GPOINTER:
7809         DEBUGpic14_emitcode(";lcall","__gptrput");
7810         break;                  
7811     }
7812 }
7813 /*-----------------------------------------------------------------*/
7814 /* genDataPointerSet - remat pointer to data space                 */
7815 /*-----------------------------------------------------------------*/
7816 static void genDataPointerSet(operand *right,
7817                               operand *result,
7818                               iCode *ic)
7819 {
7820     int size, offset = 0 ;
7821     char *l, buffer[256];
7822
7823     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7824     aopOp(right,ic,FALSE);
7825     
7826     l = aopGet(AOP(result),0,FALSE,TRUE);
7827     size = AOP_SIZE(right);
7828     // tsd, was l+1 - the underline `_' prefix was being stripped
7829     while (size--) {
7830         if (offset)
7831             sprintf(buffer,"(%s + %d)",l,offset);
7832         else
7833             sprintf(buffer,"%s",l);
7834
7835         if (AOP_TYPE(right) == AOP_LIT) {
7836           unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
7837           lit = lit >> (8*offset);
7838           if(lit&0xff) {
7839             pic14_emitcode("movlw","%d",lit);
7840             pic14_emitcode("movwf","%s",buffer);
7841
7842             emitpcode(POC_MOVLW, popGetLit(lit&0xff));
7843             emitpcode(POC_MOVWF, popRegFromString(buffer));
7844
7845           } else {
7846             pic14_emitcode("clrf","%s",buffer);
7847             emitpcode(POC_CLRF, popRegFromString(buffer));
7848           }
7849         }else {
7850           pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
7851           pic14_emitcode("movwf","%s",buffer);
7852
7853           emitpcode(POC_MOVFW, popGet(AOP(right),offset,FALSE,FALSE));
7854           emitpcode(POC_MOVWF, popRegFromString(buffer));
7855
7856         }
7857
7858         offset++;
7859     }
7860
7861     freeAsmop(right,NULL,ic,TRUE);
7862     freeAsmop(result,NULL,ic,TRUE);
7863 }
7864
7865 /*-----------------------------------------------------------------*/
7866 /* genNearPointerSet - pic14_emitcode for near pointer put                */
7867 /*-----------------------------------------------------------------*/
7868 static void genNearPointerSet (operand *right,
7869                                operand *result, 
7870                                iCode *ic)
7871 {
7872     asmop *aop = NULL;
7873     char *l;
7874     sym_link *retype;
7875     sym_link *ptype = operandType(result);
7876
7877     
7878     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7879     retype= getSpec(operandType(right));
7880
7881     aopOp(result,ic,FALSE);
7882     
7883     /* if the result is rematerializable &
7884        in data space & not a bit variable */
7885     if (AOP_TYPE(result) == AOP_IMMD &&
7886         DCL_TYPE(ptype) == POINTER   &&
7887         !IS_BITVAR(retype)) {
7888         genDataPointerSet (right,result,ic);
7889         return;
7890     }
7891
7892     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7893
7894     /* if the value is already in a pointer register
7895     then don't need anything more */
7896     if (!AOP_INPREG(AOP(result))) {
7897         /* otherwise get a free pointer register */
7898         //aop = newAsmop(0);
7899         //preg = getFreePtr(ic,&aop,FALSE);
7900         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7901         //pic14_emitcode("mov","%s,%s",
7902         //         preg->name,
7903         //         aopGet(AOP(result),0,FALSE,TRUE));
7904         //rname = preg->name ;
7905         pic14_emitcode("movwf","fsr");
7906     }// else
7907     //   rname = aopGet(AOP(result),0,FALSE,FALSE);
7908
7909     freeAsmop(result,NULL,ic,TRUE);
7910     aopOp (right,ic,FALSE);
7911     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7912
7913     /* if bitfield then unpack the bits */
7914     if (IS_BITVAR(retype)) {
7915       werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
7916              "The programmer is obviously confused");
7917       //genPackBits (retype,right,rname,POINTER);
7918       exit(1);
7919     }
7920     else {
7921         /* we have can just get the values */
7922         int size = AOP_SIZE(right);
7923         int offset = 0 ;    
7924
7925     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7926         while (size--) {
7927             l = aopGet(AOP(right),offset,FALSE,TRUE);
7928             if (*l == '@' ) {
7929               //MOVA(l);
7930               //pic14_emitcode("mov","@%s,a",rname);
7931               pic14_emitcode("movf","indf,w ;1");
7932             } else {
7933
7934               if (AOP_TYPE(right) == AOP_LIT) {
7935                 unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
7936                 if(lit) {
7937                   pic14_emitcode("movlw","%s",l);
7938                   pic14_emitcode("movwf","indf ;2");
7939                 } else 
7940                   pic14_emitcode("clrf","indf");
7941               }else {
7942                 pic14_emitcode("movf","%s,w",l);
7943                 pic14_emitcode("movwf","indf ;2");
7944               }
7945             //pic14_emitcode("mov","@%s,%s",rname,l);
7946             }
7947             if (size)
7948               pic14_emitcode("incf","fsr,f ;3");
7949             //pic14_emitcode("inc","%s",rname);
7950             offset++;
7951         }
7952     }
7953
7954     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7955     /* now some housekeeping stuff */
7956     if (aop) {
7957         /* we had to allocate for this iCode */
7958         freeAsmop(NULL,aop,ic,TRUE);
7959     } else { 
7960         /* we did not allocate which means left
7961         already in a pointer register, then
7962         if size > 0 && this could be used again
7963         we have to point it back to where it 
7964         belongs */
7965     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7966         if (AOP_SIZE(right) > 1 &&
7967             !OP_SYMBOL(result)->remat &&
7968             ( OP_SYMBOL(result)->liveTo > ic->seq ||
7969               ic->depth )) {
7970             int size = AOP_SIZE(right) - 1;
7971             while (size--)
7972               pic14_emitcode("decf","fsr,f");
7973               //pic14_emitcode("dec","%s",rname);
7974         }
7975     }
7976
7977     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7978     /* done */
7979     freeAsmop(right,NULL,ic,TRUE);
7980
7981
7982 }
7983
7984 /*-----------------------------------------------------------------*/
7985 /* genPagedPointerSet - pic14_emitcode for Paged pointer put             */
7986 /*-----------------------------------------------------------------*/
7987 static void genPagedPointerSet (operand *right,
7988                                operand *result, 
7989                                iCode *ic)
7990 {
7991     asmop *aop = NULL;
7992     regs *preg = NULL ;
7993     char *rname , *l;
7994     sym_link *retype;
7995        
7996     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7997
7998     retype= getSpec(operandType(right));
7999     
8000     aopOp(result,ic,FALSE);
8001     
8002     /* if the value is already in a pointer register
8003        then don't need anything more */
8004     if (!AOP_INPREG(AOP(result))) {
8005         /* otherwise get a free pointer register */
8006         aop = newAsmop(0);
8007         preg = getFreePtr(ic,&aop,FALSE);
8008         pic14_emitcode("mov","%s,%s",
8009                 preg->name,
8010                 aopGet(AOP(result),0,FALSE,TRUE));
8011         rname = preg->name ;
8012     } else
8013         rname = aopGet(AOP(result),0,FALSE,FALSE);
8014     
8015     freeAsmop(result,NULL,ic,TRUE);
8016     aopOp (right,ic,FALSE);
8017
8018     /* if bitfield then unpack the bits */
8019     if (IS_BITVAR(retype)) 
8020         genPackBits (retype,right,rname,PPOINTER);
8021     else {
8022         /* we have can just get the values */
8023         int size = AOP_SIZE(right);
8024         int offset = 0 ;        
8025         
8026         while (size--) {
8027             l = aopGet(AOP(right),offset,FALSE,TRUE);
8028             
8029             MOVA(l);
8030             pic14_emitcode("movx","@%s,a",rname);
8031
8032             if (size)
8033                 pic14_emitcode("inc","%s",rname);
8034
8035             offset++;
8036         }
8037     }
8038     
8039     /* now some housekeeping stuff */
8040     if (aop) {
8041         /* we had to allocate for this iCode */
8042         freeAsmop(NULL,aop,ic,TRUE);
8043     } else { 
8044         /* we did not allocate which means left
8045            already in a pointer register, then
8046            if size > 0 && this could be used again
8047            we have to point it back to where it 
8048            belongs */
8049         if (AOP_SIZE(right) > 1 &&
8050             !OP_SYMBOL(result)->remat &&
8051             ( OP_SYMBOL(result)->liveTo > ic->seq ||
8052               ic->depth )) {
8053             int size = AOP_SIZE(right) - 1;
8054             while (size--)
8055                 pic14_emitcode("dec","%s",rname);
8056         }
8057     }
8058
8059     /* done */
8060     freeAsmop(right,NULL,ic,TRUE);
8061     
8062         
8063 }
8064
8065 /*-----------------------------------------------------------------*/
8066 /* genFarPointerSet - set value from far space                     */
8067 /*-----------------------------------------------------------------*/
8068 static void genFarPointerSet (operand *right,
8069                               operand *result, iCode *ic)
8070 {
8071     int size, offset ;
8072     sym_link *retype = getSpec(operandType(right));
8073
8074     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8075     aopOp(result,ic,FALSE);
8076
8077     /* if the operand is already in dptr 
8078     then we do nothing else we move the value to dptr */
8079     if (AOP_TYPE(result) != AOP_STR) {
8080         /* if this is remateriazable */
8081         if (AOP_TYPE(result) == AOP_IMMD)
8082             pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
8083         else { /* we need to get it byte by byte */
8084             pic14_emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
8085             pic14_emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
8086             if (options.model == MODEL_FLAT24)
8087             {
8088                pic14_emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
8089             }
8090         }
8091     }
8092     /* so dptr know contains the address */
8093     freeAsmop(result,NULL,ic,TRUE);
8094     aopOp(right,ic,FALSE);
8095
8096     /* if bit then unpack */
8097     if (IS_BITVAR(retype)) 
8098         genPackBits(retype,right,"dptr",FPOINTER);
8099     else {
8100         size = AOP_SIZE(right);
8101         offset = 0 ;
8102
8103         while (size--) {
8104             char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
8105             MOVA(l);
8106             pic14_emitcode("movx","@dptr,a");
8107             if (size)
8108                 pic14_emitcode("inc","dptr");
8109         }
8110     }
8111
8112     freeAsmop(right,NULL,ic,TRUE);
8113 }
8114
8115 /*-----------------------------------------------------------------*/
8116 /* genGenPointerSet - set value from generic pointer space         */
8117 /*-----------------------------------------------------------------*/
8118 static void genGenPointerSet (operand *right,
8119                               operand *result, iCode *ic)
8120 {
8121   int size, offset ;
8122   sym_link *retype = getSpec(operandType(right));
8123
8124   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8125
8126   aopOp(result,ic,FALSE);
8127   aopOp(right,ic,FALSE);
8128   size = AOP_SIZE(right);
8129
8130   DEBUGpic14_emitcode ("; ","result %s=%s, right %s=%s, size = %d",
8131                        AopType(AOP_TYPE(result)),
8132                        aopGet(AOP(result),0,TRUE,FALSE),
8133                        AopType(AOP_TYPE(right)),
8134                        aopGet(AOP(right),0,FALSE,FALSE),
8135                        size);
8136
8137   /* if the operand is already in dptr 
8138      then we do nothing else we move the value to dptr */
8139   if (AOP_TYPE(result) != AOP_STR) {
8140     /* if this is remateriazable */
8141     if (AOP_TYPE(result) == AOP_IMMD) {
8142       pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
8143       pic14_emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
8144     }
8145     else { /* we need to get it byte by byte */
8146       //char *l = aopGet(AOP(result),0,FALSE,FALSE);
8147       size = AOP_SIZE(right);
8148       offset = 0 ;
8149
8150       /* hack hack! see if this the FSR. If so don't load W */
8151       if(AOP_TYPE(right) != AOP_ACC) {
8152
8153         if(size==2)
8154           emitpcode(POC_DECF,popCopyReg(&pc_fsr));
8155
8156         if(size==4) {
8157           emitpcode(POC_MOVLW,popGetLit(0xfd));
8158           emitpcode(POC_ADDWF,popCopyReg(&pc_fsr));
8159         }
8160
8161         while(size--) {
8162           emitpcode(POC_MOVFW,popGet(AOP(right),offset++,FALSE,FALSE));
8163           emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
8164           
8165           if(size)
8166             emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8167         }
8168
8169
8170         goto release;
8171       } 
8172
8173       if(aopIdx(AOP(result),0) != 4) {
8174
8175         emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
8176         goto release;
8177       }
8178
8179       emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
8180       goto release;
8181
8182     }
8183   }
8184   /* so dptr know contains the address */
8185
8186
8187   /* if bit then unpack */
8188   if (IS_BITVAR(retype)) 
8189     genPackBits(retype,right,"dptr",GPOINTER);
8190   else {
8191     size = AOP_SIZE(right);
8192     offset = 0 ;
8193
8194     while (--size) {
8195       //char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
8196       if(size)
8197         pic14_emitcode("incf","fsr,f");
8198       pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset++,FALSE,FALSE));
8199       pic14_emitcode("movwf","indf");
8200       //MOVA(l);
8201       //DEBUGpic14_emitcode(";lcall","__gptrput");
8202       //if (size)
8203       //    pic14_emitcode("inc","dptr");
8204     }
8205   }
8206
8207  release:
8208   freeAsmop(right,NULL,ic,TRUE);
8209   freeAsmop(result,NULL,ic,TRUE);
8210 }
8211
8212 /*-----------------------------------------------------------------*/
8213 /* genPointerSet - stores the value into a pointer location        */
8214 /*-----------------------------------------------------------------*/
8215 static void genPointerSet (iCode *ic)
8216 {    
8217     operand *right, *result ;
8218     sym_link *type, *etype;
8219     int p_type;
8220
8221     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8222
8223     right = IC_RIGHT(ic);
8224     result = IC_RESULT(ic) ;
8225
8226     /* depending on the type of pointer we need to
8227     move it to the correct pointer register */
8228     type = operandType(result);
8229     etype = getSpec(type);
8230     /* if left is of type of pointer then it is simple */
8231     if (IS_PTR(type) && !IS_FUNC(type->next)) {
8232         p_type = DCL_TYPE(type);
8233     }
8234     else {
8235         /* we have to go by the storage class */
8236         p_type = PTR_TYPE(SPEC_OCLS(etype));
8237
8238 /*      if (SPEC_OCLS(etype)->codesp ) { */
8239 /*          p_type = CPOINTER ;  */
8240 /*      } */
8241 /*      else */
8242 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
8243 /*              p_type = FPOINTER ; */
8244 /*          else */
8245 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
8246 /*                  p_type = PPOINTER ; */
8247 /*              else */
8248 /*                  if (SPEC_OCLS(etype) == idata ) */
8249 /*                      p_type = IPOINTER ; */
8250 /*                  else */
8251 /*                      p_type = POINTER ; */
8252     }
8253
8254     /* now that we have the pointer type we assign
8255     the pointer values */
8256     switch (p_type) {
8257
8258     case POINTER:
8259     case IPOINTER:
8260         genNearPointerSet (right,result,ic);
8261         break;
8262
8263     case PPOINTER:
8264         genPagedPointerSet (right,result,ic);
8265         break;
8266
8267     case FPOINTER:
8268         genFarPointerSet (right,result,ic);
8269         break;
8270
8271     case GPOINTER:
8272         genGenPointerSet (right,result,ic);
8273         break;
8274     }
8275
8276 }
8277
8278 /*-----------------------------------------------------------------*/
8279 /* genIfx - generate code for Ifx statement                        */
8280 /*-----------------------------------------------------------------*/
8281 static void genIfx (iCode *ic, iCode *popIc)
8282 {
8283   operand *cond = IC_COND(ic);
8284   int isbit =0;
8285
8286   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8287
8288   aopOp(cond,ic,FALSE);
8289
8290   /* get the value into acc */
8291   if (AOP_TYPE(cond) != AOP_CRY)
8292     pic14_toBoolean(cond);
8293   else
8294     isbit = 1;
8295   /* the result is now in the accumulator */
8296   freeAsmop(cond,NULL,ic,TRUE);
8297
8298   /* if there was something to be popped then do it */
8299   if (popIc)
8300     genIpop(popIc);
8301
8302   /* if the condition is  a bit variable */
8303   if (isbit && IS_ITEMP(cond) && 
8304       SPIL_LOC(cond)) {
8305     genIfxJump(ic,SPIL_LOC(cond)->rname);
8306     DEBUGpic14_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
8307   }
8308   else {
8309     if (isbit && !IS_ITEMP(cond))
8310       genIfxJump(ic,OP_SYMBOL(cond)->rname);
8311     else
8312       genIfxJump(ic,"a");
8313   }
8314   ic->generated = 1;
8315
8316 }
8317
8318 /*-----------------------------------------------------------------*/
8319 /* genAddrOf - generates code for address of                       */
8320 /*-----------------------------------------------------------------*/
8321 static void genAddrOf (iCode *ic)
8322 {
8323   //symbol *sym = OP_SYMBOL(IC_LEFT(ic));
8324   operand *right, *result, *left;
8325   //int size, offset ;
8326
8327   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8328
8329
8330   //aopOp(IC_RESULT(ic),ic,FALSE);
8331
8332   aopOp((left=IC_LEFT(ic)),ic,FALSE);
8333   aopOp((right=IC_RIGHT(ic)),ic,FALSE);
8334   aopOp((result=IC_RESULT(ic)),ic,TRUE);
8335
8336   if(result)
8337     DEBUGpic14_emitcode ("; ","result %s",
8338                          AopType(AOP_TYPE(IC_RESULT(ic))));
8339
8340   if(left)
8341     DEBUGpic14_emitcode ("; ","left %s",
8342                          AopType(AOP_TYPE(IC_LEFT(ic))));
8343   if(right)
8344     DEBUGpic14_emitcode ("; ","right %s",
8345                          AopType(AOP_TYPE(IC_RIGHT(ic))));
8346   
8347   emitpcode(POC_MOVLW, popGet(AOP(left),0,FALSE,FALSE));
8348   emitpcode(POC_MOVWF, popGet(AOP(result),0,FALSE,FALSE));
8349
8350 #if 0
8351   /* object not on stack then we need the name */
8352   size = AOP_SIZE(IC_RESULT(ic));
8353   offset = 0;
8354
8355   while (size--) {
8356     char s[SDCC_NAME_MAX];
8357     if (offset) 
8358       sprintf(s,"#(%s >> %d)",
8359               sym->rname,
8360               offset*8);
8361     else
8362       sprintf(s,"#%s",sym->rname);
8363     aopPut(AOP(IC_RESULT(ic)),s,offset++);
8364   }
8365 #endif
8366
8367
8368   //  freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8369   freeAsmop(left,NULL,ic,FALSE);
8370   freeAsmop(result,NULL,ic,TRUE);
8371
8372 }
8373
8374 #if 0
8375 /*-----------------------------------------------------------------*/
8376 /* genFarFarAssign - assignment when both are in far space         */
8377 /*-----------------------------------------------------------------*/
8378 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
8379 {
8380     int size = AOP_SIZE(right);
8381     int offset = 0;
8382     char *l ;
8383     /* first push the right side on to the stack */
8384     while (size--) {
8385         l = aopGet(AOP(right),offset++,FALSE,FALSE);
8386         MOVA(l);
8387         pic14_emitcode ("push","acc");
8388     }
8389     
8390     freeAsmop(right,NULL,ic,FALSE);
8391     /* now assign DPTR to result */
8392     aopOp(result,ic,FALSE);
8393     size = AOP_SIZE(result);
8394     while (size--) {
8395         pic14_emitcode ("pop","acc");
8396         aopPut(AOP(result),"a",--offset);
8397     }
8398     freeAsmop(result,NULL,ic,FALSE);
8399         
8400 }
8401 #endif
8402
8403 /*-----------------------------------------------------------------*/
8404 /* genAssign - generate code for assignment                        */
8405 /*-----------------------------------------------------------------*/
8406 static void genAssign (iCode *ic)
8407 {
8408   operand *result, *right;
8409   int size, offset,know_W;
8410   unsigned long lit = 0L;
8411
8412   result = IC_RESULT(ic);
8413   right  = IC_RIGHT(ic) ;
8414
8415   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8416
8417   /* if they are the same */
8418   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
8419     return ;
8420
8421   aopOp(right,ic,FALSE);
8422   aopOp(result,ic,TRUE);
8423
8424   DEBUGpic14_emitcode ("; ","result %s, right %s, size = %d",
8425                        AopType(AOP_TYPE(IC_RESULT(ic))),
8426                        AopType(AOP_TYPE(IC_RIGHT(ic))),
8427                        AOP_SIZE(result));
8428
8429   /* if they are the same registers */
8430   if (pic14_sameRegs(AOP(right),AOP(result)))
8431     goto release;
8432
8433   /* if the result is a bit */
8434   if (AOP_TYPE(result) == AOP_CRY) {
8435
8436     /* if the right size is a literal then
8437        we know what the value is */
8438     if (AOP_TYPE(right) == AOP_LIT) {
8439           
8440       emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
8441                   popGet(AOP(result),0,FALSE,FALSE));
8442
8443       if (((int) operandLitValue(right))) 
8444         pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
8445                        AOP(result)->aopu.aop_dir,
8446                        AOP(result)->aopu.aop_dir);
8447       else
8448         pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
8449                        AOP(result)->aopu.aop_dir,
8450                        AOP(result)->aopu.aop_dir);
8451       goto release;
8452     }
8453
8454     /* the right is also a bit variable */
8455     if (AOP_TYPE(right) == AOP_CRY) {
8456       emitpcode(POC_BCF,    popGet(AOP(result),0,FALSE,FALSE));
8457       emitpcode(POC_BTFSC,  popGet(AOP(right),0,FALSE,FALSE));
8458       emitpcode(POC_BSF,    popGet(AOP(result),0,FALSE,FALSE));
8459
8460       pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
8461                      AOP(result)->aopu.aop_dir,
8462                      AOP(result)->aopu.aop_dir);
8463       pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
8464                      AOP(right)->aopu.aop_dir,
8465                      AOP(right)->aopu.aop_dir);
8466       pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
8467                      AOP(result)->aopu.aop_dir,
8468                      AOP(result)->aopu.aop_dir);
8469       goto release ;
8470     }
8471
8472     /* we need to or */
8473     emitpcode(POC_BCF,    popGet(AOP(result),0,FALSE,FALSE));
8474     pic14_toBoolean(right);
8475     emitSKPZ;
8476     emitpcode(POC_BSF,    popGet(AOP(result),0,FALSE,FALSE));
8477     //aopPut(AOP(result),"a",0);
8478     goto release ;
8479   }
8480
8481   /* bit variables done */
8482   /* general case */
8483   size = AOP_SIZE(result);
8484   offset = 0 ;
8485   if(AOP_TYPE(right) == AOP_LIT)
8486     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
8487
8488   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
8489     if(aopIdx(AOP(result),0) == 4) {
8490       emitpcode(POC_MOVFW, popGet(AOP(right),offset,FALSE,FALSE));
8491       emitpcode(POC_MOVWF, popGet(AOP(result),offset,FALSE,FALSE));
8492       goto release;
8493     } else
8494       DEBUGpic14_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
8495   }
8496
8497   know_W=-1;
8498   while (size--) {
8499     if(AOP_TYPE(right) == AOP_LIT) {
8500       if(lit&0xff) {
8501         if(know_W != (lit&0xff))
8502           emitpcode(POC_MOVLW,popGetLit(lit&0xff));
8503         know_W = lit&0xff;
8504         emitpcode(POC_MOVWF, popGet(AOP(result),offset,FALSE,FALSE));
8505       } else
8506         emitpcode(POC_CLRF, popGet(AOP(result),offset,FALSE,FALSE));
8507
8508       lit >>= 8;
8509
8510     } else if (AOP_TYPE(right) == AOP_CRY) {
8511       emitpcode(POC_CLRF, popGet(AOP(result),offset,FALSE,FALSE));
8512       if(offset == 0) {
8513         emitpcode(POC_BTFSS, popGet(AOP(right),0,FALSE,FALSE));
8514         emitpcode(POC_INCF, popGet(AOP(result),0,FALSE,FALSE));
8515       }
8516     } else {
8517       emitpcode(POC_MOVFW, popGet(AOP(right),offset,FALSE,FALSE));
8518       emitpcode(POC_MOVWF, popGet(AOP(result),offset,FALSE,FALSE));
8519     }
8520             
8521     offset++;
8522   }
8523
8524     
8525  release:
8526   freeAsmop (right,NULL,ic,FALSE);
8527   freeAsmop (result,NULL,ic,TRUE);
8528 }   
8529
8530 /*-----------------------------------------------------------------*/
8531 /* genJumpTab - genrates code for jump table                       */
8532 /*-----------------------------------------------------------------*/
8533 static void genJumpTab (iCode *ic)
8534 {
8535     symbol *jtab;
8536     char *l;
8537
8538     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8539
8540     aopOp(IC_JTCOND(ic),ic,FALSE);
8541     /* get the condition into accumulator */
8542     l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
8543     MOVA(l);
8544     /* multiply by three */
8545     pic14_emitcode("add","a,acc");
8546     pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
8547
8548     jtab = newiTempLabel(NULL);
8549     pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
8550     pic14_emitcode("jmp","@a+dptr");
8551     pic14_emitcode("","%05d_DS_:",jtab->key+100);
8552
8553     emitpcode(POC_MOVLW, popGetLabel(jtab->key));
8554     emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
8555     emitSKPNC;
8556     emitpcode(POC_INCF, popCopyReg(&pc_pclath));
8557     emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
8558     emitpLabel(jtab->key);
8559
8560     freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
8561
8562     /* now generate the jump labels */
8563     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
8564          jtab = setNextItem(IC_JTLABELS(ic))) {
8565         pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
8566         emitpcode(POC_GOTO,popGetLabel(jtab->key));
8567         
8568     }
8569
8570 }
8571
8572 /*-----------------------------------------------------------------*/
8573 /* genMixedOperation - gen code for operators between mixed types  */
8574 /*-----------------------------------------------------------------*/
8575 /*
8576   TSD - Written for the PIC port - but this unfortunately is buggy.
8577   This routine is good in that it is able to efficiently promote 
8578   types to different (larger) sizes. Unfortunately, the temporary
8579   variables that are optimized out by this routine are sometimes
8580   used in other places. So until I know how to really parse the 
8581   iCode tree, I'm going to not be using this routine :(.
8582 */
8583 static int genMixedOperation (iCode *ic)
8584 {
8585 #if 0
8586   operand *result = IC_RESULT(ic);
8587   sym_link *ctype = operandType(IC_LEFT(ic));
8588   operand *right = IC_RIGHT(ic);
8589   int ret = 0;
8590   int big,small;
8591   int offset;
8592
8593   iCode *nextic;
8594   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
8595
8596   pic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
8597
8598   nextic = ic->next;
8599   if(!nextic)
8600     return 0;
8601
8602   nextright = IC_RIGHT(nextic);
8603   nextleft  = IC_LEFT(nextic);
8604   nextresult = IC_RESULT(nextic);
8605
8606   aopOp(right,ic,FALSE);
8607   aopOp(result,ic,FALSE);
8608   aopOp(nextright,  nextic, FALSE);
8609   aopOp(nextleft,   nextic, FALSE);
8610   aopOp(nextresult, nextic, FALSE);
8611
8612   if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
8613
8614     operand *t = right;
8615     right = nextright;
8616     nextright = t; 
8617
8618     pic14_emitcode(";remove right +","");
8619
8620   } else   if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
8621 /*
8622     operand *t = right;
8623     right = nextleft;
8624     nextleft = t; 
8625 */
8626     pic14_emitcode(";remove left +","");
8627   } else
8628     return 0;
8629
8630   big = AOP_SIZE(nextleft);
8631   small = AOP_SIZE(nextright);
8632
8633   switch(nextic->op) {
8634
8635   case '+':
8636     pic14_emitcode(";optimize a +","");
8637     /* if unsigned or not an integral type */
8638     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
8639       pic14_emitcode(";add a bit to something","");
8640     } else {
8641
8642       pic14_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
8643
8644       if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
8645         pic14_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
8646         pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
8647       } else
8648         pic14_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
8649
8650       offset = 0;
8651       while(--big) {
8652
8653         offset++;
8654
8655         if(--small) {
8656           if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
8657             pic14_emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8658             pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
8659           }
8660
8661           pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8662           emitSKPNC;
8663           pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
8664                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
8665                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
8666           pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8667           pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
8668
8669         } else {
8670           pic14_emitcode("rlf","known_zero,w");
8671
8672           /*
8673             if right is signed
8674               btfsc  right,7
8675                addlw ff
8676           */
8677           if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
8678             pic14_emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8679             pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
8680           } else {
8681             pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
8682           }
8683         }
8684       }
8685       ret = 1;
8686     }
8687   }
8688   ret = 1;
8689
8690 release:
8691   freeAsmop(right,NULL,ic,TRUE);
8692   freeAsmop(result,NULL,ic,TRUE);
8693   freeAsmop(nextright,NULL,ic,TRUE);
8694   freeAsmop(nextleft,NULL,ic,TRUE);
8695   if(ret)
8696     nextic->generated = 1;
8697
8698   return ret;
8699 #else
8700   return 0;
8701 #endif
8702 }
8703 /*-----------------------------------------------------------------*/
8704 /* genCast - gen code for casting                                  */
8705 /*-----------------------------------------------------------------*/
8706 static void genCast (iCode *ic)
8707 {
8708     operand *result = IC_RESULT(ic);
8709     sym_link *ctype = operandType(IC_LEFT(ic));
8710     operand *right = IC_RIGHT(ic);
8711     int size, offset ;
8712
8713     DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
8714     /* if they are equivalent then do nothing */
8715     if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
8716         return ;
8717
8718     aopOp(right,ic,FALSE) ;
8719     aopOp(result,ic,FALSE);
8720
8721     /* if the result is a bit */
8722     if (AOP_TYPE(result) == AOP_CRY) {
8723         /* if the right size is a literal then
8724         we know what the value is */
8725         if (AOP_TYPE(right) == AOP_LIT) {
8726
8727           emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
8728                       popGet(AOP(result),0,FALSE,FALSE));
8729
8730             if (((int) operandLitValue(right))) 
8731               pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
8732                        AOP(result)->aopu.aop_dir,
8733                        AOP(result)->aopu.aop_dir);
8734             else
8735               pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
8736                        AOP(result)->aopu.aop_dir,
8737                        AOP(result)->aopu.aop_dir);
8738
8739             goto release;
8740         }
8741
8742         /* the right is also a bit variable */
8743         if (AOP_TYPE(right) == AOP_CRY) {
8744
8745           emitCLRC;
8746           emitpcode(POC_BTFSC,  popGet(AOP(right),0,FALSE,FALSE));
8747
8748           pic14_emitcode("clrc","");
8749           pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
8750                    AOP(right)->aopu.aop_dir,
8751                    AOP(right)->aopu.aop_dir);
8752             aopPut(AOP(result),"c",0);
8753             goto release ;
8754         }
8755
8756         /* we need to or */
8757         pic14_toBoolean(right);
8758         aopPut(AOP(result),"a",0);
8759         goto release ;
8760     }
8761
8762     /* if they are the same size : or less */
8763     if (AOP_SIZE(result) <= AOP_SIZE(right)) {
8764
8765         /* if they are in the same place */
8766         if (pic14_sameRegs(AOP(right),AOP(result)))
8767             goto release;
8768
8769         /* if they in different places then copy */
8770         size = AOP_SIZE(result);
8771         offset = 0 ;
8772         while (size--) {
8773             aopPut(AOP(result),
8774                    aopGet(AOP(right),offset,FALSE,FALSE),
8775                    offset);
8776             offset++;
8777         }
8778         goto release;
8779     }
8780
8781
8782     /* if the result is of type pointer */
8783     if (IS_PTR(ctype)) {
8784
8785         int p_type;
8786         sym_link *type = operandType(right);
8787         sym_link *etype = getSpec(type);
8788
8789         /* pointer to generic pointer */
8790         if (IS_GENPTR(ctype)) {
8791             char *l = zero;
8792             
8793             if (IS_PTR(type)) 
8794                 p_type = DCL_TYPE(type);
8795             else {
8796                 /* we have to go by the storage class */
8797                 p_type = PTR_TYPE(SPEC_OCLS(etype));
8798
8799 /*              if (SPEC_OCLS(etype)->codesp )  */
8800 /*                  p_type = CPOINTER ;  */
8801 /*              else */
8802 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
8803 /*                      p_type = FPOINTER ; */
8804 /*                  else */
8805 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
8806 /*                          p_type = PPOINTER; */
8807 /*                      else */
8808 /*                          if (SPEC_OCLS(etype) == idata ) */
8809 /*                              p_type = IPOINTER ; */
8810 /*                          else */
8811 /*                              p_type = POINTER ; */
8812             }
8813                 
8814             /* the first two bytes are known */
8815             size = GPTRSIZE - 1; 
8816             offset = 0 ;
8817             while (size--) {
8818                 aopPut(AOP(result),
8819                        aopGet(AOP(right),offset,FALSE,FALSE),
8820                        offset);
8821                 offset++;
8822             }
8823             /* the last byte depending on type */
8824             switch (p_type) {
8825             case IPOINTER:
8826             case POINTER:
8827                 l = zero;
8828                 break;
8829             case FPOINTER:
8830                 l = one;
8831                 break;
8832             case CPOINTER:
8833                 l = "#0x02";
8834                 break;                          
8835             case PPOINTER:
8836                 l = "#0x03";
8837                 break;
8838                 
8839             default:
8840                 /* this should never happen */
8841                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8842                        "got unknown pointer type");
8843                 exit(1);
8844             }
8845             aopPut(AOP(result),l, GPTRSIZE - 1);            
8846             goto release ;
8847         }
8848         
8849         /* just copy the pointers */
8850         size = AOP_SIZE(result);
8851         offset = 0 ;
8852         while (size--) {
8853             aopPut(AOP(result),
8854                    aopGet(AOP(right),offset,FALSE,FALSE),
8855                    offset);
8856             offset++;
8857         }
8858         goto release ;
8859     }
8860     
8861
8862     if (AOP_TYPE(right) == AOP_CRY) {
8863       int offset = 1;
8864       size = AOP_SIZE(right);
8865
8866       emitpcode(POC_CLRF,   popGet(AOP(result),0,FALSE,FALSE));
8867       emitpcode(POC_BTFSC,  popGet(AOP(right),0,FALSE,FALSE));
8868       emitpcode(POC_INCF,   popGet(AOP(result),0,FALSE,FALSE));
8869
8870       pic14_emitcode("clrf","%s ; %d", aopGet(AOP(result),0,FALSE,FALSE),__LINE__);
8871       pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
8872                AOP(right)->aopu.aop_dir,
8873                AOP(right)->aopu.aop_dir);
8874       pic14_emitcode("incf","%s,f", aopGet(AOP(result),0,FALSE,FALSE),__LINE__);
8875       while (size--) {
8876         pic14_emitcode("clrf","%s;%d", aopGet(AOP(result),offset,FALSE,FALSE),__LINE__);
8877         emitpcode(POC_CLRF,   popGet(AOP(result),offset++,FALSE,FALSE));
8878       }
8879       goto release;
8880     }
8881
8882     /* so we now know that the size of destination is greater
8883     than the size of the source.
8884     Now, if the next iCode is an operator then we might be
8885     able to optimize the operation without performing a cast.
8886     */
8887     if(genMixedOperation(ic))
8888       goto release;
8889
8890     
8891     /* we move to result for the size of source */
8892     size = AOP_SIZE(right);
8893     offset = 0 ;
8894     while (size--) {
8895       pic14_emitcode(";","%d",__LINE__);
8896       /* aopPut(AOP(result),
8897              aopGet(AOP(right),offset,FALSE,FALSE),
8898              offset); */
8899       emitpcode(POC_MOVFW,   popGet(AOP(right),offset,FALSE,FALSE));
8900       emitpcode(POC_MOVWF,   popGet(AOP(result),offset,FALSE,FALSE));
8901       offset++;
8902     }
8903
8904     /* now depending on the sign of the destination */
8905     size = AOP_SIZE(result) - AOP_SIZE(right);
8906     /* if unsigned or not an integral type */
8907     if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) {
8908       while (size--) {
8909           emitpcode(POC_CLRF,   popGet(AOP(result),offset,FALSE,FALSE));
8910           pic14_emitcode("clrf","%s  ;%d",aopGet(AOP(result),offset,FALSE,FALSE),__LINE__);
8911           offset++;
8912       }
8913     } else {
8914       /* we need to extend the sign :{ */
8915
8916       emitpcodeNULLop(POC_CLRW);
8917
8918       if(offset)
8919         emitpcode(POC_BTFSC,   newpCodeOpBit(aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
8920       else
8921         emitpcode(POC_BTFSC,   newpCodeOpBit(aopGet(AOP(right),offset,FALSE,FALSE),7,0));
8922
8923       emitpcode(POC_MOVLW,   popGetLit(0xff));
8924
8925         pic14_emitcode("clrw","");
8926         pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
8927                  AOP(right)->aopu.aop_dir,
8928                  AOP(right)->aopu.aop_dir);
8929         pic14_emitcode("movlw","0xff");
8930         while (size--) {
8931           emitpcode(POC_MOVWF,   popGet(AOP(result),offset,FALSE,FALSE));
8932           pic14_emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
8933           offset++;
8934           // aopPut(AOP(result),"a",offset++);
8935         }
8936
8937     }
8938
8939     /* we are done hurray !!!! */
8940
8941 release:
8942     freeAsmop(right,NULL,ic,TRUE);
8943     freeAsmop(result,NULL,ic,TRUE);
8944
8945 }
8946
8947 /*-----------------------------------------------------------------*/
8948 /* genDjnz - generate decrement & jump if not zero instrucion      */
8949 /*-----------------------------------------------------------------*/
8950 static int genDjnz (iCode *ic, iCode *ifx)
8951 {
8952     symbol *lbl, *lbl1;
8953     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8954
8955     if (!ifx)
8956         return 0;
8957     
8958     /* if the if condition has a false label
8959        then we cannot save */
8960     if (IC_FALSE(ifx))
8961         return 0;
8962
8963     /* if the minus is not of the form 
8964        a = a - 1 */
8965     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
8966         !IS_OP_LITERAL(IC_RIGHT(ic)))
8967         return 0;
8968
8969     if (operandLitValue(IC_RIGHT(ic)) != 1)
8970         return 0;
8971
8972     /* if the size of this greater than one then no
8973        saving */
8974     if (getSize(operandType(IC_RESULT(ic))) > 1)
8975         return 0;
8976
8977     /* otherwise we can save BIG */
8978     lbl = newiTempLabel(NULL);
8979     lbl1= newiTempLabel(NULL);
8980
8981     aopOp(IC_RESULT(ic),ic,FALSE);
8982     
8983     if (IS_AOP_PREG(IC_RESULT(ic))) {
8984         pic14_emitcode("dec","%s",
8985                  aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
8986         pic14_emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
8987         pic14_emitcode("jnz","%05d_DS_",lbl->key+100);
8988     } else {    
8989
8990
8991       emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
8992       emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
8993
8994       pic14_emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
8995       pic14_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
8996
8997     }
8998 /*     pic14_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
8999 /*     pic14_emitcode ("","%05d_DS_:",lbl->key+100); */
9000 /*     pic14_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
9001 /*     pic14_emitcode ("","%05d_DS_:",lbl1->key+100); */
9002
9003     
9004     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
9005     ifx->generated = 1;
9006     return 1;
9007 }
9008
9009 /*-----------------------------------------------------------------*/
9010 /* genReceive - generate code for a receive iCode                  */
9011 /*-----------------------------------------------------------------*/
9012 static void genReceive (iCode *ic)
9013 {    
9014     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9015
9016     if (isOperandInFarSpace(IC_RESULT(ic)) && 
9017         ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
9018           IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
9019
9020         int size = getSize(operandType(IC_RESULT(ic)));
9021         int offset =  fReturnSizePic - size;
9022         while (size--) {
9023             pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
9024                                     fReturn[fReturnSizePic - offset - 1] : "acc"));
9025             offset++;
9026         }
9027         aopOp(IC_RESULT(ic),ic,FALSE);  
9028         size = AOP_SIZE(IC_RESULT(ic));
9029         offset = 0;
9030         while (size--) {
9031             pic14_emitcode ("pop","acc");
9032             aopPut (AOP(IC_RESULT(ic)),"a",offset++);
9033         }
9034         
9035     } else {
9036         _G.accInUse++;
9037         aopOp(IC_RESULT(ic),ic,FALSE);  
9038         _G.accInUse--;
9039         assignResultValue(IC_RESULT(ic));       
9040     }
9041
9042     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
9043 }
9044
9045 /*-----------------------------------------------------------------*/
9046 /* genpic14Code - generate code for pic14 based controllers        */
9047 /*-----------------------------------------------------------------*/
9048 /*
9049  * At this point, ralloc.c has gone through the iCode and attempted
9050  * to optimize in a way suitable for a PIC. Now we've got to generate
9051  * PIC instructions that correspond to the iCode.
9052  *
9053  * Once the instructions are generated, we'll pass through both the
9054  * peep hole optimizer and the pCode optimizer.
9055  *-----------------------------------------------------------------*/
9056
9057 void genpic14Code (iCode *lic)
9058 {
9059     iCode *ic;
9060     int cln = 0;
9061
9062     lineHead = lineCurr = NULL;
9063
9064     pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
9065     addpBlock(pb);
9066
9067     /* if debug information required */
9068 /*     if (options.debug && currFunc) { */
9069     if (currFunc) {
9070         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
9071         _G.debugLine = 1;
9072         if (IS_STATIC(currFunc->etype)) {
9073             pic14_emitcode("",";F%s$%s$0$0     %d",moduleName,currFunc->name,__LINE__);
9074             //addpCode2pBlock(pb,newpCodeLabel(moduleName,currFunc->name));
9075         } else {
9076             pic14_emitcode("",";G$%s$0$0   %d",currFunc->name,__LINE__);
9077             //addpCode2pBlock(pb,newpCodeLabel(NULL,currFunc->name));
9078         }
9079         _G.debugLine = 0;
9080     }
9081
9082
9083     for (ic = lic ; ic ; ic = ic->next ) {
9084
9085       DEBUGpic14_emitcode(";ic","");
9086         if ( cln != ic->lineno ) {
9087             if ( options.debug ) {
9088                 _G.debugLine = 1;
9089                 pic14_emitcode("",";C$%s$%d$%d$%d ==.",
9090                          FileBaseName(ic->filename),ic->lineno,
9091                          ic->level,ic->block);
9092                 _G.debugLine = 0;
9093             }
9094             pic14_emitcode("#CSRC","%s %d",FileBaseName(ic->filename),ic->lineno);
9095             cln = ic->lineno ;
9096         }
9097         /* if the result is marked as
9098            spilt and rematerializable or code for
9099            this has already been generated then
9100            do nothing */
9101         if (resultRemat(ic) || ic->generated ) 
9102             continue ;
9103         
9104         /* depending on the operation */
9105         switch (ic->op) {
9106         case '!' :
9107             genNot(ic);
9108             break;
9109             
9110         case '~' :
9111             genCpl(ic);
9112             break;
9113             
9114         case UNARYMINUS:
9115             genUminus (ic);
9116             break;
9117             
9118         case IPUSH:
9119             genIpush (ic);
9120             break;
9121             
9122         case IPOP:
9123             /* IPOP happens only when trying to restore a 
9124                spilt live range, if there is an ifx statement
9125                following this pop then the if statement might
9126                be using some of the registers being popped which
9127                would destory the contents of the register so
9128                we need to check for this condition and handle it */
9129             if (ic->next            && 
9130                 ic->next->op == IFX &&
9131                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
9132                 genIfx (ic->next,ic);
9133             else
9134                 genIpop (ic);
9135             break; 
9136             
9137         case CALL:
9138             genCall (ic);
9139             break;
9140             
9141         case PCALL:
9142             genPcall (ic);
9143             break;
9144             
9145         case FUNCTION:
9146             genFunction (ic);
9147             break;
9148             
9149         case ENDFUNCTION:
9150             genEndFunction (ic);
9151             break;
9152             
9153         case RETURN:
9154             genRet (ic);
9155             break;
9156             
9157         case LABEL:
9158             genLabel (ic);
9159             break;
9160             
9161         case GOTO:
9162             genGoto (ic);
9163             break;
9164             
9165         case '+' :
9166             genPlus (ic) ;
9167             break;
9168             
9169         case '-' :
9170             if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
9171                 genMinus (ic);
9172             break;
9173             
9174         case '*' :
9175             genMult (ic);
9176             break;
9177             
9178         case '/' :
9179             genDiv (ic) ;
9180             break;
9181             
9182         case '%' :
9183             genMod (ic);
9184             break;
9185             
9186         case '>' :
9187             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
9188             break;
9189             
9190         case '<' :
9191             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
9192             break;
9193             
9194         case LE_OP:
9195         case GE_OP:
9196         case NE_OP:
9197             
9198             /* note these two are xlated by algebraic equivalence
9199                during parsing SDCC.y */
9200             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
9201                    "got '>=' or '<=' shouldn't have come here");
9202             break;      
9203             
9204         case EQ_OP:
9205             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
9206             break;          
9207             
9208         case AND_OP:
9209             genAndOp (ic);
9210             break;
9211             
9212         case OR_OP:
9213             genOrOp (ic);
9214             break;
9215             
9216         case '^' :
9217             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
9218             break;
9219             
9220         case '|' :
9221                 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
9222             break;
9223             
9224         case BITWISEAND:
9225             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
9226             break;
9227             
9228         case INLINEASM:
9229             genInline (ic);
9230             break;
9231             
9232         case RRC:
9233             genRRC (ic);
9234             break;
9235             
9236         case RLC:
9237             genRLC (ic);
9238             break;
9239             
9240         case GETHBIT:
9241             genGetHbit (ic);
9242             break;
9243             
9244         case LEFT_OP:
9245             genLeftShift (ic);
9246             break;
9247             
9248         case RIGHT_OP:
9249             genRightShift (ic);
9250             break;
9251             
9252         case GET_VALUE_AT_ADDRESS:
9253             genPointerGet(ic);
9254             break;
9255             
9256         case '=' :
9257             if (POINTER_SET(ic))
9258                 genPointerSet(ic);
9259             else
9260                 genAssign(ic);
9261             break;
9262             
9263         case IFX:
9264             genIfx (ic,NULL);
9265             break;
9266             
9267         case ADDRESS_OF:
9268             genAddrOf (ic);
9269             break;
9270             
9271         case JUMPTABLE:
9272             genJumpTab (ic);
9273             break;
9274             
9275         case CAST:
9276             genCast (ic);
9277             break;
9278             
9279         case RECEIVE:
9280             genReceive(ic);
9281             break;
9282             
9283         case SEND:
9284             addSet(&_G.sendSet,ic);
9285             break;
9286
9287         default :
9288             ic = ic;
9289         }
9290     }
9291     
9292
9293     /* now we are ready to call the 
9294        peep hole optimizer */
9295     if (!options.nopeep) {
9296       printf("peep hole optimizing\n");
9297         peepHole (&lineHead);
9298     }
9299     /* now do the actual printing */
9300     printLine (lineHead,codeOutFile);
9301
9302     printf("printing pBlock\n\n");
9303     printpBlock(stdout,pb);
9304
9305     return;
9306 }