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