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