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