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