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