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