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