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