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