PIC Port Added support for subtraction
[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 #if defined(_MSC_VER)
40 #define __FUNCTION__            __FILE__
41 #endif
42
43 #ifdef HAVE_SYS_ISA_DEFS_H
44 #include <sys/isa_defs.h>
45 #else
46 #ifdef HAVE_ENDIAN_H
47 #include <endian.h>
48 #else
49 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
50 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
51 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
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 //char *aopLiteral (value *val, int offset);
63 unsigned int pic14aopLiteral (value *val, int offset);
64
65 /* this is the down and dirty file with all kinds of 
66    kludgy & hacky stuff. This is what it is all about
67    CODE GENERATION for a specific MCU . some of the
68    routines may be reusable, will have to see */
69
70 static char *zero = "#0x00";
71 static char *one  = "#0x01";
72 static char *spname = "sp";
73
74 char *fReturnpic14[] = {"FSR","dph","b","a" };
75 //char *fReturn390[] = {"dpl","dph","dpx", "b","a" };
76 unsigned fReturnSizePic = 4; /* shared with ralloc.c */
77 static char **fReturn = fReturnpic14;
78
79 static char *accUse[] = {"a","b"};
80
81 //static short rbank = -1;
82
83 static struct {
84     short r0Pushed;
85     short r1Pushed;
86     short accInUse;
87     short inLine;
88     short debugLine;
89     short nRegsSaved;
90     set *sendSet;
91 } _G;
92
93 char *Safe_strdup(char *str);  // in pcode.c
94
95 extern int pic14_ptrRegReq ;
96 extern int pic14_nRegs;
97 extern FILE *codeOutFile;
98 static void saverbank (int, iCode *,bool);
99 #define RESULTONSTACK(x) \
100                          (IC_RESULT(x) && IC_RESULT(x)->aop && \
101                          IC_RESULT(x)->aop->type == AOP_STK )
102
103 #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode(";XXX mov","a,%s  %s,%d",x,__FILE__,__LINE__);
104 #define CLRC    emitcode(";XXX clr","c %s,%d",__FILE__,__LINE__);
105
106 #define BIT_NUMBER(x) (x & 7)
107 #define BIT_REGISTER(x) (x>>3)
108
109 static lineNode *lineHead = NULL;
110 static lineNode *lineCurr = NULL;
111
112 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
113 0xE0, 0xC0, 0x80, 0x00};
114 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
115 0x07, 0x03, 0x01, 0x00};
116
117 #define LSB     0
118 #define MSB16   1
119 #define MSB24   2
120 #define MSB32   3
121
122
123 #define FUNCTION_LABEL_INC  20
124 static int labelOffset=0;
125 static int debug_verbose=1;
126
127 static  pBlock *pb;
128
129 /*-----------------------------------------------------------------*/
130 /* Macros for emitting instructions                                */
131 /*-----------------------------------------------------------------*/
132
133 #define emitSKPC    emitpcode(POC_BTFSS,popCopyGPR2Bit(&pc_status,PIC_C_BIT))
134 #define emitSKPNC   emitpcode(POC_BTFSC,popCopyGPR2Bit(&pc_status,PIC_C_BIT))
135 #define emitSKPZ    emitpcode(POC_BTFSS,popCopyGPR2Bit(&pc_status,PIC_Z_BIT))
136 #define emitSKPNZ   emitpcode(POC_BTFSC,popCopyGPR2Bit(&pc_status,PIC_Z_BIT))
137 #define emitCLRZ    emitpcode(POC_BCF,  popCopyGPR2Bit(&pc_status,PIC_Z_BIT))
138 #define emitCLRC    emitpcode(POC_BCF,  popCopyGPR2Bit(&pc_status,PIC_C_BIT))
139 #define emitSETZ    emitpcode(POC_BSF,  popCopyGPR2Bit(&pc_status,PIC_Z_BIT))
140 #define emitSETC    emitpcode(POC_BSF,  popCopyGPR2Bit(&pc_status,PIC_C_BIT))
141
142 //#define emitSKPC    emitcode("btfss","status,c")
143 //#define emitSKPNC   emitcode("btfsc","status,c")
144 //#define emitSKPZ    emitcode("btfss","status,z")
145 //#define emitSKPNZ   emitcode("btfsc","status,z")
146
147 /*-----------------------------------------------------------------*/
148 /*  my_powof2(n) - If `n' is an integaer power of 2, then the      */
149 /*                 exponent of 2 is returned, otherwise -1 is      */
150 /*                 returned.                                       */
151 /* note that this is similar to the function `powof2' in SDCCsymt  */
152 /* if(n == 2^y)                                                    */
153 /*   return y;                                                     */
154 /* return -1;                                                      */
155 /*-----------------------------------------------------------------*/
156 static int my_powof2 (unsigned long num)
157 {
158   if(num) {
159     if( (num & (num-1)) == 0) {
160       int nshifts = -1;
161       while(num) {
162         num>>=1;
163         nshifts++;
164       }
165       return nshifts;
166     }
167   }
168
169   return -1;
170 }
171
172 static void emitpLabel(int key)
173 {
174   addpCode2pBlock(pb,newpCodeLabel(key));
175 }
176
177 static void emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
178 {
179
180   addpCode2pBlock(pb,newpCode(poc,pcop));
181
182 }
183 /*-----------------------------------------------------------------*/
184 /* emitcode - writes the code into a file : for now it is simple    */
185 /*-----------------------------------------------------------------*/
186 static void emitcode (char *inst,char *fmt, ...)
187 {
188     va_list ap;
189     char lb[MAX_INLINEASM];  
190     char *lbp = lb;
191
192     va_start(ap,fmt);   
193
194     if (inst && *inst) {
195         if (fmt && *fmt)
196             sprintf(lb,"%s\t",inst);
197         else
198             sprintf(lb,"%s",inst);
199         vsprintf(lb+(strlen(lb)),fmt,ap);
200     }  else
201         vsprintf(lb,fmt,ap);
202
203     while (isspace(*lbp)) lbp++;
204
205     if (lbp && *lbp) 
206         lineCurr = (lineCurr ?
207                     connectLine(lineCurr,newLineNode(lb)) :
208                     (lineHead = newLineNode(lb)));
209     lineCurr->isInline = _G.inLine;
210     lineCurr->isDebug  = _G.debugLine;
211
212     if(debug_verbose)
213       addpCode2pBlock(pb,newpCodeCharP(lb));
214
215     va_end(ap);
216 }
217
218 static void DEBUGemitcode (char *inst,char *fmt, ...)
219 {
220     va_list ap;
221     char lb[MAX_INLINEASM];  
222     char *lbp = lb;
223
224     if(!debug_verbose)
225       return;
226
227     va_start(ap,fmt);   
228
229     if (inst && *inst) {
230         if (fmt && *fmt)
231             sprintf(lb,"%s\t",inst);
232         else
233             sprintf(lb,"%s",inst);
234         vsprintf(lb+(strlen(lb)),fmt,ap);
235     }  else
236         vsprintf(lb,fmt,ap);
237
238     while (isspace(*lbp)) lbp++;
239
240     if (lbp && *lbp) 
241         lineCurr = (lineCurr ?
242                     connectLine(lineCurr,newLineNode(lb)) :
243                     (lineHead = newLineNode(lb)));
244     lineCurr->isInline = _G.inLine;
245     lineCurr->isDebug  = _G.debugLine;
246
247     addpCode2pBlock(pb,newpCodeCharP(lb));
248
249     va_end(ap);
250 }
251
252
253 /*-----------------------------------------------------------------*/
254 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
255 /*-----------------------------------------------------------------*/
256 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
257 {
258     bool r0iu = FALSE , r1iu = FALSE;
259     bool r0ou = FALSE , r1ou = FALSE;
260
261     /* the logic: if r0 & r1 used in the instruction
262     then we are in trouble otherwise */
263
264     /* first check if r0 & r1 are used by this
265     instruction, in which case we are in trouble */
266     if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
267         (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
268     {
269         goto endOfWorld;      
270     }
271
272     r0ou = bitVectBitValue(ic->rMask,R0_IDX);
273     r1ou = bitVectBitValue(ic->rMask,R1_IDX);
274
275     /* if no usage of r0 then return it */
276     if (!r0iu && !r0ou) {
277         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
278         (*aopp)->type = AOP_R0;
279         
280         return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
281     }
282
283     /* if no usage of r1 then return it */
284     if (!r1iu && !r1ou) {
285         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
286         (*aopp)->type = AOP_R1;
287
288         return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R1_IDX);
289     }    
290
291     /* now we know they both have usage */
292     /* if r0 not used in this instruction */
293     if (!r0iu) {
294         /* push it if not already pushed */
295         if (!_G.r0Pushed) {
296             emitcode ("push","%s",
297                       pic14_regWithIdx(R0_IDX)->dname);
298             _G.r0Pushed++ ;
299         }
300         
301         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
302         (*aopp)->type = AOP_R0;
303
304         return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
305     }
306
307     /* if r1 not used then */
308
309     if (!r1iu) {
310         /* push it if not already pushed */
311         if (!_G.r1Pushed) {
312             emitcode ("push","%s",
313                       pic14_regWithIdx(R1_IDX)->dname);
314             _G.r1Pushed++ ;
315         }
316         
317         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
318         (*aopp)->type = AOP_R1;
319         return pic14_regWithIdx(R1_IDX);
320     }
321
322 endOfWorld :
323     /* I said end of world but not quite end of world yet */
324     /* if this is a result then we can push it on the stack*/
325     if (result) {
326         (*aopp)->type = AOP_STK;    
327         return NULL;
328     }
329
330     piCode(ic,stdout);
331     /* other wise this is true end of the world */
332     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
333            "getFreePtr should never reach here");
334     exit(0);
335 }
336
337 /*-----------------------------------------------------------------*/
338 /* newAsmop - creates a new asmOp                                  */
339 /*-----------------------------------------------------------------*/
340 static asmop *newAsmop (short type)
341 {
342     asmop *aop;
343
344     aop = Safe_calloc(1,sizeof(asmop));
345     aop->type = type;
346     return aop;
347 }
348
349 static void genSetDPTR(int n)
350 {
351     if (!n)
352     {
353         emitcode(";", "Select standard DPTR");
354         emitcode("mov", "dps, #0x00");
355     }
356     else
357     {
358         emitcode(";", "Select alternate DPTR");
359         emitcode("mov", "dps, #0x01");
360     }
361 }
362
363 /*-----------------------------------------------------------------*/
364 /* pointerCode - returns the code for a pointer type               */
365 /*-----------------------------------------------------------------*/
366 static int pointerCode (sym_link *etype)
367 {
368
369     return PTR_TYPE(SPEC_OCLS(etype));
370
371 }
372
373 /*-----------------------------------------------------------------*/
374 /* aopForSym - for a true symbol                                   */
375 /*-----------------------------------------------------------------*/
376 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
377 {
378     asmop *aop;
379     memmap *space= SPEC_OCLS(sym->etype);
380
381     DEBUGemitcode("; ***","%s %d",__FUNCTION__,__LINE__);
382     /* if already has one */
383     if (sym->aop)
384         return sym->aop;
385
386     /* assign depending on the storage class */
387     /* if it is on the stack or indirectly addressable */
388     /* space we need to assign either r0 or r1 to it   */    
389     if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
390         sym->aop = aop = newAsmop(0);
391         aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
392         aop->size = getSize(sym->type);
393
394         /* now assign the address of the variable to 
395         the pointer register */
396         if (aop->type != AOP_STK) {
397
398             if (sym->onStack) {
399                     if ( _G.accInUse )
400                         emitcode("push","acc");
401
402                     emitcode("mov","a,_bp");
403                     emitcode("add","a,#0x%02x",
404                              ((sym->stack < 0) ?
405                               ((char)(sym->stack - _G.nRegsSaved )) :
406                               ((char)sym->stack)) & 0xff);
407                     emitcode("mov","%s,a",
408                              aop->aopu.aop_ptr->name);
409
410                     if ( _G.accInUse )
411                         emitcode("pop","acc");
412             } else
413                 emitcode("mov","%s,#%s",
414                          aop->aopu.aop_ptr->name,
415                          sym->rname);
416             aop->paged = space->paged;
417         } else
418             aop->aopu.aop_stk = sym->stack;
419         return aop;
420     }
421     
422     if (sym->onStack && options.stack10bit)
423     {
424         /* It's on the 10 bit stack, which is located in
425          * far data space.
426          */
427          
428       //DEBUGemitcode(";","%d",__LINE__);
429
430         if ( _G.accInUse )
431                 emitcode("push","acc");
432
433         emitcode("mov","a,_bp");
434         emitcode("add","a,#0x%02x",
435                  ((sym->stack < 0) ?
436                    ((char)(sym->stack - _G.nRegsSaved )) :
437                    ((char)sym->stack)) & 0xff);
438         
439         genSetDPTR(1);
440         emitcode ("mov","dpx1,#0x40");
441         emitcode ("mov","dph1,#0x00");
442         emitcode ("mov","dpl1, a");
443         genSetDPTR(0);
444         
445         if ( _G.accInUse )
446             emitcode("pop","acc");
447             
448         sym->aop = aop = newAsmop(AOP_DPTR2);
449         aop->size = getSize(sym->type); 
450         return aop;
451     }
452
453     //DEBUGemitcode(";","%d",__LINE__);
454     /* if in bit space */
455     if (IN_BITSPACE(space)) {
456         sym->aop = aop = newAsmop (AOP_CRY);
457         aop->aopu.aop_dir = sym->rname ;
458         aop->size = getSize(sym->type);
459         DEBUGemitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
460         return aop;
461     }
462     /* if it is in direct space */
463     if (IN_DIRSPACE(space)) {
464         sym->aop = aop = newAsmop (AOP_DIR);
465         aop->aopu.aop_dir = sym->rname ;
466         aop->size = getSize(sym->type);
467         DEBUGemitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
468         return aop;
469     }
470
471     /* special case for a function */
472     if (IS_FUNC(sym->type)) {   
473         sym->aop = aop = newAsmop(AOP_IMMD);    
474         //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
475         aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
476         strcpy(aop->aopu.aop_immd,sym->rname);
477         aop->size = FPTRSIZE; 
478         return aop;
479     }
480
481
482     /* only remaining is far space */
483     /* in which case DPTR gets the address */
484     sym->aop = aop = newAsmop(AOP_DPTR);
485     emitcode ("mov","dptr,#%s", sym->rname);
486     aop->size = getSize(sym->type);
487
488     DEBUGemitcode(";","%d size = %d",__LINE__,aop->size);
489     /* if it is in code space */
490     if (IN_CODESPACE(space))
491         aop->code = 1;
492
493     return aop;     
494 }
495
496 /*-----------------------------------------------------------------*/
497 /* aopForRemat - rematerialzes an object                           */
498 /*-----------------------------------------------------------------*/
499 static asmop *aopForRemat (symbol *sym)
500 {
501     iCode *ic = sym->rematiCode;
502     asmop *aop = newAsmop(AOP_IMMD);
503     int val = 0;
504     DEBUGemitcode(";","%s %d",__FUNCTION__,__LINE__);
505     for (;;) {
506         if (ic->op == '+')
507             val += operandLitValue(IC_RIGHT(ic));
508         else if (ic->op == '-')
509             val -= operandLitValue(IC_RIGHT(ic));
510         else
511             break;
512         
513         ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
514     }
515
516     if (val)
517         sprintf(buffer,"(%s %c 0x%04x)",
518                 OP_SYMBOL(IC_LEFT(ic))->rname, 
519                 val >= 0 ? '+' : '-',
520                 abs(val) & 0xffff);
521     else
522         strcpy(buffer,OP_SYMBOL(IC_LEFT(ic))->rname);
523
524     //DEBUGemitcode(";","%s",buffer);
525     aop->aopu.aop_immd = Safe_calloc(1,strlen(buffer)+1);
526     strcpy(aop->aopu.aop_immd,buffer);    
527     return aop;        
528 }
529
530 /*-----------------------------------------------------------------*/
531 /* regsInCommon - two operands have some registers in common       */
532 /*-----------------------------------------------------------------*/
533 static bool regsInCommon (operand *op1, operand *op2)
534 {
535     symbol *sym1, *sym2;
536     int i;
537
538     /* if they have registers in common */
539     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
540         return FALSE ;
541
542     sym1 = OP_SYMBOL(op1);
543     sym2 = OP_SYMBOL(op2);
544
545     if (sym1->nRegs == 0 || sym2->nRegs == 0)
546         return FALSE ;
547
548     for (i = 0 ; i < sym1->nRegs ; i++) {
549         int j;
550         if (!sym1->regs[i])
551             continue ;
552
553         for (j = 0 ; j < sym2->nRegs ;j++ ) {
554             if (!sym2->regs[j])
555                 continue ;
556
557             if (sym2->regs[j] == sym1->regs[i])
558                 return TRUE ;
559         }
560     }
561
562     return FALSE ;
563 }
564
565 /*-----------------------------------------------------------------*/
566 /* operandsEqu - equivalent                                        */
567 /*-----------------------------------------------------------------*/
568 static bool operandsEqu ( operand *op1, operand *op2)
569 {
570     symbol *sym1, *sym2;
571
572     /* if they not symbols */
573     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
574         return FALSE;
575
576     sym1 = OP_SYMBOL(op1);
577     sym2 = OP_SYMBOL(op2);
578
579     /* if both are itemps & one is spilt
580        and the other is not then false */
581     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
582         sym1->isspilt != sym2->isspilt )
583         return FALSE ;
584
585     /* if they are the same */
586     if (sym1 == sym2)
587         return TRUE ;
588
589     if (strcmp(sym1->rname,sym2->rname) == 0)
590         return TRUE;
591
592
593     /* if left is a tmp & right is not */
594     if (IS_ITEMP(op1)  && 
595         !IS_ITEMP(op2) &&
596         sym1->isspilt  &&
597         (sym1->usl.spillLoc == sym2))
598         return TRUE;
599
600     if (IS_ITEMP(op2)  && 
601         !IS_ITEMP(op1) &&
602         sym2->isspilt  &&
603         sym1->level > 0 &&
604         (sym2->usl.spillLoc == sym1))
605         return TRUE ;
606
607     return FALSE ;
608 }
609
610 /*-----------------------------------------------------------------*/
611 /* sameRegs - two asmops have the same registers                   */
612 /*-----------------------------------------------------------------*/
613 static bool sameRegs (asmop *aop1, asmop *aop2 )
614 {
615     int i;
616
617     if (aop1 == aop2)
618         return TRUE ;
619
620     if (aop1->type != AOP_REG ||
621         aop2->type != AOP_REG )
622         return FALSE ;
623
624     if (aop1->size != aop2->size )
625         return FALSE ;
626
627     for (i = 0 ; i < aop1->size ; i++ )
628         if (aop1->aopu.aop_reg[i] !=
629             aop2->aopu.aop_reg[i] )
630             return FALSE ;
631
632     return TRUE ;
633 }
634
635 /*-----------------------------------------------------------------*/
636 /* aopOp - allocates an asmop for an operand  :                    */
637 /*-----------------------------------------------------------------*/
638 static void aopOp (operand *op, iCode *ic, bool result)
639 {
640     asmop *aop;
641     symbol *sym;
642     int i;
643
644     if (!op)
645         return ;
646
647     DEBUGemitcode(";","%d",__LINE__);
648     /* if this a literal */
649     if (IS_OP_LITERAL(op)) {
650       DEBUGemitcode(";","%d",__LINE__);
651         op->aop = aop = newAsmop(AOP_LIT);
652         aop->aopu.aop_lit = op->operand.valOperand;
653         aop->size = getSize(operandType(op));
654         return;
655     }
656
657     /* if already has a asmop then continue */
658     if (op->aop)
659         return ;
660
661     /* if the underlying symbol has a aop */
662     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
663       DEBUGemitcode(";","%d",__LINE__);
664         op->aop = OP_SYMBOL(op)->aop;
665         return;
666     }
667
668     /* if this is a true symbol */
669     if (IS_TRUE_SYMOP(op)) {    
670       DEBUGemitcode(";","%d",__LINE__);
671         op->aop = aopForSym(ic,OP_SYMBOL(op),result);
672         return ;
673     }
674
675     /* this is a temporary : this has
676     only four choices :
677     a) register
678     b) spillocation
679     c) rematerialize 
680     d) conditional   
681     e) can be a return use only */
682
683     sym = OP_SYMBOL(op);
684
685
686     /* if the type is a conditional */
687     if (sym->regType == REG_CND) {
688       DEBUGemitcode(";","%d",__LINE__);
689         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
690         aop->size = 0;
691         return;
692     }
693
694     /* if it is spilt then two situations
695     a) is rematerialize 
696     b) has a spill location */
697     if (sym->isspilt || sym->nRegs == 0) {
698
699       DEBUGemitcode(";","%d",__LINE__);
700         /* rematerialize it NOW */
701         if (sym->remat) {
702             sym->aop = op->aop = aop =
703                                       aopForRemat (sym);
704             aop->size = getSize(sym->type);
705             DEBUGemitcode(";","%d",__LINE__);
706             return;
707         }
708
709         if (sym->accuse) {
710             int i;
711             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
712             aop->size = getSize(sym->type);
713             for ( i = 0 ; i < 2 ; i++ )
714                 aop->aopu.aop_str[i] = accUse[i];
715             DEBUGemitcode(";","%d",__LINE__);
716             return;  
717         }
718
719         if (sym->ruonly ) {
720             int i;
721             aop = op->aop = sym->aop = newAsmop(AOP_STR);
722             aop->size = getSize(sym->type);
723             for ( i = 0 ; i < fReturnSizePic ; i++ )
724               aop->aopu.aop_str[i] = fReturn[i];
725             DEBUGemitcode(";","%d",__LINE__);
726             return;
727         }
728
729         /* else spill location  */
730         DEBUGemitcode(";","%s %d %s",__FUNCTION__,__LINE__,sym->usl.spillLoc->rname);
731         sym->aop = op->aop = aop = 
732                                   aopForSym(ic,sym->usl.spillLoc,result);
733         aop->size = getSize(sym->type);
734         return;
735     }
736
737     /* must be in a register */
738     sym->aop = op->aop = aop = newAsmop(AOP_REG);
739     aop->size = sym->nRegs;
740     for ( i = 0 ; i < sym->nRegs ;i++)
741         aop->aopu.aop_reg[i] = sym->regs[i];
742 }
743
744 /*-----------------------------------------------------------------*/
745 /* freeAsmop - free up the asmop given to an operand               */
746 /*----------------------------------------------------------------*/
747 static void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
748 {   
749     asmop *aop ;
750
751     if (!op)
752         aop = aaop;
753     else 
754         aop = op->aop;
755
756     if (!aop)
757         return ;
758
759     if (aop->freed)
760         goto dealloc; 
761
762     aop->freed = 1;
763
764     /* depending on the asmop type only three cases need work AOP_RO
765        , AOP_R1 && AOP_STK */
766     switch (aop->type) {
767         case AOP_R0 :
768             if (_G.r0Pushed ) {
769                 if (pop) {
770                     emitcode ("pop","ar0");     
771                     _G.r0Pushed--;
772                 }
773             }
774             bitVectUnSetBit(ic->rUsed,R0_IDX);
775             break;
776
777         case AOP_R1 :
778             if (_G.r1Pushed ) {
779                 if (pop) {
780                     emitcode ("pop","ar1");
781                     _G.r1Pushed--;
782                 }
783             }
784             bitVectUnSetBit(ic->rUsed,R1_IDX);          
785             break;
786
787         case AOP_STK :
788         {
789             int sz = aop->size;    
790             int stk = aop->aopu.aop_stk + aop->size;
791             bitVectUnSetBit(ic->rUsed,R0_IDX);
792             bitVectUnSetBit(ic->rUsed,R1_IDX);          
793
794             getFreePtr(ic,&aop,FALSE);
795             
796             if (options.stack10bit)
797             {
798                 /* I'm not sure what to do here yet... */
799                 /* #STUB */
800                 fprintf(stderr, 
801                         "*** Warning: probably generating bad code for "
802                         "10 bit stack mode.\n");
803             }
804             
805             if (stk) {
806                 emitcode ("mov","a,_bp");
807                 emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
808                 emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
809             } else {
810                 emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
811             }
812
813             while (sz--) {
814                 emitcode("pop","acc");
815                 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
816                 if (!sz) break;
817                 emitcode("dec","%s",aop->aopu.aop_ptr->name);
818             }
819             op->aop = aop;
820             freeAsmop(op,NULL,ic,TRUE);
821             if (_G.r0Pushed) {
822                 emitcode("pop","ar0");
823                 _G.r0Pushed--;
824             }
825
826             if (_G.r1Pushed) {
827                 emitcode("pop","ar1");
828                 _G.r1Pushed--;
829             }       
830         }
831     }
832
833 dealloc:
834     /* all other cases just dealloc */
835     if (op ) {
836         op->aop = NULL;
837         if (IS_SYMOP(op)) {
838             OP_SYMBOL(op)->aop = NULL;    
839             /* if the symbol has a spill */
840             if (SPIL_LOC(op))
841                 SPIL_LOC(op)->aop = NULL;
842         }
843     }
844 }
845
846 /*-----------------------------------------------------------------*/
847 /* aopGet - for fetching value of the aop                          */
848 /*-----------------------------------------------------------------*/
849 static char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
850 {
851     char *s = buffer ;
852     char *rs;
853
854     //DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
855     /* offset is greater than
856     size then zero */
857     if (offset > (aop->size - 1) &&
858         aop->type != AOP_LIT)
859         return zero;
860
861     /* depending on type */
862     switch (aop->type) {
863         
864     case AOP_R0:
865     case AOP_R1:
866         DEBUGemitcode(";","%d",__LINE__);
867         /* if we need to increment it */       
868         while (offset > aop->coff) {        
869             emitcode ("inc","%s",aop->aopu.aop_ptr->name);  
870             aop->coff++;
871         }
872         
873         while (offset < aop->coff) {
874             emitcode("dec","%s",aop->aopu.aop_ptr->name);
875             aop->coff--;
876         }
877         
878         aop->coff = offset ;
879         if (aop->paged) {
880             emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
881             return (dname ? "acc" : "a");
882         }       
883         sprintf(s,"@%s",aop->aopu.aop_ptr->name);
884         rs = Safe_calloc(1,strlen(s)+1);
885         strcpy(rs,s);   
886         return rs;
887         
888     case AOP_DPTR:
889     case AOP_DPTR2:
890         DEBUGemitcode(";","%d",__LINE__);
891     if (aop->type == AOP_DPTR2)
892     {
893         genSetDPTR(1);
894     }
895     
896         while (offset > aop->coff) {
897             emitcode ("inc","dptr");
898             aop->coff++;
899         }
900         
901         while (offset < aop->coff) {        
902             emitcode("lcall","__decdptr");
903             aop->coff--;
904         }
905         
906         aop->coff = offset;
907         if (aop->code) {
908             emitcode("clr","a");
909             emitcode("movc","a,@a+dptr");
910         }
911     else {
912             emitcode("movx","a,@dptr");
913     }
914             
915     if (aop->type == AOP_DPTR2)
916     {
917         genSetDPTR(0);
918     }
919             
920     return (dname ? "acc" : "a");
921         
922         
923     case AOP_IMMD:
924       DEBUGemitcode(";","%d",__LINE__);
925         if (bit16) 
926             sprintf (s,"%s",aop->aopu.aop_immd);
927         else
928             if (offset) 
929                 sprintf(s,"(%s >> %d)",
930                         aop->aopu.aop_immd,
931                         offset*8);
932             else
933                 sprintf(s,"%s",
934                         aop->aopu.aop_immd);
935         rs = Safe_calloc(1,strlen(s)+1);
936         strcpy(rs,s);   
937         return rs;
938         
939     case AOP_DIR:
940         if (offset)
941             sprintf(s,"(%s + %d)",
942                     aop->aopu.aop_dir,
943                     offset);
944         else
945             sprintf(s,"%s",aop->aopu.aop_dir);
946         rs = Safe_calloc(1,strlen(s)+1);
947         strcpy(rs,s);   
948         return rs;
949         
950     case AOP_REG:
951       DEBUGemitcode(";","%d",__LINE__);
952         if (dname) 
953             return aop->aopu.aop_reg[offset]->dname;
954         else
955             return aop->aopu.aop_reg[offset]->name;
956         
957     case AOP_CRY:
958       emitcode(";","%d",__LINE__);
959       //emitcode("clr","a");
960       //emitcode("mov","c,%s",aop->aopu.aop_dir);
961       //emitcode("rlc","a") ;
962       //return (dname ? "acc" : "a");
963       return aop->aopu.aop_dir;
964         
965     case AOP_ACC:
966         DEBUGemitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
967         //if (!offset && dname)
968         //    return "acc";
969         //return aop->aopu.aop_str[offset];
970         return "AOP_accumulator_bug";
971
972     case AOP_LIT:
973         DEBUGemitcode(";","%d",__LINE__);
974         sprintf(s,"0x%02x", pic14aopLiteral (aop->aopu.aop_lit,offset));
975         rs = Safe_calloc(1,strlen(s)+1);
976         strcpy(rs,s);   
977         return rs;
978         
979     case AOP_STR:
980         DEBUGemitcode(";","%d",__LINE__);
981         aop->coff = offset ;
982         if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
983             dname)
984             return "acc";
985         
986         return aop->aopu.aop_str[offset];
987         
988     }
989
990     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
991            "aopget got unsupported aop->type");
992     exit(0);
993 }
994
995 /*-----------------------------------------------------------------*/
996 /* popGetLabel - create a new pCodeOp of type PO_LABEL             */
997 /*-----------------------------------------------------------------*/
998 static pCodeOp *popGetLabel(unsigned int key)
999 {
1000   return newpCodeOpLabel(key+100+labelOffset);
1001 }
1002
1003 /*-----------------------------------------------------------------*/
1004 /* popCopy - copy a pcode operator                                 */
1005 /*-----------------------------------------------------------------*/
1006 static pCodeOp *popCopy(pCodeOp *pc)
1007 {
1008   pCodeOp *pcop;
1009
1010   pcop = Safe_calloc(1,sizeof(pCodeOp) );
1011   pcop->type = pc->type;
1012   if(!(pcop->name = strdup(pc->name)))
1013     fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1014
1015   return pcop;
1016 }
1017
1018 /*-----------------------------------------------------------------*/
1019 /* popCopy - copy a pcode operator                                 */
1020 /*-----------------------------------------------------------------*/
1021 static pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval)
1022 {
1023   pCodeOp *pcop;
1024
1025   pcop = Safe_calloc(1,sizeof(pCodeOpBit) );
1026   pcop->type = PO_BIT;
1027   if(!(pcop->name = strdup(pc->name)))
1028     fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1029   ((pCodeOpBit *)pcop)->bit = bitval;
1030
1031   ((pCodeOpBit *)pcop)->inBitSpace = 0; //(pc->type == PO_BIT) ? 1 : 0;
1032
1033   return pcop;
1034 }
1035
1036 /*-----------------------------------------------------------------*/
1037 /* popGet - asm operator to pcode operator conversion              */
1038 /*-----------------------------------------------------------------*/
1039 static pCodeOp *popGetLit(unsigned int lit)
1040 {
1041
1042   return newpCodeOpLit(lit);
1043 }
1044
1045
1046 /*-----------------------------------------------------------------*/
1047 /* popGet - asm operator to pcode operator conversion              */
1048 /*-----------------------------------------------------------------*/
1049 static pCodeOp *popGetWithString(char *str)
1050 {
1051   pCodeOp *pcop;
1052
1053
1054   if(!str) {
1055     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1056     exit (1);
1057   }
1058
1059   pcop = newpCodeOp(str,PO_STR);
1060
1061   return pcop;
1062 }
1063 /*-----------------------------------------------------------------*/
1064 /* popGet - asm operator to pcode operator conversion              */
1065 /*-----------------------------------------------------------------*/
1066 static pCodeOp *popGet (asmop *aop, int offset, bool bit16, bool dname)
1067 {
1068     char *s = buffer ;
1069     char *rs;
1070
1071     pCodeOp *pcop;
1072
1073     //DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1074     /* offset is greater than
1075     size then zero */
1076
1077     if (offset > (aop->size - 1) &&
1078         aop->type != AOP_LIT)
1079       return NULL;  //zero;
1080
1081     /* depending on type */
1082     switch (aop->type) {
1083         
1084     case AOP_R0:
1085     case AOP_R1:
1086     case AOP_DPTR:
1087     case AOP_DPTR2:
1088     case AOP_ACC:
1089         DEBUGemitcode(";8051 legacy","%d",__LINE__);
1090         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1091         pcop->type = PO_SFR_REGISTER;
1092
1093         PCOR(pcop)->rIdx = -1;
1094         PCOR(pcop)->r = NULL;
1095         // Really nasty hack to check for temporary registers
1096
1097         pcop->name = Safe_strdup("BAD_REGISTER");
1098
1099         return pcop;
1100         
1101     case AOP_IMMD:
1102       DEBUGemitcode(";","%d",__LINE__);
1103         pcop = Safe_calloc(1,sizeof(pCodeOp) );
1104         pcop->type = PO_IMMEDIATE;
1105         if (bit16) 
1106             sprintf (s,"%s",aop->aopu.aop_immd);
1107         else
1108             if (offset) 
1109                 sprintf(s,"(%s >> %d)",
1110                         aop->aopu.aop_immd,
1111                         offset*8);
1112             else
1113                 sprintf(s,"%s",
1114                         aop->aopu.aop_immd);
1115         pcop->name = Safe_calloc(1,strlen(s)+1);
1116         strcpy(pcop->name,s);   
1117         return pcop;
1118         
1119     case AOP_DIR:
1120         pcop = Safe_calloc(1,sizeof(pCodeOp) );
1121         pcop->type = PO_DIR;
1122         if (offset)
1123             sprintf(s,"(%s + %d)",
1124                     aop->aopu.aop_dir,
1125                     offset);
1126         else
1127             sprintf(s,"%s",aop->aopu.aop_dir);
1128         pcop->name = Safe_calloc(1,strlen(s)+1);
1129         strcpy(pcop->name,s);   
1130         return pcop;
1131         
1132     case AOP_REG:
1133       {
1134         int len;
1135
1136         DEBUGemitcode(";","%d",__LINE__);
1137         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1138         pcop->type = PO_GPR_REGISTER;
1139         if (dname)
1140           rs = aop->aopu.aop_reg[offset]->dname;
1141         else 
1142           rs = aop->aopu.aop_reg[offset]->name;
1143
1144         PCOR(pcop)->rIdx = aop->aopu.aop_reg[offset]->rIdx;
1145         PCOR(pcop)->r = pic14_regWithIdx(aop->aopu.aop_reg[offset]->rIdx);
1146         // Really nasty hack to check for temporary registers
1147         len = strlen(rs);
1148         if(len >=3 && rs[0]=='r' && rs[1]=='0' && rs[2]=='x')
1149           pcop->type = PO_GPR_TEMP;
1150         else
1151           fprintf(stderr,"popGet - AOP_REG is not a temp: %s\n",rs);
1152
1153         DEBUGemitcode(";","%d  %s",__LINE__,rs);
1154         pcop->name = NULL;// Safe_calloc(1,(strlen(rs)+1));
1155         //strcpy(pcop->name,rs);   
1156         return pcop;
1157       }
1158
1159     case AOP_CRY:
1160       pcop = newpCodeOpBit(aop->aopu.aop_dir,0);
1161       return pcop;
1162         
1163     case AOP_LIT:
1164       DEBUGemitcode(";","%d",__LINE__);
1165       return newpCodeOpLit(pic14aopLiteral (aop->aopu.aop_lit,offset));
1166
1167     case AOP_STR:
1168       DEBUGemitcode(";","%d",__LINE__);
1169
1170       pcop = Safe_calloc(1,sizeof(pCodeOp) );
1171       pcop->type = PO_STR;
1172
1173       //aop->coff = offset ;
1174         if (strcmp(aop->aopu.aop_str[offset],"a") == 0 && dname)
1175           sprintf(s,"%s","acc");
1176         else
1177           sprintf(s,"%s",aop->aopu.aop_str[offset]);
1178         pcop->name = Safe_calloc(1,strlen(s)+1);
1179         strcpy(pcop->name,s);   
1180         return pcop;
1181         
1182     }
1183
1184     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1185            "popGet got unsupported aop->type");
1186     exit(0);
1187 }
1188 /*-----------------------------------------------------------------*/
1189 /* aopPut - puts a string for a aop                                */
1190 /*-----------------------------------------------------------------*/
1191 static void aopPut (asmop *aop, char *s, int offset)
1192 {
1193     char *d = buffer ;
1194     symbol *lbl ;
1195
1196     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1197
1198     if (aop->size && offset > ( aop->size - 1)) {
1199         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1200                "aopPut got offset > aop->size");
1201         exit(0);
1202     }
1203
1204     /* will assign value to value */
1205     /* depending on where it is ofcourse */
1206     switch (aop->type) {
1207     case AOP_DIR:
1208         if (offset)
1209             sprintf(d,"(%s + %d)",
1210                     aop->aopu.aop_dir,offset);
1211         else
1212             sprintf(d,"%s",aop->aopu.aop_dir);
1213         
1214         if (strcmp(d,s)) {
1215           DEBUGemitcode(";","%d",__LINE__);
1216           if(strcmp(s,"W"))
1217             emitcode("movf","%s,w",s);
1218           emitcode("movwf","%s",d);
1219
1220           if(strcmp(s,"W"))
1221             emitcode(";BUG! should have this:movf","%s,w   %d",s,__LINE__);
1222           emitpcode(POC_MOVWF,popGet(aop,offset,FALSE,FALSE));
1223
1224
1225         }
1226         break;
1227         
1228     case AOP_REG:
1229         if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0 &&
1230             strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1231           /*
1232             if (*s == '@'           ||
1233                 strcmp(s,"r0") == 0 ||
1234                 strcmp(s,"r1") == 0 ||
1235                 strcmp(s,"r2") == 0 ||
1236                 strcmp(s,"r3") == 0 ||
1237                 strcmp(s,"r4") == 0 ||
1238                 strcmp(s,"r5") == 0 ||
1239                 strcmp(s,"r6") == 0 || 
1240                 strcmp(s,"r7") == 0 )
1241                 emitcode("mov","%s,%s  ; %d",
1242                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1243             else
1244           */
1245
1246           if(strcmp(s,"W"))
1247             emitcode("movf","%s,w  ; %d",s,__LINE__);
1248
1249           emitcode("movwf","%s",
1250                    aop->aopu.aop_reg[offset]->name);
1251
1252           if(strcmp(s,"W"))
1253             emitcode(";BUG! should have this:movf","%s,w   %d",s,__LINE__);
1254           emitpcode(POC_MOVWF,popGet(aop,offset,FALSE,FALSE));
1255
1256         }
1257         break;
1258         
1259     case AOP_DPTR:
1260     case AOP_DPTR2:
1261     
1262     if (aop->type == AOP_DPTR2)
1263     {
1264         genSetDPTR(1);
1265     }
1266     
1267         if (aop->code) {
1268             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1269                    "aopPut writting to code space");
1270             exit(0);
1271         }
1272         
1273         while (offset > aop->coff) {
1274             aop->coff++;
1275             emitcode ("inc","dptr");
1276         }
1277         
1278         while (offset < aop->coff) {
1279             aop->coff-- ;
1280             emitcode("lcall","__decdptr");
1281         }
1282         
1283         aop->coff = offset;
1284         
1285         /* if not in accumulater */
1286         MOVA(s);        
1287         
1288         emitcode ("movx","@dptr,a");
1289         
1290     if (aop->type == AOP_DPTR2)
1291     {
1292         genSetDPTR(0);
1293     }
1294         break;
1295         
1296     case AOP_R0:
1297     case AOP_R1:
1298         while (offset > aop->coff) {
1299             aop->coff++;
1300             emitcode("inc","%s",aop->aopu.aop_ptr->name);
1301         }
1302         while (offset < aop->coff) {
1303             aop->coff-- ;
1304             emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1305         }
1306         aop->coff = offset;
1307         
1308         if (aop->paged) {
1309             MOVA(s);           
1310             emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1311             
1312         } else
1313             if (*s == '@') {
1314                 MOVA(s);
1315                 emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1316             } else
1317                 if (strcmp(s,"r0") == 0 ||
1318                     strcmp(s,"r1") == 0 ||
1319                     strcmp(s,"r2") == 0 ||
1320                     strcmp(s,"r3") == 0 ||
1321                     strcmp(s,"r4") == 0 ||
1322                     strcmp(s,"r5") == 0 ||
1323                     strcmp(s,"r6") == 0 || 
1324                     strcmp(s,"r7") == 0 ) {
1325                     char buffer[10];
1326                     sprintf(buffer,"a%s",s);
1327                     emitcode("mov","@%s,%s",
1328                              aop->aopu.aop_ptr->name,buffer);
1329                 } else
1330                     emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1331         
1332         break;
1333         
1334     case AOP_STK:
1335         if (strcmp(s,"a") == 0)
1336             emitcode("push","acc");
1337         else
1338             emitcode("push","%s",s);
1339         
1340         break;
1341         
1342     case AOP_CRY:
1343         /* if bit variable */
1344         if (!aop->aopu.aop_dir) {
1345             emitcode("clr","a");
1346             emitcode("rlc","a");
1347         } else {
1348             if (s == zero) 
1349                 emitcode("clr","%s",aop->aopu.aop_dir);
1350             else
1351                 if (s == one)
1352                     emitcode("setb","%s",aop->aopu.aop_dir);
1353                 else
1354                     if (!strcmp(s,"c"))
1355                         emitcode("mov","%s,c",aop->aopu.aop_dir);
1356                     else {
1357                         lbl = newiTempLabel(NULL);
1358                         
1359                         if (strcmp(s,"a")) {
1360                             MOVA(s);
1361                         }
1362                         emitcode("clr","c");
1363                         emitcode("jz","%05d_DS_",lbl->key+100);
1364                         emitcode("cpl","c");
1365                         emitcode("","%05d_DS_:",lbl->key+100);
1366                         emitcode("mov","%s,c",aop->aopu.aop_dir);
1367                     }
1368         }
1369         break;
1370         
1371     case AOP_STR:
1372         aop->coff = offset;
1373         if (strcmp(aop->aopu.aop_str[offset],s))
1374             emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1375         break;
1376         
1377     case AOP_ACC:
1378         aop->coff = offset;
1379         if (!offset && (strcmp(s,"acc") == 0))
1380             break;
1381         
1382         if (strcmp(aop->aopu.aop_str[offset],s))
1383             emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1384         break;
1385
1386     default :
1387         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1388                "aopPut got unsupported aop->type");
1389         exit(0);    
1390     }    
1391
1392 }
1393
1394 /*-----------------------------------------------------------------*/
1395 /* reAdjustPreg - points a register back to where it should        */
1396 /*-----------------------------------------------------------------*/
1397 static void reAdjustPreg (asmop *aop)
1398 {
1399     int size ;
1400
1401     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1402     aop->coff = 0;
1403     if ((size = aop->size) <= 1)
1404         return ;
1405     size-- ;
1406     switch (aop->type) {
1407         case AOP_R0 :
1408         case AOP_R1 :
1409             while (size--)
1410                 emitcode("dec","%s",aop->aopu.aop_ptr->name);
1411             break;          
1412         case AOP_DPTR :
1413         case AOP_DPTR2:
1414             if (aop->type == AOP_DPTR2)
1415             {
1416                 genSetDPTR(1);
1417             } 
1418             while (size--)
1419             {
1420                 emitcode("lcall","__decdptr");
1421             }
1422                 
1423             if (aop->type == AOP_DPTR2)
1424             {
1425                 genSetDPTR(0);
1426             }                
1427             break;  
1428
1429     }   
1430
1431 }
1432
1433 #define AOP(op) op->aop
1434 #define AOP_TYPE(op) AOP(op)->type
1435 #define AOP_SIZE(op) AOP(op)->size
1436 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1437                        AOP_TYPE(x) == AOP_R0))
1438
1439 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
1440                         AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1441                          AOP(x)->paged)) 
1442
1443 #define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
1444                       (x->aopu.aop_reg[0] == pic14_regWithIdx(R0_IDX) || \
1445                       x->aopu.aop_reg[0] == pic14_regWithIdx(R1_IDX) )))
1446
1447 /*-----------------------------------------------------------------*/
1448 /* genNotFloat - generates not for float operations              */
1449 /*-----------------------------------------------------------------*/
1450 static void genNotFloat (operand *op, operand *res)
1451 {
1452     int size, offset;
1453     char *l;
1454     symbol *tlbl ;
1455
1456     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1457     /* we will put 127 in the first byte of 
1458     the result */
1459     aopPut(AOP(res),"#127",0);
1460     size = AOP_SIZE(op) - 1;
1461     offset = 1;
1462
1463     l = aopGet(op->aop,offset++,FALSE,FALSE);
1464     MOVA(l);    
1465
1466     while(size--) {
1467         emitcode("orl","a,%s",
1468                  aopGet(op->aop,
1469                         offset++,FALSE,FALSE));
1470     }
1471     tlbl = newiTempLabel(NULL);
1472
1473     tlbl = newiTempLabel(NULL);
1474     aopPut(res->aop,one,1);
1475     emitcode("jz","%05d_DS_",(tlbl->key+100));
1476     aopPut(res->aop,zero,1);
1477     emitcode("","%05d_DS_:",(tlbl->key+100));
1478
1479     size = res->aop->size - 2;
1480     offset = 2;    
1481     /* put zeros in the rest */
1482     while (size--) 
1483         aopPut(res->aop,zero,offset++);
1484 }
1485
1486 #if 0
1487 /*-----------------------------------------------------------------*/
1488 /* opIsGptr: returns non-zero if the passed operand is             */   
1489 /* a generic pointer type.                                         */
1490 /*-----------------------------------------------------------------*/ 
1491 static int opIsGptr(operand *op)
1492 {
1493     sym_link *type = operandType(op);
1494     
1495     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1496     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1497     {
1498         return 1;
1499     }
1500     return 0;        
1501 }
1502 #endif
1503
1504 /*-----------------------------------------------------------------*/
1505 /* getDataSize - get the operand data size                         */
1506 /*-----------------------------------------------------------------*/
1507 static int getDataSize(operand *op)
1508 {
1509     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1510
1511
1512     return AOP_SIZE(op);
1513
1514     // tsd- in the pic port, the genptr size is 1, so this code here
1515     // fails. ( in the 8051 port, the size was 4).
1516 #if 0
1517     int size;
1518     size = AOP_SIZE(op);
1519     if (size == GPTRSIZE)
1520     {
1521         sym_link *type = operandType(op);
1522         if (IS_GENPTR(type))
1523         {
1524             /* generic pointer; arithmetic operations
1525              * should ignore the high byte (pointer type).
1526              */
1527             size--;
1528     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1529         }
1530     }
1531     return size;
1532 #endif
1533 }
1534
1535 /*-----------------------------------------------------------------*/
1536 /* outAcc - output Acc                                             */
1537 /*-----------------------------------------------------------------*/
1538 static void outAcc(operand *result)
1539 {
1540     int size, offset;
1541     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1542     size = getDataSize(result);
1543     if(size){
1544         aopPut(AOP(result),"a",0);
1545         size--;
1546         offset = 1;
1547         /* unsigned or positive */
1548         while(size--){
1549             aopPut(AOP(result),zero,offset++);
1550         }
1551     }
1552 }
1553
1554 /*-----------------------------------------------------------------*/
1555 /* outBitC - output a bit C                                        */
1556 /*-----------------------------------------------------------------*/
1557 static void outBitC(operand *result)
1558 {
1559
1560     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1561     /* if the result is bit */
1562     if (AOP_TYPE(result) == AOP_CRY) 
1563         aopPut(AOP(result),"c",0);
1564     else {
1565         emitcode("clr","a  ; %d", __LINE__);
1566         emitcode("rlc","a");
1567         outAcc(result);
1568     }
1569 }
1570
1571 /*-----------------------------------------------------------------*/
1572 /* toBoolean - emit code for orl a,operator(sizeop)                */
1573 /*-----------------------------------------------------------------*/
1574 static void toBoolean(operand *oper)
1575 {
1576     int size = AOP_SIZE(oper) - 1;
1577     int offset = 1;
1578
1579     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1580
1581     if ( AOP_TYPE(oper) != AOP_ACC) {
1582       emitpcode(POC_MOVFW,popGet(AOP(oper),0,FALSE,FALSE));
1583       emitcode("movf","%s,w",aopGet(AOP(oper),0,FALSE,FALSE));
1584     }
1585     while (size--) {
1586       emitcode("iorwf","%s,w",aopGet(AOP(oper),offset,FALSE,FALSE));
1587       emitpcode(POC_IORFW, popGet(AOP(oper),offset++,FALSE,FALSE));
1588     }
1589 }
1590
1591
1592 /*-----------------------------------------------------------------*/
1593 /* genNot - generate code for ! operation                          */
1594 /*-----------------------------------------------------------------*/
1595 static void genNot (iCode *ic)
1596 {
1597     symbol *tlbl;
1598     sym_link *optype = operandType(IC_LEFT(ic));
1599
1600     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1601     /* assign asmOps to operand & result */
1602     aopOp (IC_LEFT(ic),ic,FALSE);
1603     aopOp (IC_RESULT(ic),ic,TRUE);
1604
1605     /* if in bit space then a special case */
1606     if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1607       emitcode("movlw","1<<%s");
1608       //emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
1609       //emitcode("cpl","c"); 
1610       //outBitC(IC_RESULT(ic));
1611       goto release;
1612     }
1613
1614     /* if type float then do float */
1615     if (IS_FLOAT(optype)) {
1616         genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
1617         goto release;
1618     }
1619
1620     toBoolean(IC_LEFT(ic));
1621
1622     tlbl = newiTempLabel(NULL);
1623     emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
1624     emitcode("","%05d_DS_:",tlbl->key+100);
1625     outBitC(IC_RESULT(ic));
1626
1627 release:    
1628     /* release the aops */
1629     freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1630     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1631 }
1632
1633
1634 /*-----------------------------------------------------------------*/
1635 /* genCpl - generate code for complement                           */
1636 /*-----------------------------------------------------------------*/
1637 static void genCpl (iCode *ic)
1638 {
1639     int offset = 0;
1640     int size ;
1641
1642
1643     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1644     /* assign asmOps to operand & result */
1645     aopOp (IC_LEFT(ic),ic,FALSE);
1646     aopOp (IC_RESULT(ic),ic,TRUE);
1647
1648     /* if both are in bit space then 
1649     a special case */
1650     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1651         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
1652
1653         emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
1654         emitcode("cpl","c"); 
1655         emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
1656         goto release; 
1657     } 
1658
1659     size = AOP_SIZE(IC_RESULT(ic));
1660     while (size--) {
1661         char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1662         MOVA(l);       
1663         emitcode("cpl","a");
1664         aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1665     }
1666
1667
1668 release:
1669     /* release the aops */
1670     freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1671     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1672 }
1673
1674 /*-----------------------------------------------------------------*/
1675 /* genUminusFloat - unary minus for floating points                */
1676 /*-----------------------------------------------------------------*/
1677 static void genUminusFloat(operand *op,operand *result)
1678 {
1679     int size ,offset =0 ;
1680     char *l;
1681
1682     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1683     /* for this we just need to flip the 
1684     first it then copy the rest in place */
1685     size = AOP_SIZE(op) - 1;
1686     l = aopGet(AOP(op),3,FALSE,FALSE);
1687
1688     MOVA(l);    
1689
1690     emitcode("cpl","acc.7");
1691     aopPut(AOP(result),"a",3);    
1692
1693     while(size--) {
1694         aopPut(AOP(result),
1695                aopGet(AOP(op),offset,FALSE,FALSE),
1696                offset);
1697         offset++;
1698     }          
1699 }
1700
1701 /*-----------------------------------------------------------------*/
1702 /* genUminus - unary minus code generation                         */
1703 /*-----------------------------------------------------------------*/
1704 static void genUminus (iCode *ic)
1705 {
1706     int offset ,size ;
1707     sym_link *optype, *rtype;
1708
1709
1710     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1711     /* assign asmops */
1712     aopOp(IC_LEFT(ic),ic,FALSE);
1713     aopOp(IC_RESULT(ic),ic,TRUE);
1714
1715     /* if both in bit space then special
1716     case */
1717     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1718         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
1719
1720         emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
1721         emitcode("cpl","c"); 
1722         emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
1723         goto release; 
1724     } 
1725
1726     optype = operandType(IC_LEFT(ic));
1727     rtype = operandType(IC_RESULT(ic));
1728
1729     /* if float then do float stuff */
1730     if (IS_FLOAT(optype)) {
1731         genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1732         goto release;
1733     }
1734
1735     /* otherwise subtract from zero */
1736     size = AOP_SIZE(IC_LEFT(ic));
1737     offset = 0 ;
1738     CLRC ;
1739     while(size--) {
1740         char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1741         if (!strcmp(l,"a")) {
1742             emitcode("cpl","a");
1743             emitcode("inc","a");
1744         } else {
1745             emitcode("clr","a");
1746             emitcode("subb","a,%s",l);
1747         }       
1748         aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1749     }
1750
1751     /* if any remaining bytes in the result */
1752     /* we just need to propagate the sign   */
1753     if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1754         emitcode("rlc","a");
1755         emitcode("subb","a,acc");
1756         while (size--) 
1757             aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1758     }       
1759
1760 release:
1761     /* release the aops */
1762     freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1763     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
1764 }
1765
1766 /*-----------------------------------------------------------------*/
1767 /* saveRegisters - will look for a call and save the registers     */
1768 /*-----------------------------------------------------------------*/
1769 static void saveRegisters(iCode *lic) 
1770 {
1771     int i;
1772     iCode *ic;
1773     bitVect *rsave;
1774     sym_link *detype;
1775
1776     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1777     /* look for call */
1778     for (ic = lic ; ic ; ic = ic->next) 
1779         if (ic->op == CALL || ic->op == PCALL)
1780             break;
1781
1782     if (!ic) {
1783         fprintf(stderr,"found parameter push with no function call\n");
1784         return ;
1785     }
1786
1787     /* if the registers have been saved already then
1788     do nothing */
1789     if (ic->regsSaved || (OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1790         return ;
1791
1792     /* find the registers in use at this time 
1793     and push them away to safety */
1794     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1795                           ic->rUsed);
1796
1797     ic->regsSaved = 1;
1798     if (options.useXstack) {
1799         if (bitVectBitValue(rsave,R0_IDX))
1800             emitcode("mov","b,r0");
1801         emitcode("mov","r0,%s",spname);
1802         for (i = 0 ; i < pic14_nRegs ; i++) {
1803             if (bitVectBitValue(rsave,i)) {
1804                 if (i == R0_IDX)
1805                     emitcode("mov","a,b");
1806                 else
1807                     emitcode("mov","a,%s",pic14_regWithIdx(i)->name);
1808                 emitcode("movx","@r0,a");
1809                 emitcode("inc","r0");
1810             }
1811         }
1812         emitcode("mov","%s,r0",spname);
1813         if (bitVectBitValue(rsave,R0_IDX))
1814             emitcode("mov","r0,b");         
1815     } else
1816         for (i = 0 ; i < pic14_nRegs ; i++) {
1817             if (bitVectBitValue(rsave,i))
1818                 emitcode("push","%s",pic14_regWithIdx(i)->dname);
1819         }
1820
1821     detype = getSpec(operandType(IC_LEFT(ic)));
1822     if (detype        && 
1823         (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1824         IS_ISR(currFunc->etype) &&
1825         !ic->bankSaved) 
1826
1827         saverbank(SPEC_BANK(detype),ic,TRUE);
1828
1829 }
1830 /*-----------------------------------------------------------------*/
1831 /* unsaveRegisters - pop the pushed registers                      */
1832 /*-----------------------------------------------------------------*/
1833 static void unsaveRegisters (iCode *ic)
1834 {
1835     int i;
1836     bitVect *rsave;
1837
1838     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1839     /* find the registers in use at this time 
1840     and push them away to safety */
1841     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1842                           ic->rUsed);
1843     
1844     if (options.useXstack) {
1845         emitcode("mov","r0,%s",spname); 
1846         for (i =  pic14_nRegs ; i >= 0 ; i--) {
1847             if (bitVectBitValue(rsave,i)) {
1848                 emitcode("dec","r0");
1849                 emitcode("movx","a,@r0");
1850                 if (i == R0_IDX)
1851                     emitcode("mov","b,a");
1852                 else
1853                     emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
1854             }       
1855
1856         }
1857         emitcode("mov","%s,r0",spname);
1858         if (bitVectBitValue(rsave,R0_IDX))
1859             emitcode("mov","r0,b");
1860     } else
1861         for (i =  pic14_nRegs ; i >= 0 ; i--) {
1862             if (bitVectBitValue(rsave,i))
1863                 emitcode("pop","%s",pic14_regWithIdx(i)->dname);
1864         }
1865
1866 }  
1867
1868
1869 /*-----------------------------------------------------------------*/
1870 /* pushSide -                                                      */
1871 /*-----------------------------------------------------------------*/
1872 static void pushSide(operand * oper, int size)
1873 {
1874         int offset = 0;
1875     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1876         while (size--) {
1877                 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
1878                 if (AOP_TYPE(oper) != AOP_REG &&
1879                     AOP_TYPE(oper) != AOP_DIR &&
1880                     strcmp(l,"a") ) {
1881                         emitcode("mov","a,%s",l);
1882                         emitcode("push","acc");
1883                 } else
1884                         emitcode("push","%s",l);
1885         }
1886 }
1887
1888 /*-----------------------------------------------------------------*/
1889 /* assignResultValue -                                             */
1890 /*-----------------------------------------------------------------*/
1891 static void assignResultValue(operand * oper)
1892 {
1893         int offset = 0;
1894         int size = AOP_SIZE(oper);
1895
1896     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1897
1898     // The last byte in the assignment is in W
1899     aopPut(AOP(oper),"W",size-1);
1900
1901     if(size>1) {
1902       while (--size) {
1903         aopPut(AOP(oper),fReturn[offset],offset);
1904         offset++;
1905
1906       }
1907     }
1908 }
1909
1910
1911 /*-----------------------------------------------------------------*/
1912 /* genXpush - pushes onto the external stack                       */
1913 /*-----------------------------------------------------------------*/
1914 static void genXpush (iCode *ic)
1915 {
1916     asmop *aop = newAsmop(0);
1917     regs *r ;
1918     int size,offset = 0;
1919
1920     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1921     aopOp(IC_LEFT(ic),ic,FALSE);
1922     r = getFreePtr(ic,&aop,FALSE);
1923
1924     
1925     emitcode("mov","%s,_spx",r->name);
1926
1927     size = AOP_SIZE(IC_LEFT(ic));
1928     while(size--) {
1929
1930         char *l = aopGet(AOP(IC_LEFT(ic)),
1931                          offset++,FALSE,FALSE); 
1932         MOVA(l);            
1933         emitcode("movx","@%s,a",r->name);       
1934         emitcode("inc","%s",r->name);
1935
1936     }
1937
1938         
1939     emitcode("mov","_spx,%s",r->name);
1940
1941     freeAsmop(NULL,aop,ic,TRUE);
1942     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1943 }
1944
1945 /*-----------------------------------------------------------------*/
1946 /* genIpush - genrate code for pushing this gets a little complex  */
1947 /*-----------------------------------------------------------------*/
1948 static void genIpush (iCode *ic)
1949 {
1950     int size, offset = 0 ;
1951     char *l;
1952
1953
1954     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1955     /* if this is not a parm push : ie. it is spill push 
1956     and spill push is always done on the local stack */
1957     if (!ic->parmPush) {
1958
1959         /* and the item is spilt then do nothing */
1960         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1961             return ;
1962
1963         aopOp(IC_LEFT(ic),ic,FALSE);
1964         size = AOP_SIZE(IC_LEFT(ic));
1965         /* push it on the stack */
1966         while(size--) {
1967             l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1968             if (*l == '#') {
1969                 MOVA(l);
1970                 l = "acc";
1971             }
1972             emitcode("push","%s",l);
1973         }
1974         return ;        
1975     }
1976
1977     /* this is a paramter push: in this case we call
1978     the routine to find the call and save those
1979     registers that need to be saved */   
1980     saveRegisters(ic);
1981
1982     /* if use external stack then call the external
1983     stack pushing routine */
1984     if (options.useXstack) {
1985         genXpush(ic);
1986         return ;
1987     }
1988
1989     /* then do the push */
1990     aopOp(IC_LEFT(ic),ic,FALSE);
1991
1992
1993         // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1994     size = AOP_SIZE(IC_LEFT(ic));
1995
1996     while (size--) {
1997         l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1998         if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && 
1999             AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2000             strcmp(l,"a") ) {
2001             emitcode("mov","a,%s",l);
2002             emitcode("push","acc");
2003         } else
2004             emitcode("push","%s",l);
2005     }       
2006
2007     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2008 }
2009
2010 /*-----------------------------------------------------------------*/
2011 /* genIpop - recover the registers: can happen only for spilling   */
2012 /*-----------------------------------------------------------------*/
2013 static void genIpop (iCode *ic)
2014 {
2015     int size,offset ;
2016
2017
2018     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2019     /* if the temp was not pushed then */
2020     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2021         return ;
2022
2023     aopOp(IC_LEFT(ic),ic,FALSE);
2024     size = AOP_SIZE(IC_LEFT(ic));
2025     offset = (size-1);
2026     while (size--) 
2027         emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
2028                                    FALSE,TRUE));
2029
2030     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2031 }
2032
2033 /*-----------------------------------------------------------------*/
2034 /* unsaverbank - restores the resgister bank from stack            */
2035 /*-----------------------------------------------------------------*/
2036 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2037 {
2038     int i;
2039     asmop *aop ;
2040     regs *r = NULL;
2041
2042     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2043     if (popPsw) {
2044         if (options.useXstack) {
2045             aop = newAsmop(0);
2046             r = getFreePtr(ic,&aop,FALSE);
2047             
2048             
2049             emitcode("mov","%s,_spx",r->name);
2050             emitcode("movx","a,@%s",r->name);
2051             emitcode("mov","psw,a");
2052             emitcode("dec","%s",r->name);
2053             
2054         }else
2055             emitcode ("pop","psw");
2056     }
2057
2058     for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
2059         if (options.useXstack) {       
2060             emitcode("movx","a,@%s",r->name);
2061             //emitcode("mov","(%s+%d),a",
2062             //       regspic14[i].base,8*bank+regspic14[i].offset);
2063             emitcode("dec","%s",r->name);
2064
2065         } else 
2066           emitcode("pop",""); //"(%s+%d)",
2067         //regspic14[i].base,8*bank); //+regspic14[i].offset);
2068     }
2069
2070     if (options.useXstack) {
2071
2072         emitcode("mov","_spx,%s",r->name);
2073         freeAsmop(NULL,aop,ic,TRUE);
2074
2075     } 
2076 }
2077
2078 /*-----------------------------------------------------------------*/
2079 /* saverbank - saves an entire register bank on the stack          */
2080 /*-----------------------------------------------------------------*/
2081 static void saverbank (int bank, iCode *ic, bool pushPsw)
2082 {
2083     int i;
2084     asmop *aop ;
2085     regs *r = NULL;
2086
2087     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2088     if (options.useXstack) {
2089
2090         aop = newAsmop(0);
2091         r = getFreePtr(ic,&aop,FALSE);  
2092         emitcode("mov","%s,_spx",r->name);
2093
2094     }
2095
2096     for (i = 0 ; i < pic14_nRegs ;i++) {
2097         if (options.useXstack) {
2098             emitcode("inc","%s",r->name);
2099             //emitcode("mov","a,(%s+%d)",
2100             //         regspic14[i].base,8*bank+regspic14[i].offset);
2101             emitcode("movx","@%s,a",r->name);           
2102         } else 
2103           emitcode("push","");// "(%s+%d)",
2104                      //regspic14[i].base,8*bank+regspic14[i].offset);
2105     }
2106     
2107     if (pushPsw) {
2108         if (options.useXstack) {
2109             emitcode("mov","a,psw");
2110             emitcode("movx","@%s,a",r->name);   
2111             emitcode("inc","%s",r->name);
2112             emitcode("mov","_spx,%s",r->name);       
2113             freeAsmop (NULL,aop,ic,TRUE);
2114             
2115         } else
2116             emitcode("push","psw");
2117         
2118         emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2119     }
2120     ic->bankSaved = 1;
2121
2122 }
2123
2124 /*-----------------------------------------------------------------*/
2125 /* genCall - generates a call statement                            */
2126 /*-----------------------------------------------------------------*/
2127 static void genCall (iCode *ic)
2128 {
2129     sym_link *detype;   
2130
2131     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2132
2133     /* if caller saves & we have not saved then */
2134     if (!ic->regsSaved)
2135         saveRegisters(ic);
2136
2137     /* if we are calling a function that is not using
2138     the same register bank then we need to save the
2139     destination registers on the stack */
2140     detype = getSpec(operandType(IC_LEFT(ic)));
2141     if (detype        && 
2142         (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
2143         IS_ISR(currFunc->etype) &&
2144         !ic->bankSaved) 
2145
2146         saverbank(SPEC_BANK(detype),ic,TRUE);
2147
2148     /* if send set is not empty the assign */
2149     if (_G.sendSet) {
2150         iCode *sic ;
2151
2152         for (sic = setFirstItem(_G.sendSet) ; sic ; 
2153              sic = setNextItem(_G.sendSet)) {
2154             int size, offset = 0;
2155
2156             aopOp(IC_LEFT(sic),sic,FALSE);
2157             size = AOP_SIZE(IC_LEFT(sic));
2158             while (size--) {
2159                 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
2160                                 FALSE,FALSE);
2161                 DEBUGemitcode(";","%d - left type %d",__LINE__,AOP(IC_LEFT(sic))->type);
2162
2163                 if (strcmp(l,fReturn[offset])) {
2164
2165                   if ( ((AOP(IC_LEFT(sic))->type) == AOP_IMMD) ||
2166                        ((AOP(IC_LEFT(sic))->type) == AOP_LIT) )
2167                     emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(sic)),size,FALSE,FALSE));
2168                   //emitcode("movlw","%s",l);
2169                   else
2170                     emitpcode(POC_MOVFW,popGet(AOP(IC_LEFT(sic)),size,FALSE,FALSE));
2171                   //emitcode("movf","%s,w",l);
2172
2173                   // The last one is passed in W
2174                   if(size)
2175                     emitcode("movwf","%s",fReturn[offset]);
2176                 }
2177                 offset++;
2178             }
2179             freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2180         }
2181         _G.sendSet = NULL;
2182     }
2183     /* make the call */
2184     emitpcode(POC_CALL,popGetWithString(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2185                                         OP_SYMBOL(IC_LEFT(ic))->rname :
2186                                         OP_SYMBOL(IC_LEFT(ic))->name));
2187
2188     emitcode("call","%s",(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2189                            OP_SYMBOL(IC_LEFT(ic))->rname :
2190                            OP_SYMBOL(IC_LEFT(ic))->name));
2191
2192     /* if we need assign a result value */
2193     if ((IS_ITEMP(IC_RESULT(ic)) && 
2194          (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2195           OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2196         IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2197
2198         _G.accInUse++;
2199         aopOp(IC_RESULT(ic),ic,FALSE);
2200         _G.accInUse--;
2201
2202         assignResultValue(IC_RESULT(ic));
2203                 
2204         freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2205     }
2206
2207     /* adjust the stack for parameters if 
2208     required */
2209     if (ic->parmBytes) {
2210         int i;
2211         if (ic->parmBytes > 3) {
2212             emitcode("mov","a,%s",spname);
2213             emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2214             emitcode("mov","%s,a",spname);
2215         } else 
2216             for ( i = 0 ; i <  ic->parmBytes ;i++)
2217                 emitcode("dec","%s",spname);
2218
2219     }
2220
2221     /* if register bank was saved then pop them */
2222     if (ic->bankSaved)
2223         unsaverbank(SPEC_BANK(detype),ic,TRUE);
2224
2225     /* if we hade saved some registers then unsave them */
2226     if (ic->regsSaved && !(OP_SYMBOL(IC_LEFT(ic))->calleeSave))
2227         unsaveRegisters (ic);
2228
2229
2230 }
2231
2232 /*-----------------------------------------------------------------*/
2233 /* genPcall - generates a call by pointer statement                */
2234 /*-----------------------------------------------------------------*/
2235 static void genPcall (iCode *ic)
2236 {
2237     sym_link *detype;
2238     symbol *rlbl = newiTempLabel(NULL);
2239
2240
2241     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2242     /* if caller saves & we have not saved then */
2243     if (!ic->regsSaved)
2244         saveRegisters(ic);
2245
2246     /* if we are calling a function that is not using
2247     the same register bank then we need to save the
2248     destination registers on the stack */
2249     detype = getSpec(operandType(IC_LEFT(ic)));
2250     if (detype        && 
2251         IS_ISR(currFunc->etype) &&
2252         (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)))
2253         saverbank(SPEC_BANK(detype),ic,TRUE);
2254
2255
2256     /* push the return address on to the stack */
2257     emitcode("mov","a,#%05d_DS_",(rlbl->key+100));
2258     emitcode("push","acc");    
2259     emitcode("mov","a,#(%05d_DS_ >> 8)",(rlbl->key+100));
2260     emitcode("push","acc");
2261     
2262     if (options.model == MODEL_FLAT24)
2263     {
2264         emitcode("mov","a,#(%05d_DS_ >> 16)",(rlbl->key+100));
2265         emitcode("push","acc");    
2266     }
2267
2268     /* now push the calling address */
2269     aopOp(IC_LEFT(ic),ic,FALSE);
2270
2271     pushSide(IC_LEFT(ic), FPTRSIZE);
2272
2273     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
2274
2275     /* if send set is not empty the assign */
2276     if (_G.sendSet) {
2277         iCode *sic ;
2278
2279         for (sic = setFirstItem(_G.sendSet) ; sic ; 
2280              sic = setNextItem(_G.sendSet)) {
2281             int size, offset = 0;
2282             aopOp(IC_LEFT(sic),sic,FALSE);
2283             size = AOP_SIZE(IC_LEFT(sic));
2284             while (size--) {
2285                 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
2286                                 FALSE,FALSE);
2287                 if (strcmp(l,fReturn[offset]))
2288                     emitcode("mov","%s,%s",
2289                              fReturn[offset],
2290                              l);
2291                 offset++;
2292             }
2293             freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2294         }
2295         _G.sendSet = NULL;
2296     }
2297
2298     emitcode("ret","");
2299     emitcode("","%05d_DS_:",(rlbl->key+100));
2300
2301
2302     /* if we need assign a result value */
2303     if ((IS_ITEMP(IC_RESULT(ic)) &&
2304          (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2305           OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2306         IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2307
2308         _G.accInUse++;
2309         aopOp(IC_RESULT(ic),ic,FALSE);
2310         _G.accInUse--;
2311         
2312         assignResultValue(IC_RESULT(ic));
2313
2314         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2315     }
2316
2317     /* adjust the stack for parameters if 
2318     required */
2319     if (ic->parmBytes) {
2320         int i;
2321         if (ic->parmBytes > 3) {
2322             emitcode("mov","a,%s",spname);
2323             emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2324             emitcode("mov","%s,a",spname);
2325         } else 
2326             for ( i = 0 ; i <  ic->parmBytes ;i++)
2327                 emitcode("dec","%s",spname);
2328
2329     }
2330
2331     /* if register bank was saved then unsave them */
2332     if (detype        && 
2333         (SPEC_BANK(currFunc->etype) != 
2334          SPEC_BANK(detype)))
2335         unsaverbank(SPEC_BANK(detype),ic,TRUE);
2336
2337     /* if we hade saved some registers then
2338     unsave them */
2339     if (ic->regsSaved)
2340         unsaveRegisters (ic);
2341
2342 }
2343
2344 /*-----------------------------------------------------------------*/
2345 /* resultRemat - result  is rematerializable                       */
2346 /*-----------------------------------------------------------------*/
2347 static int resultRemat (iCode *ic)
2348 {
2349     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2350     if (SKIP_IC(ic) || ic->op == IFX)
2351         return 0;
2352
2353     if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2354         symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2355         if (sym->remat && !POINTER_SET(ic)) 
2356             return 1;
2357     }
2358
2359     return 0;
2360 }
2361
2362 #if defined(__BORLANDC__) || defined(_MSC_VER)
2363 #define STRCASECMP stricmp
2364 #else
2365 #define STRCASECMP strcasecmp
2366 #endif
2367
2368 /*-----------------------------------------------------------------*/
2369 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2370 /*-----------------------------------------------------------------*/
2371 static bool inExcludeList(char *s)
2372 {
2373     int i =0;
2374     
2375     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2376     if (options.excludeRegs[i] &&
2377     STRCASECMP(options.excludeRegs[i],"none") == 0)
2378         return FALSE ;
2379
2380     for ( i = 0 ; options.excludeRegs[i]; i++) {
2381         if (options.excludeRegs[i] &&
2382         STRCASECMP(s,options.excludeRegs[i]) == 0)
2383             return TRUE;
2384     }
2385     return FALSE ;
2386 }
2387
2388 /*-----------------------------------------------------------------*/
2389 /* genFunction - generated code for function entry                 */
2390 /*-----------------------------------------------------------------*/
2391 static void genFunction (iCode *ic)
2392 {
2393     symbol *sym;
2394     sym_link *fetype;
2395
2396     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2397     labelOffset += FUNCTION_LABEL_INC;
2398
2399     _G.nRegsSaved = 0;
2400     /* create the function header */
2401     emitcode(";","-----------------------------------------");
2402     emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2403     emitcode(";","-----------------------------------------");
2404
2405     emitcode("","%s:",sym->rname);
2406     addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname));
2407
2408     fetype = getSpec(operandType(IC_LEFT(ic)));
2409
2410     /* if critical function then turn interrupts off */
2411     if (SPEC_CRTCL(fetype))
2412         emitcode("clr","ea");
2413
2414     /* here we need to generate the equates for the
2415        register bank if required */
2416 #if 0
2417     if (SPEC_BANK(fetype) != rbank) {
2418         int i ;
2419
2420         rbank = SPEC_BANK(fetype);
2421         for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2422             if (strcmp(regspic14[i].base,"0") == 0)
2423                 emitcode("","%s = 0x%02x",
2424                          regspic14[i].dname,
2425                          8*rbank+regspic14[i].offset);
2426             else
2427                 emitcode ("","%s = %s + 0x%02x",
2428                           regspic14[i].dname,
2429                           regspic14[i].base,
2430                           8*rbank+regspic14[i].offset);
2431         }
2432     }
2433 #endif
2434
2435     /* if this is an interrupt service routine then
2436     save acc, b, dpl, dph  */
2437     if (IS_ISR(sym->etype)) {
2438         
2439         if (!inExcludeList("acc"))          
2440             emitcode ("push","acc");    
2441         if (!inExcludeList("b"))
2442             emitcode ("push","b");
2443         if (!inExcludeList("dpl"))
2444             emitcode ("push","dpl");
2445         if (!inExcludeList("dph"))
2446             emitcode ("push","dph");
2447         if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2448         {
2449             emitcode ("push", "dpx");
2450             /* Make sure we're using standard DPTR */
2451             emitcode ("push", "dps");
2452             emitcode ("mov", "dps, #0x00");
2453             if (options.stack10bit)
2454             {   
2455                 /* This ISR could conceivably use DPTR2. Better save it. */
2456                 emitcode ("push", "dpl1");
2457                 emitcode ("push", "dph1");
2458                 emitcode ("push", "dpx1");
2459             }
2460         }
2461         /* if this isr has no bank i.e. is going to
2462            run with bank 0 , then we need to save more
2463            registers :-) */
2464         if (!SPEC_BANK(sym->etype)) {
2465
2466             /* if this function does not call any other
2467                function then we can be economical and
2468                save only those registers that are used */
2469             if (! sym->hasFcall) {
2470                 int i;
2471
2472                 /* if any registers used */
2473                 if (sym->regsUsed) {
2474                     /* save the registers used */
2475                     for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2476                         if (bitVectBitValue(sym->regsUsed,i) ||
2477                           (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2478                             emitcode("push","%s",pic14_regWithIdx(i)->dname);                       
2479                     }
2480                 }
2481                 
2482             } else {
2483                 /* this function has  a function call cannot
2484                    determines register usage so we will have the
2485                    entire bank */
2486                 saverbank(0,ic,FALSE);
2487             }       
2488         }
2489     } else {
2490         /* if callee-save to be used for this function
2491            then save the registers being used in this function */
2492         if (sym->calleeSave) {
2493             int i;
2494             
2495             /* if any registers used */
2496             if (sym->regsUsed) {
2497                 /* save the registers used */
2498                 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2499                     if (bitVectBitValue(sym->regsUsed,i) ||
2500                       (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2501                         emitcode("push","%s",pic14_regWithIdx(i)->dname);
2502                         _G.nRegsSaved++;
2503                     }
2504                 }
2505             }
2506         }
2507     }
2508
2509     /* set the register bank to the desired value */
2510     if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype)) {
2511         emitcode("push","psw");
2512         emitcode("mov","psw,#0x%02x",(SPEC_BANK(sym->etype) << 3)&0x00ff);   
2513     }
2514
2515     if (IS_RENT(sym->etype) || options.stackAuto) {
2516
2517         if (options.useXstack) {
2518             emitcode("mov","r0,%s",spname);
2519             emitcode("mov","a,_bp");
2520             emitcode("movx","@r0,a");
2521             emitcode("inc","%s",spname);
2522         }
2523         else
2524         {
2525             /* set up the stack */
2526             emitcode ("push","_bp");     /* save the callers stack  */
2527         }
2528         emitcode ("mov","_bp,%s",spname);
2529     }
2530
2531     /* adjust the stack for the function */
2532     if (sym->stack) {
2533
2534         int i = sym->stack;
2535         if (i > 256 ) 
2536             werror(W_STACK_OVERFLOW,sym->name);
2537
2538         if (i > 3 && sym->recvSize < 4) {              
2539
2540             emitcode ("mov","a,sp");
2541             emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2542             emitcode ("mov","sp,a");
2543            
2544         }
2545         else
2546             while(i--)
2547                 emitcode("inc","sp");
2548     }
2549
2550      if (sym->xstack) {
2551
2552         emitcode ("mov","a,_spx");
2553         emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2554         emitcode ("mov","_spx,a");
2555     }    
2556
2557 }
2558
2559 /*-----------------------------------------------------------------*/
2560 /* genEndFunction - generates epilogue for functions               */
2561 /*-----------------------------------------------------------------*/
2562 static void genEndFunction (iCode *ic)
2563 {
2564     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2565
2566     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2567
2568     if (IS_RENT(sym->etype) || options.stackAuto)
2569     {
2570         emitcode ("mov","%s,_bp",spname);
2571     }
2572
2573     /* if use external stack but some variables were
2574     added to the local stack then decrement the
2575     local stack */
2576     if (options.useXstack && sym->stack) {      
2577         emitcode("mov","a,sp");
2578         emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2579         emitcode("mov","sp,a");
2580     }
2581
2582
2583     if ((IS_RENT(sym->etype) || options.stackAuto)) {
2584         if (options.useXstack) {
2585             emitcode("mov","r0,%s",spname);
2586             emitcode("movx","a,@r0");
2587             emitcode("mov","_bp,a");
2588             emitcode("dec","%s",spname);
2589         }
2590         else
2591         {
2592             emitcode ("pop","_bp");
2593         }
2594     }
2595
2596     /* restore the register bank  */    
2597     if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype))
2598         emitcode ("pop","psw");
2599
2600     if (IS_ISR(sym->etype)) {
2601
2602         /* now we need to restore the registers */
2603         /* if this isr has no bank i.e. is going to
2604            run with bank 0 , then we need to save more
2605            registers :-) */
2606         if (!SPEC_BANK(sym->etype)) {
2607             
2608             /* if this function does not call any other
2609                function then we can be economical and
2610                save only those registers that are used */
2611             if (! sym->hasFcall) {
2612                 int i;
2613                 
2614                 /* if any registers used */
2615                 if (sym->regsUsed) {
2616                     /* save the registers used */
2617                     for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2618                         if (bitVectBitValue(sym->regsUsed,i) ||
2619                           (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2620                             emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2621                     }
2622                 }
2623                 
2624             } else {
2625                 /* this function has  a function call cannot
2626                    determines register usage so we will have the
2627                    entire bank */
2628                 unsaverbank(0,ic,FALSE);
2629             }       
2630         }
2631
2632         if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2633         {
2634             if (options.stack10bit)
2635             {
2636                 emitcode ("pop", "dpx1");
2637                 emitcode ("pop", "dph1");
2638                 emitcode ("pop", "dpl1");
2639             }   
2640             emitcode ("pop", "dps");
2641             emitcode ("pop", "dpx");
2642         }
2643         if (!inExcludeList("dph"))
2644             emitcode ("pop","dph");
2645         if (!inExcludeList("dpl"))
2646             emitcode ("pop","dpl");
2647         if (!inExcludeList("b"))
2648             emitcode ("pop","b");
2649         if (!inExcludeList("acc"))
2650             emitcode ("pop","acc");
2651
2652         if (SPEC_CRTCL(sym->etype))
2653             emitcode("setb","ea");
2654
2655         /* if debug then send end of function */
2656 /*      if (options.debug && currFunc) { */
2657         if (currFunc) {
2658             _G.debugLine = 1;
2659             emitcode(";","C$%s$%d$%d$%d ==.",
2660                      FileBaseName(ic->filename),currFunc->lastLine,
2661                      ic->level,ic->block); 
2662             if (IS_STATIC(currFunc->etype))         
2663                 emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
2664             else
2665                 emitcode(";","XG$%s$0$0 ==.",currFunc->name);
2666             _G.debugLine = 0;
2667         }
2668         
2669         emitcode ("reti","");
2670     }
2671     else {
2672         if (SPEC_CRTCL(sym->etype))
2673             emitcode("setb","ea");
2674         
2675         if (sym->calleeSave) {
2676             int i;
2677             
2678             /* if any registers used */
2679             if (sym->regsUsed) {
2680                 /* save the registers used */
2681                 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2682                     if (bitVectBitValue(sym->regsUsed,i) ||
2683                       (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2684                         emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2685                 }
2686             }
2687             
2688         }
2689
2690         /* if debug then send end of function */
2691         if (currFunc) {
2692             _G.debugLine = 1;
2693             emitcode(";","C$%s$%d$%d$%d ==.",
2694                      FileBaseName(ic->filename),currFunc->lastLine,
2695                      ic->level,ic->block); 
2696             if (IS_STATIC(currFunc->etype))         
2697                 emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
2698             else
2699                 emitcode(";","XG$%s$0$0 ==.",currFunc->name);
2700             _G.debugLine = 0;
2701         }
2702
2703         emitcode ("return","");
2704         emitpcode(POC_RETURN,NULL);
2705
2706         /* Mark the end of a function */
2707         addpCode2pBlock(pb,newpCodeFunction(NULL,NULL));
2708     }
2709
2710 }
2711
2712 /*-----------------------------------------------------------------*/
2713 /* genRet - generate code for return statement                     */
2714 /*-----------------------------------------------------------------*/
2715 static void genRet (iCode *ic)
2716 {
2717     int size,offset = 0 , pushed = 0;
2718     
2719     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2720     /* if we have no return value then
2721        just generate the "ret" */
2722     if (!IC_LEFT(ic)) 
2723         goto jumpret;       
2724     
2725     /* we have something to return then
2726        move the return value into place */
2727     aopOp(IC_LEFT(ic),ic,FALSE);
2728     size = AOP_SIZE(IC_LEFT(ic));
2729     
2730     while (size--) {
2731             char *l ;
2732             if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
2733                     /* #NOCHANGE */
2734                     l = aopGet(AOP(IC_LEFT(ic)),offset++,
2735                            FALSE,TRUE);
2736                     emitcode("push","%s",l);
2737                     pushed++;
2738             } else {
2739                     l = aopGet(AOP(IC_LEFT(ic)),offset,
2740                                FALSE,FALSE);
2741                     if (strcmp(fReturn[offset],l)) {
2742                       if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD) ||
2743                           ((AOP(IC_LEFT(ic))->type) == AOP_LIT) )
2744                         emitcode("movlw","%s",l);
2745                       else
2746                         emitcode("movf","%s,w",l);
2747                       if(size)
2748                         emitcode("movwf","%s",fReturn[offset]);
2749                       offset++;
2750                     }
2751             }
2752     }    
2753
2754     if (pushed) {
2755         while(pushed) {
2756             pushed--;
2757             if (strcmp(fReturn[pushed],"a"))
2758                 emitcode("pop",fReturn[pushed]);
2759             else
2760                 emitcode("pop","acc");
2761         }
2762     }
2763     freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2764     
2765  jumpret:
2766         /* generate a jump to the return label
2767            if the next is not the return statement */
2768     if (!(ic->next && ic->next->op == LABEL &&
2769           IC_LABEL(ic->next) == returnLabel))
2770         
2771         emitcode("goto","_%05d_DS_",returnLabel->key+100 + labelOffset);
2772     
2773 }
2774
2775 /*-----------------------------------------------------------------*/
2776 /* genLabel - generates a label                                    */
2777 /*-----------------------------------------------------------------*/
2778 static void genLabel (iCode *ic)
2779 {
2780     /* special case never generate */
2781     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2782     if (IC_LABEL(ic) == entryLabel)
2783         return ;
2784
2785     emitpLabel(IC_LABEL(ic)->key+100 + labelOffset);
2786     emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
2787 }
2788
2789 /*-----------------------------------------------------------------*/
2790 /* genGoto - generates a goto                                      */
2791 /*-----------------------------------------------------------------*/
2792 //tsd
2793 static void genGoto (iCode *ic)
2794 {
2795     emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
2796 }
2797
2798 /*-----------------------------------------------------------------*/
2799 /* findLabelBackwards: walks back through the iCode chain looking  */
2800 /* for the given label. Returns number of iCode instructions       */
2801 /* between that label and given ic.                                */
2802 /* Returns zero if label not found.                                */
2803 /*-----------------------------------------------------------------*/
2804 #if 0
2805 static int findLabelBackwards(iCode *ic, int key)
2806 {
2807     int count = 0;
2808     
2809     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2810     while (ic->prev)
2811     {
2812         ic = ic->prev;
2813         count++;
2814         
2815         if (ic->op == LABEL && IC_LABEL(ic)->key == key)
2816         {
2817             /* printf("findLabelBackwards = %d\n", count); */
2818             return count;
2819         }
2820     }
2821     
2822     return 0;
2823 }
2824 #endif
2825 /*-----------------------------------------------------------------*/
2826 /* genPlusIncr :- does addition with increment if possible         */
2827 /*-----------------------------------------------------------------*/
2828 static bool genPlusIncr (iCode *ic)
2829 {
2830     unsigned int icount ;
2831     unsigned int size = getDataSize(IC_RESULT(ic));
2832
2833     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2834     DEBUGemitcode ("; ","result %d, left %d, right %d",
2835                    AOP_TYPE(IC_RESULT(ic)),
2836                    AOP_TYPE(IC_LEFT(ic)),
2837                    AOP_TYPE(IC_RIGHT(ic)));
2838
2839     /* will try to generate an increment */
2840     /* if the right side is not a literal 
2841        we cannot */
2842     if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2843         return FALSE ;
2844     
2845     DEBUGemitcode ("; ","%s  %d",__FUNCTION__,__LINE__);
2846     /* if the literal value of the right hand side
2847        is greater than 1 then it is faster to add */
2848     if ((icount =  floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
2849         return FALSE ;
2850     
2851     /* if increment 16 bits in register */
2852     if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2853         (icount == 1)) {
2854
2855       int offset = MSB16;
2856
2857       emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2858       //emitcode("incf","%s,f",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2859
2860       while(--size) {
2861         emitSKPNZ;
2862         emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),offset++,FALSE,FALSE));
2863         //emitcode(" incf","%s,f",aopGet(AOP(IC_RESULT(ic)),offset++,FALSE,FALSE));
2864       }
2865
2866       return TRUE;
2867     }
2868     
2869     DEBUGemitcode ("; ","%s  %d",__FUNCTION__,__LINE__);
2870     /* if left is in accumulator  - probably a bit operation*/
2871     if( strcmp(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE),"a")  &&
2872         (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) ) {
2873       
2874       emitpcode(POC_BCF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2875       emitcode("bcf","(%s >> 3), (%s & 7)",
2876                AOP(IC_RESULT(ic))->aopu.aop_dir,
2877                AOP(IC_RESULT(ic))->aopu.aop_dir);
2878       if(icount)
2879         emitpcode(POC_XORLW,popGetLit(1));
2880       //emitcode("xorlw","1");
2881       else
2882         emitpcode(POC_ANDLW,popGetLit(1));
2883       //emitcode("andlw","1");
2884
2885       emitSKPZ;
2886       emitpcode(POC_BSF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2887       emitcode("bsf","(%s >> 3), (%s & 7)",
2888                AOP(IC_RESULT(ic))->aopu.aop_dir,
2889                AOP(IC_RESULT(ic))->aopu.aop_dir);
2890
2891       return TRUE;
2892     }
2893
2894
2895
2896     /* if the sizes are greater than 1 then we cannot */
2897     if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2898         AOP_SIZE(IC_LEFT(ic)) > 1   )
2899         return FALSE ;
2900     
2901     /* If we are incrementing the same register by two: */
2902
2903     if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2904         
2905       while (icount--) 
2906         emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2907       //emitcode("incf","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2908         
2909       return TRUE ;
2910     }
2911     
2912     DEBUGemitcode ("; ","couldn't increment result-%s  left-%s",
2913                    aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
2914                    aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2915     return FALSE ;
2916 }
2917
2918 /*-----------------------------------------------------------------*/
2919 /* outBitAcc - output a bit in acc                                 */
2920 /*-----------------------------------------------------------------*/
2921 static void outBitAcc(operand *result)
2922 {
2923     symbol *tlbl = newiTempLabel(NULL);
2924     /* if the result is a bit */
2925     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2926
2927     if (AOP_TYPE(result) == AOP_CRY){
2928         aopPut(AOP(result),"a",0);
2929     }
2930     else {
2931         emitcode("jz","%05d_DS_",tlbl->key+100);
2932         emitcode("mov","a,%s",one);
2933         emitcode("","%05d_DS_:",tlbl->key+100);
2934         outAcc(result);
2935     }
2936 }
2937
2938 /*-----------------------------------------------------------------*/
2939 /* genPlusBits - generates code for addition of two bits           */
2940 /*-----------------------------------------------------------------*/
2941 static void genPlusBits (iCode *ic)
2942 {
2943
2944     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2945     /*
2946       The following block of code will add two bits. 
2947       Note that it'll even work if the destination is
2948       the carry (C in the status register).
2949       It won't work if the 'Z' bit is a source or destination.
2950     */
2951
2952     /* If the result is stored in the accumulator (w) */
2953     if(strcmp(aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),"a") == 0 ) {
2954       //emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
2955       //              popGet(AOP(result),0,FALSE,FALSE));
2956
2957       emitpcode(POC_MOVLW, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2958       emitpcode(POC_BCF,   popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2959       emitpcode(POC_BTFSC, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
2960       emitpcode(POC_XORWF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2961       emitpcode(POC_BTFSC, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2962       emitpcode(POC_XORWF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2963
2964         emitcode("movlw","(1 << (%s & 7))",
2965                  AOP(IC_RESULT(ic))->aopu.aop_dir,
2966                  AOP(IC_RESULT(ic))->aopu.aop_dir);
2967         emitcode("bcf","(%s >> 3), (%s & 7)",
2968                  AOP(IC_RESULT(ic))->aopu.aop_dir,
2969                  AOP(IC_RESULT(ic))->aopu.aop_dir);
2970         emitcode("btfsc","(%s >> 3), (%s & 7)",
2971                  AOP(IC_RIGHT(ic))->aopu.aop_dir,
2972                  AOP(IC_RIGHT(ic))->aopu.aop_dir);
2973         emitcode("xorwf","(%s >>3),f",
2974                  AOP(IC_RESULT(ic))->aopu.aop_dir);
2975         emitcode("btfsc","(%s >> 3), (%s & 7)",
2976                  AOP(IC_LEFT(ic))->aopu.aop_dir,
2977                  AOP(IC_LEFT(ic))->aopu.aop_dir);
2978         emitcode("xorwf","(%s>>3),f",
2979                  AOP(IC_RESULT(ic))->aopu.aop_dir);
2980     } else { 
2981
2982       emitpcode(POC_CLRW, NULL);
2983       emitpcode(POC_BTFSC, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
2984       emitpcode(POC_XORLW, popGetLit(1));
2985       emitpcode(POC_BTFSC, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2986       emitpcode(POC_XORLW, popGetLit(1));
2987
2988       emitcode("clrw","");
2989       emitcode("btfsc","(%s >> 3), (%s & 7)",
2990                  AOP(IC_RIGHT(ic))->aopu.aop_dir,
2991                  AOP(IC_RIGHT(ic))->aopu.aop_dir);
2992       emitcode("xorlw","1");
2993       emitcode("btfsc","(%s >> 3), (%s & 7)",
2994                AOP(IC_LEFT(ic))->aopu.aop_dir,
2995                AOP(IC_LEFT(ic))->aopu.aop_dir);
2996       emitcode("xorlw","1");
2997     }
2998
2999 }
3000
3001 #if 0
3002 /* This is the original version of this code.
3003  *
3004  * This is being kept around for reference, 
3005  * because I am not entirely sure I got it right...
3006  */
3007 static void adjustArithmeticResult(iCode *ic)
3008 {
3009     if (AOP_SIZE(IC_RESULT(ic)) == 3 && 
3010         AOP_SIZE(IC_LEFT(ic)) == 3   &&
3011         !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
3012         aopPut(AOP(IC_RESULT(ic)),
3013                aopGet(AOP(IC_LEFT(ic)),2,FALSE,FALSE),
3014                2);
3015
3016     if (AOP_SIZE(IC_RESULT(ic)) == 3 && 
3017         AOP_SIZE(IC_RIGHT(ic)) == 3   &&
3018         !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
3019         aopPut(AOP(IC_RESULT(ic)),
3020                aopGet(AOP(IC_RIGHT(ic)),2,FALSE,FALSE),
3021                2);
3022     
3023     if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
3024         AOP_SIZE(IC_LEFT(ic)) < 3    &&
3025         AOP_SIZE(IC_RIGHT(ic)) < 3   &&
3026         !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
3027         !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
3028         char buffer[5];
3029         sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
3030         aopPut(AOP(IC_RESULT(ic)),buffer,2);
3031     }
3032 }
3033 //#else
3034 /* This is the pure and virtuous version of this code.
3035  * I'm pretty certain it's right, but not enough to toss the old 
3036  * code just yet...
3037  */
3038 static void adjustArithmeticResult(iCode *ic)
3039 {
3040     if (opIsGptr(IC_RESULT(ic)) &&
3041         opIsGptr(IC_LEFT(ic))   &&
3042         !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
3043     {
3044         aopPut(AOP(IC_RESULT(ic)),
3045                aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1,FALSE,FALSE),
3046                GPTRSIZE - 1);
3047     }
3048
3049     if (opIsGptr(IC_RESULT(ic)) &&
3050         opIsGptr(IC_RIGHT(ic))   &&
3051         !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
3052     {
3053         aopPut(AOP(IC_RESULT(ic)),
3054                aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1,FALSE,FALSE),
3055                GPTRSIZE - 1);
3056     }
3057
3058     if (opIsGptr(IC_RESULT(ic))            &&
3059         AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE   &&
3060         AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE  &&
3061          !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
3062          !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
3063          char buffer[5];
3064          sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
3065          aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
3066      }
3067 }
3068 #endif
3069
3070 /*-----------------------------------------------------------------*/
3071 /* genPlus - generates code for addition                           */
3072 /*-----------------------------------------------------------------*/
3073 static void genPlus (iCode *ic)
3074 {
3075     int size, offset = 0;
3076
3077     /* special cases :- */
3078     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3079
3080     aopOp (IC_LEFT(ic),ic,FALSE);
3081     aopOp (IC_RIGHT(ic),ic,FALSE);
3082     aopOp (IC_RESULT(ic),ic,TRUE);
3083
3084     /* if literal, literal on the right or
3085        if left requires ACC or right is already
3086        in ACC */
3087
3088     if (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) {
3089         operand *t = IC_RIGHT(ic);
3090         IC_RIGHT(ic) = IC_LEFT(ic);
3091         IC_LEFT(ic) = t;
3092     }
3093
3094     /* if both left & right are in bit space */
3095     if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
3096         AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
3097         genPlusBits (ic);
3098         goto release ;
3099     }
3100
3101     /* if left in bit space & right literal */
3102     if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
3103         AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
3104         /* if result in bit space */
3105         if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
3106           if((unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit) != 0L) {
3107             emitpcode(POC_MOVLW, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3108             if (!sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
3109               emitpcode(POC_BTFSC, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3110             emitpcode(POC_XORWF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3111           }
3112         } else {
3113             size = getDataSize(IC_RESULT(ic));
3114             while (size--) {
3115                 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));  
3116                 emitcode("addc","a,#00  ;%d",__LINE__);
3117                 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
3118             }
3119         }
3120         goto release ;
3121     }
3122
3123     /* if I can do an increment instead
3124     of add then GOOD for ME */
3125     if (genPlusIncr (ic) == TRUE)
3126         goto release;   
3127
3128     size = getDataSize(IC_RESULT(ic));
3129
3130     if(AOP(IC_RIGHT(ic))->type == AOP_LIT) {
3131       /* Add a literal to something else */
3132       bool know_W=0;
3133       unsigned lit = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3134       unsigned l1=0;
3135
3136       offset = 0;
3137       DEBUGemitcode(";","adding lit to something. size %d",size);
3138       while(size--){
3139
3140       DEBUGemitcode(";","size %d",size);
3141
3142         switch (lit & 0xff) {
3143         case 0:
3144           break;
3145         case 1:
3146           if(sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))))
3147             emitpcode(POC_INCF, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3148           else {
3149             know_W = 0;
3150             emitpcode(POC_INCFW, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3151             if(AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
3152               emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
3153           }
3154           break;
3155         case 0xff:
3156           if(sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))))
3157             emitpcode(POC_DECF, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3158           else {
3159             know_W = 0;
3160             emitpcode(POC_DECFW, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3161             if(AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
3162               emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
3163           }
3164           break;
3165         default:
3166           if( !know_W || ( (lit&0xff) != l1)  ) {
3167             know_W = 1;
3168             emitpcode(POC_MOVLW,popGetLit(lit&0xff));
3169           }
3170           if(sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))))
3171             emitpcode(POC_ADDWF, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3172           else {
3173             know_W = 0;
3174             emitpcode(POC_ADDFW, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3175             emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
3176             if(size) {
3177               emitSKPNC;
3178               emitpcode(POC_INCF, popGet(AOP(IC_LEFT(ic)),offset+1,FALSE,FALSE));
3179             }
3180           }
3181         }
3182
3183         l1 = lit & 0xff;
3184         lit >>= 8;
3185         offset++;
3186       }
3187
3188     } else if(AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
3189
3190       emitcode(";bitadd","right is bit: %s",aopGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3191       emitcode(";bitadd","left is bit: %s",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3192       emitcode(";bitadd","result is bit: %s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3193
3194       /* here we are adding a bit to a char or int */
3195       if(size == 1) {
3196         if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
3197
3198           emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3199           emitpcode(POC_INCF ,  popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3200
3201           emitcode("btfsc","(%s >> 3), (%s & 7)",
3202                    AOP(IC_RIGHT(ic))->aopu.aop_dir,
3203                    AOP(IC_RIGHT(ic))->aopu.aop_dir);
3204           emitcode(" incf","%s,f", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3205         } else {
3206
3207           if(AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
3208             emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3209             emitpcode(POC_XORLW , popGetLit(1));
3210
3211             emitcode("btfsc","(%s >> 3), (%s & 7)",
3212                      AOP(IC_RIGHT(ic))->aopu.aop_dir,
3213                      AOP(IC_RIGHT(ic))->aopu.aop_dir);
3214             emitcode(" xorlw","1");
3215           } else {
3216             emitpcode(POC_MOVFW , popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3217             emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3218             emitpcode(POC_INCFW , popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3219
3220             emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3221             emitcode("btfsc","(%s >> 3), (%s & 7)",
3222                      AOP(IC_RIGHT(ic))->aopu.aop_dir,
3223                      AOP(IC_RIGHT(ic))->aopu.aop_dir);
3224             emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3225           }
3226           
3227           if(AOP_TYPE(IC_RESULT(ic)) != AOP_ACC) {
3228             
3229             if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
3230               emitpcode(POC_ANDLW , popGetLit(1));
3231               emitpcode(POC_BCF ,   popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3232               emitSKPZ;
3233               emitpcode(POC_BSF ,   popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3234             } else {
3235               emitpcode(POC_MOVWF ,   popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3236               emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3237             }
3238           }
3239         }
3240
3241       } else {
3242         int offset = 1;
3243
3244         if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
3245           emitCLRZ;
3246           emitpcode(POC_BTFSC, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3247           emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3248
3249           emitcode("clrz","");
3250
3251           emitcode("btfsc","(%s >> 3), (%s & 7)",
3252                    AOP(IC_RIGHT(ic))->aopu.aop_dir,
3253                    AOP(IC_RIGHT(ic))->aopu.aop_dir);
3254           emitcode(" incf","%s,f", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3255
3256         } else {
3257
3258           emitpcode(POC_MOVFW, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3259           emitpcode(POC_BTFSC, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3260           emitpcode(POC_INCFW, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3261           emitpcode(POC_MOVWF, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3262
3263
3264           emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3265           emitcode("btfsc","(%s >> 3), (%s & 7)",
3266                    AOP(IC_RIGHT(ic))->aopu.aop_dir,
3267                    AOP(IC_RIGHT(ic))->aopu.aop_dir);
3268           emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3269           emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3270
3271         }
3272
3273         while(--size){
3274           emitSKPZ;
3275           emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),offset++,FALSE,FALSE));
3276       //emitcode(" incf","%s,f", aopGet(AOP(IC_RIGHT(ic)),offset++,FALSE,FALSE));
3277         }
3278
3279       }
3280       
3281     } else {
3282     
3283       if(strcmp(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE),"a") == 0 ) {
3284         emitpcode(POC_ADDFW, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3285         emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3286       } else {
3287
3288         if ( AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
3289           emitpcode(POC_ADDFW, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3290           if ( AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
3291             emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3292         } else {
3293
3294           emitpcode(POC_MOVFW,popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3295
3296           if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
3297             emitpcode(POC_ADDWF, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3298           else {
3299             if( (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD) ||
3300                 (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ) {
3301               emitpcode(POC_ADDLW, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3302             } else {
3303               emitpcode(POC_ADDFW, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3304               if ( AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
3305                 emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3306             }
3307           }
3308         }
3309       }
3310
3311       offset = 1;
3312       size--;
3313
3314       while(size--){
3315         if (!sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
3316           emitpcode(POC_MOVFW, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3317           emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
3318
3319           emitcode("movf","%s,w",  aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3320           emitcode("movwf","%s",  aopGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
3321         }
3322
3323         emitpcode(POC_MOVFW,   popGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3324         emitSKPNC;
3325         emitpcode(POC_INCFSZW, popGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3326         emitpcode(POC_ADDWF,   popGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
3327
3328         /*
3329         emitcode("movf","%s,w",  aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3330         emitSKPNC;
3331         emitcode("incfsz","%s,w",aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3332         emitcode("addwf","%s,f", aopGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
3333         */
3334
3335         offset++;
3336       }
3337
3338     }
3339
3340     //adjustArithmeticResult(ic);
3341
3342  release:
3343       freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3344       freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3345       freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3346 }
3347
3348 /*-----------------------------------------------------------------*/
3349 /* genMinusDec :- does subtraction with decrement if possible     */
3350 /*-----------------------------------------------------------------*/
3351 static bool genMinusDec (iCode *ic)
3352 {
3353     unsigned int icount ;
3354     unsigned int size = getDataSize(IC_RESULT(ic));
3355
3356     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3357     /* will try to generate an increment */
3358     /* if the right side is not a literal 
3359     we cannot */
3360     if ((AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT) || 
3361         (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) || 
3362         (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) )
3363         return FALSE ;
3364
3365     DEBUGemitcode ("; lit val","%d",(unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit));
3366
3367     /* if the literal value of the right hand side
3368     is greater than 4 then it is not worth it */
3369     if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
3370         return FALSE ;
3371
3372     /* if decrement 16 bits in register */
3373     if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
3374         (size > 1) &&
3375         (icount == 1)) {
3376
3377       if(size == 2) { 
3378         emitpcode(POC_DECF,    popGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
3379         emitpcode(POC_INCFSZW, popGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
3380         emitpcode(POC_DECF,    popGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
3381
3382         emitcode("decf","%s,f",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
3383         emitcode("incfsz","%s,w",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
3384         emitcode(" decf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
3385       } else {
3386         /* size is 3 or 4 */
3387         emitpcode(POC_MOVLW,  popGetLit(0xff));
3388         emitpcode(POC_ADDWF,  popGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
3389         emitSKPNC;
3390         emitpcode(POC_ADDWF,  popGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
3391         emitSKPNC;
3392         emitpcode(POC_ADDWF,  popGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
3393
3394         emitcode("movlw","0xff");
3395         emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
3396
3397         emitSKPNC;
3398         emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
3399         emitSKPNC;
3400         emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
3401
3402         if(size > 3) {
3403           emitSKPNC;
3404           emitpcode(POC_ADDWF,  popGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
3405
3406           emitcode("skpnc","");
3407           emitSKPNC;
3408           emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
3409         }
3410
3411       }
3412
3413       return TRUE;
3414
3415     }
3416
3417     /* if the sizes are greater than 1 then we cannot */
3418     if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
3419         AOP_SIZE(IC_LEFT(ic)) > 1   )
3420         return FALSE ;
3421
3422     /* we can if the aops of the left & result match or
3423     if they are in registers and the registers are the
3424     same */
3425     if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
3426
3427       while (icount--) 
3428         emitpcode(POC_DECF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3429
3430         //emitcode ("decf","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3431
3432         return TRUE ;
3433     }
3434
3435     DEBUGemitcode ("; returning"," result=%s, left=%s",
3436                    aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
3437                    aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3438     if(size==1) {
3439
3440       emitcode("decf","%s,w",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3441       emitcode("movwf","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3442
3443       emitpcode(POC_DECFW,  popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3444       emitpcode(POC_MOVWF,  popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3445
3446       return TRUE;
3447     }
3448
3449     return FALSE ;
3450 }
3451
3452 /*-----------------------------------------------------------------*/
3453 /* addSign - complete with sign                                    */
3454 /*-----------------------------------------------------------------*/
3455 static void addSign(operand *result, int offset, int sign)
3456 {
3457     int size = (getDataSize(result) - offset);
3458     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3459     if(size > 0){
3460         if(sign){
3461             emitcode("rlc","a");
3462             emitcode("subb","a,acc");
3463             while(size--)
3464                 aopPut(AOP(result),"a",offset++); 
3465         } else
3466             while(size--)
3467                 aopPut(AOP(result),zero,offset++);
3468     }
3469 }
3470
3471 /*-----------------------------------------------------------------*/
3472 /* genMinusBits - generates code for subtraction  of two bits      */
3473 /*-----------------------------------------------------------------*/
3474 static void genMinusBits (iCode *ic)
3475 {
3476     symbol *lbl = newiTempLabel(NULL);
3477     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3478     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
3479         emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
3480         emitcode("jnb","%s,%05d_DS_",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
3481         emitcode("cpl","c");
3482         emitcode("","%05d_DS_:",(lbl->key+100));
3483         outBitC(IC_RESULT(ic));
3484     }
3485     else{
3486         emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
3487         emitcode("subb","a,acc");
3488         emitcode("jnb","%s,%05d_DS_",AOP(IC_LEFT(ic))->aopu.aop_dir,(lbl->key+100));
3489         emitcode("inc","a");
3490         emitcode("","%05d_DS_:",(lbl->key+100));
3491         aopPut(AOP(IC_RESULT(ic)),"a",0);
3492         addSign(IC_RESULT(ic), MSB16, SPEC_USIGN(getSpec(operandType(IC_RESULT(ic)))));
3493     }
3494 }
3495
3496 /*-----------------------------------------------------------------*/
3497 /* genMinus - generates code for subtraction                       */
3498 /*-----------------------------------------------------------------*/
3499 static void genMinus (iCode *ic)
3500 {
3501   int size, offset = 0;
3502   unsigned long lit = 0L;
3503
3504   DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3505   aopOp (IC_LEFT(ic),ic,FALSE);
3506   aopOp (IC_RIGHT(ic),ic,FALSE);
3507   aopOp (IC_RESULT(ic),ic,TRUE);
3508
3509   if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY  &&
3510       AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
3511     operand *t = IC_RIGHT(ic);
3512     IC_RIGHT(ic) = IC_LEFT(ic);
3513     IC_LEFT(ic) = t;
3514   }
3515
3516   /* special cases :- */
3517   /* if both left & right are in bit space */
3518   if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
3519       AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
3520     genPlusBits (ic);
3521     goto release ;
3522   }
3523
3524   /* if I can do an decrement instead
3525      of subtract then GOOD for ME */
3526   if (genMinusDec (ic) == TRUE)
3527     goto release;   
3528
3529   size = getDataSize(IC_RESULT(ic));   
3530
3531   if(AOP(IC_RIGHT(ic))->type == AOP_LIT) {
3532     /* Add a literal to something else */
3533
3534     lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3535     lit = - (long)lit;
3536
3537     /* add the first byte: */
3538     emitcode("movlw","0x%x", lit & 0xff);
3539     emitcode("addwf","%s,f", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3540     emitpcode(POC_MOVLW,  popGetLit(lit & 0xff));
3541     emitpcode(POC_ADDWF,  popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3542
3543
3544     offset = 1;
3545     size--;
3546
3547     while(size-- > 0) {
3548
3549       lit >>= 8;
3550
3551       if(lit & 0xff) {
3552
3553         if((lit & 0xff) == 0xff) {
3554           emitpcode(POC_MOVLW,  popGetLit(0xff));
3555           emitSKPC;
3556           emitpcode(POC_ADDWF,  popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3557         } else {
3558           emitpcode(POC_MOVLW,  popGetLit(lit & 0xff));
3559           emitSKPNC;
3560           emitpcode(POC_MOVLW,  popGetLit((lit+1) & 0xff));
3561           emitpcode(POC_ADDWF,  popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3562         }
3563
3564       } else {
3565         /* do the rlf known zero trick here */
3566         emitpcode(POC_MOVLW,  popGetLit(1));
3567         emitSKPNC;
3568         emitpcode(POC_ADDWF,  popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3569       }
3570       offset++;
3571     }
3572
3573   } else if(AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
3574     // bit subtraction
3575
3576     emitcode(";bitsub","right is bit: %s",aopGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3577     emitcode(";bitsub","left is bit: %s",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3578     emitcode(";bitsub","result is bit: %s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3579
3580     /* here we are subtracting a bit from a char or int */
3581     if(size == 1) {
3582       if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
3583
3584         emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3585         emitpcode(POC_DECF ,  popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3586
3587         emitcode("btfsc","(%s >> 3), (%s & 7)",
3588                  AOP(IC_RIGHT(ic))->aopu.aop_dir,
3589                  AOP(IC_RIGHT(ic))->aopu.aop_dir);
3590         emitcode(" incf","%s,f", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3591       } else {
3592
3593         if(AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
3594           emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3595           emitpcode(POC_XORLW , popGetLit(1));
3596         }else  if( (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD) ||
3597               (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ) {
3598
3599           lit = (unsigned long)floatFromVal(AOP(IC_LEFT(ic))->aopu.aop_lit);
3600
3601           if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
3602             if (sameRegs(AOP(IC_RIGHT(ic)), AOP(IC_RESULT(ic))) ) {
3603               if(lit & 1) {
3604                 emitpcode(POC_MOVLW , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3605                 emitpcode(POC_XORWF , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3606               }
3607             }else{
3608               emitpcode(POC_BCF ,     popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3609               if(lit & 1) 
3610                 emitpcode(POC_BTFSS , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3611               else
3612                 emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3613               emitpcode(POC_BSF ,     popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3614             }
3615             goto release;
3616           } else {
3617             emitpcode(POC_MOVLW , popGetLit(lit & 0xff));
3618             emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3619             emitpcode(POC_MOVLW , popGetLit((lit-1) & 0xff));
3620             emitpcode(POC_MOVWF , popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3621
3622           }
3623
3624         } else {
3625           emitpcode(POC_MOVFW , popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3626           emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3627           emitpcode(POC_DECFW , popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3628         }
3629           
3630         if(AOP_TYPE(IC_RESULT(ic)) != AOP_ACC) {
3631             
3632           emitpcode(POC_MOVWF ,   popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3633
3634         } else  {
3635           emitpcode(POC_ANDLW , popGetLit(1));
3636 /*
3637           emitpcode(POC_BCF ,   popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3638           emitSKPZ;
3639           emitpcode(POC_BSF ,   popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3640 */
3641         }
3642
3643       }
3644
3645     }
3646   } else {
3647
3648     if(strcmp(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE),"a") == 0 ) {
3649       DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3650       emitpcode(POC_SUBFW, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3651       emitpcode(POC_SUBLW, popGetLit(0));
3652       emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3653     } else {
3654
3655       if ( AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
3656         emitpcode(POC_SUBFW, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3657         emitpcode(POC_SUBLW, popGetLit(0));
3658         if ( AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
3659           emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3660       } else {
3661
3662         DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3663         if(AOP_TYPE(IC_RIGHT(ic)) != AOP_ACC) 
3664           emitpcode(POC_MOVFW,popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3665
3666         if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
3667           emitpcode(POC_SUBWF, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3668         else {
3669           if( (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD) ||
3670               (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ) {
3671             emitpcode(POC_SUBLW, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3672           } else {
3673             emitpcode(POC_SUBFW, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3674           }
3675           if ( AOP_TYPE(IC_RESULT(ic)) != AOP_ACC) {
3676             if ( AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
3677               emitpcode(POC_BCF ,   popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3678               emitSKPZ;
3679               emitpcode(POC_BSF ,   popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3680             }else
3681               emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3682           }
3683         }
3684       }
3685     }
3686
3687     /*
3688       emitpcode(POC_MOVFW,  popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3689
3690       if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
3691       emitpcode(POC_SUBFW,  popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3692       } else {
3693       emitpcode(POC_SUBFW,  popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3694       emitpcode(POC_MOVWF,  popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3695       }
3696     */
3697     offset = 1;
3698     size--;
3699
3700     while(size--){
3701       if (!sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
3702         emitpcode(POC_MOVFW,  popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3703         emitpcode(POC_MOVWF,  popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3704       }
3705       emitpcode(POC_MOVFW,  popGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3706       emitSKPNC;
3707       emitpcode(POC_INCFSZW,popGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3708       emitpcode(POC_SUBWF,  popGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
3709
3710       offset++;
3711     }
3712
3713   }
3714
3715
3716   //    adjustArithmeticResult(ic);
3717         
3718  release:
3719   freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3720   freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3721   freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3722 }
3723
3724
3725 /*-----------------------------------------------------------------*/
3726 /* genMultbits :- multiplication of bits                           */
3727 /*-----------------------------------------------------------------*/
3728 static void genMultbits (operand *left, 
3729                          operand *right, 
3730                          operand *result)
3731 {
3732     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3733
3734     emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3735     emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
3736     outBitC(result);
3737 }
3738
3739
3740 /*-----------------------------------------------------------------*/
3741 /* genMultOneByte : 8 bit multiplication & division                */
3742 /*-----------------------------------------------------------------*/
3743 static void genMultOneByte (operand *left,
3744                             operand *right,
3745                             operand *result)
3746 {
3747     sym_link *opetype = operandType(result);
3748     char *l ;
3749     symbol *lbl ;
3750     int size,offset;
3751
3752     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3753     /* (if two literals, the value is computed before) */
3754     /* if one literal, literal on the right */
3755     if (AOP_TYPE(left) == AOP_LIT){
3756         operand *t = right;
3757         right = left;
3758         left = t;
3759     }
3760
3761     size = AOP_SIZE(result);
3762     /* signed or unsigned */
3763     emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3764     l = aopGet(AOP(left),0,FALSE,FALSE);
3765     MOVA(l);       
3766     emitcode("mul","ab");
3767     /* if result size = 1, mul signed = mul unsigned */
3768     aopPut(AOP(result),"a",0);
3769     if (size > 1){
3770         if (SPEC_USIGN(opetype)){
3771             aopPut(AOP(result),"b",1);
3772             if (size > 2)
3773                 /* for filling the MSBs */
3774                 emitcode("clr","a");
3775         }
3776         else{
3777             emitcode("mov","a,b");
3778
3779             /* adjust the MSB if left or right neg */
3780
3781             /* if one literal */
3782             if (AOP_TYPE(right) == AOP_LIT){
3783                 /* AND literal negative */
3784                 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3785                     /* adjust MSB (c==0 after mul) */
3786                     emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
3787                 }
3788             }
3789             else{
3790                 lbl = newiTempLabel(NULL);
3791                 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3792                 emitcode("cjne","a,#0x80,%05d_DS_", (lbl->key+100));
3793                 emitcode("","%05d_DS_:",(lbl->key+100));
3794                 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3795                 lbl = newiTempLabel(NULL);      
3796                 emitcode("jc","%05d_DS_",(lbl->key+100));          
3797                 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
3798                 emitcode("","%05d_DS_:",(lbl->key+100));
3799             }
3800
3801             lbl = newiTempLabel(NULL);
3802             emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
3803             emitcode("cjne","a,#0x80,%05d_DS_", (lbl->key+100));
3804             emitcode("","%05d_DS_:",(lbl->key+100));
3805             emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
3806             lbl = newiTempLabel(NULL);      
3807             emitcode("jc","%05d_DS_",(lbl->key+100));          
3808             emitcode("subb","a,%s", aopGet(AOP(right),0,FALSE,FALSE));
3809             emitcode("","%05d_DS_:",(lbl->key+100));
3810
3811             aopPut(AOP(result),"a",1);
3812             if(size > 2){
3813                 /* get the sign */
3814                 emitcode("rlc","a");
3815                 emitcode("subb","a,acc");
3816             }
3817         }
3818         size -= 2;   
3819         offset = 2;
3820         if (size > 0)
3821             while (size--)
3822                 aopPut(AOP(result),"a",offset++);
3823     }
3824 }
3825
3826 /*-----------------------------------------------------------------*/
3827 /* genMult - generates code for multiplication                     */
3828 /*-----------------------------------------------------------------*/
3829 static void genMult (iCode *ic)
3830 {
3831     operand *left = IC_LEFT(ic);
3832     operand *right = IC_RIGHT(ic);
3833     operand *result= IC_RESULT(ic);   
3834
3835     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3836     /* assign the amsops */
3837     aopOp (left,ic,FALSE);
3838     aopOp (right,ic,FALSE);
3839     aopOp (result,ic,TRUE);
3840
3841     /* special cases first */
3842     /* both are bits */
3843     if (AOP_TYPE(left) == AOP_CRY &&
3844         AOP_TYPE(right)== AOP_CRY) {
3845         genMultbits(left,right,result);
3846         goto release ;
3847     }
3848
3849     /* if both are of size == 1 */
3850     if (AOP_SIZE(left) == 1 &&
3851         AOP_SIZE(right) == 1 ) {
3852         genMultOneByte(left,right,result);
3853         goto release ;
3854     }
3855
3856     /* should have been converted to function call */       
3857     assert(1) ;
3858
3859 release :
3860     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3861     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3862     freeAsmop(result,NULL,ic,TRUE); 
3863 }
3864
3865 /*-----------------------------------------------------------------*/
3866 /* genDivbits :- division of bits                                  */
3867 /*-----------------------------------------------------------------*/
3868 static void genDivbits (operand *left, 
3869                         operand *right, 
3870                         operand *result)
3871 {
3872
3873     char *l;
3874
3875     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3876     /* the result must be bit */    
3877     emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3878     l = aopGet(AOP(left),0,FALSE,FALSE);
3879
3880     MOVA(l);    
3881
3882     emitcode("div","ab");
3883     emitcode("rrc","a");
3884     aopPut(AOP(result),"c",0);
3885 }
3886
3887 /*-----------------------------------------------------------------*/
3888 /* genDivOneByte : 8 bit division                                  */
3889 /*-----------------------------------------------------------------*/
3890 static void genDivOneByte (operand *left,
3891                            operand *right,
3892                            operand *result)
3893 {
3894     sym_link *opetype = operandType(result);
3895     char *l ;
3896     symbol *lbl ;
3897     int size,offset;
3898
3899     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3900     size = AOP_SIZE(result) - 1;
3901     offset = 1;
3902     /* signed or unsigned */
3903     if (SPEC_USIGN(opetype)) {
3904         /* unsigned is easy */
3905         emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3906         l = aopGet(AOP(left),0,FALSE,FALSE);
3907         MOVA(l);        
3908         emitcode("div","ab");
3909         aopPut(AOP(result),"a",0);
3910         while (size--)
3911             aopPut(AOP(result),zero,offset++);
3912         return ;
3913     }
3914
3915     /* signed is a little bit more difficult */
3916
3917     /* save the signs of the operands */
3918     l = aopGet(AOP(left),0,FALSE,FALSE);    
3919     MOVA(l);    
3920     emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE));
3921     emitcode("push","acc"); /* save it on the stack */
3922
3923     /* now sign adjust for both left & right */
3924     l =  aopGet(AOP(right),0,FALSE,FALSE);    
3925     MOVA(l);       
3926     lbl = newiTempLabel(NULL);
3927     emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
3928     emitcode("cpl","a");   
3929     emitcode("inc","a");
3930     emitcode("","%05d_DS_:",(lbl->key+100));
3931     emitcode("mov","b,a");
3932
3933     /* sign adjust left side */
3934     l =  aopGet(AOP(left),0,FALSE,FALSE);    
3935     MOVA(l);
3936
3937     lbl = newiTempLabel(NULL);
3938     emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3939     emitcode("cpl","a");
3940     emitcode("inc","a");
3941     emitcode("","%05d_DS_:",(lbl->key+100));
3942
3943     /* now the division */
3944     emitcode("div","ab");
3945     /* we are interested in the lower order
3946     only */
3947     emitcode("mov","b,a");
3948     lbl = newiTempLabel(NULL);
3949     emitcode("pop","acc");   
3950     /* if there was an over flow we don't 
3951     adjust the sign of the result */
3952     emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3953     emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3954     CLRC;
3955     emitcode("clr","a");
3956     emitcode("subb","a,b");
3957     emitcode("mov","b,a");
3958     emitcode("","%05d_DS_:",(lbl->key+100));
3959
3960     /* now we are done */
3961     aopPut(AOP(result),"b",0);
3962     if(size > 0){
3963         emitcode("mov","c,b.7");
3964         emitcode("subb","a,acc");   
3965     }
3966     while (size--)
3967         aopPut(AOP(result),"a",offset++);
3968
3969 }
3970
3971 /*-----------------------------------------------------------------*/
3972 /* genDiv - generates code for division                            */
3973 /*-----------------------------------------------------------------*/
3974 static void genDiv (iCode *ic)
3975 {
3976     operand *left = IC_LEFT(ic);
3977     operand *right = IC_RIGHT(ic);
3978     operand *result= IC_RESULT(ic);   
3979
3980     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3981     /* assign the amsops */
3982     aopOp (left,ic,FALSE);
3983     aopOp (right,ic,FALSE);
3984     aopOp (result,ic,TRUE);
3985
3986     /* special cases first */
3987     /* both are bits */
3988     if (AOP_TYPE(left) == AOP_CRY &&
3989         AOP_TYPE(right)== AOP_CRY) {
3990         genDivbits(left,right,result);
3991         goto release ;
3992     }
3993
3994     /* if both are of size == 1 */
3995     if (AOP_SIZE(left) == 1 &&
3996         AOP_SIZE(right) == 1 ) {
3997         genDivOneByte(left,right,result);
3998         goto release ;
3999     }
4000
4001     /* should have been converted to function call */
4002     assert(1);
4003 release :
4004     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4005     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4006     freeAsmop(result,NULL,ic,TRUE); 
4007 }
4008
4009 /*-----------------------------------------------------------------*/
4010 /* genModbits :- modulus of bits                                   */
4011 /*-----------------------------------------------------------------*/
4012 static void genModbits (operand *left, 
4013                         operand *right, 
4014                         operand *result)
4015 {
4016
4017     char *l;
4018
4019     /* the result must be bit */    
4020     emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
4021     l = aopGet(AOP(left),0,FALSE,FALSE);
4022
4023     MOVA(l);       
4024
4025     emitcode("div","ab");
4026     emitcode("mov","a,b");
4027     emitcode("rrc","a");
4028     aopPut(AOP(result),"c",0);
4029 }
4030
4031 /*-----------------------------------------------------------------*/
4032 /* genModOneByte : 8 bit modulus                                   */
4033 /*-----------------------------------------------------------------*/
4034 static void genModOneByte (operand *left,
4035                            operand *right,
4036                            operand *result)
4037 {
4038     sym_link *opetype = operandType(result);
4039     char *l ;
4040     symbol *lbl ;
4041
4042     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4043     /* signed or unsigned */
4044     if (SPEC_USIGN(opetype)) {
4045         /* unsigned is easy */
4046         emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
4047         l = aopGet(AOP(left),0,FALSE,FALSE);
4048         MOVA(l);    
4049         emitcode("div","ab");
4050         aopPut(AOP(result),"b",0);
4051         return ;
4052     }
4053
4054     /* signed is a little bit more difficult */
4055
4056     /* save the signs of the operands */
4057     l = aopGet(AOP(left),0,FALSE,FALSE);    
4058     MOVA(l);
4059
4060     emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
4061     emitcode("push","acc"); /* save it on the stack */
4062
4063     /* now sign adjust for both left & right */
4064     l =  aopGet(AOP(right),0,FALSE,FALSE);    
4065     MOVA(l);
4066
4067     lbl = newiTempLabel(NULL);
4068     emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
4069     emitcode("cpl","a");   
4070     emitcode("inc","a");
4071     emitcode("","%05d_DS_:",(lbl->key+100));
4072     emitcode("mov","b,a"); 
4073
4074     /* sign adjust left side */
4075     l =  aopGet(AOP(left),0,FALSE,FALSE);    
4076     MOVA(l);
4077
4078     lbl = newiTempLabel(NULL);
4079     emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4080     emitcode("cpl","a");   
4081     emitcode("inc","a");
4082     emitcode("","%05d_DS_:",(lbl->key+100));
4083
4084     /* now the multiplication */
4085     emitcode("div","ab");
4086     /* we are interested in the lower order
4087     only */
4088     lbl = newiTempLabel(NULL);
4089     emitcode("pop","acc");   
4090     /* if there was an over flow we don't 
4091     adjust the sign of the result */
4092     emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4093     emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4094     CLRC ;
4095     emitcode("clr","a");
4096     emitcode("subb","a,b");
4097     emitcode("mov","b,a");
4098     emitcode("","%05d_DS_:",(lbl->key+100));
4099
4100     /* now we are done */
4101     aopPut(AOP(result),"b",0);
4102
4103 }
4104
4105 /*-----------------------------------------------------------------*/
4106 /* genMod - generates code for division                            */
4107 /*-----------------------------------------------------------------*/
4108 static void genMod (iCode *ic)
4109 {
4110     operand *left = IC_LEFT(ic);
4111     operand *right = IC_RIGHT(ic);
4112     operand *result= IC_RESULT(ic);  
4113
4114     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4115     /* assign the amsops */
4116     aopOp (left,ic,FALSE);
4117     aopOp (right,ic,FALSE);
4118     aopOp (result,ic,TRUE);
4119
4120     /* special cases first */
4121     /* both are bits */
4122     if (AOP_TYPE(left) == AOP_CRY &&
4123         AOP_TYPE(right)== AOP_CRY) {
4124         genModbits(left,right,result);
4125         goto release ;
4126     }
4127
4128     /* if both are of size == 1 */
4129     if (AOP_SIZE(left) == 1 &&
4130         AOP_SIZE(right) == 1 ) {
4131         genModOneByte(left,right,result);
4132         goto release ;
4133     }
4134
4135     /* should have been converted to function call */
4136     assert(1);
4137
4138 release :
4139     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4140     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4141     freeAsmop(result,NULL,ic,TRUE); 
4142 }
4143
4144 /*-----------------------------------------------------------------*/
4145 /* genIfxJump :- will create a jump depending on the ifx           */
4146 /*-----------------------------------------------------------------*/
4147 static void genIfxJump (iCode *ic, char *jval)
4148 {
4149
4150     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4151     /* if true label then we jump if condition
4152     supplied is true */
4153     if ( IC_TRUE(ic) ) {
4154
4155         if(strcmp(jval,"a") == 0)
4156           emitSKPZ;
4157         else if (strcmp(jval,"c") == 0)
4158           emitSKPC;
4159         else {
4160           //pCodeOp *p = popGetWithString(jval);
4161           //p->type = PO_BIT;
4162           //emitpcode(POC_BTFSC,  p);
4163           emitpcode(POC_BTFSC,  newpCodeOpBit(jval,0));
4164         //emitcode("btfsc","(%s >> 3),(%s & 7)",jval,jval);
4165         }
4166
4167         emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
4168         emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
4169
4170     }
4171     else {
4172         /* false label is present */
4173         if(strcmp(jval,"a") == 0)
4174           emitSKPNZ;
4175         else if (strcmp(jval,"c") == 0)
4176           emitSKPNC;
4177         else {
4178           //pCodeOp *p = popGetWithString(jval);
4179           //p->type = PO_BIT;
4180           //emitpcode(POC_BTFSS,  p);
4181           emitpcode(POC_BTFSS,  newpCodeOpBit(jval,0));
4182
4183         //        emitcode("btfss","(%s >> 3),(%s & 7)",jval,jval);
4184         }
4185
4186         emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
4187         emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
4188
4189     }
4190
4191
4192     /* mark the icode as generated */
4193     ic->generated = 1;
4194 }
4195
4196 /*-----------------------------------------------------------------*/
4197 /* genSkip                                                         */
4198 /*-----------------------------------------------------------------*/
4199 static void genSkip(iCode *ifx,int status_bit)
4200 {
4201   if(!ifx)
4202     return;
4203
4204   if ( IC_TRUE(ifx) ) {
4205     switch(status_bit) {
4206     case 'z':
4207       emitSKPNZ;
4208       break;
4209
4210     case 'c':
4211       emitSKPNC;
4212       break;
4213
4214     case 'd':
4215       emitcode("skpndc","");
4216       break;
4217
4218     }
4219
4220     emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4221     emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4222
4223   } else {
4224
4225     switch(status_bit) {
4226
4227     case 'z':
4228       emitSKPZ;
4229       break;
4230
4231     case 'c':
4232       emitSKPC;
4233       break;
4234
4235     case 'd':
4236       emitcode("skpdc","");
4237       break;
4238     }
4239     emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4240     emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4241
4242   }
4243
4244 }
4245
4246 /*-----------------------------------------------------------------*/
4247 /* genSkipc                                                        */
4248 /*-----------------------------------------------------------------*/
4249 static void genSkipc(iCode *ifx, int condition)
4250 {
4251   if(!ifx)
4252     return;
4253
4254   if(condition)
4255     emitSKPNC;
4256   else
4257     emitSKPC;
4258
4259   if ( IC_TRUE(ifx) )
4260     emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4261   else
4262     emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4263
4264   if ( IC_TRUE(ifx) )
4265     emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4266   else
4267     emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4268
4269 }
4270
4271 /*-----------------------------------------------------------------*/
4272 /* genSkipz                                                        */
4273 /*-----------------------------------------------------------------*/
4274 static void genSkipz(iCode *ifx, int condition)
4275 {
4276   if(!ifx)
4277     return;
4278
4279   if(condition)
4280     emitSKPNZ;
4281   else
4282     emitSKPZ;
4283
4284   if ( IC_TRUE(ifx) )
4285     emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4286   else
4287     emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4288
4289   if ( IC_TRUE(ifx) )
4290     emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4291   else
4292     emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4293
4294 }
4295 /*-----------------------------------------------------------------*/
4296 /* genCmp :- greater or less than comparison                       */
4297 /*-----------------------------------------------------------------*/
4298 static void genCmp (operand *left,operand *right,
4299                     operand *result, iCode *ifx, int sign)
4300 {
4301   int size, offset = 0 ;
4302   unsigned long lit = 0L,i = 0;
4303
4304   DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4305   /* if left & right are bit variables */
4306   if (AOP_TYPE(left) == AOP_CRY &&
4307       AOP_TYPE(right) == AOP_CRY ) {
4308     emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4309     emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4310   } else {
4311     /* subtract right from left if at the
4312        end the carry flag is set then we know that
4313        left is greater than right */
4314     size = max(AOP_SIZE(left),AOP_SIZE(right));
4315
4316     /* if unsigned char cmp with lit, do cjne left,#right,zz */
4317     if((size == 1) && !sign &&
4318        (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
4319       symbol *lbl  = newiTempLabel(NULL);
4320       emitcode("cjne","%s,%s,%05d_DS_",
4321                aopGet(AOP(left),offset,FALSE,FALSE),
4322                aopGet(AOP(right),offset,FALSE,FALSE),
4323                lbl->key+100);
4324       emitcode("","%05d_DS_:",lbl->key+100);
4325     } else {
4326
4327       if(AOP_TYPE(right) == AOP_LIT) {
4328
4329         DEBUGemitcode(";right lit","%d",sign);
4330
4331         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4332         //default:
4333         while(size--) {
4334           i = (lit >> (size*8)) & 0xff;
4335           if(i == 0) {
4336             emitpcode(POC_MOVFW, popGet(AOP(left),size,FALSE,FALSE));
4337             emitcode("movf","%s,w",aopGet(AOP(left),size,FALSE,FALSE));
4338             genSkipz(ifx,IC_TRUE(ifx) == NULL);
4339           } else {
4340             emitpcode(POC_MOVLW, popGetLit(i));
4341             emitpcode(POC_SUBFW, popGet(AOP(left),size,FALSE,FALSE));
4342
4343             emitcode("movlw","0x%x",i);
4344             emitcode("subwf","%s,w",aopGet(AOP(left),size,FALSE,FALSE));
4345             genSkipc(ifx,IC_TRUE(ifx) == NULL);
4346           }
4347
4348         }
4349         ifx->generated = 1;
4350         return;
4351       }
4352       if(AOP_TYPE(left) == AOP_LIT) {
4353
4354         DEBUGemitcode(";left lit","%d",sign);
4355
4356         lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit))+1;
4357
4358         //default:
4359         while(size--) {
4360           i = (lit >> (size*8)) & 0xff;
4361           if(i == 0) {
4362             emitpcode(POC_MOVFW, popGet(AOP(right),size,FALSE,FALSE));
4363             emitcode("movf","%s,w",aopGet(AOP(right),size,FALSE,FALSE));
4364             genSkipz(ifx,IC_TRUE(ifx) != NULL);
4365           } else if( i == 1 ) {
4366             emitpcode(POC_DECFW, popGet(AOP(right),size,FALSE,FALSE));
4367             emitcode("decf","%s,w",aopGet(AOP(right),size,FALSE,FALSE));
4368             genSkipz(ifx,IC_TRUE(ifx) != NULL);
4369
4370           } else {
4371             emitpcode(POC_MOVLW, popGetLit(i));
4372             emitpcode(POC_SUBFW, popGet(AOP(right),size,FALSE,FALSE));
4373
4374             emitcode("movlw","0x%x",i);
4375             emitcode("subwf","%s,w",aopGet(AOP(right),size,FALSE,FALSE));
4376             genSkipc(ifx,IC_TRUE(ifx) != NULL);
4377           }
4378         }
4379         ifx->generated = 1;
4380         return;
4381       }
4382
4383
4384       // CLRC;
4385       DEBUGemitcode(";sign","%d",sign);
4386
4387       emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4388       emitcode("subwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));//++
4389
4390       emitpcode(POC_MOVFW, popGet(AOP(right),offset,FALSE,FALSE));
4391       emitpcode(POC_SUBFW, popGet(AOP(left),offset++,FALSE,FALSE));
4392
4393       size--;
4394       while (size--) {
4395
4396         emitpcode(POC_MOVFW,   popGet(AOP(right),offset,FALSE,FALSE));
4397         emitSKPC;
4398         emitpcode(POC_INCFSZW, popGet(AOP(right),offset,FALSE,FALSE));
4399         emitpcode(POC_SUBFW,   popGet(AOP(left),offset,FALSE,FALSE));
4400
4401 /*
4402         emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4403         emitSKPC;
4404         emitcode("incfsz","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4405         emitcode("subwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4406 */
4407         offset++;
4408       }
4409     }
4410   }
4411
4412   //release:
4413   if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4414     outBitC(result);
4415   } else {
4416     /* if the result is used in the next
4417        ifx conditional branch then generate
4418        code a little differently */
4419     if (ifx )
4420       genIfxJump (ifx,"c");
4421     else
4422       outBitC(result);
4423     /* leave the result in acc */
4424   }
4425
4426 }
4427
4428 /*-----------------------------------------------------------------*/
4429 /* genCmpGt :- greater than comparison                             */
4430 /*-----------------------------------------------------------------*/
4431 static void genCmpGt (iCode *ic, iCode *ifx)
4432 {
4433     operand *left, *right, *result;
4434     sym_link *letype , *retype;
4435     int sign ;
4436
4437     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4438     left = IC_LEFT(ic);
4439     right= IC_RIGHT(ic);
4440     result = IC_RESULT(ic);
4441
4442     letype = getSpec(operandType(left));
4443     retype =getSpec(operandType(right));
4444     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4445     /* assign the amsops */
4446     aopOp (left,ic,FALSE);
4447     aopOp (right,ic,FALSE);
4448     aopOp (result,ic,TRUE);
4449
4450     genCmp(right, left, result, ifx, sign);
4451
4452     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4453     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4454     freeAsmop(result,NULL,ic,TRUE); 
4455 }
4456
4457 /*-----------------------------------------------------------------*/
4458 /* genCmpLt - less than comparisons                                */
4459 /*-----------------------------------------------------------------*/
4460 static void genCmpLt (iCode *ic, iCode *ifx)
4461 {
4462     operand *left, *right, *result;
4463     sym_link *letype , *retype;
4464     int sign ;
4465
4466     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4467     left = IC_LEFT(ic);
4468     right= IC_RIGHT(ic);
4469     result = IC_RESULT(ic);
4470
4471     letype = getSpec(operandType(left));
4472     retype =getSpec(operandType(right));
4473     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4474
4475     /* assign the amsops */
4476     aopOp (left,ic,FALSE);
4477     aopOp (right,ic,FALSE);
4478     aopOp (result,ic,TRUE);
4479
4480     genCmp(left, right, result, ifx, sign);
4481
4482     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4483     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4484     freeAsmop(result,NULL,ic,TRUE); 
4485 }
4486
4487 /*-----------------------------------------------------------------*/
4488 /* gencjneshort - compare and jump if not equal                    */
4489 /*-----------------------------------------------------------------*/
4490 static void gencjneshort(operand *left, operand *right, symbol *lbl)
4491 {
4492     int size = max(AOP_SIZE(left),AOP_SIZE(right));
4493     int offset = 0;
4494     unsigned long lit = 0L;
4495
4496     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4497     /* if the left side is a literal or 
4498     if the right is in a pointer register and left 
4499     is not */
4500     if ((AOP_TYPE(left) == AOP_LIT) || 
4501         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4502         operand *t = right;
4503         right = left;
4504         left = t;
4505     }
4506     if(AOP_TYPE(right) == AOP_LIT)
4507         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4508
4509     /* if the right side is a literal then anything goes */
4510     if (AOP_TYPE(right) == AOP_LIT &&
4511         AOP_TYPE(left) != AOP_DIR ) {
4512         while (size--) {
4513           if(lit & 0xff) {
4514             emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4515             emitcode("xorlw","0x%x",lit & 0xff);
4516           } else
4517             emitcode("movf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
4518
4519           emitSKPNZ;
4520           emitcode("goto","_%05d_DS_",lbl->key+100+labelOffset);
4521           offset++;
4522           lit >>= 8;
4523         }
4524     }
4525
4526     /* if the right side is in a register or in direct space or
4527     if the left is a pointer register & right is not */    
4528     else if (AOP_TYPE(right) == AOP_REG ||
4529              AOP_TYPE(right) == AOP_DIR || 
4530              (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4531              (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
4532         while (size--) {
4533           if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
4534              ( (lit & 0xff) != 0)) {
4535             emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4536             emitcode("xorlw","0x%x",lit & 0xff);
4537             lit >>= 8;
4538           } else
4539             emitcode("movf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
4540
4541           emitSKPZ;
4542           emitcode("goto","_%05d_DS_",lbl->key+100+labelOffset);
4543           offset++;
4544 /*
4545             MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
4546             if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
4547                ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
4548                 emitcode("jnz","%05d_DS_",lbl->key+100);
4549             else
4550                 emitcode("cjne","a,%s,%05d_DS_",
4551                          aopGet(AOP(right),offset,FALSE,TRUE),
4552                          lbl->key+100);
4553             offset++;
4554 */
4555         }
4556     } else {
4557         /* right is a pointer reg need both a & b */
4558         while(size--) {
4559             char *l = aopGet(AOP(left),offset,FALSE,FALSE);
4560             if(strcmp(l,"b"))
4561                 emitcode("mov","b,%s",l);
4562             MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4563             emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
4564             offset++;
4565         }
4566     }
4567 }
4568
4569 /*-----------------------------------------------------------------*/
4570 /* gencjne - compare and jump if not equal                         */
4571 /*-----------------------------------------------------------------*/
4572 static void gencjne(operand *left, operand *right, symbol *lbl)
4573 {
4574     symbol *tlbl  = newiTempLabel(NULL);
4575
4576     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4577     gencjneshort(left, right, lbl);
4578
4579     emitcode("mov","a,%s",one);
4580     emitcode("sjmp","%05d_DS_",tlbl->key+100);
4581     emitcode("","%05d_DS_:",lbl->key+100);
4582     emitcode("clr","a");
4583     emitcode("","%05d_DS_:",tlbl->key+100);
4584 }
4585
4586
4587 /*-----------------------------------------------------------------*/
4588 /* genCmpEq - generates code for equal to                          */
4589 /*-----------------------------------------------------------------*/
4590 static void genCmpEq (iCode *ic, iCode *ifx)
4591 {
4592     operand *left, *right, *result;
4593     unsigned long lit = 0L;
4594     int size,offset=0;
4595
4596     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4597     if(ifx)
4598       DEBUGemitcode ("; ifx is non-null","");
4599     else
4600       DEBUGemitcode ("; ifx is null","");
4601
4602     aopOp((left=IC_LEFT(ic)),ic,FALSE);
4603     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4604     aopOp((result=IC_RESULT(ic)),ic,TRUE);
4605
4606     size = max(AOP_SIZE(left),AOP_SIZE(right));
4607
4608     /* if literal, literal on the right or 
4609     if the right is in a pointer register and left 
4610     is not */
4611     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
4612         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4613         operand *t = IC_RIGHT(ic);
4614         IC_RIGHT(ic) = IC_LEFT(ic);
4615         IC_LEFT(ic) = t;
4616     }
4617
4618     if(ifx && !AOP_SIZE(result)){
4619         symbol *tlbl;
4620         /* if they are both bit variables */
4621         if (AOP_TYPE(left) == AOP_CRY &&
4622             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4623             if(AOP_TYPE(right) == AOP_LIT){
4624                 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4625                 if(lit == 0L){
4626                     emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4627                     emitcode("cpl","c");
4628                 } else if(lit == 1L) {
4629                     emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4630                 } else {
4631                     emitcode("clr","c");
4632                 }
4633                 /* AOP_TYPE(right) == AOP_CRY */
4634             } else {
4635                 symbol *lbl = newiTempLabel(NULL);
4636                 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4637                 emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4638                 emitcode("cpl","c");
4639                 emitcode("","%05d_DS_:",(lbl->key+100));
4640             }
4641             /* if true label then we jump if condition
4642             supplied is true */
4643             tlbl = newiTempLabel(NULL);
4644             if ( IC_TRUE(ifx) ) {
4645                 emitcode("jnc","%05d_DS_",tlbl->key+100);
4646                 emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
4647             } else {
4648                 emitcode("jc","%05d_DS_",tlbl->key+100);
4649                 emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
4650             }
4651             emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
4652         } else {
4653
4654           /* They're not both bit variables. Is the right a literal? */
4655           if(AOP_TYPE(right) == AOP_LIT) {
4656
4657             lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4658             while (size--) {
4659
4660               if(size >= 1) {
4661                 int l = lit & 0xff;
4662                 int h = (lit>>8) & 0xff;
4663                 int optimized=0;
4664
4665                 /* Check special cases for integers */
4666                 switch(lit & 0xffff) {
4667                 case 0x0000:
4668                   emitpcode(POC_MOVFW,popGet(AOP(left),offset,FALSE,FALSE));
4669                   emitpcode(POC_IORFW,popGet(AOP(left),offset+1,FALSE,FALSE));
4670                   //emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4671                   //emitcode("iorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4672                   genSkip(ifx,'z');
4673                   optimized++;
4674                   break;
4675                 case 0x0001:
4676                   emitpcode(POC_DECFW,popGet(AOP(left),offset,FALSE,FALSE));
4677                   emitpcode(POC_IORFW,popGet(AOP(left),offset+1,FALSE,FALSE));
4678                   emitcode("decf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4679                   emitcode("iorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4680                   genSkip(ifx,'z');
4681                   optimized++;
4682                   break;
4683                 case 0x0100:
4684                   emitpcode(POC_DECFW,popGet(AOP(left),offset+1,FALSE,FALSE));
4685                   emitpcode(POC_IORFW,popGet(AOP(left),offset,FALSE,FALSE));
4686                   emitcode("decf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4687                   emitcode("iorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4688                   genSkip(ifx,'z');
4689                   optimized++;
4690                   break;
4691                 case 0x00ff:
4692                   emitpcode(POC_INCFW,popGet(AOP(left),offset,FALSE,FALSE));
4693                   emitpcode(POC_IORFW,popGet(AOP(left),offset+1,FALSE,FALSE));
4694                   emitcode("incf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4695                   emitcode("iorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4696                   genSkip(ifx,'z');
4697                   optimized++;
4698                   break;
4699                 case 0xff00:
4700                   emitpcode(POC_INCFW,popGet(AOP(left),offset+1,FALSE,FALSE));
4701                   emitpcode(POC_IORFW,popGet(AOP(left),offset,FALSE,FALSE));
4702                   emitcode("incf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4703                   emitcode("iorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4704                   genSkip(ifx,'z');
4705                   optimized++;
4706                   break;
4707                 default:
4708                   if(h == 0) {
4709                     emitpcode(POC_MOVFW,popGet(AOP(left),offset,FALSE,FALSE));
4710                     emitpcode(POC_XORLW,popGetLit(l));
4711                     emitpcode(POC_IORFW,popGet(AOP(left),offset+1,FALSE,FALSE));
4712
4713                     emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4714                     emitcode("xorlw","0x%x",l);
4715                     emitcode("iorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4716                     optimized++;
4717                     genSkip(ifx,'z');
4718                   } else if (l == 0) {
4719                     emitpcode(POC_MOVFW,popGet(AOP(left),offset+1,FALSE,FALSE));
4720                     emitpcode(POC_XORLW,popGetLit(h));
4721                     emitpcode(POC_IORFW,popGet(AOP(left),offset,FALSE,FALSE));
4722
4723                     emitcode("movf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4724                     emitcode("xorlw","0x%x",h);
4725                     emitcode("iorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4726                     optimized++;
4727                     genSkip(ifx,'z');
4728                   } else {
4729                     emitpcode(POC_MOVFW,popGet(AOP(left),offset,FALSE,FALSE));
4730                     emitpcode(POC_XORLW,popGetLit(l));
4731                     emitpcode(POC_MOVLW,popGetLit(h));
4732                     emitSKPZ;
4733                     emitpcode(POC_XORFW,popGet(AOP(left),offset+1,FALSE,FALSE));
4734 /*
4735                     emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4736                     emitcode("xorlw","0x%x",l);
4737                     emitcode("movlw","0x%x",h);
4738                     emitSKPZ;
4739                     emitcode("xorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4740 */
4741                     optimized++;
4742                     genSkip(ifx,'z');
4743                   }
4744
4745                 }
4746                 if(optimized) {
4747                   size--;
4748                   offset+=2;
4749                   lit>>=16;
4750
4751                   continue;
4752                 }
4753                   
4754               }
4755                 
4756               switch(lit & 0xff) {
4757               case 1:
4758                 if ( IC_TRUE(ifx) ) {
4759
4760                   emitcode("decf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4761
4762                   emitpcode(POC_DECFW,popGet(AOP(left),offset,FALSE,FALSE));
4763                   emitSKPNZ;
4764                   emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4765
4766                   emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4767                 } else {
4768                   emitpcode(POC_DECFSZW,popGet(AOP(left),offset,FALSE,FALSE));
4769                   emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4770
4771                   emitcode("decfsz","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4772                   emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4773                 }
4774                 break;
4775               case 0xff:
4776                 if ( IC_TRUE(ifx) ) {
4777                   emitcode("incf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4778
4779                   emitpcode(POC_INCFW,popGet(AOP(left),offset,FALSE,FALSE));
4780                   emitSKPNZ;
4781                   emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4782
4783                   emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4784                 } else {
4785                   emitpcode(POC_INCFSZW,popGet(AOP(left),offset,FALSE,FALSE));
4786                   emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4787
4788                   emitcode("incfsz","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4789                   emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4790                 }
4791                 break;
4792               default:
4793                 emitpcode(POC_MOVFW,popGet(AOP(left),offset,FALSE,FALSE));
4794                 //emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4795                 if(lit)
4796                   emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4797                 //emitcode("xorlw","0x%x",lit & 0xff);
4798                 genSkip(ifx,'z');
4799               }
4800
4801
4802               //              emitcode("goto","_%05d_DS_",tlbl->key+100+labelOffset);
4803               //emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);                
4804               offset++;
4805               lit >>= 8;
4806             }
4807
4808           } else if(AOP_TYPE(right) == AOP_CRY ) {
4809             /* we know the left is not a bit, but that the right is */
4810             emitpcode(POC_MOVFW,popGet(AOP(left),offset,FALSE,FALSE));
4811             emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
4812                       popGet(AOP(right),offset,FALSE,FALSE));
4813             emitpcode(POC_XORLW,popGetLit(1));
4814
4815             emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4816             if ( IC_TRUE(ifx) )
4817               emitcode("btfsc","(%s >> 3), (%s & 7)",
4818                        AOP(right)->aopu.aop_dir,
4819                        AOP(right)->aopu.aop_dir);
4820             else
4821               emitcode("btfss","(%s >> 3), (%s & 7)",
4822                        AOP(right)->aopu.aop_dir,
4823                        AOP(right)->aopu.aop_dir);
4824
4825             emitcode("xorlw","1");
4826
4827             /* if the two are equal, then W will be 0 and the Z bit is set
4828              * we could test Z now, or go ahead and check the high order bytes if
4829              * the variable we're comparing is larger than a byte. */
4830
4831             while(--size)
4832               emitpcode(POC_IORFW,popGet(AOP(left),offset,FALSE,FALSE));
4833             //emitcode("iorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4834
4835             if ( IC_TRUE(ifx) ) {
4836               emitSKPNZ;
4837               emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4838               emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4839             } else {
4840               emitSKPZ;
4841               emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4842               emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4843             }
4844
4845           } else {
4846             /* They're both variables that are larger than bits */
4847             int s = size;
4848
4849             tlbl = newiTempLabel(NULL);
4850
4851             while(size--) {
4852               emitpcode(POC_MOVFW,popGet(AOP(left),offset,FALSE,FALSE));
4853               emitpcode(POC_XORFW,popGet(AOP(right),offset,FALSE,FALSE));
4854
4855               emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4856               emitcode("xorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4857
4858               if ( IC_TRUE(ifx) ) {
4859                 if(size) {
4860                   emitSKPZ;
4861                   emitpcode(POC_GOTO,popGetLabel(tlbl->key));
4862                   emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset);
4863                 } else {
4864                   emitSKPNZ;
4865                   emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4866                   emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4867                 }
4868               } else {
4869                 emitSKPZ;
4870                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4871                 emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4872               }
4873               offset++;
4874             }
4875             if(s>1 && IC_TRUE(ifx)) {
4876               emitpLabel(tlbl->key+100+labelOffset);
4877               emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);                
4878             }
4879           }
4880         }
4881         /* mark the icode as generated */
4882         ifx->generated = 1;
4883         goto release ;
4884     }
4885
4886     /* if they are both bit variables */
4887     if (AOP_TYPE(left) == AOP_CRY &&
4888         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4889         if(AOP_TYPE(right) == AOP_LIT){
4890             unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4891             if(lit == 0L){
4892                 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4893                 emitcode("cpl","c");
4894             } else if(lit == 1L) {
4895                 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4896             } else {
4897                 emitcode("clr","c");
4898             }
4899             /* AOP_TYPE(right) == AOP_CRY */
4900         } else {
4901             symbol *lbl = newiTempLabel(NULL);
4902             emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4903             emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4904             emitcode("cpl","c");
4905             emitcode("","%05d_DS_:",(lbl->key+100));
4906         }
4907         /* c = 1 if egal */
4908         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
4909             outBitC(result);
4910             goto release ;
4911         }
4912         if (ifx) {
4913             genIfxJump (ifx,"c");
4914             goto release ;
4915         }
4916         /* if the result is used in an arithmetic operation
4917         then put the result in place */
4918         outBitC(result);
4919     } else {
4920         gencjne(left,right,newiTempLabel(NULL));    
4921         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4922             aopPut(AOP(result),"a",0);
4923             goto release ;
4924         }
4925         if (ifx) {
4926             genIfxJump (ifx,"a");
4927             goto release ;
4928         }
4929         /* if the result is used in an arithmetic operation
4930         then put the result in place */
4931         if (AOP_TYPE(result) != AOP_CRY) 
4932             outAcc(result);
4933         /* leave the result in acc */
4934     }
4935
4936 release:
4937     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4938     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4939     freeAsmop(result,NULL,ic,TRUE);
4940 }
4941
4942 /*-----------------------------------------------------------------*/
4943 /* ifxForOp - returns the icode containing the ifx for operand     */
4944 /*-----------------------------------------------------------------*/
4945 static iCode *ifxForOp ( operand *op, iCode *ic )
4946 {
4947     /* if true symbol then needs to be assigned */
4948     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4949     if (IS_TRUE_SYMOP(op))
4950         return NULL ;
4951
4952     /* if this has register type condition and
4953     the next instruction is ifx with the same operand
4954     and live to of the operand is upto the ifx only then */
4955     if (ic->next &&
4956         ic->next->op == IFX &&
4957         IC_COND(ic->next)->key == op->key &&
4958         OP_SYMBOL(op)->liveTo <= ic->next->seq )
4959         return ic->next;
4960
4961     return NULL;
4962 }
4963 /*-----------------------------------------------------------------*/
4964 /* genAndOp - for && operation                                     */
4965 /*-----------------------------------------------------------------*/
4966 static void genAndOp (iCode *ic)
4967 {
4968     operand *left,*right, *result;
4969     symbol *tlbl;
4970
4971     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4972     /* note here that && operations that are in an
4973     if statement are taken away by backPatchLabels
4974     only those used in arthmetic operations remain */
4975     aopOp((left=IC_LEFT(ic)),ic,FALSE);
4976     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4977     aopOp((result=IC_RESULT(ic)),ic,FALSE);
4978
4979     /* if both are bit variables */
4980     if (AOP_TYPE(left) == AOP_CRY &&
4981         AOP_TYPE(right) == AOP_CRY ) {
4982         emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4983         emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
4984         outBitC(result);
4985     } else {
4986         tlbl = newiTempLabel(NULL);
4987         toBoolean(left);    
4988         emitcode("jz","%05d_DS_",tlbl->key+100);
4989         toBoolean(right);
4990         emitcode("","%05d_DS_:",tlbl->key+100);
4991         outBitAcc(result);
4992     }
4993
4994     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4995     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4996     freeAsmop(result,NULL,ic,TRUE);
4997 }
4998
4999
5000 /*-----------------------------------------------------------------*/
5001 /* genOrOp - for || operation                                      */
5002 /*-----------------------------------------------------------------*/
5003 /*
5004   tsd pic port -
5005   modified this code, but it doesn't appear to ever get called
5006 */
5007
5008 static void genOrOp (iCode *ic)
5009 {
5010     operand *left,*right, *result;
5011     symbol *tlbl;
5012
5013     /* note here that || operations that are in an
5014     if statement are taken away by backPatchLabels
5015     only those used in arthmetic operations remain */
5016     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5017     aopOp((left=IC_LEFT(ic)),ic,FALSE);
5018     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5019     aopOp((result=IC_RESULT(ic)),ic,FALSE);
5020
5021     /* if both are bit variables */
5022     if (AOP_TYPE(left) == AOP_CRY &&
5023         AOP_TYPE(right) == AOP_CRY ) {
5024       emitcode("clrc","");
5025       emitcode("btfss","(%s >> 3), (%s & 7)",
5026                AOP(left)->aopu.aop_dir,
5027                AOP(left)->aopu.aop_dir);
5028       emitcode("btfsc","(%s >> 3), (%s & 7)",
5029                AOP(right)->aopu.aop_dir,
5030                AOP(right)->aopu.aop_dir);
5031       emitcode("setc","");
5032
5033     } else {
5034         tlbl = newiTempLabel(NULL);
5035         toBoolean(left);
5036         emitSKPZ;
5037         emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
5038         toBoolean(right);
5039         emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
5040
5041         outBitAcc(result);
5042     }
5043
5044     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5045     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5046     freeAsmop(result,NULL,ic,TRUE);            
5047 }
5048
5049 /*-----------------------------------------------------------------*/
5050 /* isLiteralBit - test if lit == 2^n                               */
5051 /*-----------------------------------------------------------------*/
5052 static int isLiteralBit(unsigned long lit)
5053 {
5054     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5055     0x100L,0x200L,0x400L,0x800L,
5056     0x1000L,0x2000L,0x4000L,0x8000L,
5057     0x10000L,0x20000L,0x40000L,0x80000L,
5058     0x100000L,0x200000L,0x400000L,0x800000L,
5059     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5060     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5061     int idx;
5062     
5063     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5064     for(idx = 0; idx < 32; idx++)
5065         if(lit == pw[idx])
5066             return idx+1;
5067     return 0;
5068 }
5069
5070 /*-----------------------------------------------------------------*/
5071 /* continueIfTrue -                                                */
5072 /*-----------------------------------------------------------------*/
5073 static void continueIfTrue (iCode *ic)
5074 {
5075     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5076     if(IC_TRUE(ic))
5077         emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5078     ic->generated = 1;
5079 }
5080
5081 /*-----------------------------------------------------------------*/
5082 /* jmpIfTrue -                                                     */
5083 /*-----------------------------------------------------------------*/
5084 static void jumpIfTrue (iCode *ic)
5085 {
5086     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5087     if(!IC_TRUE(ic))
5088         emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5089     ic->generated = 1;
5090 }
5091
5092 /*-----------------------------------------------------------------*/
5093 /* jmpTrueOrFalse -                                                */
5094 /*-----------------------------------------------------------------*/
5095 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5096 {
5097     // ugly but optimized by peephole
5098     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5099     if(IC_TRUE(ic)){
5100         symbol *nlbl = newiTempLabel(NULL);
5101         emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
5102         emitcode("","%05d_DS_:",tlbl->key+100);
5103         emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5104         emitcode("","%05d_DS_:",nlbl->key+100);
5105     }
5106     else{
5107         emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5108         emitcode("","%05d_DS_:",tlbl->key+100);
5109     }
5110     ic->generated = 1;
5111 }
5112
5113 /*-----------------------------------------------------------------*/
5114 /* genAnd  - code for and                                          */
5115 /*-----------------------------------------------------------------*/
5116 static void genAnd (iCode *ic, iCode *ifx)
5117 {
5118     operand *left, *right, *result;
5119     int size, offset=0;  
5120     unsigned long lit = 0L;
5121     int bytelit = 0;
5122     char buffer[10];
5123
5124     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5125     aopOp((left = IC_LEFT(ic)),ic,FALSE);
5126     aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5127     aopOp((result=IC_RESULT(ic)),ic,TRUE);
5128
5129 #ifdef DEBUG_TYPE
5130     emitcode("","; Type res[%d] = l[%d]&r[%d]",
5131              AOP_TYPE(result),
5132              AOP_TYPE(left), AOP_TYPE(right));
5133     emitcode("","; Size res[%d] = l[%d]&r[%d]",
5134              AOP_SIZE(result),
5135              AOP_SIZE(left), AOP_SIZE(right));
5136 #endif
5137
5138     /* if left is a literal & right is not then exchange them */
5139     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5140         AOP_NEEDSACC(left)) {
5141         operand *tmp = right ;
5142         right = left;
5143         left = tmp;
5144     }
5145
5146     /* if result = right then exchange them */
5147     if(sameRegs(AOP(result),AOP(right))){
5148         operand *tmp = right ;
5149         right = left;
5150         left = tmp;
5151     }
5152
5153     /* if right is bit then exchange them */
5154     if (AOP_TYPE(right) == AOP_CRY &&
5155         AOP_TYPE(left) != AOP_CRY){
5156         operand *tmp = right ;
5157         right = left;
5158         left = tmp;
5159     }
5160     if(AOP_TYPE(right) == AOP_LIT)
5161         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5162
5163     size = AOP_SIZE(result);
5164
5165     // if(bit & yy)
5166     // result = bit & yy;
5167     if (AOP_TYPE(left) == AOP_CRY){
5168         // c = bit & literal;
5169         if(AOP_TYPE(right) == AOP_LIT){
5170             if(lit & 1) {
5171                 if(size && sameRegs(AOP(result),AOP(left)))
5172                     // no change
5173                     goto release;
5174                 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5175             } else {
5176                 // bit(result) = 0;
5177                 if(size && (AOP_TYPE(result) == AOP_CRY)){
5178                     emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5179                     goto release;
5180                 }
5181                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5182                     jumpIfTrue(ifx);
5183                     goto release;
5184                 }
5185                 emitcode("clr","c");
5186             }
5187         } else {
5188             if (AOP_TYPE(right) == AOP_CRY){
5189                 // c = bit & bit;
5190                 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5191                 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5192             } else {
5193                 // c = bit & val;
5194                 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
5195                 // c = lsb
5196                 emitcode("rrc","a");
5197                 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5198             }
5199         }
5200         // bit = c
5201         // val = c
5202         if(size)
5203             outBitC(result);
5204         // if(bit & ...)
5205         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5206             genIfxJump(ifx, "c");           
5207         goto release ;
5208     }
5209
5210     // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5211     // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5212     if((AOP_TYPE(right) == AOP_LIT) &&
5213        (AOP_TYPE(result) == AOP_CRY) &&
5214        (AOP_TYPE(left) != AOP_CRY)){
5215         int posbit = isLiteralBit(lit);
5216         /* left &  2^n */
5217         if(posbit){
5218             posbit--;
5219             MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5220             // bit = left & 2^n
5221             if(size)
5222                 emitcode("mov","c,acc.%d",posbit&0x07);
5223             // if(left &  2^n)
5224             else{
5225                 if(ifx){
5226                     sprintf(buffer,"acc.%d",posbit&0x07);
5227                     genIfxJump(ifx, buffer);
5228                 }
5229                 goto release;
5230             }
5231         } else {
5232             symbol *tlbl = newiTempLabel(NULL);
5233             int sizel = AOP_SIZE(left);
5234             if(size)
5235                 emitcode("setb","c");
5236             while(sizel--){
5237                 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5238                     MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
5239                     // byte ==  2^n ?
5240                     if((posbit = isLiteralBit(bytelit)) != 0)
5241                         emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5242                     else{
5243                         if(bytelit != 0x0FFL)
5244                             emitcode("anl","a,%s",
5245                                      aopGet(AOP(right),offset,FALSE,TRUE));
5246                         emitcode("jnz","%05d_DS_",tlbl->key+100);
5247                     }
5248                 }
5249                 offset++;
5250             }
5251             // bit = left & literal
5252             if(size){
5253                 emitcode("clr","c");
5254                 emitcode("","%05d_DS_:",tlbl->key+100);
5255             }
5256             // if(left & literal)
5257             else{
5258                 if(ifx)
5259                     jmpTrueOrFalse(ifx, tlbl);
5260                 goto release ;
5261             }
5262         }
5263         outBitC(result);
5264         goto release ;
5265     }
5266
5267     /* if left is same as result */
5268     if(sameRegs(AOP(result),AOP(left))){
5269       for(;size--; offset++,lit>>=8) {
5270         if(AOP_TYPE(right) == AOP_LIT){
5271           switch(lit & 0xff) {
5272           case 0x00:
5273             /*  and'ing with 0 has clears the result */
5274             emitcode("clrf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5275             break;
5276           case 0xff:
5277             emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5278             break;
5279
5280           default:
5281             {
5282               int p = my_powof2( (~lit) & 0xff );
5283               if(p>=0) {
5284                 /* only one bit is set in the literal, so use a bcf instruction */
5285                 emitcode("bcf","%s,%d",aopGet(AOP(left),offset,FALSE,TRUE),p);
5286               } else {
5287                 emitcode("movlw","0x%x", (lit & 0xff));
5288                 emitcode("andwf","%s,f",aopGet(AOP(left),offset,FALSE,TRUE),p);
5289               }
5290             }    
5291           }
5292         } else {
5293           if (AOP_TYPE(left) == AOP_ACC) 
5294             emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5295           else {                    
5296             emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5297             emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
5298
5299           }
5300         }
5301       }
5302
5303     } else {
5304         // left & result in different registers
5305         if(AOP_TYPE(result) == AOP_CRY){
5306             // result = bit
5307             // if(size), result in bit
5308             // if(!size && ifx), conditional oper: if(left & right)
5309             symbol *tlbl = newiTempLabel(NULL);
5310             int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5311             if(size)
5312                 emitcode("setb","c");
5313             while(sizer--){
5314                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5315                 emitcode("anl","a,%s",
5316                          aopGet(AOP(left),offset,FALSE,FALSE));
5317                 emitcode("jnz","%05d_DS_",tlbl->key+100);
5318                 offset++;
5319             }
5320             if(size){
5321                 CLRC;
5322                 emitcode("","%05d_DS_:",tlbl->key+100);
5323                 outBitC(result);
5324             } else if(ifx)
5325                 jmpTrueOrFalse(ifx, tlbl);
5326         } else {
5327           for(;(size--);offset++) {
5328             // normal case
5329             // result = left & right
5330             if(AOP_TYPE(right) == AOP_LIT){
5331               int t = (lit >> (offset*8)) & 0x0FFL;
5332               switch(t) { 
5333               case 0x00:
5334                 emitcode("clrf","%s",
5335                          aopGet(AOP(result),offset,FALSE,FALSE));
5336                 break;
5337               case 0xff:
5338                 emitcode("movf","%s,w",
5339                          aopGet(AOP(left),offset,FALSE,FALSE));
5340                 emitcode("movwf","%s",
5341                          aopGet(AOP(result),offset,FALSE,FALSE));
5342                 break;
5343               default:
5344                 emitcode("movlw","0x%x",t);
5345                 emitcode("andwf","%s,w",
5346                          aopGet(AOP(left),offset,FALSE,FALSE));
5347                 emitcode("movwf","%s",
5348                          aopGet(AOP(result),offset,FALSE,FALSE));
5349               
5350               }
5351               continue;
5352             }
5353
5354             if (AOP_TYPE(left) == AOP_ACC) 
5355               emitcode("andwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5356             else {
5357               emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5358               emitcode("andwf","%s,w",
5359                        aopGet(AOP(left),offset,FALSE,FALSE));
5360             }
5361             emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5362           }
5363         }
5364     }
5365
5366 release :
5367     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5368     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5369     freeAsmop(result,NULL,ic,TRUE);     
5370 }
5371
5372 /*-----------------------------------------------------------------*/
5373 /* genOr  - code for or                                            */
5374 /*-----------------------------------------------------------------*/
5375 static void genOr (iCode *ic, iCode *ifx)
5376 {
5377     operand *left, *right, *result;
5378     int size, offset=0;
5379     unsigned long lit = 0L;
5380
5381     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5382
5383     aopOp((left = IC_LEFT(ic)),ic,FALSE);
5384     aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5385     aopOp((result=IC_RESULT(ic)),ic,TRUE);
5386
5387
5388     /* if left is a literal & right is not then exchange them */
5389     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5390         AOP_NEEDSACC(left)) {
5391         operand *tmp = right ;
5392         right = left;
5393         left = tmp;
5394     }
5395
5396     /* if result = right then exchange them */
5397     if(sameRegs(AOP(result),AOP(right))){
5398         operand *tmp = right ;
5399         right = left;
5400         left = tmp;
5401     }
5402
5403     /* if right is bit then exchange them */
5404     if (AOP_TYPE(right) == AOP_CRY &&
5405         AOP_TYPE(left) != AOP_CRY){
5406         operand *tmp = right ;
5407         right = left;
5408         left = tmp;
5409     }
5410
5411     if(AOP_TYPE(right) == AOP_LIT)
5412         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5413
5414     size = AOP_SIZE(result);
5415
5416     // if(bit | yy)
5417     // xx = bit | yy;
5418     if (AOP_TYPE(left) == AOP_CRY){
5419         if(AOP_TYPE(right) == AOP_LIT){
5420             // c = bit & literal;
5421             if(lit){
5422                 // lit != 0 => result = 1
5423                 if(AOP_TYPE(result) == AOP_CRY){
5424                   if(size)
5425                     emitpcode(POC_BSF, popGet(AOP(result),0,FALSE,FALSE));
5426                   //emitcode("bsf","(%s >> 3), (%s & 7)",
5427                   //     AOP(result)->aopu.aop_dir,
5428                   //     AOP(result)->aopu.aop_dir);
5429                     else if(ifx)
5430                         continueIfTrue(ifx);
5431                     goto release;
5432                 }
5433             } else {
5434                 // lit == 0 => result = left
5435                 if(size && sameRegs(AOP(result),AOP(left)))
5436                     goto release;
5437                 emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5438             }
5439         } else {
5440             if (AOP_TYPE(right) == AOP_CRY){
5441               if(sameRegs(AOP(result),AOP(left))){
5442                 // c = bit | bit;
5443                 emitpcode(POC_BCF,   popGet(AOP(result),0,FALSE,FALSE));
5444                 emitpcode(POC_BTFSC, popGet(AOP(right),0,FALSE,FALSE));
5445                 emitpcode(POC_BSF,   popGet(AOP(result),0,FALSE,FALSE));
5446
5447                 emitcode("bcf","(%s >> 3), (%s & 7)",
5448                          AOP(result)->aopu.aop_dir,
5449                          AOP(result)->aopu.aop_dir);
5450                 emitcode("btfsc","(%s >> 3), (%s & 7)",
5451                          AOP(right)->aopu.aop_dir,
5452                          AOP(right)->aopu.aop_dir);
5453                 emitcode("bsf","(%s >> 3), (%s & 7)",
5454                          AOP(result)->aopu.aop_dir,
5455                          AOP(result)->aopu.aop_dir);
5456               } else {
5457
5458                 emitpcode(POC_BCF,   popGet(AOP(result),0,FALSE,FALSE));
5459                 emitpcode(POC_BTFSS, popGet(AOP(right),0,FALSE,FALSE));
5460                 emitpcode(POC_BTFSC, popGet(AOP(left),0,FALSE,FALSE));
5461                 emitpcode(POC_BSF,   popGet(AOP(result),0,FALSE,FALSE));
5462
5463                 emitcode("bcf","(%s >> 3), (%s & 7)",
5464                          AOP(result)->aopu.aop_dir,
5465                          AOP(result)->aopu.aop_dir);
5466                 emitcode("btfss","(%s >> 3), (%s & 7)",
5467                          AOP(right)->aopu.aop_dir,
5468                          AOP(right)->aopu.aop_dir);
5469                 emitcode("btfsc","(%s >> 3), (%s & 7)",
5470                          AOP(left)->aopu.aop_dir,
5471                          AOP(left)->aopu.aop_dir);
5472                 emitcode("bsf","(%s >> 3), (%s & 7)",
5473                          AOP(result)->aopu.aop_dir,
5474                          AOP(result)->aopu.aop_dir);
5475               }
5476             }
5477             else{
5478                 // c = bit | val;
5479                 symbol *tlbl = newiTempLabel(NULL);
5480                 emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5481                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5482                     emitcode(";XXX setb","c");
5483                 emitcode(";XXX jb","%s,%05d_DS_",
5484                          AOP(left)->aopu.aop_dir,tlbl->key+100);
5485                 toBoolean(right);
5486                 emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5487                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5488                     jmpTrueOrFalse(ifx, tlbl);
5489                     goto release;
5490                 } else {
5491                     CLRC;
5492                     emitcode("","%05d_DS_:",tlbl->key+100);
5493                 }
5494             }
5495         }
5496         // bit = c
5497         // val = c
5498         if(size)
5499             outBitC(result);
5500         // if(bit | ...)
5501         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5502             genIfxJump(ifx, "c");           
5503         goto release ;
5504     }
5505
5506     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5507     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5508     if((AOP_TYPE(right) == AOP_LIT) &&
5509        (AOP_TYPE(result) == AOP_CRY) &&
5510        (AOP_TYPE(left) != AOP_CRY)){
5511         if(lit){
5512           emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5513             // result = 1
5514             if(size)
5515                 emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5516             else 
5517                 continueIfTrue(ifx);
5518             goto release;
5519         } else {
5520           emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5521             // lit = 0, result = boolean(left)
5522             if(size)
5523                 emitcode(";XXX setb","c");
5524             toBoolean(right);
5525             if(size){
5526                 symbol *tlbl = newiTempLabel(NULL);
5527                 emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5528                 CLRC;
5529                 emitcode("","%05d_DS_:",tlbl->key+100);
5530             } else {
5531                 genIfxJump (ifx,"a");
5532                 goto release;
5533             }
5534         }
5535         outBitC(result);
5536         goto release ;
5537     }
5538
5539     /* if left is same as result */
5540     if(sameRegs(AOP(result),AOP(left))){
5541       for(;size--; offset++,lit>>=8) {
5542         if(AOP_TYPE(right) == AOP_LIT){
5543           if((lit & 0xff) == 0)
5544             /*  or'ing with 0 has no effect */
5545             continue;
5546           else {
5547             int p = my_powof2(lit & 0xff);
5548             if(p>=0) {
5549               /* only one bit is set in the literal, so use a bsf instruction */
5550               emitpcode(POC_BSF,   popGet(AOP(left),offset,FALSE,FALSE));
5551               emitcode("bsf","%s,%d",aopGet(AOP(left),offset,FALSE,TRUE),p);
5552             } else {
5553               emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5554               emitpcode(POC_IORWF, popGet(AOP(left),offset,FALSE,FALSE));
5555
5556               emitcode("movlw","0x%x", (lit & 0xff));
5557               emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,TRUE),p);
5558             }
5559                     
5560           }
5561         } else {
5562           if (AOP_TYPE(left) == AOP_ACC) {
5563             emitpcode(POC_IORFW,  popGet(AOP(right),offset,FALSE,FALSE));
5564             emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5565           } else {                  
5566             emitpcode(POC_MOVFW,  popGet(AOP(right),offset,FALSE,FALSE));
5567             emitpcode(POC_IORWF,  popGet(AOP(left),offset,FALSE,FALSE));
5568
5569             emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5570             emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
5571
5572           }
5573         }
5574       }
5575     } else {
5576         // left & result in different registers
5577         if(AOP_TYPE(result) == AOP_CRY){
5578             // result = bit
5579             // if(size), result in bit
5580             // if(!size && ifx), conditional oper: if(left | right)
5581             symbol *tlbl = newiTempLabel(NULL);
5582             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5583             emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5584
5585             if(size)
5586                 emitcode(";XXX setb","c");
5587             while(sizer--){
5588                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5589                 emitcode(";XXX orl","a,%s",
5590                          aopGet(AOP(left),offset,FALSE,FALSE));
5591                 emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5592                 offset++;
5593             }
5594             if(size){
5595                 CLRC;
5596                 emitcode("","%05d_DS_:",tlbl->key+100);
5597                 outBitC(result);
5598             } else if(ifx)
5599                 jmpTrueOrFalse(ifx, tlbl);
5600         } else for(;(size--);offset++){
5601           // normal case
5602           // result = left & right
5603           if(AOP_TYPE(right) == AOP_LIT){
5604             int t = (lit >> (offset*8)) & 0x0FFL;
5605             switch(t) { 
5606             case 0x00:
5607               emitpcode(POC_MOVFW,  popGet(AOP(left),offset,FALSE,FALSE));
5608               emitpcode(POC_MOVWF,  popGet(AOP(result),offset,FALSE,FALSE));
5609
5610               emitcode("movf","%s,w",
5611                        aopGet(AOP(left),offset,FALSE,FALSE));
5612               emitcode("movwf","%s",
5613                        aopGet(AOP(result),offset,FALSE,FALSE));
5614               break;
5615             default:
5616               emitpcode(POC_MOVLW,  popGetLit(t));
5617               emitpcode(POC_IORFW,  popGet(AOP(left),offset,FALSE,FALSE));
5618               emitpcode(POC_MOVWF,  popGet(AOP(result),offset,FALSE,FALSE));
5619
5620               emitcode("movlw","0x%x",t);
5621               emitcode("iorwf","%s,w",
5622                        aopGet(AOP(left),offset,FALSE,FALSE));
5623               emitcode("movwf","%s",
5624                        aopGet(AOP(result),offset,FALSE,FALSE));
5625               
5626             }
5627             continue;
5628           }
5629
5630           // faster than result <- left, anl result,right
5631           // and better if result is SFR
5632           if (AOP_TYPE(left) == AOP_ACC) {
5633             emitpcode(POC_IORWF,  popGet(AOP(right),offset,FALSE,FALSE));
5634             emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5635           } else {
5636             emitpcode(POC_MOVFW,  popGet(AOP(right),offset,FALSE,FALSE));
5637             emitpcode(POC_IORFW,  popGet(AOP(left),offset,FALSE,FALSE));
5638
5639             emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5640             emitcode("iorwf","%s,w",
5641                      aopGet(AOP(left),offset,FALSE,FALSE));
5642           }
5643           emitpcode(POC_MOVWF,  popGet(AOP(result),offset,FALSE,FALSE));
5644           emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5645         }
5646     }
5647
5648 release :
5649     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5650     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5651     freeAsmop(result,NULL,ic,TRUE);     
5652 }
5653
5654 /*-----------------------------------------------------------------*/
5655 /* genXor - code for xclusive or                                   */
5656 /*-----------------------------------------------------------------*/
5657 static void genXor (iCode *ic, iCode *ifx)
5658 {
5659     operand *left, *right, *result;
5660     int size, offset=0;
5661     unsigned long lit = 0L;
5662
5663     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5664
5665     aopOp((left = IC_LEFT(ic)),ic,FALSE);
5666     aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5667     aopOp((result=IC_RESULT(ic)),ic,TRUE);
5668
5669     /* if left is a literal & right is not ||
5670        if left needs acc & right does not */
5671     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5672         (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
5673         operand *tmp = right ;
5674         right = left;
5675         left = tmp;
5676     }
5677
5678     /* if result = right then exchange them */
5679     if(sameRegs(AOP(result),AOP(right))){
5680         operand *tmp = right ;
5681         right = left;
5682         left = tmp;
5683     }
5684
5685     /* if right is bit then exchange them */
5686     if (AOP_TYPE(right) == AOP_CRY &&
5687         AOP_TYPE(left) != AOP_CRY){
5688         operand *tmp = right ;
5689         right = left;
5690         left = tmp;
5691     }
5692     if(AOP_TYPE(right) == AOP_LIT)
5693         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5694
5695     size = AOP_SIZE(result);
5696
5697     // if(bit ^ yy)
5698     // xx = bit ^ yy;
5699     if (AOP_TYPE(left) == AOP_CRY){
5700         if(AOP_TYPE(right) == AOP_LIT){
5701             // c = bit & literal;
5702             if(lit>>1){
5703                 // lit>>1  != 0 => result = 1
5704                 if(AOP_TYPE(result) == AOP_CRY){
5705                     if(size)
5706                         emitcode("setb","%s",AOP(result)->aopu.aop_dir);
5707                     else if(ifx)
5708                         continueIfTrue(ifx);
5709                     goto release;
5710                 }
5711                 emitcode("setb","c");
5712             } else{
5713                 // lit == (0 or 1)
5714                 if(lit == 0){
5715                     // lit == 0, result = left
5716                     if(size && sameRegs(AOP(result),AOP(left)))
5717                         goto release;
5718                     emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5719                 } else{
5720                     // lit == 1, result = not(left)
5721                     if(size && sameRegs(AOP(result),AOP(left))){
5722                         emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
5723                         goto release;
5724                     } else {
5725                         emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5726                         emitcode("cpl","c");
5727                     }
5728                 }
5729             }
5730
5731         } else {
5732             // right != literal
5733             symbol *tlbl = newiTempLabel(NULL);
5734             if (AOP_TYPE(right) == AOP_CRY){
5735                 // c = bit ^ bit;
5736                 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5737             }
5738             else{
5739                 int sizer = AOP_SIZE(right);
5740                 // c = bit ^ val
5741                 // if val>>1 != 0, result = 1
5742                 emitcode("setb","c");
5743                 while(sizer){
5744                     MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
5745                     if(sizer == 1)
5746                         // test the msb of the lsb
5747                         emitcode("anl","a,#0xfe");
5748                     emitcode("jnz","%05d_DS_",tlbl->key+100);
5749                     sizer--;
5750                 }
5751                 // val = (0,1)
5752                 emitcode("rrc","a");
5753             }
5754             emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
5755             emitcode("cpl","c");
5756             emitcode("","%05d_DS_:",(tlbl->key+100));
5757         }
5758         // bit = c
5759         // val = c
5760         if(size)
5761             outBitC(result);
5762         // if(bit | ...)
5763         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5764             genIfxJump(ifx, "c");           
5765         goto release ;
5766     }
5767
5768     if(sameRegs(AOP(result),AOP(left))){
5769         /* if left is same as result */
5770         for(;size--; offset++) {
5771             if(AOP_TYPE(right) == AOP_LIT){
5772                 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
5773                     continue;
5774                 else
5775                     if (IS_AOP_PREG(left)) {
5776                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5777                         emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
5778                         aopPut(AOP(result),"a",offset);
5779                     } else 
5780                         emitcode("xrl","%s,%s",
5781                                  aopGet(AOP(left),offset,FALSE,TRUE),
5782                                  aopGet(AOP(right),offset,FALSE,FALSE));
5783             } else {
5784                 if (AOP_TYPE(left) == AOP_ACC)
5785                     emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
5786                 else {
5787                     MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5788                     if (IS_AOP_PREG(left)) {
5789                         emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
5790                         aopPut(AOP(result),"a",offset);
5791                     } else
5792                         emitcode("xrl","%s,a",
5793                                  aopGet(AOP(left),offset,FALSE,TRUE));
5794                 }
5795             }
5796         }
5797     } else {
5798         // left & result in different registers
5799         if(AOP_TYPE(result) == AOP_CRY){
5800             // result = bit
5801             // if(size), result in bit
5802             // if(!size && ifx), conditional oper: if(left ^ right)
5803             symbol *tlbl = newiTempLabel(NULL);
5804             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5805             if(size)
5806                 emitcode("setb","c");
5807             while(sizer--){
5808                 if((AOP_TYPE(right) == AOP_LIT) &&
5809                    (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
5810                     MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
5811                 } else {
5812                     MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5813                     emitcode("xrl","a,%s",
5814                              aopGet(AOP(left),offset,FALSE,FALSE));
5815                 }
5816                 emitcode("jnz","%05d_DS_",tlbl->key+100);
5817                 offset++;
5818             }
5819             if(size){
5820                 CLRC;
5821                 emitcode("","%05d_DS_:",tlbl->key+100);
5822                 outBitC(result);
5823             } else if(ifx)
5824                 jmpTrueOrFalse(ifx, tlbl);
5825         } else for(;(size--);offset++){
5826             // normal case
5827             // result = left & right
5828             if(AOP_TYPE(right) == AOP_LIT){
5829               int t = (lit >> (offset*8)) & 0x0FFL;
5830               switch(t) { 
5831               case 0x00:
5832                 emitcode("movf","%s,w",
5833                          aopGet(AOP(left),offset,FALSE,FALSE));
5834                 emitcode("movwf","%s",
5835                          aopGet(AOP(result),offset,FALSE,FALSE));
5836                 break;
5837               case 0xff:
5838                 emitcode("comf","%s,w",
5839                          aopGet(AOP(left),offset,FALSE,FALSE));
5840                 emitcode("movwf","%s",
5841                          aopGet(AOP(result),offset,FALSE,FALSE));
5842                 break;
5843               default:
5844                 emitcode("movlw","0x%x",t);
5845                 emitcode("xorwf","%s,w",
5846                          aopGet(AOP(left),offset,FALSE,FALSE));
5847                 emitcode("movwf","%s",
5848                          aopGet(AOP(result),offset,FALSE,FALSE));
5849
5850               }
5851               continue;
5852             }
5853
5854             // faster than result <- left, anl result,right
5855             // and better if result is SFR
5856             if (AOP_TYPE(left) == AOP_ACC)
5857                 emitcode("xorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5858             else {
5859                 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5860                 emitcode("xorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
5861             }
5862             if ( AOP_TYPE(result) != AOP_ACC)
5863               emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5864         }
5865     }
5866
5867 release :
5868     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5869     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5870     freeAsmop(result,NULL,ic,TRUE);     
5871 }
5872
5873 /*-----------------------------------------------------------------*/
5874 /* genInline - write the inline code out                           */
5875 /*-----------------------------------------------------------------*/
5876 static void genInline (iCode *ic)
5877 {
5878     char buffer[MAX_INLINEASM];
5879     char *bp = buffer;
5880     char *bp1= buffer;
5881     
5882     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5883
5884     _G.inLine += (!options.asmpeep);
5885     strcpy(buffer,IC_INLINE(ic));
5886
5887     /* emit each line as a code */
5888     while (*bp) {
5889         if (*bp == '\n') {
5890             *bp++ = '\0';
5891             emitcode(bp1,"");
5892             bp1 = bp;
5893         } else {
5894             if (*bp == ':') {
5895                 bp++;
5896                 *bp = '\0';
5897                 bp++;
5898                 emitcode(bp1,"");
5899                 bp1 = bp;
5900             } else
5901                 bp++;
5902         }
5903     }
5904     if (bp1 != bp)
5905         emitcode(bp1,"");
5906     /*     emitcode("",buffer); */
5907     _G.inLine -= (!options.asmpeep);
5908 }
5909
5910 /*-----------------------------------------------------------------*/
5911 /* genRRC - rotate right with carry                                */
5912 /*-----------------------------------------------------------------*/
5913 static void genRRC (iCode *ic)
5914 {
5915     operand *left , *result ;
5916     int size, offset = 0;
5917     char *l;    
5918
5919     /* rotate right with carry */
5920     left = IC_LEFT(ic);
5921     result=IC_RESULT(ic);
5922     aopOp (left,ic,FALSE);
5923     aopOp (result,ic,FALSE);
5924
5925     /* move it to the result */
5926     size = AOP_SIZE(result);    
5927     offset = size - 1 ;
5928     CLRC;
5929     while (size--) {
5930         l = aopGet(AOP(left),offset,FALSE,FALSE);
5931         MOVA(l);
5932         emitcode("rrc","a");
5933         if (AOP_SIZE(result) > 1)
5934             aopPut(AOP(result),"a",offset--);
5935     }
5936     /* now we need to put the carry into the
5937     highest order byte of the result */
5938     if (AOP_SIZE(result) > 1) {
5939         l = aopGet(AOP(result),AOP_SIZE(result)-1,FALSE,FALSE);
5940         MOVA(l);
5941     }
5942     emitcode("mov","acc.7,c");
5943     aopPut(AOP(result),"a",AOP_SIZE(result)-1);
5944     freeAsmop(left,NULL,ic,TRUE);
5945     freeAsmop(result,NULL,ic,TRUE);
5946 }
5947
5948 /*-----------------------------------------------------------------*/
5949 /* genRLC - generate code for rotate left with carry               */
5950 /*-----------------------------------------------------------------*/
5951 static void genRLC (iCode *ic)
5952 {    
5953     operand *left , *result ;
5954     int size, offset = 0;
5955     char *l;    
5956
5957     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5958     /* rotate right with carry */
5959     left = IC_LEFT(ic);
5960     result=IC_RESULT(ic);
5961     aopOp (left,ic,FALSE);
5962     aopOp (result,ic,FALSE);
5963
5964     /* move it to the result */
5965     size = AOP_SIZE(result);    
5966     offset = 0 ;
5967     if (size--) {
5968         l = aopGet(AOP(left),offset,FALSE,FALSE);
5969         MOVA(l);
5970         emitcode("add","a,acc");
5971         if (AOP_SIZE(result) > 1)
5972             aopPut(AOP(result),"a",offset++);
5973         while (size--) {
5974             l = aopGet(AOP(left),offset,FALSE,FALSE);
5975             MOVA(l);
5976             emitcode("rlc","a");
5977             if (AOP_SIZE(result) > 1)
5978                 aopPut(AOP(result),"a",offset++);
5979         }
5980     }
5981     /* now we need to put the carry into the
5982     highest order byte of the result */
5983     if (AOP_SIZE(result) > 1) {
5984         l = aopGet(AOP(result),0,FALSE,FALSE);
5985         MOVA(l);
5986     }
5987     emitcode("mov","acc.0,c");
5988     aopPut(AOP(result),"a",0);
5989     freeAsmop(left,NULL,ic,TRUE);
5990     freeAsmop(result,NULL,ic,TRUE);
5991 }
5992
5993 /*-----------------------------------------------------------------*/
5994 /* genGetHbit - generates code get highest order bit               */
5995 /*-----------------------------------------------------------------*/
5996 static void genGetHbit (iCode *ic)
5997 {
5998     operand *left, *result;
5999     left = IC_LEFT(ic);
6000     result=IC_RESULT(ic);
6001     aopOp (left,ic,FALSE);
6002     aopOp (result,ic,FALSE);
6003
6004     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6005     /* get the highest order byte into a */
6006     MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6007     if(AOP_TYPE(result) == AOP_CRY){
6008         emitcode("rlc","a");
6009         outBitC(result);
6010     }
6011     else{
6012         emitcode("rl","a");
6013         emitcode("anl","a,#0x01");
6014         outAcc(result);
6015     }
6016
6017
6018     freeAsmop(left,NULL,ic,TRUE);
6019     freeAsmop(result,NULL,ic,TRUE);
6020 }
6021
6022 /*-----------------------------------------------------------------*/
6023 /* AccRol - rotate left accumulator by known count                 */
6024 /*-----------------------------------------------------------------*/
6025 static void AccRol (int shCount)
6026 {
6027     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6028     shCount &= 0x0007;              // shCount : 0..7
6029     switch(shCount){
6030         case 0 :
6031             break;
6032         case 1 :
6033             emitcode("rl","a");
6034             break;
6035         case 2 :
6036             emitcode("rl","a");
6037             emitcode("rl","a");
6038             break;
6039         case 3 :
6040             emitcode("swap","a");
6041             emitcode("rr","a");
6042             break;
6043         case 4 :
6044             emitcode("swap","a");
6045             break;
6046         case 5 :
6047             emitcode("swap","a");
6048             emitcode("rl","a");
6049             break;
6050         case 6 :
6051             emitcode("rr","a");
6052             emitcode("rr","a");
6053             break;
6054         case 7 :
6055             emitcode("rr","a");
6056             break;
6057     }
6058 }
6059
6060 /*-----------------------------------------------------------------*/
6061 /* AccLsh - left shift accumulator by known count                  */
6062 /*-----------------------------------------------------------------*/
6063 static void AccLsh (int shCount)
6064 {
6065     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6066     if(shCount != 0){
6067         if(shCount == 1)
6068             emitcode("add","a,acc");
6069         else 
6070             if(shCount == 2) {
6071             emitcode("add","a,acc");
6072             emitcode("add","a,acc");
6073         } else {
6074             /* rotate left accumulator */
6075             AccRol(shCount);
6076             /* and kill the lower order bits */
6077             emitcode("anl","a,#0x%02x", SLMask[shCount]);
6078         }
6079     }
6080 }
6081
6082 /*-----------------------------------------------------------------*/
6083 /* AccRsh - right shift accumulator by known count                 */
6084 /*-----------------------------------------------------------------*/
6085 static void AccRsh (int shCount)
6086 {
6087     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6088     if(shCount != 0){
6089         if(shCount == 1){
6090             CLRC;
6091             emitcode("rrc","a");
6092         } else {
6093             /* rotate right accumulator */
6094             AccRol(8 - shCount);
6095             /* and kill the higher order bits */
6096             emitcode("anl","a,#0x%02x", SRMask[shCount]);
6097         }
6098     }
6099 }
6100
6101 /*-----------------------------------------------------------------*/
6102 /* AccSRsh - signed right shift accumulator by known count                 */
6103 /*-----------------------------------------------------------------*/
6104 static void AccSRsh (int shCount)
6105 {
6106     symbol *tlbl ;
6107     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6108     if(shCount != 0){
6109         if(shCount == 1){
6110             emitcode("mov","c,acc.7");
6111             emitcode("rrc","a");
6112         } else if(shCount == 2){
6113             emitcode("mov","c,acc.7");
6114             emitcode("rrc","a");
6115             emitcode("mov","c,acc.7");
6116             emitcode("rrc","a");
6117         } else {
6118             tlbl = newiTempLabel(NULL);
6119             /* rotate right accumulator */
6120             AccRol(8 - shCount);
6121             /* and kill the higher order bits */
6122             emitcode("anl","a,#0x%02x", SRMask[shCount]);
6123             emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6124             emitcode("orl","a,#0x%02x",
6125                      (unsigned char)~SRMask[shCount]);
6126             emitcode("","%05d_DS_:",tlbl->key+100);
6127         }
6128     }
6129 }
6130
6131 /*-----------------------------------------------------------------*/
6132 /* shiftR1Left2Result - shift right one byte from left to result   */
6133 /*-----------------------------------------------------------------*/
6134 static void shiftR1Left2Result (operand *left, int offl,
6135                                 operand *result, int offr,
6136                                 int shCount, int sign)
6137 {
6138     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6139     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6140     /* shift right accumulator */
6141     if(sign)
6142         AccSRsh(shCount);
6143     else
6144         AccRsh(shCount);
6145     aopPut(AOP(result),"a",offr);
6146 }
6147
6148 /*-----------------------------------------------------------------*/
6149 /* shiftL1Left2Result - shift left one byte from left to result    */
6150 /*-----------------------------------------------------------------*/
6151 static void shiftL1Left2Result (operand *left, int offl,
6152                                 operand *result, int offr, int shCount)
6153 {
6154     char *l;
6155     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6156     l = aopGet(AOP(left),offl,FALSE,FALSE);
6157     MOVA(l);
6158     /* shift left accumulator */
6159     AccLsh(shCount);
6160     aopPut(AOP(result),"a",offr);
6161 }
6162
6163 /*-----------------------------------------------------------------*/
6164 /* movLeft2Result - move byte from left to result                  */
6165 /*-----------------------------------------------------------------*/
6166 static void movLeft2Result (operand *left, int offl,
6167                             operand *result, int offr, int sign)
6168 {
6169     char *l;
6170     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6171     if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6172         l = aopGet(AOP(left),offl,FALSE,FALSE);
6173
6174         if (*l == '@' && (IS_AOP_PREG(result))) {
6175             emitcode("mov","a,%s",l);
6176             aopPut(AOP(result),"a",offr);
6177         } else {
6178             if(!sign)
6179                 aopPut(AOP(result),l,offr);
6180             else{
6181                 /* MSB sign in acc.7 ! */
6182                 if(getDataSize(left) == offl+1){
6183                     emitcode("mov","a,%s",l);
6184                     aopPut(AOP(result),"a",offr);
6185                 }
6186             }
6187         }
6188     }
6189 }
6190
6191 /*-----------------------------------------------------------------*/
6192 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
6193 /*-----------------------------------------------------------------*/
6194 static void AccAXRrl1 (char *x)
6195 {
6196     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6197     emitcode("rrc","a");
6198     emitcode("xch","a,%s", x);
6199     emitcode("rrc","a");
6200     emitcode("xch","a,%s", x);
6201 }
6202
6203 /*-----------------------------------------------------------------*/
6204 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
6205 /*-----------------------------------------------------------------*/
6206 static void AccAXLrl1 (char *x)
6207 {
6208     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6209     emitcode("xch","a,%s",x);
6210     emitcode("rlc","a");
6211     emitcode("xch","a,%s",x);
6212     emitcode("rlc","a");
6213 }
6214
6215 /*-----------------------------------------------------------------*/
6216 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
6217 /*-----------------------------------------------------------------*/
6218 static void AccAXLsh1 (char *x)
6219 {
6220     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6221     emitcode("xch","a,%s",x);
6222     emitcode("add","a,acc");
6223     emitcode("xch","a,%s",x);
6224     emitcode("rlc","a");
6225 }
6226
6227 /*-----------------------------------------------------------------*/
6228 /* AccAXLsh - left shift a:x by known count (0..7)                 */
6229 /*-----------------------------------------------------------------*/
6230 static void AccAXLsh (char *x, int shCount)
6231 {
6232     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6233     switch(shCount){
6234         case 0 :
6235             break;
6236         case 1 :
6237             AccAXLsh1(x);
6238             break;
6239         case 2 :
6240             AccAXLsh1(x);
6241             AccAXLsh1(x);
6242             break;
6243         case 3 :
6244         case 4 :
6245         case 5 :                        // AAAAABBB:CCCCCDDD
6246             AccRol(shCount);            // BBBAAAAA:CCCCCDDD
6247             emitcode("anl","a,#0x%02x",
6248                      SLMask[shCount]);  // BBB00000:CCCCCDDD
6249             emitcode("xch","a,%s",x);   // CCCCCDDD:BBB00000
6250             AccRol(shCount);            // DDDCCCCC:BBB00000
6251             emitcode("xch","a,%s",x);   // BBB00000:DDDCCCCC
6252             emitcode("xrl","a,%s",x);   // (BBB^DDD)CCCCC:DDDCCCCC
6253             emitcode("xch","a,%s",x);   // DDDCCCCC:(BBB^DDD)CCCCC
6254             emitcode("anl","a,#0x%02x",
6255                      SLMask[shCount]);  // DDD00000:(BBB^DDD)CCCCC
6256             emitcode("xch","a,%s",x);   // (BBB^DDD)CCCCC:DDD00000
6257             emitcode("xrl","a,%s",x);   // BBBCCCCC:DDD00000            
6258             break;
6259         case 6 :                        // AAAAAABB:CCCCCCDD
6260             emitcode("anl","a,#0x%02x",
6261                      SRMask[shCount]);  // 000000BB:CCCCCCDD
6262             emitcode("mov","c,acc.0");  // c = B
6263             emitcode("xch","a,%s",x);   // CCCCCCDD:000000BB
6264             AccAXRrl1(x);               // BCCCCCCD:D000000B
6265             AccAXRrl1(x);               // BBCCCCCC:DD000000
6266             break;
6267         case 7 :                        // a:x <<= 7
6268             emitcode("anl","a,#0x%02x",
6269                      SRMask[shCount]);  // 0000000B:CCCCCCCD
6270             emitcode("mov","c,acc.0");  // c = B
6271             emitcode("xch","a,%s",x);   // CCCCCCCD:0000000B
6272             AccAXRrl1(x);               // BCCCCCCC:D0000000
6273             break;
6274         default :
6275             break;
6276     }
6277 }
6278
6279 /*-----------------------------------------------------------------*/
6280 /* AccAXRsh - right shift a:x known count (0..7)                   */
6281 /*-----------------------------------------------------------------*/
6282 static void AccAXRsh (char *x, int shCount)
6283 {   
6284     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6285     switch(shCount){
6286         case 0 :
6287             break;
6288         case 1 :
6289             CLRC;
6290             AccAXRrl1(x);               // 0->a:x
6291             break;
6292         case 2 :
6293             CLRC;
6294             AccAXRrl1(x);               // 0->a:x
6295             CLRC;
6296             AccAXRrl1(x);               // 0->a:x
6297             break;
6298         case 3 :
6299         case 4 :
6300         case 5 :                        // AAAAABBB:CCCCCDDD = a:x
6301             AccRol(8 - shCount);        // BBBAAAAA:DDDCCCCC
6302             emitcode("xch","a,%s",x);   // CCCCCDDD:BBBAAAAA
6303             AccRol(8 - shCount);        // DDDCCCCC:BBBAAAAA
6304             emitcode("anl","a,#0x%02x",
6305                      SRMask[shCount]);  // 000CCCCC:BBBAAAAA
6306             emitcode("xrl","a,%s",x);   // BBB(CCCCC^AAAAA):BBBAAAAA
6307             emitcode("xch","a,%s",x);   // BBBAAAAA:BBB(CCCCC^AAAAA)
6308             emitcode("anl","a,#0x%02x",
6309                      SRMask[shCount]);  // 000AAAAA:BBB(CCCCC^AAAAA)
6310             emitcode("xch","a,%s",x);   // BBB(CCCCC^AAAAA):000AAAAA
6311             emitcode("xrl","a,%s",x);   // BBBCCCCC:000AAAAA
6312             emitcode("xch","a,%s",x);   // 000AAAAA:BBBCCCCC
6313             break;
6314         case 6 :                        // AABBBBBB:CCDDDDDD
6315             emitcode("mov","c,acc.7");
6316             AccAXLrl1(x);               // ABBBBBBC:CDDDDDDA
6317             AccAXLrl1(x);               // BBBBBBCC:DDDDDDAA
6318             emitcode("xch","a,%s",x);   // DDDDDDAA:BBBBBBCC
6319             emitcode("anl","a,#0x%02x",
6320                      SRMask[shCount]);  // 000000AA:BBBBBBCC
6321             break;
6322         case 7 :                        // ABBBBBBB:CDDDDDDD
6323             emitcode("mov","c,acc.7");  // c = A
6324             AccAXLrl1(x);               // BBBBBBBC:DDDDDDDA
6325             emitcode("xch","a,%s",x);   // DDDDDDDA:BBBBBBCC
6326             emitcode("anl","a,#0x%02x",
6327                      SRMask[shCount]);  // 0000000A:BBBBBBBC
6328             break;
6329         default :
6330             break;
6331     }
6332 }
6333
6334 /*-----------------------------------------------------------------*/
6335 /* AccAXRshS - right shift signed a:x known count (0..7)           */
6336 /*-----------------------------------------------------------------*/
6337 static void AccAXRshS (char *x, int shCount)
6338 {   
6339     symbol *tlbl ;
6340     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6341     switch(shCount){
6342         case 0 :
6343             break;
6344         case 1 :
6345             emitcode("mov","c,acc.7");
6346             AccAXRrl1(x);               // s->a:x
6347             break;
6348         case 2 :
6349             emitcode("mov","c,acc.7");
6350             AccAXRrl1(x);               // s->a:x
6351             emitcode("mov","c,acc.7");
6352             AccAXRrl1(x);               // s->a:x
6353             break;
6354         case 3 :
6355         case 4 :
6356         case 5 :                        // AAAAABBB:CCCCCDDD = a:x
6357             tlbl = newiTempLabel(NULL);
6358             AccRol(8 - shCount);        // BBBAAAAA:CCCCCDDD
6359             emitcode("xch","a,%s",x);   // CCCCCDDD:BBBAAAAA
6360             AccRol(8 - shCount);        // DDDCCCCC:BBBAAAAA
6361             emitcode("anl","a,#0x%02x",
6362                      SRMask[shCount]);  // 000CCCCC:BBBAAAAA
6363             emitcode("xrl","a,%s",x);   // BBB(CCCCC^AAAAA):BBBAAAAA
6364             emitcode("xch","a,%s",x);   // BBBAAAAA:BBB(CCCCC^AAAAA)
6365             emitcode("anl","a,#0x%02x",
6366                      SRMask[shCount]);  // 000AAAAA:BBB(CCCCC^AAAAA)
6367             emitcode("xch","a,%s",x);   // BBB(CCCCC^AAAAA):000AAAAA
6368             emitcode("xrl","a,%s",x);   // BBBCCCCC:000AAAAA
6369             emitcode("xch","a,%s",x);   // 000SAAAA:BBBCCCCC
6370             emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100); 
6371             emitcode("orl","a,#0x%02x",
6372                      (unsigned char)~SRMask[shCount]);  // 111AAAAA:BBBCCCCC
6373             emitcode("","%05d_DS_:",tlbl->key+100);
6374             break;                      // SSSSAAAA:BBBCCCCC
6375         case 6 :                        // AABBBBBB:CCDDDDDD
6376             tlbl = newiTempLabel(NULL);
6377             emitcode("mov","c,acc.7");
6378             AccAXLrl1(x);               // ABBBBBBC:CDDDDDDA
6379             AccAXLrl1(x);               // BBBBBBCC:DDDDDDAA
6380             emitcode("xch","a,%s",x);   // DDDDDDAA:BBBBBBCC
6381             emitcode("anl","a,#0x%02x",
6382                      SRMask[shCount]);  // 000000AA:BBBBBBCC
6383             emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100); 
6384             emitcode("orl","a,#0x%02x",
6385                      (unsigned char)~SRMask[shCount]);  // 111111AA:BBBBBBCC
6386             emitcode("","%05d_DS_:",tlbl->key+100);
6387             break;
6388         case 7 :                        // ABBBBBBB:CDDDDDDD
6389             tlbl = newiTempLabel(NULL);
6390             emitcode("mov","c,acc.7");  // c = A
6391             AccAXLrl1(x);               // BBBBBBBC:DDDDDDDA
6392             emitcode("xch","a,%s",x);   // DDDDDDDA:BBBBBBCC
6393             emitcode("anl","a,#0x%02x",
6394                      SRMask[shCount]);  // 0000000A:BBBBBBBC
6395             emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100); 
6396             emitcode("orl","a,#0x%02x",
6397                      (unsigned char)~SRMask[shCount]);  // 1111111A:BBBBBBBC
6398             emitcode("","%05d_DS_:",tlbl->key+100);
6399             break;
6400         default :
6401             break;
6402     }
6403 }
6404
6405 /*-----------------------------------------------------------------*/
6406 /* shiftL2Left2Result - shift left two bytes from left to result   */
6407 /*-----------------------------------------------------------------*/
6408 static void shiftL2Left2Result (operand *left, int offl,
6409                                 operand *result, int offr, int shCount)
6410 {
6411     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6412     if(sameRegs(AOP(result), AOP(left)) &&
6413        ((offl + MSB16) == offr)){
6414         /* don't crash result[offr] */
6415         MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6416         emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6417     } else {
6418         movLeft2Result(left,offl, result, offr, 0);
6419         MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6420     }
6421     /* ax << shCount (x = lsb(result))*/
6422     AccAXLsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6423     aopPut(AOP(result),"a",offr+MSB16);
6424 }
6425
6426
6427 /*-----------------------------------------------------------------*/
6428 /* shiftR2Left2Result - shift right two bytes from left to result  */
6429 /*-----------------------------------------------------------------*/
6430 static void shiftR2Left2Result (operand *left, int offl,
6431                                 operand *result, int offr,
6432                                 int shCount, int sign)
6433 {
6434     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6435     if(sameRegs(AOP(result), AOP(left)) &&
6436        ((offl + MSB16) == offr)){
6437         /* don't crash result[offr] */
6438         MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6439         emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6440     } else {
6441         movLeft2Result(left,offl, result, offr, 0);
6442         MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6443     }
6444     /* a:x >> shCount (x = lsb(result))*/
6445     if(sign)
6446         AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6447     else
6448         AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6449     if(getDataSize(result) > 1)
6450         aopPut(AOP(result),"a",offr+MSB16);
6451 }
6452
6453 /*-----------------------------------------------------------------*/
6454 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
6455 /*-----------------------------------------------------------------*/
6456 static void shiftLLeftOrResult (operand *left, int offl,
6457                                 operand *result, int offr, int shCount)
6458 {
6459     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6460     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6461     /* shift left accumulator */
6462     AccLsh(shCount);
6463     /* or with result */
6464     emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
6465     /* back to result */
6466     aopPut(AOP(result),"a",offr);
6467 }
6468
6469 /*-----------------------------------------------------------------*/
6470 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
6471 /*-----------------------------------------------------------------*/
6472 static void shiftRLeftOrResult (operand *left, int offl,
6473                                 operand *result, int offr, int shCount)
6474 {
6475     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6476     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6477     /* shift right accumulator */
6478     AccRsh(shCount);
6479     /* or with result */
6480     emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
6481     /* back to result */
6482     aopPut(AOP(result),"a",offr);
6483 }
6484
6485 /*-----------------------------------------------------------------*/
6486 /* genlshOne - left shift a one byte quantity by known count       */
6487 /*-----------------------------------------------------------------*/
6488 static void genlshOne (operand *result, operand *left, int shCount)
6489 {       
6490     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6491     shiftL1Left2Result(left, LSB, result, LSB, shCount);
6492 }
6493
6494 /*-----------------------------------------------------------------*/
6495 /* genlshTwo - left shift two bytes by known amount != 0           */
6496 /*-----------------------------------------------------------------*/
6497 static void genlshTwo (operand *result,operand *left, int shCount)
6498 {
6499     int size;
6500     
6501     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6502     size = getDataSize(result);
6503
6504     /* if shCount >= 8 */
6505     if (shCount >= 8) {
6506         shCount -= 8 ;
6507
6508         if (size > 1){
6509             if (shCount)
6510                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6511             else 
6512                 movLeft2Result(left, LSB, result, MSB16, 0);
6513         }
6514         aopPut(AOP(result),zero,LSB);   
6515     }
6516
6517     /*  1 <= shCount <= 7 */
6518     else {  
6519         if(size == 1)
6520             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
6521         else 
6522             shiftL2Left2Result(left, LSB, result, LSB, shCount);
6523     }
6524 }
6525
6526 /*-----------------------------------------------------------------*/
6527 /* shiftLLong - shift left one long from left to result            */
6528 /* offl = LSB or MSB16                                             */
6529 /*-----------------------------------------------------------------*/
6530 static void shiftLLong (operand *left, operand *result, int offr )
6531 {
6532     char *l;
6533     int size = AOP_SIZE(result);
6534
6535     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6536     if(size >= LSB+offr){
6537         l = aopGet(AOP(left),LSB,FALSE,FALSE);
6538         MOVA(l);
6539         emitcode("add","a,acc");
6540         if (sameRegs(AOP(left),AOP(result)) && 
6541             size >= MSB16+offr && offr != LSB )
6542             emitcode("xch","a,%s",
6543                      aopGet(AOP(left),LSB+offr,FALSE,FALSE));
6544         else        
6545             aopPut(AOP(result),"a",LSB+offr);
6546     }
6547
6548     if(size >= MSB16+offr){
6549         if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
6550             l = aopGet(AOP(left),MSB16,FALSE,FALSE);
6551             MOVA(l);
6552         }
6553         emitcode("rlc","a");
6554         if (sameRegs(AOP(left),AOP(result)) && 
6555             size >= MSB24+offr && offr != LSB)
6556             emitcode("xch","a,%s",
6557                      aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
6558         else        
6559             aopPut(AOP(result),"a",MSB16+offr);
6560     }
6561
6562     if(size >= MSB24+offr){
6563         if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
6564             l = aopGet(AOP(left),MSB24,FALSE,FALSE);
6565             MOVA(l);
6566         }
6567         emitcode("rlc","a");
6568         if (sameRegs(AOP(left),AOP(result)) && 
6569             size >= MSB32+offr && offr != LSB )
6570             emitcode("xch","a,%s",
6571                      aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
6572         else        
6573             aopPut(AOP(result),"a",MSB24+offr);
6574     }
6575
6576     if(size > MSB32+offr){
6577         if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
6578             l = aopGet(AOP(left),MSB32,FALSE,FALSE);
6579             MOVA(l);    
6580         }
6581         emitcode("rlc","a");
6582         aopPut(AOP(result),"a",MSB32+offr);
6583     }
6584     if(offr != LSB)
6585         aopPut(AOP(result),zero,LSB);       
6586 }
6587
6588 /*-----------------------------------------------------------------*/
6589 /* genlshFour - shift four byte by a known amount != 0             */
6590 /*-----------------------------------------------------------------*/
6591 static void genlshFour (operand *result, operand *left, int shCount)
6592 {
6593     int size;
6594
6595     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6596     size = AOP_SIZE(result);
6597
6598     /* if shifting more that 3 bytes */
6599     if (shCount >= 24 ) {
6600         shCount -= 24;
6601         if (shCount)
6602             /* lowest order of left goes to the highest
6603             order of the destination */
6604             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
6605         else
6606             movLeft2Result(left, LSB, result, MSB32, 0);
6607         aopPut(AOP(result),zero,LSB);
6608         aopPut(AOP(result),zero,MSB16);
6609         aopPut(AOP(result),zero,MSB32);
6610         return;
6611     }
6612
6613     /* more than two bytes */
6614     else if ( shCount >= 16 ) {
6615         /* lower order two bytes goes to higher order two bytes */
6616         shCount -= 16;
6617         /* if some more remaining */
6618         if (shCount)
6619             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
6620         else {
6621             movLeft2Result(left, MSB16, result, MSB32, 0);
6622             movLeft2Result(left, LSB, result, MSB24, 0);
6623         }
6624         aopPut(AOP(result),zero,MSB16);
6625         aopPut(AOP(result),zero,LSB);
6626         return;
6627     }    
6628
6629     /* if more than 1 byte */
6630     else if ( shCount >= 8 ) {
6631         /* lower order three bytes goes to higher order  three bytes */
6632         shCount -= 8;
6633         if(size == 2){
6634             if(shCount)
6635                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6636             else
6637                 movLeft2Result(left, LSB, result, MSB16, 0);
6638         }
6639         else{   /* size = 4 */
6640             if(shCount == 0){
6641                 movLeft2Result(left, MSB24, result, MSB32, 0);
6642                 movLeft2Result(left, MSB16, result, MSB24, 0);
6643                 movLeft2Result(left, LSB, result, MSB16, 0);
6644                 aopPut(AOP(result),zero,LSB);
6645             }
6646             else if(shCount == 1)
6647                 shiftLLong(left, result, MSB16);
6648             else{
6649                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
6650                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6651                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
6652                 aopPut(AOP(result),zero,LSB);
6653             }
6654         }
6655     }
6656
6657     /* 1 <= shCount <= 7 */
6658     else if(shCount <= 2){
6659         shiftLLong(left, result, LSB);
6660         if(shCount == 2)
6661             shiftLLong(result, result, LSB);
6662     }
6663     /* 3 <= shCount <= 7, optimize */
6664     else{
6665         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
6666         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
6667         shiftL2Left2Result(left, LSB, result, LSB, shCount);
6668     }
6669 }
6670
6671 /*-----------------------------------------------------------------*/
6672 /* genLeftShiftLiteral - left shifting by known count              */
6673 /*-----------------------------------------------------------------*/
6674 static void genLeftShiftLiteral (operand *left,
6675                                  operand *right,
6676                                  operand *result,
6677                                  iCode *ic)
6678 {    
6679     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6680     int size;
6681
6682     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6683     freeAsmop(right,NULL,ic,TRUE);
6684
6685     aopOp(left,ic,FALSE);
6686     aopOp(result,ic,FALSE);
6687
6688     size = getSize(operandType(result));
6689
6690 #if VIEW_SIZE
6691     emitcode("; shift left ","result %d, left %d",size,
6692              AOP_SIZE(left));
6693 #endif
6694
6695     /* I suppose that the left size >= result size */
6696     if(shCount == 0){
6697         while(size--){
6698             movLeft2Result(left, size, result, size, 0);
6699         }
6700     }
6701
6702     else if(shCount >= (size * 8))
6703         while(size--)
6704             aopPut(AOP(result),zero,size);
6705     else{
6706         switch (size) {
6707             case 1:
6708                 genlshOne (result,left,shCount);
6709                 break;
6710
6711             case 2:
6712             case 3:
6713                 genlshTwo (result,left,shCount);
6714                 break;
6715
6716             case 4:
6717                 genlshFour (result,left,shCount);
6718                 break;
6719         }
6720     }
6721     freeAsmop(left,NULL,ic,TRUE);
6722     freeAsmop(result,NULL,ic,TRUE);
6723 }
6724
6725 /*-----------------------------------------------------------------*/
6726 /* genLeftShift - generates code for left shifting                 */
6727 /*-----------------------------------------------------------------*/
6728 static void genLeftShift (iCode *ic)
6729 {
6730     operand *left,*right, *result;
6731     int size, offset;
6732     char *l;
6733     symbol *tlbl , *tlbl1;
6734
6735     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6736
6737     right = IC_RIGHT(ic);
6738     left  = IC_LEFT(ic);
6739     result = IC_RESULT(ic);
6740
6741     aopOp(right,ic,FALSE);
6742
6743     /* if the shift count is known then do it 
6744     as efficiently as possible */
6745     if (AOP_TYPE(right) == AOP_LIT) {
6746         genLeftShiftLiteral (left,right,result,ic);
6747         return ;
6748     }
6749
6750     /* shift count is unknown then we have to form 
6751     a loop get the loop count in B : Note: we take
6752     only the lower order byte since shifting
6753     more that 32 bits make no sense anyway, ( the
6754     largest size of an object can be only 32 bits ) */  
6755
6756     emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
6757     emitcode("inc","b");
6758     freeAsmop (right,NULL,ic,TRUE);
6759     aopOp(left,ic,FALSE);
6760     aopOp(result,ic,FALSE);
6761
6762     /* now move the left to the result if they are not the
6763     same */
6764     if (!sameRegs(AOP(left),AOP(result)) && 
6765         AOP_SIZE(result) > 1) {
6766
6767         size = AOP_SIZE(result);
6768         offset=0;
6769         while (size--) {
6770             l = aopGet(AOP(left),offset,FALSE,TRUE);
6771             if (*l == '@' && (IS_AOP_PREG(result))) {
6772
6773                 emitcode("mov","a,%s",l);
6774                 aopPut(AOP(result),"a",offset);
6775             } else
6776                 aopPut(AOP(result),l,offset);
6777             offset++;
6778         }
6779     }
6780
6781     tlbl = newiTempLabel(NULL);
6782     size = AOP_SIZE(result);
6783     offset = 0 ;   
6784     tlbl1 = newiTempLabel(NULL);
6785
6786     /* if it is only one byte then */
6787     if (size == 1) {
6788         symbol *tlbl1 = newiTempLabel(NULL);
6789
6790         l = aopGet(AOP(left),0,FALSE,FALSE);
6791         MOVA(l);
6792         emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
6793         emitcode("","%05d_DS_:",tlbl->key+100);
6794         emitcode("add","a,acc");
6795         emitcode("","%05d_DS_:",tlbl1->key+100);
6796         emitcode("djnz","b,%05d_DS_",tlbl->key+100);      
6797         aopPut(AOP(result),"a",0);
6798         goto release ;
6799     }
6800     
6801     reAdjustPreg(AOP(result));    
6802     
6803     emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
6804     emitcode("","%05d_DS_:",tlbl->key+100);    
6805     l = aopGet(AOP(result),offset,FALSE,FALSE);
6806     MOVA(l);
6807     emitcode("add","a,acc");         
6808     aopPut(AOP(result),"a",offset++);
6809     while (--size) {
6810         l = aopGet(AOP(result),offset,FALSE,FALSE);
6811         MOVA(l);
6812         emitcode("rlc","a");         
6813         aopPut(AOP(result),"a",offset++);
6814     }
6815     reAdjustPreg(AOP(result));
6816
6817     emitcode("","%05d_DS_:",tlbl1->key+100);
6818     emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6819 release:
6820     freeAsmop(left,NULL,ic,TRUE);
6821     freeAsmop(result,NULL,ic,TRUE);
6822 }
6823
6824 /*-----------------------------------------------------------------*/
6825 /* genrshOne - right shift a one byte quantity by known count      */
6826 /*-----------------------------------------------------------------*/
6827 static void genrshOne (operand *result, operand *left,
6828                        int shCount, int sign)
6829 {
6830     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6831     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
6832 }
6833
6834 /*-----------------------------------------------------------------*/
6835 /* genrshTwo - right shift two bytes by known amount != 0          */
6836 /*-----------------------------------------------------------------*/
6837 static void genrshTwo (operand *result,operand *left,
6838                        int shCount, int sign)
6839 {
6840     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6841     /* if shCount >= 8 */
6842     if (shCount >= 8) {
6843         shCount -= 8 ;
6844         if (shCount)
6845             shiftR1Left2Result(left, MSB16, result, LSB,
6846                                shCount, sign);
6847         else 
6848             movLeft2Result(left, MSB16, result, LSB, sign);
6849         addSign(result, MSB16, sign);
6850     }
6851
6852     /*  1 <= shCount <= 7 */
6853     else
6854         shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
6855 }
6856
6857 /*-----------------------------------------------------------------*/
6858 /* shiftRLong - shift right one long from left to result           */
6859 /* offl = LSB or MSB16                                             */
6860 /*-----------------------------------------------------------------*/
6861 static void shiftRLong (operand *left, int offl,
6862                         operand *result, int sign)
6863 {
6864     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6865     if(!sign)
6866         emitcode("clr","c");
6867     MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE));
6868     if(sign)
6869         emitcode("mov","c,acc.7");
6870     emitcode("rrc","a");
6871     aopPut(AOP(result),"a",MSB32-offl);
6872     if(offl == MSB16)
6873         /* add sign of "a" */
6874         addSign(result, MSB32, sign);
6875
6876     MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE));
6877     emitcode("rrc","a");
6878     aopPut(AOP(result),"a",MSB24-offl);
6879
6880     MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE));
6881     emitcode("rrc","a");
6882     aopPut(AOP(result),"a",MSB16-offl);
6883
6884     if(offl == LSB){
6885         MOVA(aopGet(AOP(left),LSB,FALSE,FALSE));
6886         emitcode("rrc","a");
6887         aopPut(AOP(result),"a",LSB);
6888     }
6889 }
6890
6891 /*-----------------------------------------------------------------*/
6892 /* genrshFour - shift four byte by a known amount != 0             */
6893 /*-----------------------------------------------------------------*/
6894 static void genrshFour (operand *result, operand *left,
6895                         int shCount, int sign)
6896 {
6897     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6898     /* if shifting more that 3 bytes */
6899     if(shCount >= 24 ) {
6900         shCount -= 24;
6901         if(shCount)
6902             shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
6903         else
6904             movLeft2Result(left, MSB32, result, LSB, sign);
6905         addSign(result, MSB16, sign);
6906     }
6907     else if(shCount >= 16){
6908         shCount -= 16;
6909         if(shCount)
6910             shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
6911         else{
6912             movLeft2Result(left, MSB24, result, LSB, 0);
6913             movLeft2Result(left, MSB32, result, MSB16, sign);
6914         }
6915         addSign(result, MSB24, sign);
6916     }
6917     else if(shCount >= 8){
6918         shCount -= 8;
6919         if(shCount == 1)
6920             shiftRLong(left, MSB16, result, sign);
6921         else if(shCount == 0){
6922             movLeft2Result(left, MSB16, result, LSB, 0);
6923             movLeft2Result(left, MSB24, result, MSB16, 0);
6924             movLeft2Result(left, MSB32, result, MSB24, sign);
6925             addSign(result, MSB32, sign);
6926         }
6927         else{
6928             shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
6929             shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
6930             /* the last shift is signed */
6931             shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
6932             addSign(result, MSB32, sign);
6933         }
6934     }
6935     else{   /* 1 <= shCount <= 7 */
6936         if(shCount <= 2){
6937             shiftRLong(left, LSB, result, sign);
6938             if(shCount == 2)
6939                 shiftRLong(result, LSB, result, sign);
6940         }
6941         else{
6942             shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
6943             shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
6944             shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
6945         }
6946     }
6947 }
6948
6949 /*-----------------------------------------------------------------*/
6950 /* genRightShiftLiteral - right shifting by known count            */
6951 /*-----------------------------------------------------------------*/
6952 static void genRightShiftLiteral (operand *left,
6953                                   operand *right,
6954                                   operand *result,
6955                                   iCode *ic,
6956                                   int sign)
6957 {    
6958     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6959     int size;
6960
6961     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6962     freeAsmop(right,NULL,ic,TRUE);
6963
6964     aopOp(left,ic,FALSE);
6965     aopOp(result,ic,FALSE);
6966
6967 #if VIEW_SIZE
6968     emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
6969              AOP_SIZE(left));
6970 #endif
6971
6972     size = getDataSize(left);
6973     /* test the LEFT size !!! */
6974
6975     /* I suppose that the left size >= result size */
6976     if(shCount == 0){
6977         size = getDataSize(result);
6978         while(size--)
6979             movLeft2Result(left, size, result, size, 0);
6980     }
6981
6982     else if(shCount >= (size * 8)){
6983         if(sign)
6984             /* get sign in acc.7 */
6985             MOVA(aopGet(AOP(left),size-1,FALSE,FALSE));
6986         addSign(result, LSB, sign);
6987     } else{
6988         switch (size) {
6989             case 1:
6990                 genrshOne (result,left,shCount,sign);
6991                 break;
6992
6993             case 2:
6994                 genrshTwo (result,left,shCount,sign);
6995                 break;
6996
6997             case 4:
6998                 genrshFour (result,left,shCount,sign);
6999                 break;
7000             default :
7001                 break;
7002         }
7003
7004         freeAsmop(left,NULL,ic,TRUE);
7005         freeAsmop(result,NULL,ic,TRUE);
7006     }
7007 }
7008
7009 /*-----------------------------------------------------------------*/
7010 /* genSignedRightShift - right shift of signed number              */
7011 /*-----------------------------------------------------------------*/
7012 static void genSignedRightShift (iCode *ic)
7013 {
7014     operand *right, *left, *result;
7015     int size, offset;
7016     char *l;
7017     symbol *tlbl, *tlbl1 ;
7018
7019     /* we do it the hard way put the shift count in b
7020     and loop thru preserving the sign */
7021     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7022
7023     right = IC_RIGHT(ic);
7024     left  = IC_LEFT(ic);
7025     result = IC_RESULT(ic);
7026
7027     aopOp(right,ic,FALSE);  
7028
7029
7030     if ( AOP_TYPE(right) == AOP_LIT) {
7031         genRightShiftLiteral (left,right,result,ic,1);
7032         return ;
7033     }
7034         /* shift count is unknown then we have to form 
7035        a loop get the loop count in B : Note: we take
7036        only the lower order byte since shifting
7037        more that 32 bits make no sense anyway, ( the
7038        largest size of an object can be only 32 bits ) */  
7039
7040     emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
7041     emitcode("inc","b");
7042     freeAsmop (right,NULL,ic,TRUE);
7043     aopOp(left,ic,FALSE);
7044     aopOp(result,ic,FALSE);
7045
7046     /* now move the left to the result if they are not the
7047     same */
7048     if (!sameRegs(AOP(left),AOP(result)) && 
7049         AOP_SIZE(result) > 1) {
7050
7051         size = AOP_SIZE(result);
7052         offset=0;
7053         while (size--) {
7054             l = aopGet(AOP(left),offset,FALSE,TRUE);
7055             if (*l == '@' && IS_AOP_PREG(result)) {
7056
7057                 emitcode("mov","a,%s",l);
7058                 aopPut(AOP(result),"a",offset);
7059             } else
7060                 aopPut(AOP(result),l,offset);
7061             offset++;
7062         }
7063     }
7064
7065     /* mov the highest order bit to OVR */    
7066     tlbl = newiTempLabel(NULL);
7067     tlbl1= newiTempLabel(NULL);
7068
7069     size = AOP_SIZE(result);
7070     offset = size - 1;
7071     emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
7072     emitcode("rlc","a");
7073     emitcode("mov","ov,c");
7074     /* if it is only one byte then */
7075     if (size == 1) {
7076         l = aopGet(AOP(left),0,FALSE,FALSE);
7077         MOVA(l);
7078         emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7079         emitcode("","%05d_DS_:",tlbl->key+100);
7080         emitcode("mov","c,ov");
7081         emitcode("rrc","a");
7082         emitcode("","%05d_DS_:",tlbl1->key+100);
7083         emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7084         aopPut(AOP(result),"a",0);
7085         goto release ;
7086     }
7087
7088     reAdjustPreg(AOP(result));
7089     emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7090     emitcode("","%05d_DS_:",tlbl->key+100);    
7091     emitcode("mov","c,ov");
7092     while (size--) {
7093         l = aopGet(AOP(result),offset,FALSE,FALSE);
7094         MOVA(l);
7095         emitcode("rrc","a");         
7096         aopPut(AOP(result),"a",offset--);
7097     }
7098     reAdjustPreg(AOP(result));
7099     emitcode("","%05d_DS_:",tlbl1->key+100);
7100     emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7101
7102 release:
7103     freeAsmop(left,NULL,ic,TRUE);
7104     freeAsmop(result,NULL,ic,TRUE);
7105 }
7106
7107 /*-----------------------------------------------------------------*/
7108 /* genRightShift - generate code for right shifting                */
7109 /*-----------------------------------------------------------------*/
7110 static void genRightShift (iCode *ic)
7111 {
7112     operand *right, *left, *result;
7113     sym_link *retype ;
7114     int size, offset;
7115     char *l;
7116     symbol *tlbl, *tlbl1 ;
7117
7118     /* if signed then we do it the hard way preserve the
7119     sign bit moving it inwards */
7120     retype = getSpec(operandType(IC_RESULT(ic)));
7121     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7122
7123     if (!SPEC_USIGN(retype)) {
7124         genSignedRightShift (ic);
7125         return ;
7126     }
7127
7128     /* signed & unsigned types are treated the same : i.e. the
7129     signed is NOT propagated inwards : quoting from the
7130     ANSI - standard : "for E1 >> E2, is equivalent to division
7131     by 2**E2 if unsigned or if it has a non-negative value,
7132     otherwise the result is implementation defined ", MY definition
7133     is that the sign does not get propagated */
7134
7135     right = IC_RIGHT(ic);
7136     left  = IC_LEFT(ic);
7137     result = IC_RESULT(ic);
7138
7139     aopOp(right,ic,FALSE);
7140
7141     /* if the shift count is known then do it 
7142     as efficiently as possible */
7143     if (AOP_TYPE(right) == AOP_LIT) {
7144         genRightShiftLiteral (left,right,result,ic, 0);
7145         return ;
7146     }
7147
7148     /* shift count is unknown then we have to form 
7149     a loop get the loop count in B : Note: we take
7150     only the lower order byte since shifting
7151     more that 32 bits make no sense anyway, ( the
7152     largest size of an object can be only 32 bits ) */  
7153
7154     emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
7155     emitcode("inc","b");
7156     freeAsmop (right,NULL,ic,TRUE);
7157     aopOp(left,ic,FALSE);
7158     aopOp(result,ic,FALSE);
7159
7160     /* now move the left to the result if they are not the
7161     same */
7162     if (!sameRegs(AOP(left),AOP(result)) && 
7163         AOP_SIZE(result) > 1) {
7164
7165         size = AOP_SIZE(result);
7166         offset=0;
7167         while (size--) {
7168             l = aopGet(AOP(left),offset,FALSE,TRUE);
7169             if (*l == '@' && IS_AOP_PREG(result)) {
7170
7171                 emitcode("mov","a,%s",l);
7172                 aopPut(AOP(result),"a",offset);
7173             } else
7174                 aopPut(AOP(result),l,offset);
7175             offset++;
7176         }
7177     }
7178
7179     tlbl = newiTempLabel(NULL);
7180     tlbl1= newiTempLabel(NULL);
7181     size = AOP_SIZE(result);
7182     offset = size - 1;
7183
7184     /* if it is only one byte then */
7185     if (size == 1) {
7186         l = aopGet(AOP(left),0,FALSE,FALSE);
7187         MOVA(l);
7188         emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7189         emitcode("","%05d_DS_:",tlbl->key+100);
7190         CLRC;
7191         emitcode("rrc","a");
7192         emitcode("","%05d_DS_:",tlbl1->key+100);
7193         emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7194         aopPut(AOP(result),"a",0);
7195         goto release ;
7196     }
7197
7198     reAdjustPreg(AOP(result));
7199     emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7200     emitcode("","%05d_DS_:",tlbl->key+100);    
7201     CLRC;
7202     while (size--) {
7203         l = aopGet(AOP(result),offset,FALSE,FALSE);
7204         MOVA(l);
7205         emitcode("rrc","a");         
7206         aopPut(AOP(result),"a",offset--);
7207     }
7208     reAdjustPreg(AOP(result));
7209
7210     emitcode("","%05d_DS_:",tlbl1->key+100);
7211     emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7212
7213 release:
7214     freeAsmop(left,NULL,ic,TRUE);
7215     freeAsmop(result,NULL,ic,TRUE);
7216 }
7217
7218 /*-----------------------------------------------------------------*/
7219 /* genUnpackBits - generates code for unpacking bits               */
7220 /*-----------------------------------------------------------------*/
7221 static void genUnpackBits (operand *result, char *rname, int ptype)
7222 {    
7223     int shCnt ;
7224     int rlen = 0 ;
7225     sym_link *etype;
7226     int offset = 0 ;
7227
7228     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7229     etype = getSpec(operandType(result));
7230
7231     /* read the first byte  */
7232     switch (ptype) {
7233
7234     case POINTER:
7235     case IPOINTER:
7236         emitcode("mov","a,@%s",rname);
7237         break;
7238         
7239     case PPOINTER:
7240         emitcode("movx","a,@%s",rname);
7241         break;
7242         
7243     case FPOINTER:
7244         emitcode("movx","a,@dptr");
7245         break;
7246
7247     case CPOINTER:
7248         emitcode("clr","a");
7249         emitcode("movc","a","@a+dptr");
7250         break;
7251
7252     case GPOINTER:
7253         emitcode("lcall","__gptrget");
7254         break;
7255     }
7256
7257     /* if we have bitdisplacement then it fits   */
7258     /* into this byte completely or if length is */
7259     /* less than a byte                          */
7260     if ((shCnt = SPEC_BSTR(etype)) || 
7261         (SPEC_BLEN(etype) <= 8))  {
7262
7263         /* shift right acc */
7264         AccRsh(shCnt);
7265
7266         emitcode("anl","a,#0x%02x",
7267                  ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
7268         aopPut(AOP(result),"a",offset);
7269         return ;
7270     }
7271
7272     /* bit field did not fit in a byte  */
7273     rlen = SPEC_BLEN(etype) - 8;
7274     aopPut(AOP(result),"a",offset++);
7275
7276     while (1)  {
7277
7278         switch (ptype) {
7279         case POINTER:
7280         case IPOINTER:
7281             emitcode("inc","%s",rname);
7282             emitcode("mov","a,@%s",rname);
7283             break;
7284             
7285         case PPOINTER:
7286             emitcode("inc","%s",rname);
7287             emitcode("movx","a,@%s",rname);
7288             break;
7289
7290         case FPOINTER:
7291             emitcode("inc","dptr");
7292             emitcode("movx","a,@dptr");
7293             break;
7294             
7295         case CPOINTER:
7296             emitcode("clr","a");
7297             emitcode("inc","dptr");
7298             emitcode("movc","a","@a+dptr");
7299             break;
7300             
7301         case GPOINTER:
7302             emitcode("inc","dptr");
7303             emitcode("lcall","__gptrget");
7304             break;
7305         }
7306
7307         rlen -= 8;            
7308         /* if we are done */
7309         if ( rlen <= 0 )
7310             break ;
7311         
7312         aopPut(AOP(result),"a",offset++);
7313                               
7314     }
7315     
7316     if (rlen) {
7317         emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
7318         aopPut(AOP(result),"a",offset);        
7319     }
7320     
7321     return ;
7322 }
7323
7324
7325 /*-----------------------------------------------------------------*/
7326 /* genDataPointerGet - generates code when ptr offset is known     */
7327 /*-----------------------------------------------------------------*/
7328 static void genDataPointerGet (operand *left, 
7329                                operand *result, 
7330                                iCode *ic)
7331 {
7332     char *l;
7333     char buffer[256];
7334     int size , offset = 0;
7335     aopOp(result,ic,TRUE);
7336
7337     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7338
7339     /* get the string representation of the name */
7340     l = aopGet(AOP(left),0,FALSE,TRUE);
7341     size = AOP_SIZE(result);
7342     // tsd, was l+1 - the underline `_' prefix was being stripped
7343     while (size--) {
7344         if (offset)
7345             sprintf(buffer,"(%s + %d)",l,offset);
7346         else
7347             sprintf(buffer,"%s",l);
7348         aopPut(AOP(result),buffer,offset++);
7349     }
7350
7351     freeAsmop(left,NULL,ic,TRUE);
7352     freeAsmop(result,NULL,ic,TRUE);
7353 }
7354
7355 /*-----------------------------------------------------------------*/
7356 /* genNearPointerGet - emitcode for near pointer fetch             */
7357 /*-----------------------------------------------------------------*/
7358 static void genNearPointerGet (operand *left, 
7359                                operand *result, 
7360                                iCode *ic)
7361 {
7362     asmop *aop = NULL;
7363     regs *preg = NULL ;
7364     char *rname ;
7365     sym_link *rtype, *retype;
7366     sym_link *ltype = operandType(left);    
7367     char buffer[80];
7368
7369     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7370
7371     rtype = operandType(result);
7372     retype= getSpec(rtype);
7373     
7374     aopOp(left,ic,FALSE);
7375     
7376     /* if left is rematerialisable and
7377        result is not bit variable type and
7378        the left is pointer to data space i.e
7379        lower 128 bytes of space */
7380     if (AOP_TYPE(left) == AOP_IMMD &&
7381         !IS_BITVAR(retype)         &&
7382         DCL_TYPE(ltype) == POINTER) {
7383         genDataPointerGet (left,result,ic);
7384         return ;
7385     }
7386     
7387         /* if the value is already in a pointer register
7388        then don't need anything more */
7389     if (!AOP_INPREG(AOP(left))) {
7390         /* otherwise get a free pointer register */
7391         aop = newAsmop(0);
7392         preg = getFreePtr(ic,&aop,FALSE);
7393         emitcode("mov","%s,%s",
7394                 preg->name,
7395                 aopGet(AOP(left),0,FALSE,TRUE));
7396         rname = preg->name ;
7397     } else
7398         rname = aopGet(AOP(left),0,FALSE,FALSE);
7399     
7400     freeAsmop(left,NULL,ic,TRUE);
7401     aopOp (result,ic,FALSE);
7402     
7403       /* if bitfield then unpack the bits */
7404     if (IS_BITVAR(retype)) 
7405         genUnpackBits (result,rname,POINTER);
7406     else {
7407         /* we have can just get the values */
7408         int size = AOP_SIZE(result);
7409         int offset = 0 ;        
7410         
7411         while (size--) {
7412             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
7413
7414                 emitcode("mov","a,@%s",rname);
7415                 aopPut(AOP(result),"a",offset);
7416             } else {
7417                 sprintf(buffer,"@%s",rname);
7418                 aopPut(AOP(result),buffer,offset);
7419             }
7420             offset++ ;
7421             if (size)
7422                 emitcode("inc","%s",rname);
7423         }
7424     }
7425
7426     /* now some housekeeping stuff */
7427     if (aop) {
7428         /* we had to allocate for this iCode */
7429         freeAsmop(NULL,aop,ic,TRUE);
7430     } else { 
7431         /* we did not allocate which means left
7432            already in a pointer register, then
7433            if size > 0 && this could be used again
7434            we have to point it back to where it 
7435            belongs */
7436         if (AOP_SIZE(result) > 1 &&
7437             !OP_SYMBOL(left)->remat &&
7438             ( OP_SYMBOL(left)->liveTo > ic->seq ||
7439               ic->depth )) {
7440             int size = AOP_SIZE(result) - 1;
7441             while (size--)
7442                 emitcode("dec","%s",rname);
7443         }
7444     }
7445
7446     /* done */
7447     freeAsmop(result,NULL,ic,TRUE);
7448      
7449 }
7450
7451 /*-----------------------------------------------------------------*/
7452 /* genPagedPointerGet - emitcode for paged pointer fetch           */
7453 /*-----------------------------------------------------------------*/
7454 static void genPagedPointerGet (operand *left, 
7455                                operand *result, 
7456                                iCode *ic)
7457 {
7458     asmop *aop = NULL;
7459     regs *preg = NULL ;
7460     char *rname ;
7461     sym_link *rtype, *retype;    
7462
7463     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7464
7465     rtype = operandType(result);
7466     retype= getSpec(rtype);
7467     
7468     aopOp(left,ic,FALSE);
7469
7470   /* if the value is already in a pointer register
7471        then don't need anything more */
7472     if (!AOP_INPREG(AOP(left))) {
7473         /* otherwise get a free pointer register */
7474         aop = newAsmop(0);
7475         preg = getFreePtr(ic,&aop,FALSE);
7476         emitcode("mov","%s,%s",
7477                 preg->name,
7478                 aopGet(AOP(left),0,FALSE,TRUE));
7479         rname = preg->name ;
7480     } else
7481         rname = aopGet(AOP(left),0,FALSE,FALSE);
7482     
7483     freeAsmop(left,NULL,ic,TRUE);
7484     aopOp (result,ic,FALSE);
7485
7486     /* if bitfield then unpack the bits */
7487     if (IS_BITVAR(retype)) 
7488         genUnpackBits (result,rname,PPOINTER);
7489     else {
7490         /* we have can just get the values */
7491         int size = AOP_SIZE(result);
7492         int offset = 0 ;        
7493         
7494         while (size--) {
7495             
7496             emitcode("movx","a,@%s",rname);
7497             aopPut(AOP(result),"a",offset);
7498             
7499             offset++ ;
7500             
7501             if (size)
7502                 emitcode("inc","%s",rname);
7503         }
7504     }
7505
7506     /* now some housekeeping stuff */
7507     if (aop) {
7508         /* we had to allocate for this iCode */
7509         freeAsmop(NULL,aop,ic,TRUE);
7510     } else { 
7511         /* we did not allocate which means left
7512            already in a pointer register, then
7513            if size > 0 && this could be used again
7514            we have to point it back to where it 
7515            belongs */
7516         if (AOP_SIZE(result) > 1 &&
7517             !OP_SYMBOL(left)->remat &&
7518             ( OP_SYMBOL(left)->liveTo > ic->seq ||
7519               ic->depth )) {
7520             int size = AOP_SIZE(result) - 1;
7521             while (size--)
7522                 emitcode("dec","%s",rname);
7523         }
7524     }
7525
7526     /* done */
7527     freeAsmop(result,NULL,ic,TRUE);
7528     
7529         
7530 }
7531
7532 /*-----------------------------------------------------------------*/
7533 /* genFarPointerGet - gget value from far space                    */
7534 /*-----------------------------------------------------------------*/
7535 static void genFarPointerGet (operand *left,
7536                               operand *result, iCode *ic)
7537 {
7538     int size, offset ;
7539     sym_link *retype = getSpec(operandType(result));
7540
7541     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7542
7543     aopOp(left,ic,FALSE);
7544
7545     /* if the operand is already in dptr 
7546     then we do nothing else we move the value to dptr */
7547     if (AOP_TYPE(left) != AOP_STR) {
7548         /* if this is remateriazable */
7549         if (AOP_TYPE(left) == AOP_IMMD)
7550             emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
7551         else { /* we need to get it byte by byte */
7552             emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
7553             emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
7554             if (options.model == MODEL_FLAT24)
7555             {
7556                emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
7557             }
7558         }
7559     }
7560     /* so dptr know contains the address */
7561     freeAsmop(left,NULL,ic,TRUE);
7562     aopOp(result,ic,FALSE);
7563
7564     /* if bit then unpack */
7565     if (IS_BITVAR(retype)) 
7566         genUnpackBits(result,"dptr",FPOINTER);
7567     else {
7568         size = AOP_SIZE(result);
7569         offset = 0 ;
7570
7571         while (size--) {
7572             emitcode("movx","a,@dptr");
7573             aopPut(AOP(result),"a",offset++);
7574             if (size)
7575                 emitcode("inc","dptr");
7576         }
7577     }
7578
7579     freeAsmop(result,NULL,ic,TRUE);
7580 }
7581
7582 /*-----------------------------------------------------------------*/
7583 /* emitcodePointerGet - gget value from code space                  */
7584 /*-----------------------------------------------------------------*/
7585 static void emitcodePointerGet (operand *left,
7586                                 operand *result, iCode *ic)
7587 {
7588     int size, offset ;
7589     sym_link *retype = getSpec(operandType(result));
7590
7591     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7592
7593     aopOp(left,ic,FALSE);
7594
7595     /* if the operand is already in dptr 
7596     then we do nothing else we move the value to dptr */
7597     if (AOP_TYPE(left) != AOP_STR) {
7598         /* if this is remateriazable */
7599         if (AOP_TYPE(left) == AOP_IMMD)
7600             emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
7601         else { /* we need to get it byte by byte */
7602             emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
7603             emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
7604             if (options.model == MODEL_FLAT24)
7605             {
7606                emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
7607             }
7608         }
7609     }
7610     /* so dptr know contains the address */
7611     freeAsmop(left,NULL,ic,TRUE);
7612     aopOp(result,ic,FALSE);
7613
7614     /* if bit then unpack */
7615     if (IS_BITVAR(retype)) 
7616         genUnpackBits(result,"dptr",CPOINTER);
7617     else {
7618         size = AOP_SIZE(result);
7619         offset = 0 ;
7620
7621         while (size--) {
7622             emitcode("clr","a");
7623             emitcode("movc","a,@a+dptr");
7624             aopPut(AOP(result),"a",offset++);
7625             if (size)
7626                 emitcode("inc","dptr");
7627         }
7628     }
7629
7630     freeAsmop(result,NULL,ic,TRUE);
7631 }
7632
7633 /*-----------------------------------------------------------------*/
7634 /* genGenPointerGet - gget value from generic pointer space        */
7635 /*-----------------------------------------------------------------*/
7636 static void genGenPointerGet (operand *left,
7637                               operand *result, iCode *ic)
7638 {
7639     int size, offset ;
7640     sym_link *retype = getSpec(operandType(result));
7641
7642     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7643     aopOp(left,ic,FALSE);
7644
7645     /* if the operand is already in dptr 
7646     then we do nothing else we move the value to dptr */
7647     if (AOP_TYPE(left) != AOP_STR) {
7648         /* if this is remateriazable */
7649         if (AOP_TYPE(left) == AOP_IMMD) {
7650             emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
7651             emitcode("mov","b,#%d",pointerCode(retype));
7652         }
7653         else { /* we need to get it byte by byte */
7654           
7655           emitpcode(POC_MOVFW,popGet(AOP(left),0,FALSE,FALSE));
7656           emitpcode(POC_MOVWF,popCopy(&pc_fsr));
7657           emitcode("movf","%s,w",aopGet(AOP(left),0,FALSE,FALSE));
7658           emitcode("movwf","FSR");
7659           /*
7660             emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
7661             emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
7662             if (options.model == MODEL_FLAT24)
7663             {
7664                emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
7665                emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE));
7666             }
7667             else
7668             {
7669                 emitcode("mov","b,%s",aopGet(AOP(left),2,FALSE,FALSE));
7670             }
7671           */
7672         }
7673     }
7674     /* so dptr know contains the address */
7675     freeAsmop(left,NULL,ic,TRUE);
7676     aopOp(result,ic,FALSE); 
7677
7678     /* if bit then unpack */
7679     if (IS_BITVAR(retype)) 
7680         genUnpackBits(result,"dptr",GPOINTER);
7681     else {
7682         size = AOP_SIZE(result);
7683         offset = 0 ;
7684
7685         while (size--) {
7686           emitpcode(POC_MOVFW,popCopy(&pc_fsr));
7687           emitpcode(POC_MOVWF,popGet(AOP(result),offset++,FALSE,FALSE));
7688           if(size)
7689             emitpcode(POC_INCF,popCopy(&pc_fsr));
7690 /*
7691           emitcode("movf","indf,w");
7692           emitcode("movwf","%s",
7693                    aopGet(AOP(result),offset++,FALSE,FALSE));
7694           if (size)
7695             emitcode("incf","fsr,f");
7696 */
7697         }
7698     }
7699
7700     freeAsmop(result,NULL,ic,TRUE);
7701 }
7702
7703 /*-----------------------------------------------------------------*/
7704 /* genPointerGet - generate code for pointer get                   */
7705 /*-----------------------------------------------------------------*/
7706 static void genPointerGet (iCode *ic)
7707 {
7708     operand *left, *result ;
7709     sym_link *type, *etype;
7710     int p_type;
7711
7712     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7713
7714     left = IC_LEFT(ic);
7715     result = IC_RESULT(ic) ;
7716
7717     /* depending on the type of pointer we need to
7718     move it to the correct pointer register */
7719     type = operandType(left);
7720     etype = getSpec(type);
7721     /* if left is of type of pointer then it is simple */
7722     if (IS_PTR(type) && !IS_FUNC(type->next)) 
7723         p_type = DCL_TYPE(type);
7724     else {
7725         /* we have to go by the storage class */
7726         p_type = PTR_TYPE(SPEC_OCLS(etype));
7727
7728 /*      if (SPEC_OCLS(etype)->codesp ) { */
7729 /*          p_type = CPOINTER ;  */
7730 /*      } */
7731 /*      else */
7732 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
7733 /*              p_type = FPOINTER ; */
7734 /*          else */
7735 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
7736 /*                  p_type = PPOINTER; */
7737 /*              else */
7738 /*                  if (SPEC_OCLS(etype) == idata ) */
7739 /*                      p_type = IPOINTER; */
7740 /*                  else */
7741 /*                      p_type = POINTER ; */
7742     }
7743
7744     /* now that we have the pointer type we assign
7745     the pointer values */
7746     switch (p_type) {
7747
7748     case POINTER:       
7749     case IPOINTER:
7750         genNearPointerGet (left,result,ic);
7751         break;
7752
7753     case PPOINTER:
7754         genPagedPointerGet(left,result,ic);
7755         break;
7756
7757     case FPOINTER:
7758         genFarPointerGet (left,result,ic);
7759         break;
7760
7761     case CPOINTER:
7762         emitcodePointerGet (left,result,ic);
7763         break;
7764
7765     case GPOINTER:
7766         genGenPointerGet (left,result,ic);
7767         break;
7768     }
7769
7770 }
7771
7772 /*-----------------------------------------------------------------*/
7773 /* genPackBits - generates code for packed bit storage             */
7774 /*-----------------------------------------------------------------*/
7775 static void genPackBits (sym_link    *etype ,
7776                          operand *right ,
7777                          char *rname, int p_type)
7778 {
7779     int shCount = 0 ;
7780     int offset = 0  ;
7781     int rLen = 0 ;
7782     int blen, bstr ;   
7783     char *l ;
7784
7785     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7786     blen = SPEC_BLEN(etype);
7787     bstr = SPEC_BSTR(etype);
7788
7789     l = aopGet(AOP(right),offset++,FALSE,FALSE);
7790     MOVA(l);   
7791
7792     /* if the bit lenth is less than or    */
7793     /* it exactly fits a byte then         */
7794     if (SPEC_BLEN(etype) <= 8 )  {
7795         shCount = SPEC_BSTR(etype) ;
7796
7797         /* shift left acc */
7798         AccLsh(shCount);
7799
7800         if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
7801
7802
7803             switch (p_type) {
7804                 case POINTER:
7805                     emitcode ("mov","b,a");
7806                     emitcode("mov","a,@%s",rname);
7807                     break;
7808
7809                 case FPOINTER:
7810                     emitcode ("mov","b,a");
7811                     emitcode("movx","a,@dptr");
7812                     break;
7813
7814                 case GPOINTER:
7815                     emitcode ("push","b");
7816                     emitcode ("push","acc");
7817                     emitcode ("lcall","__gptrget");
7818                     emitcode ("pop","b");
7819                     break;
7820             }
7821
7822             emitcode ("anl","a,#0x%02x",(unsigned char)
7823                       ((unsigned char)(0xFF << (blen+bstr)) | 
7824                        (unsigned char)(0xFF >> (8-bstr)) ) );
7825             emitcode ("orl","a,b");
7826             if (p_type == GPOINTER)
7827                 emitcode("pop","b");
7828         }
7829     }
7830
7831     switch (p_type) {
7832         case POINTER:
7833             emitcode("mov","@%s,a",rname);
7834             break;
7835
7836         case FPOINTER:
7837             emitcode("movx","@dptr,a");
7838             break;
7839
7840         case GPOINTER:
7841             DEBUGemitcode(";lcall","__gptrput");
7842             break;
7843     }
7844
7845     /* if we r done */
7846     if ( SPEC_BLEN(etype) <= 8 )
7847         return ;
7848
7849     emitcode("inc","%s",rname);
7850     rLen = SPEC_BLEN(etype) ;     
7851
7852     /* now generate for lengths greater than one byte */
7853     while (1) {
7854
7855         l = aopGet(AOP(right),offset++,FALSE,TRUE);
7856
7857         rLen -= 8 ;
7858         if (rLen <= 0 )
7859             break ;
7860
7861         switch (p_type) {
7862             case POINTER:
7863                 if (*l == '@') {
7864                     MOVA(l);
7865                     emitcode("mov","@%s,a",rname);
7866                 } else
7867                     emitcode("mov","@%s,%s",rname,l);
7868                 break;
7869
7870             case FPOINTER:
7871                 MOVA(l);
7872                 emitcode("movx","@dptr,a");
7873                 break;
7874
7875             case GPOINTER:
7876                 MOVA(l);
7877                 DEBUGemitcode(";lcall","__gptrput");
7878                 break;  
7879         }   
7880         emitcode ("inc","%s",rname);
7881     }
7882
7883     MOVA(l);
7884
7885     /* last last was not complete */
7886     if (rLen)   {
7887         /* save the byte & read byte */
7888         switch (p_type) {
7889             case POINTER:
7890                 emitcode ("mov","b,a");
7891                 emitcode("mov","a,@%s",rname);
7892                 break;
7893
7894             case FPOINTER:
7895                 emitcode ("mov","b,a");
7896                 emitcode("movx","a,@dptr");
7897                 break;
7898
7899             case GPOINTER:
7900                 emitcode ("push","b");
7901                 emitcode ("push","acc");
7902                 emitcode ("lcall","__gptrget");
7903                 emitcode ("pop","b");
7904                 break;
7905         }
7906
7907         emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
7908         emitcode ("orl","a,b");
7909     }
7910
7911     if (p_type == GPOINTER)
7912         emitcode("pop","b");
7913
7914     switch (p_type) {
7915
7916     case POINTER:
7917         emitcode("mov","@%s,a",rname);
7918         break;
7919         
7920     case FPOINTER:
7921         emitcode("movx","@dptr,a");
7922         break;
7923         
7924     case GPOINTER:
7925         DEBUGemitcode(";lcall","__gptrput");
7926         break;                  
7927     }
7928 }
7929 /*-----------------------------------------------------------------*/
7930 /* genDataPointerSet - remat pointer to data space                 */
7931 /*-----------------------------------------------------------------*/
7932 static void genDataPointerSet(operand *right,
7933                               operand *result,
7934                               iCode *ic)
7935 {
7936     int size, offset = 0 ;
7937     char *l, buffer[256];
7938
7939     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7940     aopOp(right,ic,FALSE);
7941     
7942     l = aopGet(AOP(result),0,FALSE,TRUE);
7943     size = AOP_SIZE(right);
7944     // tsd, was l+1 - the underline `_' prefix was being stripped
7945     while (size--) {
7946         if (offset)
7947             sprintf(buffer,"(%s + %d)",l,offset);
7948         else
7949             sprintf(buffer,"%s",l);
7950
7951         if (AOP_TYPE(right) == AOP_LIT) {
7952           unsigned int lit = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
7953           lit = lit >> (8*offset);
7954           if(lit) {
7955             emitcode("movlw","%s",lit);
7956             emitcode("movwf","%s",buffer);
7957           } else 
7958             emitcode("clrf","%s",buffer);
7959         }else {
7960           emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
7961           emitcode("movwf","%s",buffer);
7962         }
7963
7964         offset++;
7965     }
7966
7967     freeAsmop(right,NULL,ic,TRUE);
7968     freeAsmop(result,NULL,ic,TRUE);
7969 }
7970
7971 /*-----------------------------------------------------------------*/
7972 /* genNearPointerSet - emitcode for near pointer put                */
7973 /*-----------------------------------------------------------------*/
7974 static void genNearPointerSet (operand *right,
7975                                operand *result, 
7976                                iCode *ic)
7977 {
7978     asmop *aop = NULL;
7979     char *l;
7980     sym_link *retype;
7981     sym_link *ptype = operandType(result);
7982
7983     
7984     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7985     retype= getSpec(operandType(right));
7986
7987     aopOp(result,ic,FALSE);
7988     
7989     /* if the result is rematerializable &
7990        in data space & not a bit variable */
7991     if (AOP_TYPE(result) == AOP_IMMD &&
7992         DCL_TYPE(ptype) == POINTER   &&
7993         !IS_BITVAR(retype)) {
7994         genDataPointerSet (right,result,ic);
7995         return;
7996     }
7997
7998     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7999
8000     /* if the value is already in a pointer register
8001     then don't need anything more */
8002     if (!AOP_INPREG(AOP(result))) {
8003         /* otherwise get a free pointer register */
8004         //aop = newAsmop(0);
8005         //preg = getFreePtr(ic,&aop,FALSE);
8006         DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8007         //emitcode("mov","%s,%s",
8008         //         preg->name,
8009         //         aopGet(AOP(result),0,FALSE,TRUE));
8010         //rname = preg->name ;
8011         emitcode("movwf","fsr");
8012     }// else
8013     //   rname = aopGet(AOP(result),0,FALSE,FALSE);
8014
8015     freeAsmop(result,NULL,ic,TRUE);
8016     aopOp (right,ic,FALSE);
8017     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8018
8019     /* if bitfield then unpack the bits */
8020     if (IS_BITVAR(retype)) {
8021       werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8022              "The programmer is obviously confused");
8023       //genPackBits (retype,right,rname,POINTER);
8024       exit(1);
8025     }
8026     else {
8027         /* we have can just get the values */
8028         int size = AOP_SIZE(right);
8029         int offset = 0 ;    
8030
8031     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8032         while (size--) {
8033             l = aopGet(AOP(right),offset,FALSE,TRUE);
8034             if (*l == '@' ) {
8035               //MOVA(l);
8036               //emitcode("mov","@%s,a",rname);
8037               emitcode("movf","indf,w ;1");
8038             } else {
8039
8040               if (AOP_TYPE(right) == AOP_LIT) {
8041                 unsigned int lit = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
8042                 if(lit) {
8043                   emitcode("movlw","%s",l);
8044                   emitcode("movwf","indf ;2");
8045                 } else 
8046                   emitcode("clrf","indf");
8047               }else {
8048                 emitcode("movf","%s,w",l);
8049                 emitcode("movwf","indf ;2");
8050               }
8051             //emitcode("mov","@%s,%s",rname,l);
8052             }
8053             if (size)
8054               emitcode("incf","fsr,f ;3");
8055             //emitcode("inc","%s",rname);
8056             offset++;
8057         }
8058     }
8059
8060     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8061     /* now some housekeeping stuff */
8062     if (aop) {
8063         /* we had to allocate for this iCode */
8064         freeAsmop(NULL,aop,ic,TRUE);
8065     } else { 
8066         /* we did not allocate which means left
8067         already in a pointer register, then
8068         if size > 0 && this could be used again
8069         we have to point it back to where it 
8070         belongs */
8071     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8072         if (AOP_SIZE(right) > 1 &&
8073             !OP_SYMBOL(result)->remat &&
8074             ( OP_SYMBOL(result)->liveTo > ic->seq ||
8075               ic->depth )) {
8076             int size = AOP_SIZE(right) - 1;
8077             while (size--)
8078               emitcode("decf","fsr,f");
8079               //emitcode("dec","%s",rname);
8080         }
8081     }
8082
8083     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8084     /* done */
8085     freeAsmop(right,NULL,ic,TRUE);
8086
8087
8088 }
8089
8090 /*-----------------------------------------------------------------*/
8091 /* genPagedPointerSet - emitcode for Paged pointer put             */
8092 /*-----------------------------------------------------------------*/
8093 static void genPagedPointerSet (operand *right,
8094                                operand *result, 
8095                                iCode *ic)
8096 {
8097     asmop *aop = NULL;
8098     regs *preg = NULL ;
8099     char *rname , *l;
8100     sym_link *retype;
8101        
8102     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8103
8104     retype= getSpec(operandType(right));
8105     
8106     aopOp(result,ic,FALSE);
8107     
8108     /* if the value is already in a pointer register
8109        then don't need anything more */
8110     if (!AOP_INPREG(AOP(result))) {
8111         /* otherwise get a free pointer register */
8112         aop = newAsmop(0);
8113         preg = getFreePtr(ic,&aop,FALSE);
8114         emitcode("mov","%s,%s",
8115                 preg->name,
8116                 aopGet(AOP(result),0,FALSE,TRUE));
8117         rname = preg->name ;
8118     } else
8119         rname = aopGet(AOP(result),0,FALSE,FALSE);
8120     
8121     freeAsmop(result,NULL,ic,TRUE);
8122     aopOp (right,ic,FALSE);
8123
8124     /* if bitfield then unpack the bits */
8125     if (IS_BITVAR(retype)) 
8126         genPackBits (retype,right,rname,PPOINTER);
8127     else {
8128         /* we have can just get the values */
8129         int size = AOP_SIZE(right);
8130         int offset = 0 ;        
8131         
8132         while (size--) {
8133             l = aopGet(AOP(right),offset,FALSE,TRUE);
8134             
8135             MOVA(l);
8136             emitcode("movx","@%s,a",rname);
8137
8138             if (size)
8139                 emitcode("inc","%s",rname);
8140
8141             offset++;
8142         }
8143     }
8144     
8145     /* now some housekeeping stuff */
8146     if (aop) {
8147         /* we had to allocate for this iCode */
8148         freeAsmop(NULL,aop,ic,TRUE);
8149     } else { 
8150         /* we did not allocate which means left
8151            already in a pointer register, then
8152            if size > 0 && this could be used again
8153            we have to point it back to where it 
8154            belongs */
8155         if (AOP_SIZE(right) > 1 &&
8156             !OP_SYMBOL(result)->remat &&
8157             ( OP_SYMBOL(result)->liveTo > ic->seq ||
8158               ic->depth )) {
8159             int size = AOP_SIZE(right) - 1;
8160             while (size--)
8161                 emitcode("dec","%s",rname);
8162         }
8163     }
8164
8165     /* done */
8166     freeAsmop(right,NULL,ic,TRUE);
8167     
8168         
8169 }
8170
8171 /*-----------------------------------------------------------------*/
8172 /* genFarPointerSet - set value from far space                     */
8173 /*-----------------------------------------------------------------*/
8174 static void genFarPointerSet (operand *right,
8175                               operand *result, iCode *ic)
8176 {
8177     int size, offset ;
8178     sym_link *retype = getSpec(operandType(right));
8179
8180     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8181     aopOp(result,ic,FALSE);
8182
8183     /* if the operand is already in dptr 
8184     then we do nothing else we move the value to dptr */
8185     if (AOP_TYPE(result) != AOP_STR) {
8186         /* if this is remateriazable */
8187         if (AOP_TYPE(result) == AOP_IMMD)
8188             emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
8189         else { /* we need to get it byte by byte */
8190             emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
8191             emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
8192             if (options.model == MODEL_FLAT24)
8193             {
8194                emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
8195             }
8196         }
8197     }
8198     /* so dptr know contains the address */
8199     freeAsmop(result,NULL,ic,TRUE);
8200     aopOp(right,ic,FALSE);
8201
8202     /* if bit then unpack */
8203     if (IS_BITVAR(retype)) 
8204         genPackBits(retype,right,"dptr",FPOINTER);
8205     else {
8206         size = AOP_SIZE(right);
8207         offset = 0 ;
8208
8209         while (size--) {
8210             char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
8211             MOVA(l);
8212             emitcode("movx","@dptr,a");
8213             if (size)
8214                 emitcode("inc","dptr");
8215         }
8216     }
8217
8218     freeAsmop(right,NULL,ic,TRUE);
8219 }
8220
8221 /*-----------------------------------------------------------------*/
8222 /* genGenPointerSet - set value from generic pointer space         */
8223 /*-----------------------------------------------------------------*/
8224 static void genGenPointerSet (operand *right,
8225                               operand *result, iCode *ic)
8226 {
8227     int size, offset ;
8228     sym_link *retype = getSpec(operandType(right));
8229
8230     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8231
8232     aopOp(result,ic,FALSE);
8233
8234     /* if the operand is already in dptr 
8235     then we do nothing else we move the value to dptr */
8236     if (AOP_TYPE(result) != AOP_STR) {
8237         /* if this is remateriazable */
8238         if (AOP_TYPE(result) == AOP_IMMD) {
8239             emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
8240             emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
8241         }
8242         else { /* we need to get it byte by byte */
8243           char *l = aopGet(AOP(result),0,FALSE,FALSE);
8244
8245           if(strcmp("FSR",l))
8246             emitpcode(POC_MOVLW ,popGet(AOP(result),0,FALSE,FALSE));
8247           emitpcode(POC_MOVWF,popCopy(&pc_indf));
8248
8249           if(strcmp("FSR",l))
8250             emitcode("movlw","%s",aopGet(AOP(result),0,FALSE,FALSE));
8251
8252           emitcode("movwf","INDF");
8253         }
8254     }
8255     /* so dptr know contains the address */
8256     freeAsmop(result,NULL,ic,TRUE);
8257     aopOp(right,ic,FALSE);
8258
8259     /* if bit then unpack */
8260     if (IS_BITVAR(retype)) 
8261         genPackBits(retype,right,"dptr",GPOINTER);
8262     else {
8263         size = AOP_SIZE(right);
8264         offset = 0 ;
8265
8266         while (--size) {
8267           //char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
8268             if(size)
8269               emitcode("incf","fsr,f");
8270             emitcode("movf","%s,w",aopGet(AOP(right),offset++,FALSE,FALSE));
8271             emitcode("movwf","indf");
8272             //MOVA(l);
8273             //DEBUGemitcode(";lcall","__gptrput");
8274             //if (size)
8275             //    emitcode("inc","dptr");
8276         }
8277     }
8278
8279     freeAsmop(right,NULL,ic,TRUE);
8280 }
8281
8282 /*-----------------------------------------------------------------*/
8283 /* genPointerSet - stores the value into a pointer location        */
8284 /*-----------------------------------------------------------------*/
8285 static void genPointerSet (iCode *ic)
8286 {    
8287     operand *right, *result ;
8288     sym_link *type, *etype;
8289     int p_type;
8290
8291     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8292
8293     right = IC_RIGHT(ic);
8294     result = IC_RESULT(ic) ;
8295
8296     /* depending on the type of pointer we need to
8297     move it to the correct pointer register */
8298     type = operandType(result);
8299     etype = getSpec(type);
8300     /* if left is of type of pointer then it is simple */
8301     if (IS_PTR(type) && !IS_FUNC(type->next)) {
8302         p_type = DCL_TYPE(type);
8303     }
8304     else {
8305         /* we have to go by the storage class */
8306         p_type = PTR_TYPE(SPEC_OCLS(etype));
8307
8308 /*      if (SPEC_OCLS(etype)->codesp ) { */
8309 /*          p_type = CPOINTER ;  */
8310 /*      } */
8311 /*      else */
8312 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
8313 /*              p_type = FPOINTER ; */
8314 /*          else */
8315 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
8316 /*                  p_type = PPOINTER ; */
8317 /*              else */
8318 /*                  if (SPEC_OCLS(etype) == idata ) */
8319 /*                      p_type = IPOINTER ; */
8320 /*                  else */
8321 /*                      p_type = POINTER ; */
8322     }
8323
8324     /* now that we have the pointer type we assign
8325     the pointer values */
8326     switch (p_type) {
8327
8328     case POINTER:
8329     case IPOINTER:
8330         genNearPointerSet (right,result,ic);
8331         break;
8332
8333     case PPOINTER:
8334         genPagedPointerSet (right,result,ic);
8335         break;
8336
8337     case FPOINTER:
8338         genFarPointerSet (right,result,ic);
8339         break;
8340
8341     case GPOINTER:
8342         genGenPointerSet (right,result,ic);
8343         break;
8344     }
8345
8346 }
8347
8348 /*-----------------------------------------------------------------*/
8349 /* genIfx - generate code for Ifx statement                        */
8350 /*-----------------------------------------------------------------*/
8351 static void genIfx (iCode *ic, iCode *popIc)
8352 {
8353     operand *cond = IC_COND(ic);
8354     int isbit =0;
8355
8356     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8357     aopOp(cond,ic,FALSE);
8358
8359     /* get the value into acc */
8360     if (AOP_TYPE(cond) != AOP_CRY)
8361         toBoolean(cond);
8362     else
8363         isbit = 1;
8364     /* the result is now in the accumulator */
8365     freeAsmop(cond,NULL,ic,TRUE);
8366
8367     /* if there was something to be popped then do it */
8368     if (popIc)
8369         genIpop(popIc);
8370
8371     /* if the condition is  a bit variable */
8372     if (isbit && IS_ITEMP(cond) && 
8373         SPIL_LOC(cond)) {
8374       genIfxJump(ic,SPIL_LOC(cond)->rname);
8375       DEBUGemitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
8376     }
8377     else {
8378       /*
8379         if (isbit && !IS_ITEMP(cond))
8380           DEBUGemitcode ("; isbit OP_SYM","%s",OP_SYMBOL(cond)->rname);
8381         else
8382           DEBUGemitcode ("; isbit","a");
8383       */
8384
8385         if (isbit && !IS_ITEMP(cond))
8386             genIfxJump(ic,OP_SYMBOL(cond)->rname);
8387         else
8388             genIfxJump(ic,"a");
8389     }
8390     ic->generated = 1;
8391 }
8392
8393 /*-----------------------------------------------------------------*/
8394 /* genAddrOf - generates code for address of                       */
8395 /*-----------------------------------------------------------------*/
8396 static void genAddrOf (iCode *ic)
8397 {
8398     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
8399     int size, offset ;
8400
8401     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8402
8403     aopOp(IC_RESULT(ic),ic,FALSE);
8404
8405     /* if the operand is on the stack then we 
8406     need to get the stack offset of this
8407     variable */
8408     if (sym->onStack) {
8409         /* if it has an offset then we need to compute
8410         it */
8411         if (sym->stack) {
8412             emitcode("mov","a,_bp");
8413             emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
8414             aopPut(AOP(IC_RESULT(ic)),"a",0);       
8415         } else {
8416             /* we can just move _bp */
8417             aopPut(AOP(IC_RESULT(ic)),"_bp",0);
8418         }
8419         /* fill the result with zero */
8420         size = AOP_SIZE(IC_RESULT(ic)) - 1;
8421         
8422         
8423         if (options.stack10bit && size < (FPTRSIZE - 1))
8424         {
8425             fprintf(stderr, 
8426                     "*** warning: pointer to stack var truncated.\n");
8427         }
8428         
8429         offset = 1;
8430         while (size--)
8431         {
8432             /* Yuck! */
8433             if (options.stack10bit && offset == 2)
8434             {
8435                 aopPut(AOP(IC_RESULT(ic)),"#0x40", offset++);
8436             }
8437             else
8438             {
8439                 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
8440             }
8441         }
8442
8443         goto release;
8444     }
8445
8446     /* object not on stack then we need the name */
8447     size = AOP_SIZE(IC_RESULT(ic));
8448     offset = 0;
8449
8450     while (size--) {
8451         char s[SDCC_NAME_MAX];
8452         if (offset) 
8453             sprintf(s,"#(%s >> %d)",
8454                     sym->rname,
8455                     offset*8);
8456         else
8457             sprintf(s,"#%s",sym->rname);
8458         aopPut(AOP(IC_RESULT(ic)),s,offset++);
8459     }
8460
8461 release:
8462     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8463
8464 }
8465
8466 #if 0
8467 /*-----------------------------------------------------------------*/
8468 /* genFarFarAssign - assignment when both are in far space         */
8469 /*-----------------------------------------------------------------*/
8470 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
8471 {
8472     int size = AOP_SIZE(right);
8473     int offset = 0;
8474     char *l ;
8475     /* first push the right side on to the stack */
8476     while (size--) {
8477         l = aopGet(AOP(right),offset++,FALSE,FALSE);
8478         MOVA(l);
8479         emitcode ("push","acc");
8480     }
8481     
8482     freeAsmop(right,NULL,ic,FALSE);
8483     /* now assign DPTR to result */
8484     aopOp(result,ic,FALSE);
8485     size = AOP_SIZE(result);
8486     while (size--) {
8487         emitcode ("pop","acc");
8488         aopPut(AOP(result),"a",--offset);
8489     }
8490     freeAsmop(result,NULL,ic,FALSE);
8491         
8492 }
8493 #endif
8494
8495 /*-----------------------------------------------------------------*/
8496 /* genAssign - generate code for assignment                        */
8497 /*-----------------------------------------------------------------*/
8498 static void genAssign (iCode *ic)
8499 {
8500     operand *result, *right;
8501     int size, offset ;
8502         unsigned long lit = 0L;
8503
8504     result = IC_RESULT(ic);
8505     right  = IC_RIGHT(ic) ;
8506
8507     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8508
8509     /* if they are the same */
8510     if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
8511         return ;
8512
8513     aopOp(right,ic,FALSE);
8514     aopOp(result,ic,TRUE);
8515
8516     /* if they are the same registers */
8517     if (sameRegs(AOP(right),AOP(result)))
8518         goto release;
8519
8520     /* if the result is a bit */
8521     if (AOP_TYPE(result) == AOP_CRY) {
8522
8523         /* if the right size is a literal then
8524         we know what the value is */
8525         if (AOP_TYPE(right) == AOP_LIT) {
8526           
8527           emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
8528                       popGet(AOP(result),0,FALSE,FALSE));
8529
8530             if (((int) operandLitValue(right))) 
8531               emitcode("bsf","(%s >> 3),(%s & 7)",
8532                        AOP(result)->aopu.aop_dir,
8533                        AOP(result)->aopu.aop_dir);
8534             else
8535               emitcode("bcf","(%s >> 3),(%s & 7)",
8536                  AOP(result)->aopu.aop_dir,
8537                  AOP(result)->aopu.aop_dir);
8538             goto release;
8539         }
8540
8541         /* the right is also a bit variable */
8542         if (AOP_TYPE(right) == AOP_CRY) {
8543           emitpcode(POC_BCF,    popGet(AOP(result),0,FALSE,FALSE));
8544           emitpcode(POC_BTFSC,  popGet(AOP(right),0,FALSE,FALSE));
8545           emitpcode(POC_BSF,    popGet(AOP(result),0,FALSE,FALSE));
8546
8547           emitcode("bcf","(%s >> 3),(%s & 7)",
8548                    AOP(result)->aopu.aop_dir,
8549                    AOP(result)->aopu.aop_dir);
8550           emitcode("btfsc","(%s >> 3),(%s & 7)",
8551                    AOP(right)->aopu.aop_dir,
8552                    AOP(right)->aopu.aop_dir);
8553           emitcode("bsf","(%s >> 3),(%s & 7)",
8554                    AOP(result)->aopu.aop_dir,
8555                    AOP(result)->aopu.aop_dir);
8556           goto release ;
8557         }
8558
8559         /* we need to or */
8560         emitpcode(POC_BCF,    popGet(AOP(result),0,FALSE,FALSE));
8561         toBoolean(right);
8562         emitSKPZ;
8563         emitpcode(POC_BSF,    popGet(AOP(result),0,FALSE,FALSE));
8564         //aopPut(AOP(result),"a",0);
8565         goto release ;
8566     }
8567
8568     /* bit variables done */
8569     /* general case */
8570     size = AOP_SIZE(result);
8571     offset = 0 ;
8572     if(AOP_TYPE(right) == AOP_LIT)
8573         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
8574     if((AOP_TYPE(result) != AOP_REG) &&
8575        (AOP_TYPE(right) == AOP_LIT) &&
8576        !IS_FLOAT(operandType(right)) &&
8577        (lit < 256L)){
8578
8579         while (size--) {
8580           if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0) {
8581             //emitcode("clrf","%s", aopGet(AOP(result),size,FALSE,FALSE));
8582               emitpcode(POC_CLRF,popGet(AOP(result),size,FALSE,FALSE));
8583             }else {
8584               emitpcode(POC_MOVLW,popGet(AOP(right),size,FALSE,FALSE));
8585               emitpcode(POC_MOVWF,popGet(AOP(result),size,FALSE,FALSE));
8586               //emitcode("movlw","%s", aopGet(AOP(right),size,FALSE,FALSE));
8587               //emitcode("movwf","%s", aopGet(AOP(result),size,FALSE,FALSE));
8588             }
8589         }
8590     } else {
8591         while (size--) {
8592           if(AOP_TYPE(right) == AOP_LIT) {
8593             emitpcode(POC_MOVLW, popGet(AOP(right),offset,FALSE,FALSE));
8594             emitpcode(POC_MOVWF, popGet(AOP(result),offset,FALSE,FALSE));
8595
8596           } else if (AOP_TYPE(right) == AOP_CRY) {
8597             emitpcode(POC_CLRF, popGet(AOP(result),offset,FALSE,FALSE));
8598             if(offset == 0) {
8599               emitpcode(POC_BTFSS, popGet(AOP(right),0,FALSE,FALSE));
8600               emitpcode(POC_INCF, popGet(AOP(result),0,FALSE,FALSE));
8601             }
8602           } else {
8603             emitpcode(POC_MOVFW, popGet(AOP(right),offset,FALSE,FALSE));
8604             emitpcode(POC_MOVWF, popGet(AOP(result),offset,FALSE,FALSE));
8605           }
8606             
8607           //emitcode("movwf","%s", aopGet(AOP(result),offset,FALSE,FALSE));
8608           offset++;
8609         }
8610     }
8611     
8612 release:
8613     freeAsmop (right,NULL,ic,FALSE);
8614     freeAsmop (result,NULL,ic,TRUE);
8615 }   
8616
8617 /*-----------------------------------------------------------------*/
8618 /* genJumpTab - genrates code for jump table                       */
8619 /*-----------------------------------------------------------------*/
8620 static void genJumpTab (iCode *ic)
8621 {
8622     symbol *jtab;
8623     char *l;
8624
8625     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8626
8627     aopOp(IC_JTCOND(ic),ic,FALSE);
8628     /* get the condition into accumulator */
8629     l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
8630     MOVA(l);
8631     /* multiply by three */
8632     emitcode("add","a,acc");
8633     emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
8634     freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
8635
8636     jtab = newiTempLabel(NULL);
8637     emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
8638     emitcode("jmp","@a+dptr");
8639     emitcode("","%05d_DS_:",jtab->key+100);
8640     /* now generate the jump labels */
8641     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
8642          jtab = setNextItem(IC_JTLABELS(ic)))
8643         emitcode("ljmp","%05d_DS_",jtab->key+100);
8644
8645 }
8646
8647 /*-----------------------------------------------------------------*/
8648 /* genMixedOperation - gen code for operators between mixed types  */
8649 /*-----------------------------------------------------------------*/
8650 /*
8651   TSD - Written for the PIC port - but this unfortunately is buggy.
8652   This routine is good in that it is able to efficiently promote 
8653   types to different (larger) sizes. Unfortunately, the temporary
8654   variables that are optimized out by this routine are sometimes
8655   used in other places. So until I know how to really parse the 
8656   iCode tree, I'm going to not be using this routine :(.
8657 */
8658 static int genMixedOperation (iCode *ic)
8659 {
8660 #if 0
8661   operand *result = IC_RESULT(ic);
8662   sym_link *ctype = operandType(IC_LEFT(ic));
8663   operand *right = IC_RIGHT(ic);
8664   int ret = 0;
8665   int big,small;
8666   int offset;
8667
8668   iCode *nextic;
8669   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
8670
8671   emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
8672
8673   nextic = ic->next;
8674   if(!nextic)
8675     return 0;
8676
8677   nextright = IC_RIGHT(nextic);
8678   nextleft  = IC_LEFT(nextic);
8679   nextresult = IC_RESULT(nextic);
8680
8681   aopOp(right,ic,FALSE);
8682   aopOp(result,ic,FALSE);
8683   aopOp(nextright,  nextic, FALSE);
8684   aopOp(nextleft,   nextic, FALSE);
8685   aopOp(nextresult, nextic, FALSE);
8686
8687   if (sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
8688
8689     operand *t = right;
8690     right = nextright;
8691     nextright = t; 
8692
8693     emitcode(";remove right +","");
8694
8695   } else   if (sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
8696 /*
8697     operand *t = right;
8698     right = nextleft;
8699     nextleft = t; 
8700 */
8701     emitcode(";remove left +","");
8702   } else
8703     return 0;
8704
8705   big = AOP_SIZE(nextleft);
8706   small = AOP_SIZE(nextright);
8707
8708   switch(nextic->op) {
8709
8710   case '+':
8711     emitcode(";optimize a +","");
8712     /* if unsigned or not an integral type */
8713     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
8714       emitcode(";add a bit to something","");
8715     } else {
8716
8717       emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
8718
8719       if (!sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
8720         emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
8721         emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
8722       } else
8723         emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
8724
8725       offset = 0;
8726       while(--big) {
8727
8728         offset++;
8729
8730         if(--small) {
8731           if (!sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
8732             emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8733             emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
8734           }
8735
8736           emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8737           emitSKPNC;
8738           emitcode("btfsc","(%s >> 3), (%s & 7)",
8739                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
8740                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
8741           emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8742           emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
8743
8744         } else {
8745           emitcode("rlf","known_zero,w");
8746
8747           /*
8748             if right is signed
8749               btfsc  right,7
8750                addlw ff
8751           */
8752           if (!sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
8753             emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8754             emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
8755           } else {
8756             emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
8757           }
8758         }
8759       }
8760       ret = 1;
8761     }
8762   }
8763   ret = 1;
8764
8765 release:
8766   freeAsmop(right,NULL,ic,TRUE);
8767   freeAsmop(result,NULL,ic,TRUE);
8768   freeAsmop(nextright,NULL,ic,TRUE);
8769   freeAsmop(nextleft,NULL,ic,TRUE);
8770   if(ret)
8771     nextic->generated = 1;
8772
8773   return ret;
8774 #else
8775   return 0;
8776 #endif
8777 }
8778 /*-----------------------------------------------------------------*/
8779 /* genCast - gen code for casting                                  */
8780 /*-----------------------------------------------------------------*/
8781 static void genCast (iCode *ic)
8782 {
8783     operand *result = IC_RESULT(ic);
8784     sym_link *ctype = operandType(IC_LEFT(ic));
8785     operand *right = IC_RIGHT(ic);
8786     int size, offset ;
8787
8788     DEBUGemitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
8789     /* if they are equivalent then do nothing */
8790     if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
8791         return ;
8792
8793     aopOp(right,ic,FALSE) ;
8794     aopOp(result,ic,FALSE);
8795
8796     /* if the result is a bit */
8797     if (AOP_TYPE(result) == AOP_CRY) {
8798         /* if the right size is a literal then
8799         we know what the value is */
8800         if (AOP_TYPE(right) == AOP_LIT) {
8801
8802           emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
8803                       popGet(AOP(result),0,FALSE,FALSE));
8804
8805             if (((int) operandLitValue(right))) 
8806               emitcode("bsf","(%s >> 3), (%s & 7)",
8807                        AOP(result)->aopu.aop_dir,
8808                        AOP(result)->aopu.aop_dir);
8809             else
8810               emitcode("bcf","(%s >> 3), (%s & 7)",
8811                        AOP(result)->aopu.aop_dir,
8812                        AOP(result)->aopu.aop_dir);
8813
8814             goto release;
8815         }
8816
8817         /* the right is also a bit variable */
8818         if (AOP_TYPE(right) == AOP_CRY) {
8819
8820           emitCLRC;
8821           emitpcode(POC_BTFSC,  popGet(AOP(right),0,FALSE,FALSE));
8822
8823           emitcode("clrc","");
8824           emitcode("btfsc","(%s >> 3), (%s & 7)",
8825                    AOP(right)->aopu.aop_dir,
8826                    AOP(right)->aopu.aop_dir);
8827             aopPut(AOP(result),"c",0);
8828             goto release ;
8829         }
8830
8831         /* we need to or */
8832         toBoolean(right);
8833         aopPut(AOP(result),"a",0);
8834         goto release ;
8835     }
8836
8837     /* if they are the same size : or less */
8838     if (AOP_SIZE(result) <= AOP_SIZE(right)) {
8839
8840         /* if they are in the same place */
8841         if (sameRegs(AOP(right),AOP(result)))
8842             goto release;
8843
8844         /* if they in different places then copy */
8845         size = AOP_SIZE(result);
8846         offset = 0 ;
8847         while (size--) {
8848             aopPut(AOP(result),
8849                    aopGet(AOP(right),offset,FALSE,FALSE),
8850                    offset);
8851             offset++;
8852         }
8853         goto release;
8854     }
8855
8856
8857     /* if the result is of type pointer */
8858     if (IS_PTR(ctype)) {
8859
8860         int p_type;
8861         sym_link *type = operandType(right);
8862         sym_link *etype = getSpec(type);
8863
8864         /* pointer to generic pointer */
8865         if (IS_GENPTR(ctype)) {
8866             char *l = zero;
8867             
8868             if (IS_PTR(type)) 
8869                 p_type = DCL_TYPE(type);
8870             else {
8871                 /* we have to go by the storage class */
8872                 p_type = PTR_TYPE(SPEC_OCLS(etype));
8873
8874 /*              if (SPEC_OCLS(etype)->codesp )  */
8875 /*                  p_type = CPOINTER ;  */
8876 /*              else */
8877 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
8878 /*                      p_type = FPOINTER ; */
8879 /*                  else */
8880 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
8881 /*                          p_type = PPOINTER; */
8882 /*                      else */
8883 /*                          if (SPEC_OCLS(etype) == idata ) */
8884 /*                              p_type = IPOINTER ; */
8885 /*                          else */
8886 /*                              p_type = POINTER ; */
8887             }
8888                 
8889             /* the first two bytes are known */
8890             size = GPTRSIZE - 1; 
8891             offset = 0 ;
8892             while (size--) {
8893                 aopPut(AOP(result),
8894                        aopGet(AOP(right),offset,FALSE,FALSE),
8895                        offset);
8896                 offset++;
8897             }
8898             /* the last byte depending on type */
8899             switch (p_type) {
8900             case IPOINTER:
8901             case POINTER:
8902                 l = zero;
8903                 break;
8904             case FPOINTER:
8905                 l = one;
8906                 break;
8907             case CPOINTER:
8908                 l = "#0x02";
8909                 break;                          
8910             case PPOINTER:
8911                 l = "#0x03";
8912                 break;
8913                 
8914             default:
8915                 /* this should never happen */
8916                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8917                        "got unknown pointer type");
8918                 exit(1);
8919             }
8920             aopPut(AOP(result),l, GPTRSIZE - 1);            
8921             goto release ;
8922         }
8923         
8924         /* just copy the pointers */
8925         size = AOP_SIZE(result);
8926         offset = 0 ;
8927         while (size--) {
8928             aopPut(AOP(result),
8929                    aopGet(AOP(right),offset,FALSE,FALSE),
8930                    offset);
8931             offset++;
8932         }
8933         goto release ;
8934     }
8935     
8936
8937     if (AOP_TYPE(right) == AOP_CRY) {
8938       int offset = 1;
8939       size = AOP_SIZE(right);
8940
8941       emitpcode(POC_CLRF,   popGet(AOP(result),0,FALSE,FALSE));
8942       emitpcode(POC_BTFSC,  popGet(AOP(right),0,FALSE,FALSE));
8943       emitpcode(POC_INCF,   popGet(AOP(result),0,FALSE,FALSE));
8944
8945       emitcode("clrf","%s ; %d", aopGet(AOP(result),0,FALSE,FALSE),__LINE__);
8946       emitcode("btfsc","(%s >> 3), (%s & 7)",
8947                AOP(right)->aopu.aop_dir,
8948                AOP(right)->aopu.aop_dir);
8949       emitcode("incf","%s,f", aopGet(AOP(result),0,FALSE,FALSE),__LINE__);
8950       while (size--) {
8951         emitcode("clrf","%s;%d", aopGet(AOP(result),offset,FALSE,FALSE),__LINE__);
8952         emitpcode(POC_CLRF,   popGet(AOP(result),offset++,FALSE,FALSE));
8953       }
8954       goto release;
8955     }
8956
8957     /* so we now know that the size of destination is greater
8958     than the size of the source.
8959     Now, if the next iCode is an operator then we might be
8960     able to optimize the operation without performing a cast.
8961     */
8962     if(genMixedOperation(ic))
8963       goto release;
8964
8965     
8966     /* we move to result for the size of source */
8967     size = AOP_SIZE(right);
8968     offset = 0 ;
8969     while (size--) {
8970       emitcode(";","%d",__LINE__);
8971         aopPut(AOP(result),
8972                aopGet(AOP(right),offset,FALSE,FALSE),
8973                offset);
8974         offset++;
8975     }
8976
8977     /* now depending on the sign of the destination */
8978     size = AOP_SIZE(result) - AOP_SIZE(right);
8979     /* if unsigned or not an integral type */
8980     if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) {
8981       while (size--) {
8982           emitpcode(POC_CLRF,   popGet(AOP(result),offset++,FALSE,FALSE));
8983           emitcode("clrf","%s  ;%d",aopGet(AOP(result),offset++,FALSE,FALSE),__LINE__);
8984       }
8985     } else {
8986       /* we need to extend the sign :{ */
8987       //char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,FALSE,FALSE);
8988       //MOVA(l);
8989
8990       emitpcode(POC_CLRW,    NULL);
8991       emitpcode(POC_BTFSC,   popGet(AOP(right),0,FALSE,FALSE));
8992       emitpcode(POC_MOVLW,   popGetLit(0xff));
8993
8994         emitcode("clrw","");
8995         emitcode("btfsc","(%s >> 3), (%s & 7)",
8996                  AOP(right)->aopu.aop_dir,
8997                  AOP(right)->aopu.aop_dir);
8998         emitcode("movlw","0xff");
8999         while (size--) {
9000           emitpcode(POC_MOVWF,   popGet(AOP(result),offset++,FALSE,FALSE));
9001           emitcode("movwf","%s",aopGet(AOP(result),offset++,FALSE,FALSE));
9002           // aopPut(AOP(result),"a",offset++);
9003         }
9004
9005     }
9006
9007     /* we are done hurray !!!! */
9008
9009 release:
9010     freeAsmop(right,NULL,ic,TRUE);
9011     freeAsmop(result,NULL,ic,TRUE);
9012
9013 }
9014
9015 /*-----------------------------------------------------------------*/
9016 /* genDjnz - generate decrement & jump if not zero instrucion      */
9017 /*-----------------------------------------------------------------*/
9018 static int genDjnz (iCode *ic, iCode *ifx)
9019 {
9020     symbol *lbl, *lbl1;
9021     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9022
9023     if (!ifx)
9024         return 0;
9025     
9026     /* if the if condition has a false label
9027        then we cannot save */
9028     if (IC_FALSE(ifx))
9029         return 0;
9030
9031     /* if the minus is not of the form 
9032        a = a - 1 */
9033     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
9034         !IS_OP_LITERAL(IC_RIGHT(ic)))
9035         return 0;
9036
9037     if (operandLitValue(IC_RIGHT(ic)) != 1)
9038         return 0;
9039
9040     /* if the size of this greater than one then no
9041        saving */
9042     if (getSize(operandType(IC_RESULT(ic))) > 1)
9043         return 0;
9044
9045     /* otherwise we can save BIG */
9046     lbl = newiTempLabel(NULL);
9047     lbl1= newiTempLabel(NULL);
9048
9049     aopOp(IC_RESULT(ic),ic,FALSE);
9050     
9051     if (IS_AOP_PREG(IC_RESULT(ic))) {
9052         emitcode("dec","%s",
9053                  aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
9054         emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
9055         emitcode("jnz","%05d_DS_",lbl->key+100);
9056     } else {    
9057
9058
9059       emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
9060       emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
9061
9062       emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
9063       emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
9064
9065     }
9066 /*     emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
9067 /*     emitcode ("","%05d_DS_:",lbl->key+100); */
9068 /*     emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
9069 /*     emitcode ("","%05d_DS_:",lbl1->key+100); */
9070
9071     
9072     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
9073     ifx->generated = 1;
9074     return 1;
9075 }
9076
9077 /*-----------------------------------------------------------------*/
9078 /* genReceive - generate code for a receive iCode                  */
9079 /*-----------------------------------------------------------------*/
9080 static void genReceive (iCode *ic)
9081 {    
9082     DEBUGemitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9083
9084     if (isOperandInFarSpace(IC_RESULT(ic)) && 
9085         ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
9086           IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
9087
9088         int size = getSize(operandType(IC_RESULT(ic)));
9089         int offset =  fReturnSizePic - size;
9090         while (size--) {
9091             emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
9092                                     fReturn[fReturnSizePic - offset - 1] : "acc"));
9093             offset++;
9094         }
9095         aopOp(IC_RESULT(ic),ic,FALSE);  
9096         size = AOP_SIZE(IC_RESULT(ic));
9097         offset = 0;
9098         while (size--) {
9099             emitcode ("pop","acc");
9100             aopPut (AOP(IC_RESULT(ic)),"a",offset++);
9101         }
9102         
9103     } else {
9104         _G.accInUse++;
9105         aopOp(IC_RESULT(ic),ic,FALSE);  
9106         _G.accInUse--;
9107         assignResultValue(IC_RESULT(ic));       
9108     }
9109
9110     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
9111 }
9112
9113 /*-----------------------------------------------------------------*/
9114 /* genpic14Code - generate code for pic14 based controllers        */
9115 /*-----------------------------------------------------------------*/
9116 /*
9117  * At this point, ralloc.c has gone through the iCode and attempted
9118  * to optimize in a way suitable for a PIC. Now we've got to generate
9119  * PIC instructions that correspond to the iCode.
9120  *
9121  * Once the instructions are generated, we'll pass through both the
9122  * peep hole optimizer and the pCode optimizer.
9123  *-----------------------------------------------------------------*/
9124
9125 void genpic14Code (iCode *lic)
9126 {
9127     iCode *ic;
9128     int cln = 0;
9129
9130     lineHead = lineCurr = NULL;
9131
9132     pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
9133     addpBlock(pb);
9134
9135     /* if debug information required */
9136 /*     if (options.debug && currFunc) { */
9137     if (currFunc) {
9138         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
9139         _G.debugLine = 1;
9140         if (IS_STATIC(currFunc->etype)) {
9141             emitcode("",";F%s$%s$0$0     %d",moduleName,currFunc->name,__LINE__);
9142             //addpCode2pBlock(pb,newpCodeLabel(moduleName,currFunc->name));
9143         } else {
9144             emitcode("",";G$%s$0$0   %d",currFunc->name,__LINE__);
9145             //addpCode2pBlock(pb,newpCodeLabel(NULL,currFunc->name));
9146         }
9147         _G.debugLine = 0;
9148     }
9149
9150
9151     for (ic = lic ; ic ; ic = ic->next ) {
9152
9153       DEBUGemitcode(";ic","");
9154         if ( cln != ic->lineno ) {
9155             if ( options.debug ) {
9156                 _G.debugLine = 1;
9157                 emitcode("",";C$%s$%d$%d$%d ==.",
9158                          FileBaseName(ic->filename),ic->lineno,
9159                          ic->level,ic->block);
9160                 _G.debugLine = 0;
9161             }
9162             emitcode(";","%s %d",FileBaseName(ic->filename),ic->lineno);
9163             cln = ic->lineno ;
9164         }
9165         /* if the result is marked as
9166            spilt and rematerializable or code for
9167            this has already been generated then
9168            do nothing */
9169         if (resultRemat(ic) || ic->generated ) 
9170             continue ;
9171         
9172         /* depending on the operation */
9173         switch (ic->op) {
9174         case '!' :
9175             genNot(ic);
9176             break;
9177             
9178         case '~' :
9179             genCpl(ic);
9180             break;
9181             
9182         case UNARYMINUS:
9183             genUminus (ic);
9184             break;
9185             
9186         case IPUSH:
9187             genIpush (ic);
9188             break;
9189             
9190         case IPOP:
9191             /* IPOP happens only when trying to restore a 
9192                spilt live range, if there is an ifx statement
9193                following this pop then the if statement might
9194                be using some of the registers being popped which
9195                would destory the contents of the register so
9196                we need to check for this condition and handle it */
9197             if (ic->next            && 
9198                 ic->next->op == IFX &&
9199                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
9200                 genIfx (ic->next,ic);
9201             else
9202                 genIpop (ic);
9203             break; 
9204             
9205         case CALL:
9206             genCall (ic);
9207             break;
9208             
9209         case PCALL:
9210             genPcall (ic);
9211             break;
9212             
9213         case FUNCTION:
9214             genFunction (ic);
9215             break;
9216             
9217         case ENDFUNCTION:
9218             genEndFunction (ic);
9219             break;
9220             
9221         case RETURN:
9222             genRet (ic);
9223             break;
9224             
9225         case LABEL:
9226             genLabel (ic);
9227             break;
9228             
9229         case GOTO:
9230             genGoto (ic);
9231             break;
9232             
9233         case '+' :
9234             genPlus (ic) ;
9235             break;
9236             
9237         case '-' :
9238             if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
9239                 genMinus (ic);
9240             break;
9241             
9242         case '*' :
9243             genMult (ic);
9244             break;
9245             
9246         case '/' :
9247             genDiv (ic) ;
9248             break;
9249             
9250         case '%' :
9251             genMod (ic);
9252             break;
9253             
9254         case '>' :
9255             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
9256             break;
9257             
9258         case '<' :
9259             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
9260             break;
9261             
9262         case LE_OP:
9263         case GE_OP:
9264         case NE_OP:
9265             
9266             /* note these two are xlated by algebraic equivalence
9267                during parsing SDCC.y */
9268             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
9269                    "got '>=' or '<=' shouldn't have come here");
9270             break;      
9271             
9272         case EQ_OP:
9273             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
9274             break;          
9275             
9276         case AND_OP:
9277             genAndOp (ic);
9278             break;
9279             
9280         case OR_OP:
9281             genOrOp (ic);
9282             break;
9283             
9284         case '^' :
9285             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
9286             break;
9287             
9288         case '|' :
9289                 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
9290             break;
9291             
9292         case BITWISEAND:
9293             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
9294             break;
9295             
9296         case INLINEASM:
9297             genInline (ic);
9298             break;
9299             
9300         case RRC:
9301             genRRC (ic);
9302             break;
9303             
9304         case RLC:
9305             genRLC (ic);
9306             break;
9307             
9308         case GETHBIT:
9309             genGetHbit (ic);
9310             break;
9311             
9312         case LEFT_OP:
9313             genLeftShift (ic);
9314             break;
9315             
9316         case RIGHT_OP:
9317             genRightShift (ic);
9318             break;
9319             
9320         case GET_VALUE_AT_ADDRESS:
9321             genPointerGet(ic);
9322             break;
9323             
9324         case '=' :
9325             if (POINTER_SET(ic))
9326                 genPointerSet(ic);
9327             else
9328                 genAssign(ic);
9329             break;
9330             
9331         case IFX:
9332             genIfx (ic,NULL);
9333             break;
9334             
9335         case ADDRESS_OF:
9336             genAddrOf (ic);
9337             break;
9338             
9339         case JUMPTABLE:
9340             genJumpTab (ic);
9341             break;
9342             
9343         case CAST:
9344             genCast (ic);
9345             break;
9346             
9347         case RECEIVE:
9348             genReceive(ic);
9349             break;
9350             
9351         case SEND:
9352             addSet(&_G.sendSet,ic);
9353             break;
9354
9355         default :
9356             ic = ic;
9357             /*      piCode(ic,stdout); */
9358             
9359         }
9360     }
9361     
9362
9363     /* now we are ready to call the 
9364        peep hole optimizer */
9365     if (!options.nopeep) {
9366       printf("peep hole optimizing\n");
9367         peepHole (&lineHead);
9368     }
9369     /* now do the actual printing */
9370     printLine (lineHead,codeOutFile);
9371
9372     printf("printing pBlock\n\n");
9373     printpBlock(stdout,pb);
9374
9375     return;
9376 }