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