b468463f063591aa51e55c198ee777c4cdb7b163
[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
5864     etype = getSpec(operandType(result));
5865
5866     /* read the first byte  */
5867     switch (ptype) {
5868
5869     case POINTER:
5870     case IPOINTER:
5871         emitcode("mov","a,@%s",rname);
5872         break;
5873         
5874     case PPOINTER:
5875         emitcode("movx","a,@%s",rname);
5876         break;
5877         
5878     case FPOINTER:
5879         emitcode("movx","a,@dptr");
5880         break;
5881
5882     case CPOINTER:
5883         emitcode("clr","a");
5884         emitcode("movc","a","@a+dptr");
5885         break;
5886
5887     case GPOINTER:
5888         emitcode("lcall","__gptrget");
5889         break;
5890     }
5891
5892     /* if we have bitdisplacement then it fits   */
5893     /* into this byte completely or if length is */
5894     /* less than a byte                          */
5895     if ((shCnt = SPEC_BSTR(etype)) || 
5896         (SPEC_BLEN(etype) <= 8))  {
5897
5898         /* shift right acc */
5899         AccRsh(shCnt);
5900
5901         emitcode("anl","a,#0x%02x",
5902                  ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
5903         aopPut(AOP(result),"a",offset);
5904         return ;
5905     }
5906
5907     /* bit field did not fit in a byte  */
5908     rlen = SPEC_BLEN(etype) - 8;
5909     aopPut(AOP(result),"a",offset++);
5910
5911     while (1)  {
5912
5913         switch (ptype) {
5914         case POINTER:
5915         case IPOINTER:
5916             emitcode("inc","%s",rname);
5917             emitcode("mov","a,@%s",rname);
5918             break;
5919             
5920         case PPOINTER:
5921             emitcode("inc","%s",rname);
5922             emitcode("movx","a,@%s",rname);
5923             break;
5924
5925         case FPOINTER:
5926             emitcode("inc","dptr");
5927             emitcode("movx","a,@dptr");
5928             break;
5929             
5930         case CPOINTER:
5931             emitcode("clr","a");
5932             emitcode("inc","dptr");
5933             emitcode("movc","a","@a+dptr");
5934             break;
5935             
5936         case GPOINTER:
5937             emitcode("inc","dptr");
5938             emitcode("lcall","__gptrget");
5939             break;
5940         }
5941
5942         rlen -= 8;            
5943         /* if we are done */
5944         if ( rlen <= 0 )
5945             break ;
5946         
5947         aopPut(AOP(result),"a",offset++);
5948                               
5949     }
5950     
5951     if (rlen) {
5952         emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
5953         aopPut(AOP(result),"a",offset);        
5954     }
5955     
5956     return ;
5957 }
5958
5959
5960 /*-----------------------------------------------------------------*/
5961 /* genDataPointerGet - generates code when ptr offset is known     */
5962 /*-----------------------------------------------------------------*/
5963 static void genDataPointerGet (operand *left, 
5964                                operand *result, 
5965                                iCode *ic)
5966 {
5967     char *l;
5968     char buffer[256];
5969     int size , offset = 0;
5970     aopOp(result,ic,TRUE);
5971
5972     /* get the string representation of the name */
5973     l = aopGet(AOP(left),0,FALSE,TRUE);
5974     size = AOP_SIZE(result);
5975     while (size--) {
5976         if (offset)
5977             sprintf(buffer,"(%s + %d)",l+1,offset);
5978         else
5979             sprintf(buffer,"%s",l+1);
5980         aopPut(AOP(result),buffer,offset++);
5981     }
5982
5983     freeAsmop(left,NULL,ic,TRUE);
5984     freeAsmop(result,NULL,ic,TRUE);
5985 }
5986
5987 /*-----------------------------------------------------------------*/
5988 /* genNearPointerGet - emitcode for near pointer fetch             */
5989 /*-----------------------------------------------------------------*/
5990 static void genNearPointerGet (operand *left, 
5991                                operand *result, 
5992                                iCode *ic)
5993 {
5994     asmop *aop = NULL;
5995     regs *preg = NULL ;
5996     char *rname ;
5997     link *rtype, *retype;
5998     link *ltype = operandType(left);    
5999     char buffer[80];
6000
6001     rtype = operandType(result);
6002     retype= getSpec(rtype);
6003     
6004     aopOp(left,ic,FALSE);
6005     
6006     /* if left is rematerialisable and
6007        result is not bit variable type and
6008        the left is pointer to data space i.e
6009        lower 128 bytes of space */
6010     if (AOP_TYPE(left) == AOP_IMMD &&
6011         !IS_BITVAR(retype)         &&
6012         DCL_TYPE(ltype) == POINTER) {
6013         genDataPointerGet (left,result,ic);
6014         return ;
6015     }
6016     
6017         /* if the value is already in a pointer register
6018        then don't need anything more */
6019     if (!AOP_INPREG(AOP(left))) {
6020         /* otherwise get a free pointer register */
6021         aop = newAsmop(0);
6022         preg = getFreePtr(ic,&aop,FALSE);
6023         emitcode("mov","%s,%s",
6024                 preg->name,
6025                 aopGet(AOP(left),0,FALSE,TRUE));
6026         rname = preg->name ;
6027     } else
6028         rname = aopGet(AOP(left),0,FALSE,FALSE);
6029     
6030     freeAsmop(left,NULL,ic,TRUE);
6031     aopOp (result,ic,FALSE);
6032     
6033       /* if bitfield then unpack the bits */
6034     if (IS_BITVAR(retype)) 
6035         genUnpackBits (result,rname,POINTER);
6036     else {
6037         /* we have can just get the values */
6038         int size = AOP_SIZE(result);
6039         int offset = 0 ;        
6040         
6041         while (size--) {
6042             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
6043
6044                 emitcode("mov","a,@%s",rname);
6045                 aopPut(AOP(result),"a",offset);
6046             } else {
6047                 sprintf(buffer,"@%s",rname);
6048                 aopPut(AOP(result),buffer,offset);
6049             }
6050             offset++ ;
6051             if (size)
6052                 emitcode("inc","%s",rname);
6053         }
6054     }
6055
6056     /* now some housekeeping stuff */
6057     if (aop) {
6058         /* we had to allocate for this iCode */
6059         freeAsmop(NULL,aop,ic,TRUE);
6060     } else { 
6061         /* we did not allocate which means left
6062            already in a pointer register, then
6063            if size > 0 && this could be used again
6064            we have to point it back to where it 
6065            belongs */
6066         if (AOP_SIZE(result) > 1 &&
6067             !OP_SYMBOL(left)->remat &&
6068             ( OP_SYMBOL(left)->liveTo > ic->seq ||
6069               ic->depth )) {
6070             int size = AOP_SIZE(result) - 1;
6071             while (size--)
6072                 emitcode("dec","%s",rname);
6073         }
6074     }
6075
6076     /* done */
6077     freeAsmop(result,NULL,ic,TRUE);
6078      
6079 }
6080
6081 /*-----------------------------------------------------------------*/
6082 /* genPagedPointerGet - emitcode for paged pointer fetch           */
6083 /*-----------------------------------------------------------------*/
6084 static void genPagedPointerGet (operand *left, 
6085                                operand *result, 
6086                                iCode *ic)
6087 {
6088     asmop *aop = NULL;
6089     regs *preg = NULL ;
6090     char *rname ;
6091     link *rtype, *retype;    
6092
6093     rtype = operandType(result);
6094     retype= getSpec(rtype);
6095     
6096     aopOp(left,ic,FALSE);
6097
6098   /* if the value is already in a pointer register
6099        then don't need anything more */
6100     if (!AOP_INPREG(AOP(left))) {
6101         /* otherwise get a free pointer register */
6102         aop = newAsmop(0);
6103         preg = getFreePtr(ic,&aop,FALSE);
6104         emitcode("mov","%s,%s",
6105                 preg->name,
6106                 aopGet(AOP(left),0,FALSE,TRUE));
6107         rname = preg->name ;
6108     } else
6109         rname = aopGet(AOP(left),0,FALSE,FALSE);
6110     
6111     freeAsmop(left,NULL,ic,TRUE);
6112     aopOp (result,ic,FALSE);
6113
6114     /* if bitfield then unpack the bits */
6115     if (IS_BITVAR(retype)) 
6116         genUnpackBits (result,rname,PPOINTER);
6117     else {
6118         /* we have can just get the values */
6119         int size = AOP_SIZE(result);
6120         int offset = 0 ;        
6121         
6122         while (size--) {
6123             
6124             emitcode("movx","a,@%s",rname);
6125             aopPut(AOP(result),"a",offset);
6126             
6127             offset++ ;
6128             
6129             if (size)
6130                 emitcode("inc","%s",rname);
6131         }
6132     }
6133
6134     /* now some housekeeping stuff */
6135     if (aop) {
6136         /* we had to allocate for this iCode */
6137         freeAsmop(NULL,aop,ic,TRUE);
6138     } else { 
6139         /* we did not allocate which means left
6140            already in a pointer register, then
6141            if size > 0 && this could be used again
6142            we have to point it back to where it 
6143            belongs */
6144         if (AOP_SIZE(result) > 1 &&
6145             !OP_SYMBOL(left)->remat &&
6146             ( OP_SYMBOL(left)->liveTo > ic->seq ||
6147               ic->depth )) {
6148             int size = AOP_SIZE(result) - 1;
6149             while (size--)
6150                 emitcode("dec","%s",rname);
6151         }
6152     }
6153
6154     /* done */
6155     freeAsmop(result,NULL,ic,TRUE);
6156     
6157         
6158 }
6159
6160 /*-----------------------------------------------------------------*/
6161 /* genFarPointerGet - gget value from far space                    */
6162 /*-----------------------------------------------------------------*/
6163 static void genFarPointerGet (operand *left,
6164                               operand *result, iCode *ic)
6165 {
6166     int size, offset ;
6167     link *retype = getSpec(operandType(result));
6168
6169     aopOp(left,ic,FALSE);
6170
6171     /* if the operand is already in dptr 
6172     then we do nothing else we move the value to dptr */
6173     if (AOP_TYPE(left) != AOP_STR) {
6174         /* if this is remateriazable */
6175         if (AOP_TYPE(left) == AOP_IMMD)
6176             emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6177         else { /* we need to get it byte by byte */
6178             emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6179             emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6180             if (options.model == MODEL_FLAT24)
6181             {
6182                emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6183             }
6184         }
6185     }
6186     /* so dptr know contains the address */
6187     freeAsmop(left,NULL,ic,TRUE);
6188     aopOp(result,ic,FALSE);
6189
6190     /* if bit then unpack */
6191     if (IS_BITVAR(retype)) 
6192         genUnpackBits(result,"dptr",FPOINTER);
6193     else {
6194         size = AOP_SIZE(result);
6195         offset = 0 ;
6196
6197         while (size--) {
6198             emitcode("movx","a,@dptr");
6199             aopPut(AOP(result),"a",offset++);
6200             if (size)
6201                 emitcode("inc","dptr");
6202         }
6203     }
6204
6205     freeAsmop(result,NULL,ic,TRUE);
6206 }
6207
6208 /*-----------------------------------------------------------------*/
6209 /* emitcodePointerGet - gget value from code space                  */
6210 /*-----------------------------------------------------------------*/
6211 static void emitcodePointerGet (operand *left,
6212                                 operand *result, iCode *ic)
6213 {
6214     int size, offset ;
6215     link *retype = getSpec(operandType(result));
6216
6217     aopOp(left,ic,FALSE);
6218
6219     /* if the operand is already in dptr 
6220     then we do nothing else we move the value to dptr */
6221     if (AOP_TYPE(left) != AOP_STR) {
6222         /* if this is remateriazable */
6223         if (AOP_TYPE(left) == AOP_IMMD)
6224             emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6225         else { /* we need to get it byte by byte */
6226             emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6227             emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6228             if (options.model == MODEL_FLAT24)
6229             {
6230                emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6231             }
6232         }
6233     }
6234     /* so dptr know contains the address */
6235     freeAsmop(left,NULL,ic,TRUE);
6236     aopOp(result,ic,FALSE);
6237
6238     /* if bit then unpack */
6239     if (IS_BITVAR(retype)) 
6240         genUnpackBits(result,"dptr",CPOINTER);
6241     else {
6242         size = AOP_SIZE(result);
6243         offset = 0 ;
6244
6245         while (size--) {
6246             emitcode("clr","a");
6247             emitcode("movc","a,@a+dptr");
6248             aopPut(AOP(result),"a",offset++);
6249             if (size)
6250                 emitcode("inc","dptr");
6251         }
6252     }
6253
6254     freeAsmop(result,NULL,ic,TRUE);
6255 }
6256
6257 /*-----------------------------------------------------------------*/
6258 /* genGenPointerGet - gget value from generic pointer space        */
6259 /*-----------------------------------------------------------------*/
6260 static void genGenPointerGet (operand *left,
6261                               operand *result, iCode *ic)
6262 {
6263     int size, offset ;
6264     link *retype = getSpec(operandType(result));
6265
6266     aopOp(left,ic,FALSE);
6267
6268     /* if the operand is already in dptr 
6269     then we do nothing else we move the value to dptr */
6270     if (AOP_TYPE(left) != AOP_STR) {
6271         /* if this is remateriazable */
6272         if (AOP_TYPE(left) == AOP_IMMD) {
6273             emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6274             emitcode("mov","b,#%d",pointerCode(retype));
6275         }
6276         else { /* we need to get it byte by byte */
6277             emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6278             emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6279             if (options.model == MODEL_FLAT24)
6280             {
6281                emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6282                emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE));
6283             }
6284             else
6285             {
6286                 emitcode("mov","b,%s",aopGet(AOP(left),2,FALSE,FALSE));
6287             }
6288         }
6289     }
6290     /* so dptr know contains the address */
6291     freeAsmop(left,NULL,ic,TRUE);
6292     aopOp(result,ic,FALSE); 
6293
6294     /* if bit then unpack */
6295     if (IS_BITVAR(retype)) 
6296         genUnpackBits(result,"dptr",GPOINTER);
6297     else {
6298         size = AOP_SIZE(result);
6299         offset = 0 ;
6300
6301         while (size--) {
6302             emitcode("lcall","__gptrget");
6303             aopPut(AOP(result),"a",offset++);
6304             if (size)
6305                 emitcode("inc","dptr");
6306         }
6307     }
6308
6309     freeAsmop(result,NULL,ic,TRUE);
6310 }
6311
6312 /*-----------------------------------------------------------------*/
6313 /* genPointerGet - generate code for pointer get                   */
6314 /*-----------------------------------------------------------------*/
6315 static void genPointerGet (iCode *ic)
6316 {
6317     operand *left, *result ;
6318     link *type, *etype;
6319     int p_type;
6320
6321     left = IC_LEFT(ic);
6322     result = IC_RESULT(ic) ;
6323
6324     /* depending on the type of pointer we need to
6325     move it to the correct pointer register */
6326     type = operandType(left);
6327     etype = getSpec(type);
6328     /* if left is of type of pointer then it is simple */
6329     if (IS_PTR(type) && !IS_FUNC(type->next)) 
6330         p_type = DCL_TYPE(type);
6331     else {
6332         /* we have to go by the storage class */
6333         p_type = PTR_TYPE(SPEC_OCLS(etype));
6334
6335 /*      if (SPEC_OCLS(etype)->codesp ) { */
6336 /*          p_type = CPOINTER ;  */
6337 /*      } */
6338 /*      else */
6339 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
6340 /*              p_type = FPOINTER ; */
6341 /*          else */
6342 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
6343 /*                  p_type = PPOINTER; */
6344 /*              else */
6345 /*                  if (SPEC_OCLS(etype) == idata ) */
6346 /*                      p_type = IPOINTER; */
6347 /*                  else */
6348 /*                      p_type = POINTER ; */
6349     }
6350
6351     /* now that we have the pointer type we assign
6352     the pointer values */
6353     switch (p_type) {
6354
6355     case POINTER:       
6356     case IPOINTER:
6357         genNearPointerGet (left,result,ic);
6358         break;
6359
6360     case PPOINTER:
6361         genPagedPointerGet(left,result,ic);
6362         break;
6363
6364     case FPOINTER:
6365         genFarPointerGet (left,result,ic);
6366         break;
6367
6368     case CPOINTER:
6369         emitcodePointerGet (left,result,ic);
6370         break;
6371
6372     case GPOINTER:
6373         genGenPointerGet (left,result,ic);
6374         break;
6375     }
6376
6377 }
6378
6379 /*-----------------------------------------------------------------*/
6380 /* genPackBits - generates code for packed bit storage             */
6381 /*-----------------------------------------------------------------*/
6382 static void genPackBits (link    *etype ,
6383                          operand *right ,
6384                          char *rname, int p_type)
6385 {
6386     int shCount = 0 ;
6387     int offset = 0  ;
6388     int rLen = 0 ;
6389     int blen, bstr ;   
6390     char *l ;
6391
6392     blen = SPEC_BLEN(etype);
6393     bstr = SPEC_BSTR(etype);
6394
6395     l = aopGet(AOP(right),offset++,FALSE,FALSE);
6396     MOVA(l);   
6397
6398     /* if the bit lenth is less than or    */
6399     /* it exactly fits a byte then         */
6400     if (SPEC_BLEN(etype) <= 8 )  {
6401         shCount = SPEC_BSTR(etype) ;
6402
6403         /* shift left acc */
6404         AccLsh(shCount);
6405
6406         if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
6407
6408
6409             switch (p_type) {
6410                 case POINTER:
6411                     emitcode ("mov","b,a");
6412                     emitcode("mov","a,@%s",rname);
6413                     break;
6414
6415                 case FPOINTER:
6416                     emitcode ("mov","b,a");
6417                     emitcode("movx","a,@dptr");
6418                     break;
6419
6420                 case GPOINTER:
6421                     emitcode ("push","b");
6422                     emitcode ("push","acc");
6423                     emitcode ("lcall","__gptrget");
6424                     emitcode ("pop","b");
6425                     break;
6426             }
6427
6428             emitcode ("anl","a,#0x%02x",(unsigned char)
6429                       ((unsigned char)(0xFF << (blen+bstr)) | 
6430                        (unsigned char)(0xFF >> (8-bstr)) ) );
6431             emitcode ("orl","a,b");
6432             if (p_type == GPOINTER)
6433                 emitcode("pop","b");
6434         }
6435     }
6436
6437     switch (p_type) {
6438         case POINTER:
6439             emitcode("mov","@%s,a",rname);
6440             break;
6441
6442         case FPOINTER:
6443             emitcode("movx","@dptr,a");
6444             break;
6445
6446         case GPOINTER:
6447             emitcode("lcall","__gptrput");
6448             break;
6449     }
6450
6451     /* if we r done */
6452     if ( SPEC_BLEN(etype) <= 8 )
6453         return ;
6454
6455     emitcode("inc","%s",rname);
6456     rLen = SPEC_BLEN(etype) ;     
6457
6458     /* now generate for lengths greater than one byte */
6459     while (1) {
6460
6461         l = aopGet(AOP(right),offset++,FALSE,TRUE);
6462
6463         rLen -= 8 ;
6464         if (rLen <= 0 )
6465             break ;
6466
6467         switch (p_type) {
6468             case POINTER:
6469                 if (*l == '@') {
6470                     MOVA(l);
6471                     emitcode("mov","@%s,a",rname);
6472                 } else
6473                     emitcode("mov","@%s,%s",rname,l);
6474                 break;
6475
6476             case FPOINTER:
6477                 MOVA(l);
6478                 emitcode("movx","@dptr,a");
6479                 break;
6480
6481             case GPOINTER:
6482                 MOVA(l);
6483                 emitcode("lcall","__gptrput");
6484                 break;  
6485         }   
6486         emitcode ("inc","%s",rname);
6487     }
6488
6489     MOVA(l);
6490
6491     /* last last was not complete */
6492     if (rLen)   {
6493         /* save the byte & read byte */
6494         switch (p_type) {
6495             case POINTER:
6496                 emitcode ("mov","b,a");
6497                 emitcode("mov","a,@%s",rname);
6498                 break;
6499
6500             case FPOINTER:
6501                 emitcode ("mov","b,a");
6502                 emitcode("movx","a,@dptr");
6503                 break;
6504
6505             case GPOINTER:
6506                 emitcode ("push","b");
6507                 emitcode ("push","acc");
6508                 emitcode ("lcall","__gptrget");
6509                 emitcode ("pop","b");
6510                 break;
6511         }
6512
6513         emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
6514         emitcode ("orl","a,b");
6515     }
6516
6517     if (p_type == GPOINTER)
6518         emitcode("pop","b");
6519
6520     switch (p_type) {
6521
6522     case POINTER:
6523         emitcode("mov","@%s,a",rname);
6524         break;
6525         
6526     case FPOINTER:
6527         emitcode("movx","@dptr,a");
6528         break;
6529         
6530     case GPOINTER:
6531         emitcode("lcall","__gptrput");
6532         break;                  
6533     }
6534 }
6535 /*-----------------------------------------------------------------*/
6536 /* genDataPointerSet - remat pointer to data space                 */
6537 /*-----------------------------------------------------------------*/
6538 static void genDataPointerSet(operand *right,
6539                               operand *result,
6540                               iCode *ic)
6541 {
6542     int size, offset = 0 ;
6543     char *l, buffer[256];
6544
6545     aopOp(right,ic,FALSE);
6546     
6547     l = aopGet(AOP(result),0,FALSE,TRUE);
6548     size = AOP_SIZE(right);
6549     while (size--) {
6550         if (offset)
6551             sprintf(buffer,"(%s + %d)",l+1,offset);
6552         else
6553             sprintf(buffer,"%s",l+1);
6554         emitcode("mov","%s,%s",buffer,
6555                  aopGet(AOP(right),offset++,FALSE,FALSE));
6556     }
6557
6558     freeAsmop(right,NULL,ic,TRUE);
6559     freeAsmop(result,NULL,ic,TRUE);
6560 }
6561
6562 /*-----------------------------------------------------------------*/
6563 /* genNearPointerSet - emitcode for near pointer put                */
6564 /*-----------------------------------------------------------------*/
6565 static void genNearPointerSet (operand *right,
6566                                operand *result, 
6567                                iCode *ic)
6568 {
6569     asmop *aop = NULL;
6570     regs *preg = NULL ;
6571     char *rname , *l;
6572     link *retype;
6573     link *ptype = operandType(result);
6574     
6575     retype= getSpec(operandType(right));
6576
6577     aopOp(result,ic,FALSE);
6578     
6579     /* if the result is rematerializable &
6580        in data space & not a bit variable */
6581     if (AOP_TYPE(result) == AOP_IMMD &&
6582         DCL_TYPE(ptype) == POINTER   &&
6583         !IS_BITVAR(retype)) {
6584         genDataPointerSet (right,result,ic);
6585         return;
6586     }
6587
6588     /* if the value is already in a pointer register
6589     then don't need anything more */
6590     if (!AOP_INPREG(AOP(result))) {
6591         /* otherwise get a free pointer register */
6592         aop = newAsmop(0);
6593         preg = getFreePtr(ic,&aop,FALSE);
6594         emitcode("mov","%s,%s",
6595                  preg->name,
6596                  aopGet(AOP(result),0,FALSE,TRUE));
6597         rname = preg->name ;
6598     } else
6599         rname = aopGet(AOP(result),0,FALSE,FALSE);
6600
6601     freeAsmop(result,NULL,ic,TRUE);
6602     aopOp (right,ic,FALSE);
6603
6604     /* if bitfield then unpack the bits */
6605     if (IS_BITVAR(retype)) 
6606         genPackBits (retype,right,rname,POINTER);
6607     else {
6608         /* we have can just get the values */
6609         int size = AOP_SIZE(right);
6610         int offset = 0 ;    
6611
6612         while (size--) {
6613             l = aopGet(AOP(right),offset,FALSE,TRUE);
6614             if (*l == '@' ) {
6615                 MOVA(l);
6616                 emitcode("mov","@%s,a",rname);
6617             } else
6618                 emitcode("mov","@%s,%s",rname,l);
6619             if (size)
6620                 emitcode("inc","%s",rname);
6621             offset++;
6622         }
6623     }
6624
6625     /* now some housekeeping stuff */
6626     if (aop) {
6627         /* we had to allocate for this iCode */
6628         freeAsmop(NULL,aop,ic,TRUE);
6629     } else { 
6630         /* we did not allocate which means left
6631         already in a pointer register, then
6632         if size > 0 && this could be used again
6633         we have to point it back to where it 
6634         belongs */
6635         if (AOP_SIZE(right) > 1 &&
6636             !OP_SYMBOL(result)->remat &&
6637             ( OP_SYMBOL(result)->liveTo > ic->seq ||
6638               ic->depth )) {
6639             int size = AOP_SIZE(right) - 1;
6640             while (size--)
6641                 emitcode("dec","%s",rname);
6642         }
6643     }
6644
6645     /* done */
6646     freeAsmop(right,NULL,ic,TRUE);
6647
6648
6649 }
6650
6651 /*-----------------------------------------------------------------*/
6652 /* genPagedPointerSet - emitcode for Paged pointer put             */
6653 /*-----------------------------------------------------------------*/
6654 static void genPagedPointerSet (operand *right,
6655                                operand *result, 
6656                                iCode *ic)
6657 {
6658     asmop *aop = NULL;
6659     regs *preg = NULL ;
6660     char *rname , *l;
6661     link *retype;
6662        
6663     retype= getSpec(operandType(right));
6664     
6665     aopOp(result,ic,FALSE);
6666     
6667     /* if the value is already in a pointer register
6668        then don't need anything more */
6669     if (!AOP_INPREG(AOP(result))) {
6670         /* otherwise get a free pointer register */
6671         aop = newAsmop(0);
6672         preg = getFreePtr(ic,&aop,FALSE);
6673         emitcode("mov","%s,%s",
6674                 preg->name,
6675                 aopGet(AOP(result),0,FALSE,TRUE));
6676         rname = preg->name ;
6677     } else
6678         rname = aopGet(AOP(result),0,FALSE,FALSE);
6679     
6680     freeAsmop(result,NULL,ic,TRUE);
6681     aopOp (right,ic,FALSE);
6682
6683     /* if bitfield then unpack the bits */
6684     if (IS_BITVAR(retype)) 
6685         genPackBits (retype,right,rname,PPOINTER);
6686     else {
6687         /* we have can just get the values */
6688         int size = AOP_SIZE(right);
6689         int offset = 0 ;        
6690         
6691         while (size--) {
6692             l = aopGet(AOP(right),offset,FALSE,TRUE);
6693             
6694             MOVA(l);
6695             emitcode("movx","@%s,a",rname);
6696
6697             if (size)
6698                 emitcode("inc","%s",rname);
6699
6700             offset++;
6701         }
6702     }
6703     
6704     /* now some housekeeping stuff */
6705     if (aop) {
6706         /* we had to allocate for this iCode */
6707         freeAsmop(NULL,aop,ic,TRUE);
6708     } else { 
6709         /* we did not allocate which means left
6710            already in a pointer register, then
6711            if size > 0 && this could be used again
6712            we have to point it back to where it 
6713            belongs */
6714         if (AOP_SIZE(right) > 1 &&
6715             !OP_SYMBOL(result)->remat &&
6716             ( OP_SYMBOL(result)->liveTo > ic->seq ||
6717               ic->depth )) {
6718             int size = AOP_SIZE(right) - 1;
6719             while (size--)
6720                 emitcode("dec","%s",rname);
6721         }
6722     }
6723
6724     /* done */
6725     freeAsmop(right,NULL,ic,TRUE);
6726     
6727         
6728 }
6729
6730 /*-----------------------------------------------------------------*/
6731 /* genFarPointerSet - set value from far space                     */
6732 /*-----------------------------------------------------------------*/
6733 static void genFarPointerSet (operand *right,
6734                               operand *result, iCode *ic)
6735 {
6736     int size, offset ;
6737     link *retype = getSpec(operandType(right));
6738
6739     aopOp(result,ic,FALSE);
6740
6741     /* if the operand is already in dptr 
6742     then we do nothing else we move the value to dptr */
6743     if (AOP_TYPE(result) != AOP_STR) {
6744         /* if this is remateriazable */
6745         if (AOP_TYPE(result) == AOP_IMMD)
6746             emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
6747         else { /* we need to get it byte by byte */
6748             emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
6749             emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
6750             if (options.model == MODEL_FLAT24)
6751             {
6752                emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
6753             }
6754         }
6755     }
6756     /* so dptr know contains the address */
6757     freeAsmop(result,NULL,ic,TRUE);
6758     aopOp(right,ic,FALSE);
6759
6760     /* if bit then unpack */
6761     if (IS_BITVAR(retype)) 
6762         genPackBits(retype,right,"dptr",FPOINTER);
6763     else {
6764         size = AOP_SIZE(right);
6765         offset = 0 ;
6766
6767         while (size--) {
6768             char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
6769             MOVA(l);
6770             emitcode("movx","@dptr,a");
6771             if (size)
6772                 emitcode("inc","dptr");
6773         }
6774     }
6775
6776     freeAsmop(right,NULL,ic,TRUE);
6777 }
6778
6779 /*-----------------------------------------------------------------*/
6780 /* genGenPointerSet - set value from generic pointer space         */
6781 /*-----------------------------------------------------------------*/
6782 static void genGenPointerSet (operand *right,
6783                               operand *result, iCode *ic)
6784 {
6785     int size, offset ;
6786     link *retype = getSpec(operandType(right));
6787
6788     aopOp(result,ic,FALSE);
6789
6790     /* if the operand is already in dptr 
6791     then we do nothing else we move the value to dptr */
6792     if (AOP_TYPE(result) != AOP_STR) {
6793         /* if this is remateriazable */
6794         if (AOP_TYPE(result) == AOP_IMMD) {
6795             emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
6796             emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
6797         }
6798         else { /* we need to get it byte by byte */
6799             emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
6800             emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
6801             if (options.model == MODEL_FLAT24)
6802             {
6803                emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
6804                emitcode("mov","b,%s",aopGet(AOP(result),3,FALSE,FALSE));
6805             }
6806             else
6807             {
6808                 emitcode("mov","b,%s",aopGet(AOP(result),2,FALSE,FALSE));
6809             }
6810         }
6811     }
6812     /* so dptr know contains the address */
6813     freeAsmop(result,NULL,ic,TRUE);
6814     aopOp(right,ic,FALSE);
6815
6816     /* if bit then unpack */
6817     if (IS_BITVAR(retype)) 
6818         genPackBits(retype,right,"dptr",GPOINTER);
6819     else {
6820         size = AOP_SIZE(right);
6821         offset = 0 ;
6822
6823         while (size--) {
6824             char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
6825             MOVA(l);
6826             emitcode("lcall","__gptrput");
6827             if (size)
6828                 emitcode("inc","dptr");
6829         }
6830     }
6831
6832     freeAsmop(right,NULL,ic,TRUE);
6833 }
6834
6835 /*-----------------------------------------------------------------*/
6836 /* genPointerSet - stores the value into a pointer location        */
6837 /*-----------------------------------------------------------------*/
6838 static void genPointerSet (iCode *ic)
6839 {    
6840     operand *right, *result ;
6841     link *type, *etype;
6842     int p_type;
6843
6844     right = IC_RIGHT(ic);
6845     result = IC_RESULT(ic) ;
6846
6847     /* depending on the type of pointer we need to
6848     move it to the correct pointer register */
6849     type = operandType(result);
6850     etype = getSpec(type);
6851     /* if left is of type of pointer then it is simple */
6852     if (IS_PTR(type) && !IS_FUNC(type->next)) {
6853         p_type = DCL_TYPE(type);
6854     }
6855     else {
6856         /* we have to go by the storage class */
6857         p_type = PTR_TYPE(SPEC_OCLS(etype));
6858
6859 /*      if (SPEC_OCLS(etype)->codesp ) { */
6860 /*          p_type = CPOINTER ;  */
6861 /*      } */
6862 /*      else */
6863 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
6864 /*              p_type = FPOINTER ; */
6865 /*          else */
6866 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
6867 /*                  p_type = PPOINTER ; */
6868 /*              else */
6869 /*                  if (SPEC_OCLS(etype) == idata ) */
6870 /*                      p_type = IPOINTER ; */
6871 /*                  else */
6872 /*                      p_type = POINTER ; */
6873     }
6874
6875     /* now that we have the pointer type we assign
6876     the pointer values */
6877     switch (p_type) {
6878
6879     case POINTER:
6880     case IPOINTER:
6881         genNearPointerSet (right,result,ic);
6882         break;
6883
6884     case PPOINTER:
6885         genPagedPointerSet (right,result,ic);
6886         break;
6887
6888     case FPOINTER:
6889         genFarPointerSet (right,result,ic);
6890         break;
6891
6892     case GPOINTER:
6893         genGenPointerSet (right,result,ic);
6894         break;
6895     }
6896
6897 }
6898
6899 /*-----------------------------------------------------------------*/
6900 /* genIfx - generate code for Ifx statement                        */
6901 /*-----------------------------------------------------------------*/
6902 static void genIfx (iCode *ic, iCode *popIc)
6903 {
6904     operand *cond = IC_COND(ic);
6905     int isbit =0;
6906
6907     aopOp(cond,ic,FALSE);
6908
6909     /* get the value into acc */
6910     if (AOP_TYPE(cond) != AOP_CRY)
6911         toBoolean(cond);
6912     else
6913         isbit = 1;
6914     /* the result is now in the accumulator */
6915     freeAsmop(cond,NULL,ic,TRUE);
6916
6917     /* if there was something to be popped then do it */
6918     if (popIc)
6919         genIpop(popIc);
6920
6921     /* if the condition is  a bit variable */
6922     if (isbit && IS_ITEMP(cond) && 
6923         SPIL_LOC(cond))
6924         genIfxJump(ic,SPIL_LOC(cond)->rname);
6925     else
6926         if (isbit && !IS_ITEMP(cond))
6927             genIfxJump(ic,OP_SYMBOL(cond)->rname);
6928         else
6929             genIfxJump(ic,"a");
6930
6931     ic->generated = 1;
6932 }
6933
6934 /*-----------------------------------------------------------------*/
6935 /* genAddrOf - generates code for address of                       */
6936 /*-----------------------------------------------------------------*/
6937 static void genAddrOf (iCode *ic)
6938 {
6939     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
6940     int size, offset ;
6941
6942     aopOp(IC_RESULT(ic),ic,FALSE);
6943
6944     /* if the operand is on the stack then we 
6945     need to get the stack offset of this
6946     variable */
6947     if (sym->onStack) {
6948         /* if it has an offset then we need to compute
6949         it */
6950         if (sym->stack) {
6951             emitcode("mov","a,_bp");
6952             emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
6953             aopPut(AOP(IC_RESULT(ic)),"a",0);       
6954         } else {
6955             /* we can just move _bp */
6956             aopPut(AOP(IC_RESULT(ic)),"_bp",0);
6957         }
6958         /* fill the result with zero */
6959         size = AOP_SIZE(IC_RESULT(ic)) - 1;
6960         
6961         
6962         if (options.stack10bit && size < (FPTRSIZE - 1))
6963         {
6964             fprintf(stderr, 
6965                     "*** warning: pointer to stack var truncated.\n");
6966         }
6967         
6968         offset = 1;
6969         while (size--)
6970         {
6971             /* Yuck! */
6972             if (options.stack10bit && offset == 2)
6973             {
6974                 aopPut(AOP(IC_RESULT(ic)),"#0x40", offset++);
6975             }
6976             else
6977             {
6978                 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
6979             }
6980         }
6981
6982         goto release;
6983     }
6984
6985     /* object not on stack then we need the name */
6986     size = AOP_SIZE(IC_RESULT(ic));
6987     offset = 0;
6988
6989     while (size--) {
6990         char s[SDCC_NAME_MAX];
6991         if (offset) 
6992             sprintf(s,"#(%s >> %d)",
6993                     sym->rname,
6994                     offset*8);
6995         else
6996             sprintf(s,"#%s",sym->rname);
6997         aopPut(AOP(IC_RESULT(ic)),s,offset++);
6998     }
6999
7000 release:
7001     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7002
7003 }
7004
7005 /*-----------------------------------------------------------------*/
7006 /* genFarFarAssign - assignment when both are in far space         */
7007 /*-----------------------------------------------------------------*/
7008 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
7009 {
7010     int size = AOP_SIZE(right);
7011     int offset = 0;
7012     char *l ;
7013     /* first push the right side on to the stack */
7014     while (size--) {
7015         l = aopGet(AOP(right),offset++,FALSE,FALSE);
7016         MOVA(l);
7017         emitcode ("push","acc");
7018     }
7019     
7020     freeAsmop(right,NULL,ic,FALSE);
7021     /* now assign DPTR to result */
7022     aopOp(result,ic,FALSE);
7023     size = AOP_SIZE(result);
7024     while (size--) {
7025         emitcode ("pop","acc");
7026         aopPut(AOP(result),"a",--offset);
7027     }
7028     freeAsmop(result,NULL,ic,FALSE);
7029         
7030 }
7031
7032 /*-----------------------------------------------------------------*/
7033 /* genAssign - generate code for assignment                        */
7034 /*-----------------------------------------------------------------*/
7035 static void genAssign (iCode *ic)
7036 {
7037     operand *result, *right;
7038     int size, offset ;
7039         unsigned long lit = 0L;
7040
7041     result = IC_RESULT(ic);
7042     right  = IC_RIGHT(ic) ;
7043
7044     /* if they are the same */
7045     if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
7046         return ;
7047
7048     aopOp(right,ic,FALSE);
7049     
7050     /* special case both in far space */
7051     if ((AOP_TYPE(right) == AOP_DPTR ||
7052          AOP_TYPE(right) == AOP_DPTR2) &&
7053         IS_TRUE_SYMOP(result)       &&
7054         isOperandInFarSpace(result)) {
7055         
7056         genFarFarAssign (result,right,ic);
7057         return ;
7058     }
7059
7060     aopOp(result,ic,TRUE);
7061
7062     /* if they are the same registers */
7063     if (sameRegs(AOP(right),AOP(result)))
7064         goto release;
7065
7066     /* if the result is a bit */
7067     if (AOP_TYPE(result) == AOP_CRY) {
7068
7069         /* if the right size is a literal then
7070         we know what the value is */
7071         if (AOP_TYPE(right) == AOP_LIT) {
7072             if (((int) operandLitValue(right))) 
7073                 aopPut(AOP(result),one,0);
7074             else
7075                 aopPut(AOP(result),zero,0);
7076             goto release;
7077         }
7078
7079         /* the right is also a bit variable */
7080         if (AOP_TYPE(right) == AOP_CRY) {
7081             emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7082             aopPut(AOP(result),"c",0);
7083             goto release ;
7084         }
7085
7086         /* we need to or */
7087         toBoolean(right);
7088         aopPut(AOP(result),"a",0);
7089         goto release ;
7090     }
7091
7092     /* bit variables done */
7093     /* general case */
7094     size = AOP_SIZE(result);
7095     offset = 0 ;
7096     if(AOP_TYPE(right) == AOP_LIT)
7097         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7098     if((size > 1) &&
7099        (AOP_TYPE(result) != AOP_REG) &&
7100        (AOP_TYPE(right) == AOP_LIT) &&
7101        !IS_FLOAT(operandType(right)) &&
7102        (lit < 256L)){
7103         emitcode("clr","a");
7104         while (size--) {
7105             if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
7106                 aopPut(AOP(result),"a",size);
7107             else
7108                 aopPut(AOP(result),
7109                        aopGet(AOP(right),size,FALSE,FALSE),
7110                        size);
7111         }
7112     } else {
7113         while (size--) {
7114             aopPut(AOP(result),
7115                    aopGet(AOP(right),offset,FALSE,FALSE),
7116                    offset);
7117             offset++;
7118         }
7119     }
7120     
7121 release:
7122     freeAsmop (right,NULL,ic,TRUE);
7123     freeAsmop (result,NULL,ic,TRUE);
7124 }   
7125
7126 /*-----------------------------------------------------------------*/
7127 /* genJumpTab - genrates code for jump table                       */
7128 /*-----------------------------------------------------------------*/
7129 static void genJumpTab (iCode *ic)
7130 {
7131     symbol *jtab;
7132     char *l;
7133
7134     aopOp(IC_JTCOND(ic),ic,FALSE);
7135     /* get the condition into accumulator */
7136     l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
7137     MOVA(l);
7138     /* multiply by three */
7139     emitcode("add","a,acc");
7140     emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
7141     freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
7142
7143     jtab = newiTempLabel(NULL);
7144     emitcode("mov","dptr,#%05d$",jtab->key+100);
7145     emitcode("jmp","@a+dptr");
7146     emitcode("","%05d$:",jtab->key+100);
7147     /* now generate the jump labels */
7148     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
7149          jtab = setNextItem(IC_JTLABELS(ic)))
7150         emitcode("ljmp","%05d$",jtab->key+100);
7151
7152 }
7153
7154 /*-----------------------------------------------------------------*/
7155 /* genCast - gen code for casting                                  */
7156 /*-----------------------------------------------------------------*/
7157 static void genCast (iCode *ic)
7158 {
7159     operand *result = IC_RESULT(ic);
7160     link *ctype = operandType(IC_LEFT(ic));
7161     link *rtype = operandType(IC_RIGHT(ic));
7162     operand *right = IC_RIGHT(ic);
7163     int size, offset ;
7164
7165     /* if they are equivalent then do nothing */
7166     if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
7167         return ;
7168
7169     aopOp(right,ic,FALSE) ;
7170     aopOp(result,ic,FALSE);
7171
7172     /* if the result is a bit */
7173     if (AOP_TYPE(result) == AOP_CRY) {
7174         /* if the right size is a literal then
7175         we know what the value is */
7176         if (AOP_TYPE(right) == AOP_LIT) {
7177             if (((int) operandLitValue(right))) 
7178                 aopPut(AOP(result),one,0);
7179             else
7180                 aopPut(AOP(result),zero,0);
7181
7182             goto release;
7183         }
7184
7185         /* the right is also a bit variable */
7186         if (AOP_TYPE(right) == AOP_CRY) {
7187             emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7188             aopPut(AOP(result),"c",0);
7189             goto release ;
7190         }
7191
7192         /* we need to or */
7193         toBoolean(right);
7194         aopPut(AOP(result),"a",0);
7195         goto release ;
7196     }
7197
7198     /* if they are the same size : or less */
7199     if (AOP_SIZE(result) <= AOP_SIZE(right)) {
7200
7201         /* if they are in the same place */
7202         if (sameRegs(AOP(right),AOP(result)))
7203             goto release;
7204
7205         /* if they in different places then copy */
7206         size = AOP_SIZE(result);
7207         offset = 0 ;
7208         while (size--) {
7209             aopPut(AOP(result),
7210                    aopGet(AOP(right),offset,FALSE,FALSE),
7211                    offset);
7212             offset++;
7213         }
7214         goto release;
7215     }
7216
7217
7218     /* if the result is of type pointer */
7219     if (IS_PTR(ctype)) {
7220
7221         int p_type;
7222         link *type = operandType(right);
7223         link *etype = getSpec(type);
7224
7225         /* pointer to generic pointer */
7226         if (IS_GENPTR(ctype)) {
7227             char *l = zero;
7228             
7229             if (IS_PTR(type)) 
7230                 p_type = DCL_TYPE(type);
7231             else {
7232                 /* we have to go by the storage class */
7233                 p_type = PTR_TYPE(SPEC_OCLS(etype));
7234             }
7235                 
7236             /* the first two bytes are known */
7237             size = GPTRSIZE - 1; 
7238             offset = 0 ;
7239             while (size--) {
7240                 aopPut(AOP(result),
7241                        aopGet(AOP(right),offset,FALSE,FALSE),
7242                        offset);
7243                 offset++;
7244             }
7245             /* the last byte depending on type */
7246             switch (p_type) {
7247             case IPOINTER:
7248             case POINTER:
7249                 l = zero;
7250                 break;
7251             case FPOINTER:
7252                 l = one;
7253                 break;
7254             case CPOINTER:
7255                 l = "#0x02";
7256                 break;                          
7257             case PPOINTER:
7258                 l = "#0x03";
7259                 break;
7260                 
7261             default:
7262                 /* this should never happen */
7263                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
7264                        "got unknown pointer type");
7265                 exit(1);
7266             }
7267             aopPut(AOP(result),l, GPTRSIZE - 1);            
7268             goto release ;
7269         }
7270         
7271         /* just copy the pointers */
7272         size = AOP_SIZE(result);
7273         offset = 0 ;
7274         while (size--) {
7275             aopPut(AOP(result),
7276                    aopGet(AOP(right),offset,FALSE,FALSE),
7277                    offset);
7278             offset++;
7279         }
7280         goto release ;
7281     }
7282     
7283     /* so we now know that the size of destination is greater
7284     than the size of the source */
7285     /* we move to result for the size of source */
7286     size = AOP_SIZE(right);
7287     offset = 0 ;
7288     while (size--) {
7289         aopPut(AOP(result),
7290                aopGet(AOP(right),offset,FALSE,FALSE),
7291                offset);
7292         offset++;
7293     }
7294
7295     /* now depending on the sign of the source && destination */
7296     size = AOP_SIZE(result) - AOP_SIZE(right);
7297     /* if unsigned or not an integral type */
7298     if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
7299         while (size--)
7300             aopPut(AOP(result),zero,offset++);
7301     } else {
7302         /* we need to extend the sign :{ */
7303         char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
7304                          FALSE,FALSE);
7305         MOVA(l);
7306         emitcode("rlc","a");
7307         emitcode("subb","a,acc");
7308         while (size--)
7309             aopPut(AOP(result),"a",offset++);   
7310     }
7311
7312     /* we are done hurray !!!! */
7313
7314 release:
7315     freeAsmop(right,NULL,ic,TRUE);
7316     freeAsmop(result,NULL,ic,TRUE);
7317
7318 }
7319
7320 /*-----------------------------------------------------------------*/
7321 /* genDjnz - generate decrement & jump if not zero instrucion      */
7322 /*-----------------------------------------------------------------*/
7323 static int genDjnz (iCode *ic, iCode *ifx)
7324 {
7325     symbol *lbl, *lbl1;
7326     if (!ifx)
7327         return 0;
7328     
7329     /* if the if condition has a false label
7330        then we cannot save */
7331     if (IC_FALSE(ifx))
7332         return 0;
7333
7334     /* if the minus is not of the form 
7335        a = a - 1 */
7336     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
7337         !IS_OP_LITERAL(IC_RIGHT(ic)))
7338         return 0;
7339
7340     if (operandLitValue(IC_RIGHT(ic)) != 1)
7341         return 0;
7342
7343     /* if the size of this greater than one then no
7344        saving */
7345     if (getSize(operandType(IC_RESULT(ic))) > 1)
7346         return 0;
7347
7348     /* otherwise we can save BIG */
7349     lbl = newiTempLabel(NULL);
7350     lbl1= newiTempLabel(NULL);
7351
7352     aopOp(IC_RESULT(ic),ic,FALSE);
7353     
7354     if (IS_AOP_PREG(IC_RESULT(ic))) {
7355         emitcode("dec","%s",
7356                  aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
7357         emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
7358         emitcode("jnz","%05d$",lbl->key+100);
7359     } else {    
7360         emitcode ("djnz","%s,%05d$",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
7361                   lbl->key+100);
7362     }
7363     emitcode ("sjmp","%05d$",lbl1->key+100);
7364     emitcode ("","%05d$:",lbl->key+100);
7365     emitcode ("ljmp","%05d$",IC_TRUE(ifx)->key+100);
7366     emitcode ("","%05d$:",lbl1->key+100);
7367     
7368     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7369     ifx->generated = 1;
7370     return 1;
7371 }
7372
7373 /*-----------------------------------------------------------------*/
7374 /* genReceive - generate code for a receive iCode                  */
7375 /*-----------------------------------------------------------------*/
7376 static void genReceive (iCode *ic)
7377 {    
7378     if (isOperandInFarSpace(IC_RESULT(ic)) && 
7379         ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
7380           IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
7381
7382         int size = getSize(operandType(IC_RESULT(ic)));
7383         int offset =  fReturnSize - size;
7384         while (size--) {
7385             emitcode ("push","%s", (strcmp(fReturn[fReturnSize - offset - 1],"a") ?
7386                                     fReturn[fReturnSize - offset - 1] : "acc"));
7387             offset++;
7388         }
7389         aopOp(IC_RESULT(ic),ic,FALSE);  
7390         size = AOP_SIZE(IC_RESULT(ic));
7391         offset = 0;
7392         while (size--) {
7393             emitcode ("pop","acc");
7394             aopPut (AOP(IC_RESULT(ic)),"a",offset++);
7395         }
7396         
7397     } else {
7398         _G.accInUse++;
7399         aopOp(IC_RESULT(ic),ic,FALSE);  
7400         _G.accInUse--;
7401         assignResultValue(IC_RESULT(ic));       
7402     }
7403
7404     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7405 }
7406
7407 /*-----------------------------------------------------------------*/
7408 /* gen51Code - generate code for 8051 based controllers            */
7409 /*-----------------------------------------------------------------*/
7410 void gen51Code (iCode *lic)
7411 {
7412     iCode *ic;
7413     int cln = 0;
7414
7415     lineHead = lineCurr = NULL;
7416
7417     /* print the allocation information */
7418     if (allocInfo)
7419         printAllocInfo( currFunc, codeOutFile);
7420     /* if debug information required */
7421 /*     if (options.debug && currFunc) { */
7422     if (currFunc) {
7423         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
7424         _G.debugLine = 1;
7425         if (IS_STATIC(currFunc->etype))
7426             emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name); 
7427         else
7428             emitcode("","G$%s$0$0 ==.",currFunc->name);
7429         _G.debugLine = 0;
7430     }
7431     /* stack pointer name */
7432     if (options.useXstack)
7433         spname = "_spx";
7434     else
7435         spname = "sp";
7436     
7437  
7438     for (ic = lic ; ic ; ic = ic->next ) {
7439         
7440         if ( cln != ic->lineno ) {
7441             if ( options.debug ) {
7442                 _G.debugLine = 1;
7443                 emitcode("","C$%s$%d$%d$%d ==.",
7444                          ic->filename,ic->lineno,
7445                          ic->level,ic->block);
7446                 _G.debugLine = 0;
7447             }
7448             emitcode(";","%s %d",ic->filename,ic->lineno);
7449             cln = ic->lineno ;
7450         }
7451         /* if the result is marked as
7452            spilt and rematerializable or code for
7453            this has already been generated then
7454            do nothing */
7455         if (resultRemat(ic) || ic->generated ) 
7456             continue ;
7457         
7458         /* depending on the operation */
7459         switch (ic->op) {
7460         case '!' :
7461             genNot(ic);
7462             break;
7463             
7464         case '~' :
7465             genCpl(ic);
7466             break;
7467             
7468         case UNARYMINUS:
7469             genUminus (ic);
7470             break;
7471             
7472         case IPUSH:
7473             genIpush (ic);
7474             break;
7475             
7476         case IPOP:
7477             /* IPOP happens only when trying to restore a 
7478                spilt live range, if there is an ifx statement
7479                following this pop then the if statement might
7480                be using some of the registers being popped which
7481                would destory the contents of the register so
7482                we need to check for this condition and handle it */
7483             if (ic->next            && 
7484                 ic->next->op == IFX &&
7485                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
7486                 genIfx (ic->next,ic);
7487             else
7488                 genIpop (ic);
7489             break; 
7490             
7491         case CALL:
7492             genCall (ic);
7493             break;
7494             
7495         case PCALL:
7496             genPcall (ic);
7497             break;
7498             
7499         case FUNCTION:
7500             genFunction (ic);
7501             break;
7502             
7503         case ENDFUNCTION:
7504             genEndFunction (ic);
7505             break;
7506             
7507         case RETURN:
7508             genRet (ic);
7509             break;
7510             
7511         case LABEL:
7512             genLabel (ic);
7513             break;
7514             
7515         case GOTO:
7516             genGoto (ic);
7517             break;
7518             
7519         case '+' :
7520             genPlus (ic) ;
7521             break;
7522             
7523         case '-' :
7524             if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
7525                 genMinus (ic);
7526             break;
7527             
7528         case '*' :
7529             genMult (ic);
7530             break;
7531             
7532         case '/' :
7533             genDiv (ic) ;
7534             break;
7535             
7536         case '%' :
7537             genMod (ic);
7538             break;
7539             
7540         case '>' :
7541             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
7542             break;
7543             
7544         case '<' :
7545             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
7546             break;
7547             
7548         case LE_OP:
7549         case GE_OP:
7550         case NE_OP:
7551             
7552             /* note these two are xlated by algebraic equivalence
7553                during parsing SDCC.y */
7554             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
7555                    "got '>=' or '<=' shouldn't have come here");
7556             break;      
7557             
7558         case EQ_OP:
7559             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
7560             break;          
7561             
7562         case AND_OP:
7563             genAndOp (ic);
7564             break;
7565             
7566         case OR_OP:
7567             genOrOp (ic);
7568             break;
7569             
7570         case '^' :
7571             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
7572             break;
7573             
7574         case '|' :
7575                 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
7576             break;
7577             
7578         case BITWISEAND:
7579             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
7580             break;
7581             
7582         case INLINEASM:
7583             genInline (ic);
7584             break;
7585             
7586         case RRC:
7587             genRRC (ic);
7588             break;
7589             
7590         case RLC:
7591             genRLC (ic);
7592             break;
7593             
7594         case GETHBIT:
7595             genGetHbit (ic);
7596             break;
7597             
7598         case LEFT_OP:
7599             genLeftShift (ic);
7600             break;
7601             
7602         case RIGHT_OP:
7603             genRightShift (ic);
7604             break;
7605             
7606         case GET_VALUE_AT_ADDRESS:
7607             genPointerGet(ic);
7608             break;
7609             
7610         case '=' :
7611             if (POINTER_SET(ic))
7612                 genPointerSet(ic);
7613             else
7614                 genAssign(ic);
7615             break;
7616             
7617         case IFX:
7618             genIfx (ic,NULL);
7619             break;
7620             
7621         case ADDRESS_OF:
7622             genAddrOf (ic);
7623             break;
7624             
7625         case JUMPTABLE:
7626             genJumpTab (ic);
7627             break;
7628             
7629         case CAST:
7630             genCast (ic);
7631             break;
7632             
7633         case RECEIVE:
7634             genReceive(ic);
7635             break;
7636             
7637         case SEND:
7638             addSet(&_G.sendSet,ic);
7639             break;
7640
7641         default :
7642             ic = ic;
7643             /*      piCode(ic,stdout); */
7644             
7645         }
7646     }
7647     
7648
7649     /* now we are ready to call the 
7650        peep hole optimizer */
7651     if (!options.nopeep)
7652         peepHole (&lineHead);
7653
7654     /* now do the actual printing */
7655     printLine (lineHead,codeOutFile);    
7656     return;
7657 }