265e9fc0a6d9cb73ff883477711c0062e481f31c
[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                     emitSKPZ;
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));
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(0x1f));
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(0x1f));
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),offr,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       /* note, use a mov/add for the shift since the mov has a
5778          chance of getting optimized out */
5779       emitpcode(POC_MOVFW, popGet(AOP(left),offl,FALSE,FALSE));
5780       emitpcode(POC_MOVWF, popGet(AOP(result),offr,FALSE,FALSE));
5781       emitpcode(POC_ADDWF, popGet(AOP(result),offr,FALSE,FALSE));
5782       emitpcode(POC_RLFW,  popGet(AOP(left),offl+MSB16,FALSE,FALSE));
5783       emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16,FALSE,FALSE));
5784
5785       while(--shCount) {
5786         emitCLRC;
5787         emitpcode(POC_RLF, popGet(AOP(result),offr,FALSE,FALSE));
5788         emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16,FALSE,FALSE));
5789       }
5790       break;
5791     case 3:
5792     case 4:
5793     case 5:
5794       emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16,FALSE,FALSE));
5795       emitpcode(POC_ANDLW, popGetLit(0xF0));
5796       emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16,FALSE,FALSE));
5797       emitpcode(POC_SWAPFW,popGet(AOP(left),offl,FALSE,FALSE));
5798       emitpcode(POC_MOVWF, popGet(AOP(result),offr,FALSE,FALSE));
5799       emitpcode(POC_ANDLW, popGetLit(0xF0));
5800       emitpcode(POC_XORWF, popGet(AOP(result),offr,FALSE,FALSE));
5801       emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16,FALSE,FALSE));
5802
5803       if(shCount == 3) {
5804         emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16,FALSE,FALSE));
5805         emitpcode(POC_RRF, popGet(AOP(result),offr,FALSE,FALSE));
5806       }
5807       if(shCount == 5) {
5808         emitpcode(POC_RLF, popGet(AOP(result),offr,FALSE,FALSE));
5809         emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16,FALSE,FALSE));
5810       }
5811       break;
5812     case 6:
5813       emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16,FALSE,FALSE));
5814       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16,FALSE,FALSE));
5815       emitpcode(POC_RRFW, popGet(AOP(result),offl,FALSE,FALSE));
5816       emitpcode(POC_MOVWF,  popGet(AOP(result),offr,FALSE,FALSE));
5817
5818       emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16,FALSE,FALSE));
5819       emitpcode(POC_RRF,  popGet(AOP(result),offr,FALSE,FALSE));
5820       emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16,FALSE,FALSE));
5821       emitpcode(POC_ANDLW,popGetLit(0xc0));
5822       emitpcode(POC_XORFW,popGet(AOP(result),offr,FALSE,FALSE));
5823       emitpcode(POC_XORWF,popGet(AOP(result),offr,FALSE,FALSE));
5824       emitpcode(POC_XORFW,popGet(AOP(result),offr,FALSE,FALSE));
5825       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16,FALSE,FALSE));
5826       break;
5827     case 7:
5828       emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16,FALSE,FALSE));
5829       emitpcode(POC_RRFW, popGet(AOP(left),offl,FALSE,FALSE));
5830       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16,FALSE,FALSE));
5831       emitpcode(POC_CLRF, popGet(AOP(result),offr,FALSE,FALSE));
5832       emitpcode(POC_RRF,  popGet(AOP(result),offr,FALSE,FALSE));
5833     }
5834   }
5835
5836 }
5837 /*-----------------------------------------------------------------*/
5838 /* shiftR2Left2Result - shift right two bytes from left to result  */
5839 /*-----------------------------------------------------------------*/
5840 static void shiftR2Left2Result (operand *left, int offl,
5841                                 operand *result, int offr,
5842                                 int shCount, int sign)
5843 {
5844   int same=0;
5845
5846   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5847   if(pic14_sameRegs(AOP(result), AOP(left)) &&
5848      ((offl + MSB16) == offr)){
5849     same=1;
5850     /* don't crash result[offr] */
5851     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5852     pic14_emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5853   } else {
5854     movLeft2Result(left,offl, result, offr, 0);
5855     MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5856   }
5857   /* a:x >> shCount (x = lsb(result))*/
5858   if(sign)
5859     AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
5860   else {
5861       //AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
5862     
5863     //    switch() {
5864     //}
5865     if(pic14_getDataSize(result) > 1)
5866       aopPut(AOP(result),"a",offr+MSB16);
5867   }
5868 }
5869
5870 /*-----------------------------------------------------------------*/
5871 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
5872 /*-----------------------------------------------------------------*/
5873 static void shiftLLeftOrResult (operand *left, int offl,
5874                                 operand *result, int offr, int shCount)
5875 {
5876     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5877     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5878     /* shift left accumulator */
5879     AccLsh(shCount);
5880     /* or with result */
5881     pic14_emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
5882     /* back to result */
5883     aopPut(AOP(result),"a",offr);
5884 }
5885
5886 /*-----------------------------------------------------------------*/
5887 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
5888 /*-----------------------------------------------------------------*/
5889 static void shiftRLeftOrResult (operand *left, int offl,
5890                                 operand *result, int offr, int shCount)
5891 {
5892     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5893     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5894     /* shift right accumulator */
5895     AccRsh(shCount);
5896     /* or with result */
5897     pic14_emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
5898     /* back to result */
5899     aopPut(AOP(result),"a",offr);
5900 }
5901
5902 /*-----------------------------------------------------------------*/
5903 /* genlshOne - left shift a one byte quantity by known count       */
5904 /*-----------------------------------------------------------------*/
5905 static void genlshOne (operand *result, operand *left, int shCount)
5906 {       
5907     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5908     shiftL1Left2Result(left, LSB, result, LSB, shCount);
5909 }
5910
5911 /*-----------------------------------------------------------------*/
5912 /* genlshTwo - left shift two bytes by known amount != 0           */
5913 /*-----------------------------------------------------------------*/
5914 static void genlshTwo (operand *result,operand *left, int shCount)
5915 {
5916     int size;
5917     
5918     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5919     size = pic14_getDataSize(result);
5920
5921     /* if shCount >= 8 */
5922     if (shCount >= 8) {
5923         shCount -= 8 ;
5924
5925         if (size > 1){
5926             if (shCount)
5927                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5928             else 
5929                 movLeft2Result(left, LSB, result, MSB16, 0);
5930         }
5931         emitpcode(POC_CLRF,popGet(AOP(result),LSB,FALSE,FALSE));
5932     }
5933
5934     /*  1 <= shCount <= 7 */
5935     else {  
5936         if(size == 1)
5937             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
5938         else 
5939             shiftL2Left2Result(left, LSB, result, LSB, shCount);
5940     }
5941 }
5942
5943 /*-----------------------------------------------------------------*/
5944 /* shiftLLong - shift left one long from left to result            */
5945 /* offl = LSB or MSB16                                             */
5946 /*-----------------------------------------------------------------*/
5947 static void shiftLLong (operand *left, operand *result, int offr )
5948 {
5949     char *l;
5950     int size = AOP_SIZE(result);
5951
5952     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5953     if(size >= LSB+offr){
5954         l = aopGet(AOP(left),LSB,FALSE,FALSE);
5955         MOVA(l);
5956         pic14_emitcode("add","a,acc");
5957         if (pic14_sameRegs(AOP(left),AOP(result)) && 
5958             size >= MSB16+offr && offr != LSB )
5959             pic14_emitcode("xch","a,%s",
5960                      aopGet(AOP(left),LSB+offr,FALSE,FALSE));
5961         else        
5962             aopPut(AOP(result),"a",LSB+offr);
5963     }
5964
5965     if(size >= MSB16+offr){
5966         if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
5967             l = aopGet(AOP(left),MSB16,FALSE,FALSE);
5968             MOVA(l);
5969         }
5970         pic14_emitcode("rlc","a");
5971         if (pic14_sameRegs(AOP(left),AOP(result)) && 
5972             size >= MSB24+offr && offr != LSB)
5973             pic14_emitcode("xch","a,%s",
5974                      aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
5975         else        
5976             aopPut(AOP(result),"a",MSB16+offr);
5977     }
5978
5979     if(size >= MSB24+offr){
5980         if (!(pic14_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
5981             l = aopGet(AOP(left),MSB24,FALSE,FALSE);
5982             MOVA(l);
5983         }
5984         pic14_emitcode("rlc","a");
5985         if (pic14_sameRegs(AOP(left),AOP(result)) && 
5986             size >= MSB32+offr && offr != LSB )
5987             pic14_emitcode("xch","a,%s",
5988                      aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
5989         else        
5990             aopPut(AOP(result),"a",MSB24+offr);
5991     }
5992
5993     if(size > MSB32+offr){
5994         if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
5995             l = aopGet(AOP(left),MSB32,FALSE,FALSE);
5996             MOVA(l);    
5997         }
5998         pic14_emitcode("rlc","a");
5999         aopPut(AOP(result),"a",MSB32+offr);
6000     }
6001     if(offr != LSB)
6002         aopPut(AOP(result),zero,LSB);       
6003 }
6004
6005 /*-----------------------------------------------------------------*/
6006 /* genlshFour - shift four byte by a known amount != 0             */
6007 /*-----------------------------------------------------------------*/
6008 static void genlshFour (operand *result, operand *left, int shCount)
6009 {
6010     int size;
6011
6012     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6013     size = AOP_SIZE(result);
6014
6015     /* if shifting more that 3 bytes */
6016     if (shCount >= 24 ) {
6017         shCount -= 24;
6018         if (shCount)
6019             /* lowest order of left goes to the highest
6020             order of the destination */
6021             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
6022         else
6023             movLeft2Result(left, LSB, result, MSB32, 0);
6024         aopPut(AOP(result),zero,LSB);
6025         aopPut(AOP(result),zero,MSB16);
6026         aopPut(AOP(result),zero,MSB32);
6027         return;
6028     }
6029
6030     /* more than two bytes */
6031     else if ( shCount >= 16 ) {
6032         /* lower order two bytes goes to higher order two bytes */
6033         shCount -= 16;
6034         /* if some more remaining */
6035         if (shCount)
6036             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
6037         else {
6038             movLeft2Result(left, MSB16, result, MSB32, 0);
6039             movLeft2Result(left, LSB, result, MSB24, 0);
6040         }
6041         aopPut(AOP(result),zero,MSB16);
6042         aopPut(AOP(result),zero,LSB);
6043         return;
6044     }    
6045
6046     /* if more than 1 byte */
6047     else if ( shCount >= 8 ) {
6048         /* lower order three bytes goes to higher order  three bytes */
6049         shCount -= 8;
6050         if(size == 2){
6051             if(shCount)
6052                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6053             else
6054                 movLeft2Result(left, LSB, result, MSB16, 0);
6055         }
6056         else{   /* size = 4 */
6057             if(shCount == 0){
6058                 movLeft2Result(left, MSB24, result, MSB32, 0);
6059                 movLeft2Result(left, MSB16, result, MSB24, 0);
6060                 movLeft2Result(left, LSB, result, MSB16, 0);
6061                 aopPut(AOP(result),zero,LSB);
6062             }
6063             else if(shCount == 1)
6064                 shiftLLong(left, result, MSB16);
6065             else{
6066                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
6067                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6068                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
6069                 aopPut(AOP(result),zero,LSB);
6070             }
6071         }
6072     }
6073
6074     /* 1 <= shCount <= 7 */
6075     else if(shCount <= 2){
6076         shiftLLong(left, result, LSB);
6077         if(shCount == 2)
6078             shiftLLong(result, result, LSB);
6079     }
6080     /* 3 <= shCount <= 7, optimize */
6081     else{
6082         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
6083         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
6084         shiftL2Left2Result(left, LSB, result, LSB, shCount);
6085     }
6086 }
6087
6088 /*-----------------------------------------------------------------*/
6089 /* genLeftShiftLiteral - left shifting by known count              */
6090 /*-----------------------------------------------------------------*/
6091 static void genLeftShiftLiteral (operand *left,
6092                                  operand *right,
6093                                  operand *result,
6094                                  iCode *ic)
6095 {    
6096     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6097     int size;
6098
6099     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6100     freeAsmop(right,NULL,ic,TRUE);
6101
6102     aopOp(left,ic,FALSE);
6103     aopOp(result,ic,FALSE);
6104
6105     size = getSize(operandType(result));
6106
6107 #if VIEW_SIZE
6108     pic14_emitcode("; shift left ","result %d, left %d",size,
6109              AOP_SIZE(left));
6110 #endif
6111
6112     /* I suppose that the left size >= result size */
6113     if(shCount == 0){
6114         while(size--){
6115             movLeft2Result(left, size, result, size, 0);
6116         }
6117     }
6118
6119     else if(shCount >= (size * 8))
6120         while(size--)
6121             aopPut(AOP(result),zero,size);
6122     else{
6123         switch (size) {
6124             case 1:
6125                 genlshOne (result,left,shCount);
6126                 break;
6127
6128             case 2:
6129             case 3:
6130                 genlshTwo (result,left,shCount);
6131                 break;
6132
6133             case 4:
6134                 genlshFour (result,left,shCount);
6135                 break;
6136         }
6137     }
6138     freeAsmop(left,NULL,ic,TRUE);
6139     freeAsmop(result,NULL,ic,TRUE);
6140 }
6141
6142 /*-----------------------------------------------------------------*/
6143 /* genLeftShift - generates code for left shifting                 */
6144 /*-----------------------------------------------------------------*/
6145 static void genLeftShift (iCode *ic)
6146 {
6147     operand *left,*right, *result;
6148     int size, offset;
6149     char *l;
6150     symbol *tlbl , *tlbl1;
6151
6152     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6153
6154     right = IC_RIGHT(ic);
6155     left  = IC_LEFT(ic);
6156     result = IC_RESULT(ic);
6157
6158     aopOp(right,ic,FALSE);
6159
6160     /* if the shift count is known then do it 
6161     as efficiently as possible */
6162     if (AOP_TYPE(right) == AOP_LIT) {
6163         genLeftShiftLiteral (left,right,result,ic);
6164         return ;
6165     }
6166
6167     /* shift count is unknown then we have to form 
6168     a loop get the loop count in B : Note: we take
6169     only the lower order byte since shifting
6170     more that 32 bits make no sense anyway, ( the
6171     largest size of an object can be only 32 bits ) */  
6172
6173     
6174     aopOp(left,ic,FALSE);
6175     aopOp(result,ic,FALSE);
6176
6177     /* now move the left to the result if they are not the
6178     same */
6179     if (!pic14_sameRegs(AOP(left),AOP(result)) && 
6180         AOP_SIZE(result) > 1) {
6181
6182         size = AOP_SIZE(result);
6183         offset=0;
6184         while (size--) {
6185             l = aopGet(AOP(left),offset,FALSE,TRUE);
6186             if (*l == '@' && (IS_AOP_PREG(result))) {
6187
6188                 pic14_emitcode("mov","a,%s",l);
6189                 aopPut(AOP(result),"a",offset);
6190             } else
6191                 aopPut(AOP(result),l,offset);
6192             offset++;
6193         }
6194     }
6195
6196     size = AOP_SIZE(result);
6197
6198     /* if it is only one byte then */
6199     if (size == 1) {
6200       if(optimized_for_speed) {
6201         emitpcode(POC_SWAPFW, popGet(AOP(left),0,FALSE,FALSE));
6202         emitpcode(POC_ANDLW,  popGetLit(0xf0));
6203         emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),2,0));
6204         emitpcode(POC_MOVFW,  popGet(AOP(left),0,FALSE,FALSE));
6205         emitpcode(POC_MOVWF,  popGet(AOP(result),0,FALSE,FALSE));
6206         emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
6207         emitpcode(POC_ADDWF,  popGet(AOP(result),0,FALSE,FALSE));
6208         emitpcode(POC_RLFW,   popGet(AOP(result),0,FALSE,FALSE));
6209         emitpcode(POC_ANDLW,  popGetLit(0xfe));
6210         emitpcode(POC_ADDFW,  popGet(AOP(result),0,FALSE,FALSE));
6211         emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),1,0));
6212         emitpcode(POC_ADDWF,  popGet(AOP(result),0,FALSE,FALSE));
6213       } else {
6214
6215         tlbl = newiTempLabel(NULL);
6216         if (!pic14_sameRegs(AOP(left),AOP(result))) {
6217           emitpcode(POC_MOVFW,  popGet(AOP(left),0,FALSE,FALSE));
6218           emitpcode(POC_MOVWF,  popGet(AOP(result),0,FALSE,FALSE));
6219         }
6220
6221         emitpcode(POC_COMFW,  popGet(AOP(right),0,FALSE,FALSE));
6222         emitpcode(POC_RRF,    popGet(AOP(result),0,FALSE,FALSE));
6223         emitpLabel(tlbl->key+100+labelOffset);
6224         emitpcode(POC_RLF,    popGet(AOP(result),0,FALSE,FALSE));
6225         emitpcode(POC_ADDLW,  popGetLit(1));
6226         emitSKPC;
6227         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
6228       }
6229       goto release ;
6230     }
6231     
6232
6233     tlbl = newiTempLabel(NULL);
6234     offset = 0 ;   
6235     tlbl1 = newiTempLabel(NULL);
6236
6237     reAdjustPreg(AOP(result));    
6238     
6239     pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
6240     pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
6241     l = aopGet(AOP(result),offset,FALSE,FALSE);
6242     MOVA(l);
6243     pic14_emitcode("add","a,acc");         
6244     aopPut(AOP(result),"a",offset++);
6245     while (--size) {
6246         l = aopGet(AOP(result),offset,FALSE,FALSE);
6247         MOVA(l);
6248         pic14_emitcode("rlc","a");         
6249         aopPut(AOP(result),"a",offset++);
6250     }
6251     reAdjustPreg(AOP(result));
6252
6253     pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
6254     pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6255 release:
6256     freeAsmop (right,NULL,ic,TRUE);
6257     freeAsmop(left,NULL,ic,TRUE);
6258     freeAsmop(result,NULL,ic,TRUE);
6259 }
6260
6261 /*-----------------------------------------------------------------*/
6262 /* genrshOne - right shift a one byte quantity by known count      */
6263 /*-----------------------------------------------------------------*/
6264 static void genrshOne (operand *result, operand *left,
6265                        int shCount, int sign)
6266 {
6267     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6268     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
6269 }
6270
6271 /*-----------------------------------------------------------------*/
6272 /* genrshTwo - right shift two bytes by known amount != 0          */
6273 /*-----------------------------------------------------------------*/
6274 static void genrshTwo (operand *result,operand *left,
6275                        int shCount, int sign)
6276 {
6277     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6278     /* if shCount >= 8 */
6279     if (shCount >= 8) {
6280         shCount -= 8 ;
6281         if (shCount)
6282             shiftR1Left2Result(left, MSB16, result, LSB,
6283                                shCount, sign);
6284         else 
6285             movLeft2Result(left, MSB16, result, LSB, sign);
6286         addSign(result, MSB16, sign);
6287     }
6288
6289     /*  1 <= shCount <= 7 */
6290     else
6291         shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
6292 }
6293
6294 /*-----------------------------------------------------------------*/
6295 /* shiftRLong - shift right one long from left to result           */
6296 /* offl = LSB or MSB16                                             */
6297 /*-----------------------------------------------------------------*/
6298 static void shiftRLong (operand *left, int offl,
6299                         operand *result, int sign)
6300 {
6301     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6302     if(!sign)
6303         pic14_emitcode("clr","c");
6304     MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE));
6305     if(sign)
6306         pic14_emitcode("mov","c,acc.7");
6307     pic14_emitcode("rrc","a");
6308     aopPut(AOP(result),"a",MSB32-offl);
6309     if(offl == MSB16)
6310         /* add sign of "a" */
6311         addSign(result, MSB32, sign);
6312
6313     MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE));
6314     pic14_emitcode("rrc","a");
6315     aopPut(AOP(result),"a",MSB24-offl);
6316
6317     MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE));
6318     pic14_emitcode("rrc","a");
6319     aopPut(AOP(result),"a",MSB16-offl);
6320
6321     if(offl == LSB){
6322         MOVA(aopGet(AOP(left),LSB,FALSE,FALSE));
6323         pic14_emitcode("rrc","a");
6324         aopPut(AOP(result),"a",LSB);
6325     }
6326 }
6327
6328 /*-----------------------------------------------------------------*/
6329 /* genrshFour - shift four byte by a known amount != 0             */
6330 /*-----------------------------------------------------------------*/
6331 static void genrshFour (operand *result, operand *left,
6332                         int shCount, int sign)
6333 {
6334     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6335     /* if shifting more that 3 bytes */
6336     if(shCount >= 24 ) {
6337         shCount -= 24;
6338         if(shCount)
6339             shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
6340         else
6341             movLeft2Result(left, MSB32, result, LSB, sign);
6342         addSign(result, MSB16, sign);
6343     }
6344     else if(shCount >= 16){
6345         shCount -= 16;
6346         if(shCount)
6347             shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
6348         else{
6349             movLeft2Result(left, MSB24, result, LSB, 0);
6350             movLeft2Result(left, MSB32, result, MSB16, sign);
6351         }
6352         addSign(result, MSB24, sign);
6353     }
6354     else if(shCount >= 8){
6355         shCount -= 8;
6356         if(shCount == 1)
6357             shiftRLong(left, MSB16, result, sign);
6358         else if(shCount == 0){
6359             movLeft2Result(left, MSB16, result, LSB, 0);
6360             movLeft2Result(left, MSB24, result, MSB16, 0);
6361             movLeft2Result(left, MSB32, result, MSB24, sign);
6362             addSign(result, MSB32, sign);
6363         }
6364         else{
6365             shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
6366             shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
6367             /* the last shift is signed */
6368             shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
6369             addSign(result, MSB32, sign);
6370         }
6371     }
6372     else{   /* 1 <= shCount <= 7 */
6373         if(shCount <= 2){
6374             shiftRLong(left, LSB, result, sign);
6375             if(shCount == 2)
6376                 shiftRLong(result, LSB, result, sign);
6377         }
6378         else{
6379             shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
6380             shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
6381             shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
6382         }
6383     }
6384 }
6385
6386 /*-----------------------------------------------------------------*/
6387 /* genRightShiftLiteral - right shifting by known count            */
6388 /*-----------------------------------------------------------------*/
6389 static void genRightShiftLiteral (operand *left,
6390                                   operand *right,
6391                                   operand *result,
6392                                   iCode *ic,
6393                                   int sign)
6394 {    
6395     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6396     int size;
6397
6398     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6399     freeAsmop(right,NULL,ic,TRUE);
6400
6401     aopOp(left,ic,FALSE);
6402     aopOp(result,ic,FALSE);
6403
6404 #if VIEW_SIZE
6405     pic14_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
6406              AOP_SIZE(left));
6407 #endif
6408
6409     size = pic14_getDataSize(left);
6410     /* test the LEFT size !!! */
6411
6412     /* I suppose that the left size >= result size */
6413     if(shCount == 0){
6414         size = pic14_getDataSize(result);
6415         while(size--)
6416             movLeft2Result(left, size, result, size, 0);
6417     }
6418
6419     else if(shCount >= (size * 8)){
6420         if(sign)
6421             /* get sign in acc.7 */
6422             MOVA(aopGet(AOP(left),size-1,FALSE,FALSE));
6423         addSign(result, LSB, sign);
6424     } else{
6425         switch (size) {
6426             case 1:
6427                 genrshOne (result,left,shCount,sign);
6428                 break;
6429
6430             case 2:
6431                 genrshTwo (result,left,shCount,sign);
6432                 break;
6433
6434             case 4:
6435                 genrshFour (result,left,shCount,sign);
6436                 break;
6437             default :
6438                 break;
6439         }
6440
6441         freeAsmop(left,NULL,ic,TRUE);
6442         freeAsmop(result,NULL,ic,TRUE);
6443     }
6444 }
6445
6446 /*-----------------------------------------------------------------*/
6447 /* genSignedRightShift - right shift of signed number              */
6448 /*-----------------------------------------------------------------*/
6449 static void genSignedRightShift (iCode *ic)
6450 {
6451     operand *right, *left, *result;
6452     int size, offset;
6453     char *l;
6454     symbol *tlbl, *tlbl1 ;
6455
6456     /* we do it the hard way put the shift count in b
6457     and loop thru preserving the sign */
6458     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6459
6460     right = IC_RIGHT(ic);
6461     left  = IC_LEFT(ic);
6462     result = IC_RESULT(ic);
6463
6464     aopOp(right,ic,FALSE);  
6465
6466
6467     if ( AOP_TYPE(right) == AOP_LIT) {
6468         genRightShiftLiteral (left,right,result,ic,1);
6469         return ;
6470     }
6471         /* shift count is unknown then we have to form 
6472        a loop get the loop count in B : Note: we take
6473        only the lower order byte since shifting
6474        more that 32 bits make no sense anyway, ( the
6475        largest size of an object can be only 32 bits ) */  
6476
6477     pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
6478     pic14_emitcode("inc","b");
6479     freeAsmop (right,NULL,ic,TRUE);
6480     aopOp(left,ic,FALSE);
6481     aopOp(result,ic,FALSE);
6482
6483     /* now move the left to the result if they are not the
6484     same */
6485     if (!pic14_sameRegs(AOP(left),AOP(result)) && 
6486         AOP_SIZE(result) > 1) {
6487
6488         size = AOP_SIZE(result);
6489         offset=0;
6490         while (size--) {
6491             l = aopGet(AOP(left),offset,FALSE,TRUE);
6492             if (*l == '@' && IS_AOP_PREG(result)) {
6493
6494                 pic14_emitcode("mov","a,%s",l);
6495                 aopPut(AOP(result),"a",offset);
6496             } else
6497                 aopPut(AOP(result),l,offset);
6498             offset++;
6499         }
6500     }
6501
6502     /* mov the highest order bit to OVR */    
6503     tlbl = newiTempLabel(NULL);
6504     tlbl1= newiTempLabel(NULL);
6505
6506     size = AOP_SIZE(result);
6507     offset = size - 1;
6508     pic14_emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
6509     pic14_emitcode("rlc","a");
6510     pic14_emitcode("mov","ov,c");
6511     /* if it is only one byte then */
6512     if (size == 1) {
6513         l = aopGet(AOP(left),0,FALSE,FALSE);
6514         MOVA(l);
6515         pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
6516         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6517         pic14_emitcode("mov","c,ov");
6518         pic14_emitcode("rrc","a");
6519         pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
6520         pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6521         aopPut(AOP(result),"a",0);
6522         goto release ;
6523     }
6524
6525     reAdjustPreg(AOP(result));
6526     pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
6527     pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
6528     pic14_emitcode("mov","c,ov");
6529     while (size--) {
6530         l = aopGet(AOP(result),offset,FALSE,FALSE);
6531         MOVA(l);
6532         pic14_emitcode("rrc","a");         
6533         aopPut(AOP(result),"a",offset--);
6534     }
6535     reAdjustPreg(AOP(result));
6536     pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
6537     pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6538
6539 release:
6540     freeAsmop(left,NULL,ic,TRUE);
6541     freeAsmop(result,NULL,ic,TRUE);
6542 }
6543
6544 /*-----------------------------------------------------------------*/
6545 /* genRightShift - generate code for right shifting                */
6546 /*-----------------------------------------------------------------*/
6547 static void genRightShift (iCode *ic)
6548 {
6549     operand *right, *left, *result;
6550     sym_link *retype ;
6551     int size, offset;
6552     char *l;
6553     symbol *tlbl, *tlbl1 ;
6554
6555     /* if signed then we do it the hard way preserve the
6556     sign bit moving it inwards */
6557     retype = getSpec(operandType(IC_RESULT(ic)));
6558     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6559
6560     if (!SPEC_USIGN(retype)) {
6561         genSignedRightShift (ic);
6562         return ;
6563     }
6564
6565     /* signed & unsigned types are treated the same : i.e. the
6566     signed is NOT propagated inwards : quoting from the
6567     ANSI - standard : "for E1 >> E2, is equivalent to division
6568     by 2**E2 if unsigned or if it has a non-negative value,
6569     otherwise the result is implementation defined ", MY definition
6570     is that the sign does not get propagated */
6571
6572     right = IC_RIGHT(ic);
6573     left  = IC_LEFT(ic);
6574     result = IC_RESULT(ic);
6575
6576     aopOp(right,ic,FALSE);
6577
6578     /* if the shift count is known then do it 
6579     as efficiently as possible */
6580     if (AOP_TYPE(right) == AOP_LIT) {
6581         genRightShiftLiteral (left,right,result,ic, 0);
6582         return ;
6583     }
6584
6585     /* shift count is unknown then we have to form 
6586     a loop get the loop count in B : Note: we take
6587     only the lower order byte since shifting
6588     more that 32 bits make no sense anyway, ( the
6589     largest size of an object can be only 32 bits ) */  
6590
6591     pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
6592     pic14_emitcode("inc","b");
6593     aopOp(left,ic,FALSE);
6594     aopOp(result,ic,FALSE);
6595
6596     /* now move the left to the result if they are not the
6597     same */
6598     if (!pic14_sameRegs(AOP(left),AOP(result)) && 
6599         AOP_SIZE(result) > 1) {
6600
6601         size = AOP_SIZE(result);
6602         offset=0;
6603         while (size--) {
6604             l = aopGet(AOP(left),offset,FALSE,TRUE);
6605             if (*l == '@' && IS_AOP_PREG(result)) {
6606
6607                 pic14_emitcode("mov","a,%s",l);
6608                 aopPut(AOP(result),"a",offset);
6609             } else
6610                 aopPut(AOP(result),l,offset);
6611             offset++;
6612         }
6613     }
6614
6615     tlbl = newiTempLabel(NULL);
6616     tlbl1= newiTempLabel(NULL);
6617     size = AOP_SIZE(result);
6618     offset = size - 1;
6619
6620     /* if it is only one byte then */
6621     if (size == 1) {
6622 /*
6623         l = aopGet(AOP(left),0,FALSE,FALSE);
6624         MOVA(l);
6625         pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
6626         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6627         CLRC;
6628         pic14_emitcode("rrc","a");
6629         pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
6630         pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6631         aopPut(AOP(result),"a",0);
6632 */
6633         tlbl = newiTempLabel(NULL);
6634         if (!pic14_sameRegs(AOP(left),AOP(result))) {
6635           emitpcode(POC_MOVFW,  popGet(AOP(left),0,FALSE,FALSE));
6636           emitpcode(POC_MOVWF,  popGet(AOP(result),0,FALSE,FALSE));
6637         }
6638
6639         emitpcode(POC_COMFW,  popGet(AOP(right),0,FALSE,FALSE));
6640         emitpcode(POC_RLF,    popGet(AOP(result),0,FALSE,FALSE));
6641         emitpLabel(tlbl->key+100+labelOffset);
6642         emitpcode(POC_RRF,    popGet(AOP(result),0,FALSE,FALSE));
6643         emitpcode(POC_ADDLW,  popGetLit(1));
6644         emitSKPC;
6645         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
6646
6647         goto release ;
6648     }
6649
6650     reAdjustPreg(AOP(result));
6651     pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
6652     pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
6653     CLRC;
6654     while (size--) {
6655         l = aopGet(AOP(result),offset,FALSE,FALSE);
6656         MOVA(l);
6657         pic14_emitcode("rrc","a");         
6658         aopPut(AOP(result),"a",offset--);
6659     }
6660     reAdjustPreg(AOP(result));
6661
6662     pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
6663     pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6664
6665 release:
6666     freeAsmop(left,NULL,ic,TRUE);
6667     freeAsmop (right,NULL,ic,TRUE);
6668     freeAsmop(result,NULL,ic,TRUE);
6669 }
6670
6671 /*-----------------------------------------------------------------*/
6672 /* genUnpackBits - generates code for unpacking bits               */
6673 /*-----------------------------------------------------------------*/
6674 static void genUnpackBits (operand *result, char *rname, int ptype)
6675 {    
6676     int shCnt ;
6677     int rlen = 0 ;
6678     sym_link *etype;
6679     int offset = 0 ;
6680
6681     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6682     etype = getSpec(operandType(result));
6683
6684     /* read the first byte  */
6685     switch (ptype) {
6686
6687     case POINTER:
6688     case IPOINTER:
6689         pic14_emitcode("mov","a,@%s",rname);
6690         break;
6691         
6692     case PPOINTER:
6693         pic14_emitcode("movx","a,@%s",rname);
6694         break;
6695         
6696     case FPOINTER:
6697         pic14_emitcode("movx","a,@dptr");
6698         break;
6699
6700     case CPOINTER:
6701         pic14_emitcode("clr","a");
6702         pic14_emitcode("movc","a","@a+dptr");
6703         break;
6704
6705     case GPOINTER:
6706         pic14_emitcode("lcall","__gptrget");
6707         break;
6708     }
6709
6710     /* if we have bitdisplacement then it fits   */
6711     /* into this byte completely or if length is */
6712     /* less than a byte                          */
6713     if ((shCnt = SPEC_BSTR(etype)) || 
6714         (SPEC_BLEN(etype) <= 8))  {
6715
6716         /* shift right acc */
6717         AccRsh(shCnt);
6718
6719         pic14_emitcode("anl","a,#0x%02x",
6720                  ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
6721         aopPut(AOP(result),"a",offset);
6722         return ;
6723     }
6724
6725     /* bit field did not fit in a byte  */
6726     rlen = SPEC_BLEN(etype) - 8;
6727     aopPut(AOP(result),"a",offset++);
6728
6729     while (1)  {
6730
6731         switch (ptype) {
6732         case POINTER:
6733         case IPOINTER:
6734             pic14_emitcode("inc","%s",rname);
6735             pic14_emitcode("mov","a,@%s",rname);
6736             break;
6737             
6738         case PPOINTER:
6739             pic14_emitcode("inc","%s",rname);
6740             pic14_emitcode("movx","a,@%s",rname);
6741             break;
6742
6743         case FPOINTER:
6744             pic14_emitcode("inc","dptr");
6745             pic14_emitcode("movx","a,@dptr");
6746             break;
6747             
6748         case CPOINTER:
6749             pic14_emitcode("clr","a");
6750             pic14_emitcode("inc","dptr");
6751             pic14_emitcode("movc","a","@a+dptr");
6752             break;
6753             
6754         case GPOINTER:
6755             pic14_emitcode("inc","dptr");
6756             pic14_emitcode("lcall","__gptrget");
6757             break;
6758         }
6759
6760         rlen -= 8;            
6761         /* if we are done */
6762         if ( rlen <= 0 )
6763             break ;
6764         
6765         aopPut(AOP(result),"a",offset++);
6766                               
6767     }
6768     
6769     if (rlen) {
6770         pic14_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
6771         aopPut(AOP(result),"a",offset);        
6772     }
6773     
6774     return ;
6775 }
6776
6777
6778 /*-----------------------------------------------------------------*/
6779 /* genDataPointerGet - generates code when ptr offset is known     */
6780 /*-----------------------------------------------------------------*/
6781 static void genDataPointerGet (operand *left, 
6782                                operand *result, 
6783                                iCode *ic)
6784 {
6785   int size , offset = 0;
6786
6787
6788   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6789
6790
6791   /* optimization - most of the time, left and result are the same
6792    * address, but different types. for the pic code, we could omit
6793    * the following
6794    */
6795
6796   aopOp(result,ic,TRUE);
6797
6798   emitpcode(POC_MOVFW, popGet(AOP(left),0,FALSE,TRUE));
6799
6800   size = AOP_SIZE(result);
6801
6802   while (size--) {
6803     emitpcode(POC_MOVWF, popGet(AOP(result),offset,FALSE,TRUE));
6804     offset++;
6805   }
6806
6807   freeAsmop(left,NULL,ic,TRUE);
6808   freeAsmop(result,NULL,ic,TRUE);
6809 }
6810
6811 /*-----------------------------------------------------------------*/
6812 /* genNearPointerGet - pic14_emitcode for near pointer fetch             */
6813 /*-----------------------------------------------------------------*/
6814 static void genNearPointerGet (operand *left, 
6815                                operand *result, 
6816                                iCode *ic)
6817 {
6818     asmop *aop = NULL;
6819     regs *preg = NULL ;
6820     char *rname ;
6821     sym_link *rtype, *retype;
6822     sym_link *ltype = operandType(left);    
6823     char buffer[80];
6824
6825     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6826
6827     rtype = operandType(result);
6828     retype= getSpec(rtype);
6829     
6830     aopOp(left,ic,FALSE);
6831     
6832     /* if left is rematerialisable and
6833        result is not bit variable type and
6834        the left is pointer to data space i.e
6835        lower 128 bytes of space */
6836     if (AOP_TYPE(left) == AOP_IMMD &&
6837         !IS_BITVAR(retype)         &&
6838         DCL_TYPE(ltype) == POINTER) {
6839         genDataPointerGet (left,result,ic);
6840         return ;
6841     }
6842     
6843     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6844
6845         /* if the value is already in a pointer register
6846        then don't need anything more */
6847     if (!AOP_INPREG(AOP(left))) {
6848         /* otherwise get a free pointer register */
6849     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6850         aop = newAsmop(0);
6851         preg = getFreePtr(ic,&aop,FALSE);
6852         pic14_emitcode("mov","%s,%s",
6853                 preg->name,
6854                 aopGet(AOP(left),0,FALSE,TRUE));
6855         rname = preg->name ;
6856     } else
6857         rname = aopGet(AOP(left),0,FALSE,FALSE);
6858     
6859     freeAsmop(left,NULL,ic,TRUE);
6860     aopOp (result,ic,FALSE);
6861     
6862       /* if bitfield then unpack the bits */
6863     if (IS_BITVAR(retype)) 
6864         genUnpackBits (result,rname,POINTER);
6865     else {
6866         /* we have can just get the values */
6867         int size = AOP_SIZE(result);
6868         int offset = 0 ;        
6869         
6870     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6871         while (size--) {
6872             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
6873
6874                 pic14_emitcode("mov","a,@%s",rname);
6875                 aopPut(AOP(result),"a",offset);
6876             } else {
6877                 sprintf(buffer,"@%s",rname);
6878                 aopPut(AOP(result),buffer,offset);
6879             }
6880             offset++ ;
6881             if (size)
6882                 pic14_emitcode("inc","%s",rname);
6883         }
6884     }
6885
6886     /* now some housekeeping stuff */
6887     if (aop) {
6888         /* we had to allocate for this iCode */
6889     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6890         freeAsmop(NULL,aop,ic,TRUE);
6891     } else { 
6892         /* we did not allocate which means left
6893            already in a pointer register, then
6894            if size > 0 && this could be used again
6895            we have to point it back to where it 
6896            belongs */
6897     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6898         if (AOP_SIZE(result) > 1 &&
6899             !OP_SYMBOL(left)->remat &&
6900             ( OP_SYMBOL(left)->liveTo > ic->seq ||
6901               ic->depth )) {
6902             int size = AOP_SIZE(result) - 1;
6903             while (size--)
6904                 pic14_emitcode("dec","%s",rname);
6905         }
6906     }
6907
6908     /* done */
6909     freeAsmop(result,NULL,ic,TRUE);
6910      
6911 }
6912
6913 /*-----------------------------------------------------------------*/
6914 /* genPagedPointerGet - pic14_emitcode for paged pointer fetch           */
6915 /*-----------------------------------------------------------------*/
6916 static void genPagedPointerGet (operand *left, 
6917                                operand *result, 
6918                                iCode *ic)
6919 {
6920     asmop *aop = NULL;
6921     regs *preg = NULL ;
6922     char *rname ;
6923     sym_link *rtype, *retype;    
6924
6925     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6926
6927     rtype = operandType(result);
6928     retype= getSpec(rtype);
6929     
6930     aopOp(left,ic,FALSE);
6931
6932   /* if the value is already in a pointer register
6933        then don't need anything more */
6934     if (!AOP_INPREG(AOP(left))) {
6935         /* otherwise get a free pointer register */
6936         aop = newAsmop(0);
6937         preg = getFreePtr(ic,&aop,FALSE);
6938         pic14_emitcode("mov","%s,%s",
6939                 preg->name,
6940                 aopGet(AOP(left),0,FALSE,TRUE));
6941         rname = preg->name ;
6942     } else
6943         rname = aopGet(AOP(left),0,FALSE,FALSE);
6944     
6945     freeAsmop(left,NULL,ic,TRUE);
6946     aopOp (result,ic,FALSE);
6947
6948     /* if bitfield then unpack the bits */
6949     if (IS_BITVAR(retype)) 
6950         genUnpackBits (result,rname,PPOINTER);
6951     else {
6952         /* we have can just get the values */
6953         int size = AOP_SIZE(result);
6954         int offset = 0 ;        
6955         
6956         while (size--) {
6957             
6958             pic14_emitcode("movx","a,@%s",rname);
6959             aopPut(AOP(result),"a",offset);
6960             
6961             offset++ ;
6962             
6963             if (size)
6964                 pic14_emitcode("inc","%s",rname);
6965         }
6966     }
6967
6968     /* now some housekeeping stuff */
6969     if (aop) {
6970         /* we had to allocate for this iCode */
6971         freeAsmop(NULL,aop,ic,TRUE);
6972     } else { 
6973         /* we did not allocate which means left
6974            already in a pointer register, then
6975            if size > 0 && this could be used again
6976            we have to point it back to where it 
6977            belongs */
6978         if (AOP_SIZE(result) > 1 &&
6979             !OP_SYMBOL(left)->remat &&
6980             ( OP_SYMBOL(left)->liveTo > ic->seq ||
6981               ic->depth )) {
6982             int size = AOP_SIZE(result) - 1;
6983             while (size--)
6984                 pic14_emitcode("dec","%s",rname);
6985         }
6986     }
6987
6988     /* done */
6989     freeAsmop(result,NULL,ic,TRUE);
6990     
6991         
6992 }
6993
6994 /*-----------------------------------------------------------------*/
6995 /* genFarPointerGet - gget value from far space                    */
6996 /*-----------------------------------------------------------------*/
6997 static void genFarPointerGet (operand *left,
6998                               operand *result, iCode *ic)
6999 {
7000     int size, offset ;
7001     sym_link *retype = getSpec(operandType(result));
7002
7003     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7004
7005     aopOp(left,ic,FALSE);
7006
7007     /* if the operand is already in dptr 
7008     then we do nothing else we move the value to dptr */
7009     if (AOP_TYPE(left) != AOP_STR) {
7010         /* if this is remateriazable */
7011         if (AOP_TYPE(left) == AOP_IMMD)
7012             pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
7013         else { /* we need to get it byte by byte */
7014             pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
7015             pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
7016             if (options.model == MODEL_FLAT24)
7017             {
7018                pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
7019             }
7020         }
7021     }
7022     /* so dptr know contains the address */
7023     freeAsmop(left,NULL,ic,TRUE);
7024     aopOp(result,ic,FALSE);
7025
7026     /* if bit then unpack */
7027     if (IS_BITVAR(retype)) 
7028         genUnpackBits(result,"dptr",FPOINTER);
7029     else {
7030         size = AOP_SIZE(result);
7031         offset = 0 ;
7032
7033         while (size--) {
7034             pic14_emitcode("movx","a,@dptr");
7035             aopPut(AOP(result),"a",offset++);
7036             if (size)
7037                 pic14_emitcode("inc","dptr");
7038         }
7039     }
7040
7041     freeAsmop(result,NULL,ic,TRUE);
7042 }
7043
7044 /*-----------------------------------------------------------------*/
7045 /* pic14_emitcodePointerGet - gget value from code space                  */
7046 /*-----------------------------------------------------------------*/
7047 static void pic14_emitcodePointerGet (operand *left,
7048                                 operand *result, iCode *ic)
7049 {
7050     int size, offset ;
7051     sym_link *retype = getSpec(operandType(result));
7052
7053     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7054
7055     aopOp(left,ic,FALSE);
7056
7057     /* if the operand is already in dptr 
7058     then we do nothing else we move the value to dptr */
7059     if (AOP_TYPE(left) != AOP_STR) {
7060         /* if this is remateriazable */
7061         if (AOP_TYPE(left) == AOP_IMMD)
7062             pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
7063         else { /* we need to get it byte by byte */
7064             pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
7065             pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
7066             if (options.model == MODEL_FLAT24)
7067             {
7068                pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
7069             }
7070         }
7071     }
7072     /* so dptr know contains the address */
7073     freeAsmop(left,NULL,ic,TRUE);
7074     aopOp(result,ic,FALSE);
7075
7076     /* if bit then unpack */
7077     if (IS_BITVAR(retype)) 
7078         genUnpackBits(result,"dptr",CPOINTER);
7079     else {
7080         size = AOP_SIZE(result);
7081         offset = 0 ;
7082
7083         while (size--) {
7084             pic14_emitcode("clr","a");
7085             pic14_emitcode("movc","a,@a+dptr");
7086             aopPut(AOP(result),"a",offset++);
7087             if (size)
7088                 pic14_emitcode("inc","dptr");
7089         }
7090     }
7091
7092     freeAsmop(result,NULL,ic,TRUE);
7093 }
7094
7095 /*-----------------------------------------------------------------*/
7096 /* genGenPointerGet - gget value from generic pointer space        */
7097 /*-----------------------------------------------------------------*/
7098 static void genGenPointerGet (operand *left,
7099                               operand *result, iCode *ic)
7100 {
7101     int size, offset ;
7102     sym_link *retype = getSpec(operandType(result));
7103
7104     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7105     aopOp(left,ic,FALSE);
7106
7107     /* if the operand is already in dptr 
7108     then we do nothing else we move the value to dptr */
7109     if (AOP_TYPE(left) != AOP_STR) {
7110         /* if this is remateriazable */
7111         if (AOP_TYPE(left) == AOP_IMMD) {
7112             pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
7113             pic14_emitcode("mov","b,#%d",pointerCode(retype));
7114         }
7115         else { /* we need to get it byte by byte */
7116           emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
7117           //emitpcode(POC_MOVFW,popGet(AOP(left),0,FALSE,FALSE));
7118           //emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
7119           pic14_emitcode("movf","%s,w",aopGet(AOP(left),0,FALSE,FALSE));
7120           pic14_emitcode("movwf","FSR");
7121           /*
7122             pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
7123             pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
7124             if (options.model == MODEL_FLAT24)
7125             {
7126                pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
7127                pic14_emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE));
7128             }
7129             else
7130             {
7131                 pic14_emitcode("mov","b,%s",aopGet(AOP(left),2,FALSE,FALSE));
7132             }
7133           */
7134         }
7135     }
7136     /* so dptr know contains the address */
7137     freeAsmop(left,NULL,ic,TRUE);
7138     aopOp(result,ic,FALSE); 
7139
7140     /* if bit then unpack */
7141     if (IS_BITVAR(retype)) 
7142         genUnpackBits(result,"dptr",GPOINTER);
7143     else {
7144         size = AOP_SIZE(result);
7145         offset = 0 ;
7146
7147         while (size--) {
7148           emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
7149
7150           emitpcode(POC_MOVWF,popGet(AOP(result),offset++,FALSE,FALSE));
7151           if(size)
7152             emitpcode(POC_INCF,popCopyReg(&pc_fsr));
7153 /*
7154           pic14_emitcode("movf","indf,w");
7155           pic14_emitcode("movwf","%s",
7156                    aopGet(AOP(result),offset++,FALSE,FALSE));
7157           if (size)
7158             pic14_emitcode("incf","fsr,f");
7159 */
7160         }
7161     }
7162
7163     freeAsmop(result,NULL,ic,TRUE);
7164 }
7165
7166 /*-----------------------------------------------------------------*/
7167 /* genPointerGet - generate code for pointer get                   */
7168 /*-----------------------------------------------------------------*/
7169 static void genPointerGet (iCode *ic)
7170 {
7171     operand *left, *result ;
7172     sym_link *type, *etype;
7173     int p_type;
7174
7175     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7176
7177     left = IC_LEFT(ic);
7178     result = IC_RESULT(ic) ;
7179
7180     /* depending on the type of pointer we need to
7181     move it to the correct pointer register */
7182     type = operandType(left);
7183     etype = getSpec(type);
7184     /* if left is of type of pointer then it is simple */
7185     if (IS_PTR(type) && !IS_FUNC(type->next)) 
7186         p_type = DCL_TYPE(type);
7187     else {
7188         /* we have to go by the storage class */
7189         p_type = PTR_TYPE(SPEC_OCLS(etype));
7190
7191 /*      if (SPEC_OCLS(etype)->codesp ) { */
7192 /*          p_type = CPOINTER ;  */
7193 /*      } */
7194 /*      else */
7195 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
7196 /*              p_type = FPOINTER ; */
7197 /*          else */
7198 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
7199 /*                  p_type = PPOINTER; */
7200 /*              else */
7201 /*                  if (SPEC_OCLS(etype) == idata ) */
7202 /*                      p_type = IPOINTER; */
7203 /*                  else */
7204 /*                      p_type = POINTER ; */
7205     }
7206
7207     /* now that we have the pointer type we assign
7208     the pointer values */
7209     switch (p_type) {
7210
7211     case POINTER:       
7212     case IPOINTER:
7213         genNearPointerGet (left,result,ic);
7214         break;
7215
7216     case PPOINTER:
7217         genPagedPointerGet(left,result,ic);
7218         break;
7219
7220     case FPOINTER:
7221         genFarPointerGet (left,result,ic);
7222         break;
7223
7224     case CPOINTER:
7225         pic14_emitcodePointerGet (left,result,ic);
7226         break;
7227
7228     case GPOINTER:
7229         genGenPointerGet (left,result,ic);
7230         break;
7231     }
7232
7233 }
7234
7235 /*-----------------------------------------------------------------*/
7236 /* genPackBits - generates code for packed bit storage             */
7237 /*-----------------------------------------------------------------*/
7238 static void genPackBits (sym_link    *etype ,
7239                          operand *right ,
7240                          char *rname, int p_type)
7241 {
7242     int shCount = 0 ;
7243     int offset = 0  ;
7244     int rLen = 0 ;
7245     int blen, bstr ;   
7246     char *l ;
7247
7248     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7249     blen = SPEC_BLEN(etype);
7250     bstr = SPEC_BSTR(etype);
7251
7252     l = aopGet(AOP(right),offset++,FALSE,FALSE);
7253     MOVA(l);   
7254
7255     /* if the bit lenth is less than or    */
7256     /* it exactly fits a byte then         */
7257     if (SPEC_BLEN(etype) <= 8 )  {
7258         shCount = SPEC_BSTR(etype) ;
7259
7260         /* shift left acc */
7261         AccLsh(shCount);
7262
7263         if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
7264
7265
7266             switch (p_type) {
7267                 case POINTER:
7268                     pic14_emitcode ("mov","b,a");
7269                     pic14_emitcode("mov","a,@%s",rname);
7270                     break;
7271
7272                 case FPOINTER:
7273                     pic14_emitcode ("mov","b,a");
7274                     pic14_emitcode("movx","a,@dptr");
7275                     break;
7276
7277                 case GPOINTER:
7278                     pic14_emitcode ("push","b");
7279                     pic14_emitcode ("push","acc");
7280                     pic14_emitcode ("lcall","__gptrget");
7281                     pic14_emitcode ("pop","b");
7282                     break;
7283             }
7284
7285             pic14_emitcode ("anl","a,#0x%02x",(unsigned char)
7286                       ((unsigned char)(0xFF << (blen+bstr)) | 
7287                        (unsigned char)(0xFF >> (8-bstr)) ) );
7288             pic14_emitcode ("orl","a,b");
7289             if (p_type == GPOINTER)
7290                 pic14_emitcode("pop","b");
7291         }
7292     }
7293
7294     switch (p_type) {
7295         case POINTER:
7296             pic14_emitcode("mov","@%s,a",rname);
7297             break;
7298
7299         case FPOINTER:
7300             pic14_emitcode("movx","@dptr,a");
7301             break;
7302
7303         case GPOINTER:
7304             DEBUGpic14_emitcode(";lcall","__gptrput");
7305             break;
7306     }
7307
7308     /* if we r done */
7309     if ( SPEC_BLEN(etype) <= 8 )
7310         return ;
7311
7312     pic14_emitcode("inc","%s",rname);
7313     rLen = SPEC_BLEN(etype) ;     
7314
7315     /* now generate for lengths greater than one byte */
7316     while (1) {
7317
7318         l = aopGet(AOP(right),offset++,FALSE,TRUE);
7319
7320         rLen -= 8 ;
7321         if (rLen <= 0 )
7322             break ;
7323
7324         switch (p_type) {
7325             case POINTER:
7326                 if (*l == '@') {
7327                     MOVA(l);
7328                     pic14_emitcode("mov","@%s,a",rname);
7329                 } else
7330                     pic14_emitcode("mov","@%s,%s",rname,l);
7331                 break;
7332
7333             case FPOINTER:
7334                 MOVA(l);
7335                 pic14_emitcode("movx","@dptr,a");
7336                 break;
7337
7338             case GPOINTER:
7339                 MOVA(l);
7340                 DEBUGpic14_emitcode(";lcall","__gptrput");
7341                 break;  
7342         }   
7343         pic14_emitcode ("inc","%s",rname);
7344     }
7345
7346     MOVA(l);
7347
7348     /* last last was not complete */
7349     if (rLen)   {
7350         /* save the byte & read byte */
7351         switch (p_type) {
7352             case POINTER:
7353                 pic14_emitcode ("mov","b,a");
7354                 pic14_emitcode("mov","a,@%s",rname);
7355                 break;
7356
7357             case FPOINTER:
7358                 pic14_emitcode ("mov","b,a");
7359                 pic14_emitcode("movx","a,@dptr");
7360                 break;
7361
7362             case GPOINTER:
7363                 pic14_emitcode ("push","b");
7364                 pic14_emitcode ("push","acc");
7365                 pic14_emitcode ("lcall","__gptrget");
7366                 pic14_emitcode ("pop","b");
7367                 break;
7368         }
7369
7370         pic14_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
7371         pic14_emitcode ("orl","a,b");
7372     }
7373
7374     if (p_type == GPOINTER)
7375         pic14_emitcode("pop","b");
7376
7377     switch (p_type) {
7378
7379     case POINTER:
7380         pic14_emitcode("mov","@%s,a",rname);
7381         break;
7382         
7383     case FPOINTER:
7384         pic14_emitcode("movx","@dptr,a");
7385         break;
7386         
7387     case GPOINTER:
7388         DEBUGpic14_emitcode(";lcall","__gptrput");
7389         break;                  
7390     }
7391 }
7392 /*-----------------------------------------------------------------*/
7393 /* genDataPointerSet - remat pointer to data space                 */
7394 /*-----------------------------------------------------------------*/
7395 static void genDataPointerSet(operand *right,
7396                               operand *result,
7397                               iCode *ic)
7398 {
7399     int size, offset = 0 ;
7400     char *l, buffer[256];
7401
7402     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7403     aopOp(right,ic,FALSE);
7404     
7405     l = aopGet(AOP(result),0,FALSE,TRUE);
7406     size = AOP_SIZE(right);
7407     // tsd, was l+1 - the underline `_' prefix was being stripped
7408     while (size--) {
7409         if (offset)
7410             sprintf(buffer,"(%s + %d)",l,offset);
7411         else
7412             sprintf(buffer,"%s",l);
7413
7414         if (AOP_TYPE(right) == AOP_LIT) {
7415           unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
7416           lit = lit >> (8*offset);
7417           if(lit&0xff) {
7418             pic14_emitcode("movlw","%d",lit);
7419             pic14_emitcode("movwf","%s",buffer);
7420
7421             emitpcode(POC_MOVLW, popGetLit(lit&0xff));
7422             emitpcode(POC_MOVWF, popRegFromString(buffer));
7423
7424           } else {
7425             pic14_emitcode("clrf","%s",buffer);
7426             emitpcode(POC_CLRF, popRegFromString(buffer));
7427           }
7428         }else {
7429           pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
7430           pic14_emitcode("movwf","%s",buffer);
7431
7432           emitpcode(POC_MOVFW, popGet(AOP(right),offset,FALSE,FALSE));
7433           emitpcode(POC_MOVWF, popRegFromString(buffer));
7434
7435         }
7436
7437         offset++;
7438     }
7439
7440     freeAsmop(right,NULL,ic,TRUE);
7441     freeAsmop(result,NULL,ic,TRUE);
7442 }
7443
7444 /*-----------------------------------------------------------------*/
7445 /* genNearPointerSet - pic14_emitcode for near pointer put                */
7446 /*-----------------------------------------------------------------*/
7447 static void genNearPointerSet (operand *right,
7448                                operand *result, 
7449                                iCode *ic)
7450 {
7451     asmop *aop = NULL;
7452     char *l;
7453     sym_link *retype;
7454     sym_link *ptype = operandType(result);
7455
7456     
7457     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7458     retype= getSpec(operandType(right));
7459
7460     aopOp(result,ic,FALSE);
7461     
7462     /* if the result is rematerializable &
7463        in data space & not a bit variable */
7464     if (AOP_TYPE(result) == AOP_IMMD &&
7465         DCL_TYPE(ptype) == POINTER   &&
7466         !IS_BITVAR(retype)) {
7467         genDataPointerSet (right,result,ic);
7468         return;
7469     }
7470
7471     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7472
7473     /* if the value is already in a pointer register
7474     then don't need anything more */
7475     if (!AOP_INPREG(AOP(result))) {
7476         /* otherwise get a free pointer register */
7477         //aop = newAsmop(0);
7478         //preg = getFreePtr(ic,&aop,FALSE);
7479         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7480         //pic14_emitcode("mov","%s,%s",
7481         //         preg->name,
7482         //         aopGet(AOP(result),0,FALSE,TRUE));
7483         //rname = preg->name ;
7484         pic14_emitcode("movwf","fsr");
7485     }// else
7486     //   rname = aopGet(AOP(result),0,FALSE,FALSE);
7487
7488     freeAsmop(result,NULL,ic,TRUE);
7489     aopOp (right,ic,FALSE);
7490     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7491
7492     /* if bitfield then unpack the bits */
7493     if (IS_BITVAR(retype)) {
7494       werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
7495              "The programmer is obviously confused");
7496       //genPackBits (retype,right,rname,POINTER);
7497       exit(1);
7498     }
7499     else {
7500         /* we have can just get the values */
7501         int size = AOP_SIZE(right);
7502         int offset = 0 ;    
7503
7504     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7505         while (size--) {
7506             l = aopGet(AOP(right),offset,FALSE,TRUE);
7507             if (*l == '@' ) {
7508               //MOVA(l);
7509               //pic14_emitcode("mov","@%s,a",rname);
7510               pic14_emitcode("movf","indf,w ;1");
7511             } else {
7512
7513               if (AOP_TYPE(right) == AOP_LIT) {
7514                 unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
7515                 if(lit) {
7516                   pic14_emitcode("movlw","%s",l);
7517                   pic14_emitcode("movwf","indf ;2");
7518                 } else 
7519                   pic14_emitcode("clrf","indf");
7520               }else {
7521                 pic14_emitcode("movf","%s,w",l);
7522                 pic14_emitcode("movwf","indf ;2");
7523               }
7524             //pic14_emitcode("mov","@%s,%s",rname,l);
7525             }
7526             if (size)
7527               pic14_emitcode("incf","fsr,f ;3");
7528             //pic14_emitcode("inc","%s",rname);
7529             offset++;
7530         }
7531     }
7532
7533     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7534     /* now some housekeeping stuff */
7535     if (aop) {
7536         /* we had to allocate for this iCode */
7537         freeAsmop(NULL,aop,ic,TRUE);
7538     } else { 
7539         /* we did not allocate which means left
7540         already in a pointer register, then
7541         if size > 0 && this could be used again
7542         we have to point it back to where it 
7543         belongs */
7544     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7545         if (AOP_SIZE(right) > 1 &&
7546             !OP_SYMBOL(result)->remat &&
7547             ( OP_SYMBOL(result)->liveTo > ic->seq ||
7548               ic->depth )) {
7549             int size = AOP_SIZE(right) - 1;
7550             while (size--)
7551               pic14_emitcode("decf","fsr,f");
7552               //pic14_emitcode("dec","%s",rname);
7553         }
7554     }
7555
7556     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7557     /* done */
7558     freeAsmop(right,NULL,ic,TRUE);
7559
7560
7561 }
7562
7563 /*-----------------------------------------------------------------*/
7564 /* genPagedPointerSet - pic14_emitcode for Paged pointer put             */
7565 /*-----------------------------------------------------------------*/
7566 static void genPagedPointerSet (operand *right,
7567                                operand *result, 
7568                                iCode *ic)
7569 {
7570     asmop *aop = NULL;
7571     regs *preg = NULL ;
7572     char *rname , *l;
7573     sym_link *retype;
7574        
7575     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7576
7577     retype= getSpec(operandType(right));
7578     
7579     aopOp(result,ic,FALSE);
7580     
7581     /* if the value is already in a pointer register
7582        then don't need anything more */
7583     if (!AOP_INPREG(AOP(result))) {
7584         /* otherwise get a free pointer register */
7585         aop = newAsmop(0);
7586         preg = getFreePtr(ic,&aop,FALSE);
7587         pic14_emitcode("mov","%s,%s",
7588                 preg->name,
7589                 aopGet(AOP(result),0,FALSE,TRUE));
7590         rname = preg->name ;
7591     } else
7592         rname = aopGet(AOP(result),0,FALSE,FALSE);
7593     
7594     freeAsmop(result,NULL,ic,TRUE);
7595     aopOp (right,ic,FALSE);
7596
7597     /* if bitfield then unpack the bits */
7598     if (IS_BITVAR(retype)) 
7599         genPackBits (retype,right,rname,PPOINTER);
7600     else {
7601         /* we have can just get the values */
7602         int size = AOP_SIZE(right);
7603         int offset = 0 ;        
7604         
7605         while (size--) {
7606             l = aopGet(AOP(right),offset,FALSE,TRUE);
7607             
7608             MOVA(l);
7609             pic14_emitcode("movx","@%s,a",rname);
7610
7611             if (size)
7612                 pic14_emitcode("inc","%s",rname);
7613
7614             offset++;
7615         }
7616     }
7617     
7618     /* now some housekeeping stuff */
7619     if (aop) {
7620         /* we had to allocate for this iCode */
7621         freeAsmop(NULL,aop,ic,TRUE);
7622     } else { 
7623         /* we did not allocate which means left
7624            already in a pointer register, then
7625            if size > 0 && this could be used again
7626            we have to point it back to where it 
7627            belongs */
7628         if (AOP_SIZE(right) > 1 &&
7629             !OP_SYMBOL(result)->remat &&
7630             ( OP_SYMBOL(result)->liveTo > ic->seq ||
7631               ic->depth )) {
7632             int size = AOP_SIZE(right) - 1;
7633             while (size--)
7634                 pic14_emitcode("dec","%s",rname);
7635         }
7636     }
7637
7638     /* done */
7639     freeAsmop(right,NULL,ic,TRUE);
7640     
7641         
7642 }
7643
7644 /*-----------------------------------------------------------------*/
7645 /* genFarPointerSet - set value from far space                     */
7646 /*-----------------------------------------------------------------*/
7647 static void genFarPointerSet (operand *right,
7648                               operand *result, iCode *ic)
7649 {
7650     int size, offset ;
7651     sym_link *retype = getSpec(operandType(right));
7652
7653     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7654     aopOp(result,ic,FALSE);
7655
7656     /* if the operand is already in dptr 
7657     then we do nothing else we move the value to dptr */
7658     if (AOP_TYPE(result) != AOP_STR) {
7659         /* if this is remateriazable */
7660         if (AOP_TYPE(result) == AOP_IMMD)
7661             pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
7662         else { /* we need to get it byte by byte */
7663             pic14_emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
7664             pic14_emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
7665             if (options.model == MODEL_FLAT24)
7666             {
7667                pic14_emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
7668             }
7669         }
7670     }
7671     /* so dptr know contains the address */
7672     freeAsmop(result,NULL,ic,TRUE);
7673     aopOp(right,ic,FALSE);
7674
7675     /* if bit then unpack */
7676     if (IS_BITVAR(retype)) 
7677         genPackBits(retype,right,"dptr",FPOINTER);
7678     else {
7679         size = AOP_SIZE(right);
7680         offset = 0 ;
7681
7682         while (size--) {
7683             char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
7684             MOVA(l);
7685             pic14_emitcode("movx","@dptr,a");
7686             if (size)
7687                 pic14_emitcode("inc","dptr");
7688         }
7689     }
7690
7691     freeAsmop(right,NULL,ic,TRUE);
7692 }
7693
7694 /*-----------------------------------------------------------------*/
7695 /* genGenPointerSet - set value from generic pointer space         */
7696 /*-----------------------------------------------------------------*/
7697 static void genGenPointerSet (operand *right,
7698                               operand *result, iCode *ic)
7699 {
7700     int size, offset ;
7701     sym_link *retype = getSpec(operandType(right));
7702
7703     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7704
7705     aopOp(result,ic,FALSE);
7706
7707     /* if the operand is already in dptr 
7708     then we do nothing else we move the value to dptr */
7709     if (AOP_TYPE(result) != AOP_STR) {
7710         /* if this is remateriazable */
7711         if (AOP_TYPE(result) == AOP_IMMD) {
7712             pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
7713             pic14_emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
7714         }
7715         else { /* we need to get it byte by byte */
7716           char *l = aopGet(AOP(result),0,FALSE,FALSE);
7717
7718           if(strcmp("FSR",l))
7719             emitpcode(POC_MOVLW ,popGet(AOP(result),0,FALSE,FALSE));
7720           emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
7721
7722           if(strcmp("FSR",l))
7723             pic14_emitcode("movlw","%s",aopGet(AOP(result),0,FALSE,FALSE));
7724
7725           pic14_emitcode("movwf","INDF");
7726         }
7727     }
7728     /* so dptr know contains the address */
7729     freeAsmop(result,NULL,ic,TRUE);
7730     aopOp(right,ic,FALSE);
7731
7732     /* if bit then unpack */
7733     if (IS_BITVAR(retype)) 
7734         genPackBits(retype,right,"dptr",GPOINTER);
7735     else {
7736         size = AOP_SIZE(right);
7737         offset = 0 ;
7738
7739         while (--size) {
7740           //char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
7741             if(size)
7742               pic14_emitcode("incf","fsr,f");
7743             pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset++,FALSE,FALSE));
7744             pic14_emitcode("movwf","indf");
7745             //MOVA(l);
7746             //DEBUGpic14_emitcode(";lcall","__gptrput");
7747             //if (size)
7748             //    pic14_emitcode("inc","dptr");
7749         }
7750     }
7751
7752     freeAsmop(right,NULL,ic,TRUE);
7753 }
7754
7755 /*-----------------------------------------------------------------*/
7756 /* genPointerSet - stores the value into a pointer location        */
7757 /*-----------------------------------------------------------------*/
7758 static void genPointerSet (iCode *ic)
7759 {    
7760     operand *right, *result ;
7761     sym_link *type, *etype;
7762     int p_type;
7763
7764     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7765
7766     right = IC_RIGHT(ic);
7767     result = IC_RESULT(ic) ;
7768
7769     /* depending on the type of pointer we need to
7770     move it to the correct pointer register */
7771     type = operandType(result);
7772     etype = getSpec(type);
7773     /* if left is of type of pointer then it is simple */
7774     if (IS_PTR(type) && !IS_FUNC(type->next)) {
7775         p_type = DCL_TYPE(type);
7776     }
7777     else {
7778         /* we have to go by the storage class */
7779         p_type = PTR_TYPE(SPEC_OCLS(etype));
7780
7781 /*      if (SPEC_OCLS(etype)->codesp ) { */
7782 /*          p_type = CPOINTER ;  */
7783 /*      } */
7784 /*      else */
7785 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
7786 /*              p_type = FPOINTER ; */
7787 /*          else */
7788 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
7789 /*                  p_type = PPOINTER ; */
7790 /*              else */
7791 /*                  if (SPEC_OCLS(etype) == idata ) */
7792 /*                      p_type = IPOINTER ; */
7793 /*                  else */
7794 /*                      p_type = POINTER ; */
7795     }
7796
7797     /* now that we have the pointer type we assign
7798     the pointer values */
7799     switch (p_type) {
7800
7801     case POINTER:
7802     case IPOINTER:
7803         genNearPointerSet (right,result,ic);
7804         break;
7805
7806     case PPOINTER:
7807         genPagedPointerSet (right,result,ic);
7808         break;
7809
7810     case FPOINTER:
7811         genFarPointerSet (right,result,ic);
7812         break;
7813
7814     case GPOINTER:
7815         genGenPointerSet (right,result,ic);
7816         break;
7817     }
7818
7819 }
7820
7821 /*-----------------------------------------------------------------*/
7822 /* genIfx - generate code for Ifx statement                        */
7823 /*-----------------------------------------------------------------*/
7824 static void genIfx (iCode *ic, iCode *popIc)
7825 {
7826     operand *cond = IC_COND(ic);
7827     int isbit =0;
7828
7829     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7830     aopOp(cond,ic,FALSE);
7831
7832     /* get the value into acc */
7833     if (AOP_TYPE(cond) != AOP_CRY)
7834         pic14_toBoolean(cond);
7835     else
7836         isbit = 1;
7837     /* the result is now in the accumulator */
7838     freeAsmop(cond,NULL,ic,TRUE);
7839
7840     /* if there was something to be popped then do it */
7841     if (popIc)
7842         genIpop(popIc);
7843
7844     /* if the condition is  a bit variable */
7845     if (isbit && IS_ITEMP(cond) && 
7846         SPIL_LOC(cond)) {
7847       genIfxJump(ic,SPIL_LOC(cond)->rname);
7848       DEBUGpic14_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
7849     }
7850     else {
7851       /*
7852         if (isbit && !IS_ITEMP(cond))
7853           DEBUGpic14_emitcode ("; isbit OP_SYM","%s",OP_SYMBOL(cond)->rname);
7854         else
7855           DEBUGpic14_emitcode ("; isbit","a");
7856       */
7857
7858         if (isbit && !IS_ITEMP(cond))
7859             genIfxJump(ic,OP_SYMBOL(cond)->rname);
7860         else
7861             genIfxJump(ic,"a");
7862     }
7863     ic->generated = 1;
7864 }
7865
7866 /*-----------------------------------------------------------------*/
7867 /* genAddrOf - generates code for address of                       */
7868 /*-----------------------------------------------------------------*/
7869 static void genAddrOf (iCode *ic)
7870 {
7871     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
7872     int size, offset ;
7873
7874     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7875
7876     aopOp(IC_RESULT(ic),ic,FALSE);
7877
7878     /* if the operand is on the stack then we 
7879     need to get the stack offset of this
7880     variable */
7881     if (sym->onStack) {
7882         /* if it has an offset then we need to compute
7883         it */
7884         if (sym->stack) {
7885             pic14_emitcode("mov","a,_bp");
7886             pic14_emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
7887             aopPut(AOP(IC_RESULT(ic)),"a",0);       
7888         } else {
7889             /* we can just move _bp */
7890             aopPut(AOP(IC_RESULT(ic)),"_bp",0);
7891         }
7892         /* fill the result with zero */
7893         size = AOP_SIZE(IC_RESULT(ic)) - 1;
7894         
7895         
7896         if (options.stack10bit && size < (FPTRSIZE - 1))
7897         {
7898             fprintf(stderr, 
7899                     "*** warning: pointer to stack var truncated.\n");
7900         }
7901         
7902         offset = 1;
7903         while (size--)
7904         {
7905             /* Yuck! */
7906             if (options.stack10bit && offset == 2)
7907             {
7908                 aopPut(AOP(IC_RESULT(ic)),"#0x40", offset++);
7909             }
7910             else
7911             {
7912                 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
7913             }
7914         }
7915
7916         goto release;
7917     }
7918
7919     /* object not on stack then we need the name */
7920     size = AOP_SIZE(IC_RESULT(ic));
7921     offset = 0;
7922
7923     while (size--) {
7924         char s[SDCC_NAME_MAX];
7925         if (offset) 
7926             sprintf(s,"#(%s >> %d)",
7927                     sym->rname,
7928                     offset*8);
7929         else
7930             sprintf(s,"#%s",sym->rname);
7931         aopPut(AOP(IC_RESULT(ic)),s,offset++);
7932     }
7933
7934 release:
7935     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7936
7937 }
7938
7939 #if 0
7940 /*-----------------------------------------------------------------*/
7941 /* genFarFarAssign - assignment when both are in far space         */
7942 /*-----------------------------------------------------------------*/
7943 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
7944 {
7945     int size = AOP_SIZE(right);
7946     int offset = 0;
7947     char *l ;
7948     /* first push the right side on to the stack */
7949     while (size--) {
7950         l = aopGet(AOP(right),offset++,FALSE,FALSE);
7951         MOVA(l);
7952         pic14_emitcode ("push","acc");
7953     }
7954     
7955     freeAsmop(right,NULL,ic,FALSE);
7956     /* now assign DPTR to result */
7957     aopOp(result,ic,FALSE);
7958     size = AOP_SIZE(result);
7959     while (size--) {
7960         pic14_emitcode ("pop","acc");
7961         aopPut(AOP(result),"a",--offset);
7962     }
7963     freeAsmop(result,NULL,ic,FALSE);
7964         
7965 }
7966 #endif
7967
7968 /*-----------------------------------------------------------------*/
7969 /* genAssign - generate code for assignment                        */
7970 /*-----------------------------------------------------------------*/
7971 static void genAssign (iCode *ic)
7972 {
7973     operand *result, *right;
7974     int size, offset ;
7975         unsigned long lit = 0L;
7976
7977     result = IC_RESULT(ic);
7978     right  = IC_RIGHT(ic) ;
7979
7980     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7981
7982     /* if they are the same */
7983     if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
7984         return ;
7985
7986     aopOp(right,ic,FALSE);
7987     aopOp(result,ic,TRUE);
7988
7989     /* if they are the same registers */
7990     if (pic14_sameRegs(AOP(right),AOP(result)))
7991         goto release;
7992
7993     /* if the result is a bit */
7994     if (AOP_TYPE(result) == AOP_CRY) {
7995
7996         /* if the right size is a literal then
7997         we know what the value is */
7998         if (AOP_TYPE(right) == AOP_LIT) {
7999           
8000           emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
8001                       popGet(AOP(result),0,FALSE,FALSE));
8002
8003             if (((int) operandLitValue(right))) 
8004               pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
8005                        AOP(result)->aopu.aop_dir,
8006                        AOP(result)->aopu.aop_dir);
8007             else
8008               pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
8009                  AOP(result)->aopu.aop_dir,
8010                  AOP(result)->aopu.aop_dir);
8011             goto release;
8012         }
8013
8014         /* the right is also a bit variable */
8015         if (AOP_TYPE(right) == AOP_CRY) {
8016           emitpcode(POC_BCF,    popGet(AOP(result),0,FALSE,FALSE));
8017           emitpcode(POC_BTFSC,  popGet(AOP(right),0,FALSE,FALSE));
8018           emitpcode(POC_BSF,    popGet(AOP(result),0,FALSE,FALSE));
8019
8020           pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
8021                    AOP(result)->aopu.aop_dir,
8022                    AOP(result)->aopu.aop_dir);
8023           pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
8024                    AOP(right)->aopu.aop_dir,
8025                    AOP(right)->aopu.aop_dir);
8026           pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
8027                    AOP(result)->aopu.aop_dir,
8028                    AOP(result)->aopu.aop_dir);
8029           goto release ;
8030         }
8031
8032         /* we need to or */
8033         emitpcode(POC_BCF,    popGet(AOP(result),0,FALSE,FALSE));
8034         pic14_toBoolean(right);
8035         emitSKPZ;
8036         emitpcode(POC_BSF,    popGet(AOP(result),0,FALSE,FALSE));
8037         //aopPut(AOP(result),"a",0);
8038         goto release ;
8039     }
8040
8041     /* bit variables done */
8042     /* general case */
8043     size = AOP_SIZE(result);
8044     offset = 0 ;
8045     if(AOP_TYPE(right) == AOP_LIT)
8046         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
8047     if((AOP_TYPE(result) != AOP_REG) &&
8048        (AOP_TYPE(right) == AOP_LIT) &&
8049        !IS_FLOAT(operandType(right)) &&
8050        (lit < 256L)){
8051
8052         while (size--) {
8053           if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0) {
8054             //pic14_emitcode("clrf","%s", aopGet(AOP(result),size,FALSE,FALSE));
8055               emitpcode(POC_CLRF,popGet(AOP(result),size,FALSE,FALSE));
8056             }else {
8057               emitpcode(POC_MOVLW,popGet(AOP(right),size,FALSE,FALSE));
8058               emitpcode(POC_MOVWF,popGet(AOP(result),size,FALSE,FALSE));
8059               //pic14_emitcode("movlw","%s", aopGet(AOP(right),size,FALSE,FALSE));
8060               //pic14_emitcode("movwf","%s", aopGet(AOP(result),size,FALSE,FALSE));
8061             }
8062         }
8063     } else {
8064         while (size--) {
8065           if(AOP_TYPE(right) == AOP_LIT) {
8066             emitpcode(POC_MOVLW, popGet(AOP(right),offset,FALSE,FALSE));
8067             emitpcode(POC_MOVWF, popGet(AOP(result),offset,FALSE,FALSE));
8068
8069           } else if (AOP_TYPE(right) == AOP_CRY) {
8070             emitpcode(POC_CLRF, popGet(AOP(result),offset,FALSE,FALSE));
8071             if(offset == 0) {
8072               emitpcode(POC_BTFSS, popGet(AOP(right),0,FALSE,FALSE));
8073               emitpcode(POC_INCF, popGet(AOP(result),0,FALSE,FALSE));
8074             }
8075           } else {
8076             emitpcode(POC_MOVFW, popGet(AOP(right),offset,FALSE,FALSE));
8077             emitpcode(POC_MOVWF, popGet(AOP(result),offset,FALSE,FALSE));
8078           }
8079             
8080           //pic14_emitcode("movwf","%s", aopGet(AOP(result),offset,FALSE,FALSE));
8081           offset++;
8082         }
8083     }
8084     
8085 release:
8086     freeAsmop (right,NULL,ic,FALSE);
8087     freeAsmop (result,NULL,ic,TRUE);
8088 }   
8089
8090 /*-----------------------------------------------------------------*/
8091 /* genJumpTab - genrates code for jump table                       */
8092 /*-----------------------------------------------------------------*/
8093 static void genJumpTab (iCode *ic)
8094 {
8095     symbol *jtab;
8096     char *l;
8097
8098     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8099
8100     aopOp(IC_JTCOND(ic),ic,FALSE);
8101     /* get the condition into accumulator */
8102     l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
8103     MOVA(l);
8104     /* multiply by three */
8105     pic14_emitcode("add","a,acc");
8106     pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
8107
8108     jtab = newiTempLabel(NULL);
8109     pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
8110     pic14_emitcode("jmp","@a+dptr");
8111     pic14_emitcode("","%05d_DS_:",jtab->key+100);
8112
8113     emitpcode(POC_MOVLW, popGetLabel(jtab->key));
8114     emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
8115     emitSKPNC;
8116     emitpcode(POC_INCF, popCopyReg(&pc_pclath));
8117     emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
8118     emitpLabel(jtab->key+100+labelOffset);
8119
8120     freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
8121
8122     /* now generate the jump labels */
8123     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
8124          jtab = setNextItem(IC_JTLABELS(ic))) {
8125         pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
8126         emitpcode(POC_GOTO,popGetLabel(jtab->key));
8127         
8128     }
8129
8130 }
8131
8132 /*-----------------------------------------------------------------*/
8133 /* genMixedOperation - gen code for operators between mixed types  */
8134 /*-----------------------------------------------------------------*/
8135 /*
8136   TSD - Written for the PIC port - but this unfortunately is buggy.
8137   This routine is good in that it is able to efficiently promote 
8138   types to different (larger) sizes. Unfortunately, the temporary
8139   variables that are optimized out by this routine are sometimes
8140   used in other places. So until I know how to really parse the 
8141   iCode tree, I'm going to not be using this routine :(.
8142 */
8143 static int genMixedOperation (iCode *ic)
8144 {
8145 #if 0
8146   operand *result = IC_RESULT(ic);
8147   sym_link *ctype = operandType(IC_LEFT(ic));
8148   operand *right = IC_RIGHT(ic);
8149   int ret = 0;
8150   int big,small;
8151   int offset;
8152
8153   iCode *nextic;
8154   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
8155
8156   pic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
8157
8158   nextic = ic->next;
8159   if(!nextic)
8160     return 0;
8161
8162   nextright = IC_RIGHT(nextic);
8163   nextleft  = IC_LEFT(nextic);
8164   nextresult = IC_RESULT(nextic);
8165
8166   aopOp(right,ic,FALSE);
8167   aopOp(result,ic,FALSE);
8168   aopOp(nextright,  nextic, FALSE);
8169   aopOp(nextleft,   nextic, FALSE);
8170   aopOp(nextresult, nextic, FALSE);
8171
8172   if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
8173
8174     operand *t = right;
8175     right = nextright;
8176     nextright = t; 
8177
8178     pic14_emitcode(";remove right +","");
8179
8180   } else   if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
8181 /*
8182     operand *t = right;
8183     right = nextleft;
8184     nextleft = t; 
8185 */
8186     pic14_emitcode(";remove left +","");
8187   } else
8188     return 0;
8189
8190   big = AOP_SIZE(nextleft);
8191   small = AOP_SIZE(nextright);
8192
8193   switch(nextic->op) {
8194
8195   case '+':
8196     pic14_emitcode(";optimize a +","");
8197     /* if unsigned or not an integral type */
8198     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
8199       pic14_emitcode(";add a bit to something","");
8200     } else {
8201
8202       pic14_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
8203
8204       if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
8205         pic14_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
8206         pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
8207       } else
8208         pic14_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
8209
8210       offset = 0;
8211       while(--big) {
8212
8213         offset++;
8214
8215         if(--small) {
8216           if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
8217             pic14_emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8218             pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
8219           }
8220
8221           pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8222           emitSKPNC;
8223           pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
8224                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
8225                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
8226           pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8227           pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
8228
8229         } else {
8230           pic14_emitcode("rlf","known_zero,w");
8231
8232           /*
8233             if right is signed
8234               btfsc  right,7
8235                addlw ff
8236           */
8237           if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
8238             pic14_emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8239             pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
8240           } else {
8241             pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
8242           }
8243         }
8244       }
8245       ret = 1;
8246     }
8247   }
8248   ret = 1;
8249
8250 release:
8251   freeAsmop(right,NULL,ic,TRUE);
8252   freeAsmop(result,NULL,ic,TRUE);
8253   freeAsmop(nextright,NULL,ic,TRUE);
8254   freeAsmop(nextleft,NULL,ic,TRUE);
8255   if(ret)
8256     nextic->generated = 1;
8257
8258   return ret;
8259 #else
8260   return 0;
8261 #endif
8262 }
8263 /*-----------------------------------------------------------------*/
8264 /* genCast - gen code for casting                                  */
8265 /*-----------------------------------------------------------------*/
8266 static void genCast (iCode *ic)
8267 {
8268     operand *result = IC_RESULT(ic);
8269     sym_link *ctype = operandType(IC_LEFT(ic));
8270     operand *right = IC_RIGHT(ic);
8271     int size, offset ;
8272
8273     DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
8274     /* if they are equivalent then do nothing */
8275     if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
8276         return ;
8277
8278     aopOp(right,ic,FALSE) ;
8279     aopOp(result,ic,FALSE);
8280
8281     /* if the result is a bit */
8282     if (AOP_TYPE(result) == AOP_CRY) {
8283         /* if the right size is a literal then
8284         we know what the value is */
8285         if (AOP_TYPE(right) == AOP_LIT) {
8286
8287           emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
8288                       popGet(AOP(result),0,FALSE,FALSE));
8289
8290             if (((int) operandLitValue(right))) 
8291               pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
8292                        AOP(result)->aopu.aop_dir,
8293                        AOP(result)->aopu.aop_dir);
8294             else
8295               pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
8296                        AOP(result)->aopu.aop_dir,
8297                        AOP(result)->aopu.aop_dir);
8298
8299             goto release;
8300         }
8301
8302         /* the right is also a bit variable */
8303         if (AOP_TYPE(right) == AOP_CRY) {
8304
8305           emitCLRC;
8306           emitpcode(POC_BTFSC,  popGet(AOP(right),0,FALSE,FALSE));
8307
8308           pic14_emitcode("clrc","");
8309           pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
8310                    AOP(right)->aopu.aop_dir,
8311                    AOP(right)->aopu.aop_dir);
8312             aopPut(AOP(result),"c",0);
8313             goto release ;
8314         }
8315
8316         /* we need to or */
8317         pic14_toBoolean(right);
8318         aopPut(AOP(result),"a",0);
8319         goto release ;
8320     }
8321
8322     /* if they are the same size : or less */
8323     if (AOP_SIZE(result) <= AOP_SIZE(right)) {
8324
8325         /* if they are in the same place */
8326         if (pic14_sameRegs(AOP(right),AOP(result)))
8327             goto release;
8328
8329         /* if they in different places then copy */
8330         size = AOP_SIZE(result);
8331         offset = 0 ;
8332         while (size--) {
8333             aopPut(AOP(result),
8334                    aopGet(AOP(right),offset,FALSE,FALSE),
8335                    offset);
8336             offset++;
8337         }
8338         goto release;
8339     }
8340
8341
8342     /* if the result is of type pointer */
8343     if (IS_PTR(ctype)) {
8344
8345         int p_type;
8346         sym_link *type = operandType(right);
8347         sym_link *etype = getSpec(type);
8348
8349         /* pointer to generic pointer */
8350         if (IS_GENPTR(ctype)) {
8351             char *l = zero;
8352             
8353             if (IS_PTR(type)) 
8354                 p_type = DCL_TYPE(type);
8355             else {
8356                 /* we have to go by the storage class */
8357                 p_type = PTR_TYPE(SPEC_OCLS(etype));
8358
8359 /*              if (SPEC_OCLS(etype)->codesp )  */
8360 /*                  p_type = CPOINTER ;  */
8361 /*              else */
8362 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
8363 /*                      p_type = FPOINTER ; */
8364 /*                  else */
8365 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
8366 /*                          p_type = PPOINTER; */
8367 /*                      else */
8368 /*                          if (SPEC_OCLS(etype) == idata ) */
8369 /*                              p_type = IPOINTER ; */
8370 /*                          else */
8371 /*                              p_type = POINTER ; */
8372             }
8373                 
8374             /* the first two bytes are known */
8375             size = GPTRSIZE - 1; 
8376             offset = 0 ;
8377             while (size--) {
8378                 aopPut(AOP(result),
8379                        aopGet(AOP(right),offset,FALSE,FALSE),
8380                        offset);
8381                 offset++;
8382             }
8383             /* the last byte depending on type */
8384             switch (p_type) {
8385             case IPOINTER:
8386             case POINTER:
8387                 l = zero;
8388                 break;
8389             case FPOINTER:
8390                 l = one;
8391                 break;
8392             case CPOINTER:
8393                 l = "#0x02";
8394                 break;                          
8395             case PPOINTER:
8396                 l = "#0x03";
8397                 break;
8398                 
8399             default:
8400                 /* this should never happen */
8401                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8402                        "got unknown pointer type");
8403                 exit(1);
8404             }
8405             aopPut(AOP(result),l, GPTRSIZE - 1);            
8406             goto release ;
8407         }
8408         
8409         /* just copy the pointers */
8410         size = AOP_SIZE(result);
8411         offset = 0 ;
8412         while (size--) {
8413             aopPut(AOP(result),
8414                    aopGet(AOP(right),offset,FALSE,FALSE),
8415                    offset);
8416             offset++;
8417         }
8418         goto release ;
8419     }
8420     
8421
8422     if (AOP_TYPE(right) == AOP_CRY) {
8423       int offset = 1;
8424       size = AOP_SIZE(right);
8425
8426       emitpcode(POC_CLRF,   popGet(AOP(result),0,FALSE,FALSE));
8427       emitpcode(POC_BTFSC,  popGet(AOP(right),0,FALSE,FALSE));
8428       emitpcode(POC_INCF,   popGet(AOP(result),0,FALSE,FALSE));
8429
8430       pic14_emitcode("clrf","%s ; %d", aopGet(AOP(result),0,FALSE,FALSE),__LINE__);
8431       pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
8432                AOP(right)->aopu.aop_dir,
8433                AOP(right)->aopu.aop_dir);
8434       pic14_emitcode("incf","%s,f", aopGet(AOP(result),0,FALSE,FALSE),__LINE__);
8435       while (size--) {
8436         pic14_emitcode("clrf","%s;%d", aopGet(AOP(result),offset,FALSE,FALSE),__LINE__);
8437         emitpcode(POC_CLRF,   popGet(AOP(result),offset++,FALSE,FALSE));
8438       }
8439       goto release;
8440     }
8441
8442     /* so we now know that the size of destination is greater
8443     than the size of the source.
8444     Now, if the next iCode is an operator then we might be
8445     able to optimize the operation without performing a cast.
8446     */
8447     if(genMixedOperation(ic))
8448       goto release;
8449
8450     
8451     /* we move to result for the size of source */
8452     size = AOP_SIZE(right);
8453     offset = 0 ;
8454     while (size--) {
8455       pic14_emitcode(";","%d",__LINE__);
8456         aopPut(AOP(result),
8457                aopGet(AOP(right),offset,FALSE,FALSE),
8458                offset);
8459         offset++;
8460     }
8461
8462     /* now depending on the sign of the destination */
8463     size = AOP_SIZE(result) - AOP_SIZE(right);
8464     /* if unsigned or not an integral type */
8465     if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) {
8466       while (size--) {
8467           emitpcode(POC_CLRF,   popGet(AOP(result),offset,FALSE,FALSE));
8468           pic14_emitcode("clrf","%s  ;%d",aopGet(AOP(result),offset,FALSE,FALSE),__LINE__);
8469           offset++;
8470       }
8471     } else {
8472       /* we need to extend the sign :{ */
8473       //char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,FALSE,FALSE);
8474       //MOVA(l);
8475
8476       emitpcode(POC_CLRW,    NULL);
8477       emitpcode(POC_BTFSC,   popGet(AOP(right),0,FALSE,FALSE));
8478       emitpcode(POC_MOVLW,   popGetLit(0xff));
8479
8480         pic14_emitcode("clrw","");
8481         pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
8482                  AOP(right)->aopu.aop_dir,
8483                  AOP(right)->aopu.aop_dir);
8484         pic14_emitcode("movlw","0xff");
8485         while (size--) {
8486           emitpcode(POC_MOVWF,   popGet(AOP(result),offset,FALSE,FALSE));
8487           pic14_emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
8488           offset++;
8489           // aopPut(AOP(result),"a",offset++);
8490         }
8491
8492     }
8493
8494     /* we are done hurray !!!! */
8495
8496 release:
8497     freeAsmop(right,NULL,ic,TRUE);
8498     freeAsmop(result,NULL,ic,TRUE);
8499
8500 }
8501
8502 /*-----------------------------------------------------------------*/
8503 /* genDjnz - generate decrement & jump if not zero instrucion      */
8504 /*-----------------------------------------------------------------*/
8505 static int genDjnz (iCode *ic, iCode *ifx)
8506 {
8507     symbol *lbl, *lbl1;
8508     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8509
8510     if (!ifx)
8511         return 0;
8512     
8513     /* if the if condition has a false label
8514        then we cannot save */
8515     if (IC_FALSE(ifx))
8516         return 0;
8517
8518     /* if the minus is not of the form 
8519        a = a - 1 */
8520     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
8521         !IS_OP_LITERAL(IC_RIGHT(ic)))
8522         return 0;
8523
8524     if (operandLitValue(IC_RIGHT(ic)) != 1)
8525         return 0;
8526
8527     /* if the size of this greater than one then no
8528        saving */
8529     if (getSize(operandType(IC_RESULT(ic))) > 1)
8530         return 0;
8531
8532     /* otherwise we can save BIG */
8533     lbl = newiTempLabel(NULL);
8534     lbl1= newiTempLabel(NULL);
8535
8536     aopOp(IC_RESULT(ic),ic,FALSE);
8537     
8538     if (IS_AOP_PREG(IC_RESULT(ic))) {
8539         pic14_emitcode("dec","%s",
8540                  aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
8541         pic14_emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
8542         pic14_emitcode("jnz","%05d_DS_",lbl->key+100);
8543     } else {    
8544
8545
8546       emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
8547       emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
8548
8549       pic14_emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
8550       pic14_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
8551
8552     }
8553 /*     pic14_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
8554 /*     pic14_emitcode ("","%05d_DS_:",lbl->key+100); */
8555 /*     pic14_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
8556 /*     pic14_emitcode ("","%05d_DS_:",lbl1->key+100); */
8557
8558     
8559     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8560     ifx->generated = 1;
8561     return 1;
8562 }
8563
8564 /*-----------------------------------------------------------------*/
8565 /* genReceive - generate code for a receive iCode                  */
8566 /*-----------------------------------------------------------------*/
8567 static void genReceive (iCode *ic)
8568 {    
8569     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8570
8571     if (isOperandInFarSpace(IC_RESULT(ic)) && 
8572         ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
8573           IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
8574
8575         int size = getSize(operandType(IC_RESULT(ic)));
8576         int offset =  fReturnSizePic - size;
8577         while (size--) {
8578             pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
8579                                     fReturn[fReturnSizePic - offset - 1] : "acc"));
8580             offset++;
8581         }
8582         aopOp(IC_RESULT(ic),ic,FALSE);  
8583         size = AOP_SIZE(IC_RESULT(ic));
8584         offset = 0;
8585         while (size--) {
8586             pic14_emitcode ("pop","acc");
8587             aopPut (AOP(IC_RESULT(ic)),"a",offset++);
8588         }
8589         
8590     } else {
8591         _G.accInUse++;
8592         aopOp(IC_RESULT(ic),ic,FALSE);  
8593         _G.accInUse--;
8594         assignResultValue(IC_RESULT(ic));       
8595     }
8596
8597     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8598 }
8599
8600 /*-----------------------------------------------------------------*/
8601 /* genpic14Code - generate code for pic14 based controllers        */
8602 /*-----------------------------------------------------------------*/
8603 /*
8604  * At this point, ralloc.c has gone through the iCode and attempted
8605  * to optimize in a way suitable for a PIC. Now we've got to generate
8606  * PIC instructions that correspond to the iCode.
8607  *
8608  * Once the instructions are generated, we'll pass through both the
8609  * peep hole optimizer and the pCode optimizer.
8610  *-----------------------------------------------------------------*/
8611
8612 void genpic14Code (iCode *lic)
8613 {
8614     iCode *ic;
8615     int cln = 0;
8616
8617     lineHead = lineCurr = NULL;
8618
8619     pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
8620     addpBlock(pb);
8621
8622     /* if debug information required */
8623 /*     if (options.debug && currFunc) { */
8624     if (currFunc) {
8625         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
8626         _G.debugLine = 1;
8627         if (IS_STATIC(currFunc->etype)) {
8628             pic14_emitcode("",";F%s$%s$0$0     %d",moduleName,currFunc->name,__LINE__);
8629             //addpCode2pBlock(pb,newpCodeLabel(moduleName,currFunc->name));
8630         } else {
8631             pic14_emitcode("",";G$%s$0$0   %d",currFunc->name,__LINE__);
8632             //addpCode2pBlock(pb,newpCodeLabel(NULL,currFunc->name));
8633         }
8634         _G.debugLine = 0;
8635     }
8636
8637
8638     for (ic = lic ; ic ; ic = ic->next ) {
8639
8640       DEBUGpic14_emitcode(";ic","");
8641         if ( cln != ic->lineno ) {
8642             if ( options.debug ) {
8643                 _G.debugLine = 1;
8644                 pic14_emitcode("",";C$%s$%d$%d$%d ==.",
8645                          FileBaseName(ic->filename),ic->lineno,
8646                          ic->level,ic->block);
8647                 _G.debugLine = 0;
8648             }
8649             pic14_emitcode(";","%s %d",FileBaseName(ic->filename),ic->lineno);
8650             cln = ic->lineno ;
8651         }
8652         /* if the result is marked as
8653            spilt and rematerializable or code for
8654            this has already been generated then
8655            do nothing */
8656         if (resultRemat(ic) || ic->generated ) 
8657             continue ;
8658         
8659         /* depending on the operation */
8660         switch (ic->op) {
8661         case '!' :
8662             genNot(ic);
8663             break;
8664             
8665         case '~' :
8666             genCpl(ic);
8667             break;
8668             
8669         case UNARYMINUS:
8670             genUminus (ic);
8671             break;
8672             
8673         case IPUSH:
8674             genIpush (ic);
8675             break;
8676             
8677         case IPOP:
8678             /* IPOP happens only when trying to restore a 
8679                spilt live range, if there is an ifx statement
8680                following this pop then the if statement might
8681                be using some of the registers being popped which
8682                would destory the contents of the register so
8683                we need to check for this condition and handle it */
8684             if (ic->next            && 
8685                 ic->next->op == IFX &&
8686                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
8687                 genIfx (ic->next,ic);
8688             else
8689                 genIpop (ic);
8690             break; 
8691             
8692         case CALL:
8693             genCall (ic);
8694             break;
8695             
8696         case PCALL:
8697             genPcall (ic);
8698             break;
8699             
8700         case FUNCTION:
8701             genFunction (ic);
8702             break;
8703             
8704         case ENDFUNCTION:
8705             genEndFunction (ic);
8706             break;
8707             
8708         case RETURN:
8709             genRet (ic);
8710             break;
8711             
8712         case LABEL:
8713             genLabel (ic);
8714             break;
8715             
8716         case GOTO:
8717             genGoto (ic);
8718             break;
8719             
8720         case '+' :
8721             genPlus (ic) ;
8722             break;
8723             
8724         case '-' :
8725             if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
8726                 genMinus (ic);
8727             break;
8728             
8729         case '*' :
8730             genMult (ic);
8731             break;
8732             
8733         case '/' :
8734             genDiv (ic) ;
8735             break;
8736             
8737         case '%' :
8738             genMod (ic);
8739             break;
8740             
8741         case '>' :
8742             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
8743             break;
8744             
8745         case '<' :
8746             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
8747             break;
8748             
8749         case LE_OP:
8750         case GE_OP:
8751         case NE_OP:
8752             
8753             /* note these two are xlated by algebraic equivalence
8754                during parsing SDCC.y */
8755             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8756                    "got '>=' or '<=' shouldn't have come here");
8757             break;      
8758             
8759         case EQ_OP:
8760             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
8761             break;          
8762             
8763         case AND_OP:
8764             genAndOp (ic);
8765             break;
8766             
8767         case OR_OP:
8768             genOrOp (ic);
8769             break;
8770             
8771         case '^' :
8772             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
8773             break;
8774             
8775         case '|' :
8776                 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
8777             break;
8778             
8779         case BITWISEAND:
8780             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
8781             break;
8782             
8783         case INLINEASM:
8784             genInline (ic);
8785             break;
8786             
8787         case RRC:
8788             genRRC (ic);
8789             break;
8790             
8791         case RLC:
8792             genRLC (ic);
8793             break;
8794             
8795         case GETHBIT:
8796             genGetHbit (ic);
8797             break;
8798             
8799         case LEFT_OP:
8800             genLeftShift (ic);
8801             break;
8802             
8803         case RIGHT_OP:
8804             genRightShift (ic);
8805             break;
8806             
8807         case GET_VALUE_AT_ADDRESS:
8808             genPointerGet(ic);
8809             break;
8810             
8811         case '=' :
8812             if (POINTER_SET(ic))
8813                 genPointerSet(ic);
8814             else
8815                 genAssign(ic);
8816             break;
8817             
8818         case IFX:
8819             genIfx (ic,NULL);
8820             break;
8821             
8822         case ADDRESS_OF:
8823             genAddrOf (ic);
8824             break;
8825             
8826         case JUMPTABLE:
8827             genJumpTab (ic);
8828             break;
8829             
8830         case CAST:
8831             genCast (ic);
8832             break;
8833             
8834         case RECEIVE:
8835             genReceive(ic);
8836             break;
8837             
8838         case SEND:
8839             addSet(&_G.sendSet,ic);
8840             break;
8841
8842         default :
8843             ic = ic;
8844         }
8845     }
8846     
8847
8848     /* now we are ready to call the 
8849        peep hole optimizer */
8850     if (!options.nopeep) {
8851       printf("peep hole optimizing\n");
8852         peepHole (&lineHead);
8853     }
8854     /* now do the actual printing */
8855     printLine (lineHead,codeOutFile);
8856
8857     printf("printing pBlock\n\n");
8858     printpBlock(stdout,pb);
8859
8860     return;
8861 }