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