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