Now the pointer_type information of a storeage
[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 static char *fReturn8051[] = {"dpl","dph","b","a" };
65 static char *fReturn390[] = {"dpl","dph","dpx", "b","a" };
66 unsigned fReturnSize = 4; /* shared with ralloc.c */
67 static 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 /* genPlusIncr :- does addition with increment if possible         */
2253 /*-----------------------------------------------------------------*/
2254 static bool genPlusIncr (iCode *ic)
2255 {
2256     unsigned int icount ;
2257     unsigned int size = getDataSize(IC_RESULT(ic));
2258     
2259     /* will try to generate an increment */
2260     /* if the right side is not a literal 
2261        we cannot */
2262     if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2263         return FALSE ;
2264     
2265     /* if the literal value of the right hand side
2266        is greater than 4 then it is not worth it */
2267     if ((icount =  floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
2268         return FALSE ;
2269     
2270     /* if increment 16 bits in register */
2271     if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2272         (size > 1) &&
2273         (icount == 1)) {
2274         symbol *tlbl = newiTempLabel(NULL);
2275         emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2276         if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2277            IS_AOP_PREG(IC_RESULT(ic)))
2278             emitcode("cjne","%s,#0x00,%05d$"
2279                      ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2280                      ,tlbl->key+100);
2281         else {
2282             emitcode("clr","a");
2283             emitcode("cjne","a,%s,%05d$"
2284                      ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2285                      ,tlbl->key+100);
2286         }
2287     
2288         emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
2289         if (size > 2)
2290         {
2291             if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2292                IS_AOP_PREG(IC_RESULT(ic)))
2293                 emitcode("cjne","%s,#0x00,%05d$"
2294                          ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2295                          ,tlbl->key+100);
2296             else
2297                 emitcode("cjne","a,%s,%05d$"
2298                          ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2299                          ,tlbl->key+100);
2300             
2301             emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
2302        }
2303        if (size > 3)
2304        {
2305             if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2306                IS_AOP_PREG(IC_RESULT(ic)))
2307                 emitcode("cjne","%s,#0x00,%05d$"
2308                          ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2309                          ,tlbl->key+100);
2310             else{
2311                 emitcode("cjne","a,%s,%05d$"
2312                          ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2313                          ,tlbl->key+100);
2314             }
2315             emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
2316         }
2317         emitcode("","%05d$:",tlbl->key+100);
2318         return TRUE;
2319     }
2320     
2321     /* if the sizes are greater than 1 then we cannot */
2322     if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2323         AOP_SIZE(IC_LEFT(ic)) > 1   )
2324         return FALSE ;
2325     
2326     /* we can if the aops of the left & result match or
2327        if they are in registers and the registers are the
2328        same */
2329     if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2330         
2331         if (icount > 3) {
2332             MOVA(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));       
2333             emitcode("add","a,#0x%02x",((char) icount) & 0xff);
2334             aopPut(AOP(IC_RESULT(ic)),"a",0);
2335         } else {
2336             
2337             while (icount--) 
2338                 emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2339         }
2340         
2341         return TRUE ;
2342     }
2343     
2344     return FALSE ;
2345 }
2346
2347 /*-----------------------------------------------------------------*/
2348 /* outBitAcc - output a bit in acc                                 */
2349 /*-----------------------------------------------------------------*/
2350 static void outBitAcc(operand *result)
2351 {
2352     symbol *tlbl = newiTempLabel(NULL);
2353     /* if the result is a bit */
2354     if (AOP_TYPE(result) == AOP_CRY){
2355         aopPut(AOP(result),"a",0);
2356     }
2357     else {
2358         emitcode("jz","%05d$",tlbl->key+100);
2359         emitcode("mov","a,%s",one);
2360         emitcode("","%05d$:",tlbl->key+100);
2361         outAcc(result);
2362     }
2363 }
2364
2365 /*-----------------------------------------------------------------*/
2366 /* genPlusBits - generates code for addition of two bits           */
2367 /*-----------------------------------------------------------------*/
2368 static void genPlusBits (iCode *ic)
2369 {
2370     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2371         symbol *lbl = newiTempLabel(NULL);
2372         emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2373         emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
2374         emitcode("cpl","c");
2375         emitcode("","%05d$:",(lbl->key+100));
2376         outBitC(IC_RESULT(ic));
2377     }
2378     else{
2379         emitcode("clr","a");
2380         emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2381         emitcode("rlc","a");
2382         emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
2383         emitcode("addc","a,#0x00");
2384         outAcc(IC_RESULT(ic));
2385     }
2386 }
2387
2388 #if 0
2389 /* This is the original version of this code.
2390  *
2391  * This is being kept around for reference, 
2392  * because I am not entirely sure I got it right...
2393  */
2394 static void adjustArithmeticResult(iCode *ic)
2395 {
2396     if (AOP_SIZE(IC_RESULT(ic)) == 3 && 
2397         AOP_SIZE(IC_LEFT(ic)) == 3   &&
2398         !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2399         aopPut(AOP(IC_RESULT(ic)),
2400                aopGet(AOP(IC_LEFT(ic)),2,FALSE,FALSE),
2401                2);
2402
2403     if (AOP_SIZE(IC_RESULT(ic)) == 3 && 
2404         AOP_SIZE(IC_RIGHT(ic)) == 3   &&
2405         !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2406         aopPut(AOP(IC_RESULT(ic)),
2407                aopGet(AOP(IC_RIGHT(ic)),2,FALSE,FALSE),
2408                2);
2409     
2410     if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2411         AOP_SIZE(IC_LEFT(ic)) < 3    &&
2412         AOP_SIZE(IC_RIGHT(ic)) < 3   &&
2413         !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2414         !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2415         char buffer[5];
2416         sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2417         aopPut(AOP(IC_RESULT(ic)),buffer,2);
2418     }
2419 }
2420 #else
2421 /* This is the pure and virtuous version of this code.
2422  * I'm pretty certain it's right, but not enough to toss the old 
2423  * code just yet...
2424  */
2425 static void adjustArithmeticResult(iCode *ic)
2426 {
2427     if (opIsGptr(IC_RESULT(ic)) &&
2428         opIsGptr(IC_LEFT(ic))   &&
2429         !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2430     {
2431         aopPut(AOP(IC_RESULT(ic)),
2432                aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1,FALSE,FALSE),
2433                GPTRSIZE - 1);
2434     }
2435
2436     if (opIsGptr(IC_RESULT(ic)) &&
2437         opIsGptr(IC_RIGHT(ic))   &&
2438         !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2439     {
2440         aopPut(AOP(IC_RESULT(ic)),
2441                aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1,FALSE,FALSE),
2442                GPTRSIZE - 1);
2443     }
2444
2445     if (opIsGptr(IC_RESULT(ic))            &&
2446         AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE   &&
2447         AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE  &&
2448          !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2449          !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2450          char buffer[5];
2451          sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2452          aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
2453      }
2454 }
2455 #endif
2456
2457 /*-----------------------------------------------------------------*/
2458 /* genPlus - generates code for addition                           */
2459 /*-----------------------------------------------------------------*/
2460 static void genPlus (iCode *ic)
2461 {
2462     int size, offset = 0;
2463
2464     /* special cases :- */
2465
2466     aopOp (IC_LEFT(ic),ic,FALSE);
2467     aopOp (IC_RIGHT(ic),ic,FALSE);
2468     aopOp (IC_RESULT(ic),ic,TRUE);
2469
2470     /* if literal, literal on the right or
2471        if left requires ACC or right is already
2472        in ACC */
2473     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
2474         (AOP_NEEDSACC(IC_LEFT(ic))) ||
2475         AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC ){
2476         operand *t = IC_RIGHT(ic);
2477         IC_RIGHT(ic) = IC_LEFT(ic);
2478         IC_LEFT(ic) = t;
2479     }
2480
2481     /* if both left & right are in bit
2482     space */
2483     if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2484         AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2485         genPlusBits (ic);
2486         goto release ;
2487     }
2488
2489     /* if left in bit space & right literal */
2490     if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2491         AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
2492         emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2493         /* if result in bit space */
2494         if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2495             if((unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit) != 0L)
2496                 emitcode("cpl","c");
2497             outBitC(IC_RESULT(ic));
2498         } else {
2499             size = getDataSize(IC_RESULT(ic));
2500             while (size--) {
2501                 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));  
2502                 emitcode("addc","a,#00");
2503                 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2504             }
2505         }
2506         goto release ;
2507     }
2508
2509     /* if I can do an increment instead
2510     of add then GOOD for ME */
2511     if (genPlusIncr (ic) == TRUE)
2512         goto release;   
2513
2514     size = getDataSize(IC_RESULT(ic));
2515
2516     while(size--){
2517         if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
2518             MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2519             if(offset == 0)
2520                 emitcode("add","a,%s",
2521                          aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2522             else
2523                 emitcode("addc","a,%s",
2524                          aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2525         } else {
2526             MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2527             if(offset == 0)
2528                 emitcode("add","a,%s",
2529                          aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2530             else
2531                 emitcode("addc","a,%s",
2532                          aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2533         }
2534         aopPut(AOP(IC_RESULT(ic)),"a",offset++);      
2535     }
2536
2537     adjustArithmeticResult(ic);
2538
2539 release:
2540     freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2541     freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2542     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2543 }
2544
2545 /*-----------------------------------------------------------------*/
2546 /* genMinusDec :- does subtraction with deccrement if possible     */
2547 /*-----------------------------------------------------------------*/
2548 static bool genMinusDec (iCode *ic)
2549 {
2550     unsigned int icount ;
2551         unsigned int size = getDataSize(IC_RESULT(ic));
2552
2553     /* will try to generate an increment */
2554     /* if the right side is not a literal 
2555     we cannot */
2556     if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2557         return FALSE ;
2558
2559     /* if the literal value of the right hand side
2560     is greater than 4 then it is not worth it */
2561     if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
2562         return FALSE ;
2563
2564         size = getDataSize(IC_RESULT(ic));
2565     /* if decrement 16 bits in register */
2566     if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2567         (size > 1) &&
2568         (icount == 1)) {
2569         symbol *tlbl = newiTempLabel(NULL);
2570                 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2571                 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2572                    IS_AOP_PREG(IC_RESULT(ic)))
2573                         emitcode("cjne","%s,#0xff,%05d$"
2574                                          ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2575                                          ,tlbl->key+100);
2576                 else{
2577                         emitcode("mov","a,#0xff");
2578                         emitcode("cjne","a,%s,%05d$"
2579                                          ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2580                                          ,tlbl->key+100);
2581                 }
2582                 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
2583                 if (size > 2)
2584                 {
2585                         if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2586                            IS_AOP_PREG(IC_RESULT(ic)))
2587                                 emitcode("cjne","%s,#0xff,%05d$"
2588                                                  ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2589                                                  ,tlbl->key+100);
2590                         else{
2591                                 emitcode("cjne","a,%s,%05d$"
2592                                                  ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2593                                                  ,tlbl->key+100);
2594                         }
2595                         emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
2596                 }
2597                 if (size > 3)
2598                 {
2599                         if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2600                            IS_AOP_PREG(IC_RESULT(ic)))
2601                                 emitcode("cjne","%s,#0xff,%05d$"
2602                                                  ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2603                                                  ,tlbl->key+100);
2604                         else{
2605                                 emitcode("cjne","a,%s,%05d$"
2606                                                  ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2607                                                  ,tlbl->key+100);
2608                         }
2609                         emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
2610                 }
2611                 emitcode("","%05d$:",tlbl->key+100);
2612         return TRUE;
2613     }
2614
2615     /* if the sizes are greater than 1 then we cannot */
2616     if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2617         AOP_SIZE(IC_LEFT(ic)) > 1   )
2618         return FALSE ;
2619
2620     /* we can if the aops of the left & result match or
2621     if they are in registers and the registers are the
2622     same */
2623     if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2624
2625         while (icount--) 
2626             emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2627
2628         return TRUE ;
2629     }
2630
2631     return FALSE ;
2632 }
2633
2634 /*-----------------------------------------------------------------*/
2635 /* addSign - complete with sign                                    */
2636 /*-----------------------------------------------------------------*/
2637 static void addSign(operand *result, int offset, int sign)
2638 {
2639     int size = (getDataSize(result) - offset);
2640     if(size > 0){
2641         if(sign){
2642             emitcode("rlc","a");
2643             emitcode("subb","a,acc");
2644             while(size--)
2645                 aopPut(AOP(result),"a",offset++); 
2646         } else
2647             while(size--)
2648                 aopPut(AOP(result),zero,offset++);
2649     }
2650 }
2651
2652 /*-----------------------------------------------------------------*/
2653 /* genMinusBits - generates code for subtraction  of two bits      */
2654 /*-----------------------------------------------------------------*/
2655 static void genMinusBits (iCode *ic)
2656 {
2657     symbol *lbl = newiTempLabel(NULL);
2658     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2659         emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2660         emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
2661         emitcode("cpl","c");
2662         emitcode("","%05d$:",(lbl->key+100));
2663         outBitC(IC_RESULT(ic));
2664     }
2665     else{
2666         emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
2667         emitcode("subb","a,acc");
2668         emitcode("jnb","%s,%05d$",AOP(IC_LEFT(ic))->aopu.aop_dir,(lbl->key+100));
2669         emitcode("inc","a");
2670         emitcode("","%05d$:",(lbl->key+100));
2671         aopPut(AOP(IC_RESULT(ic)),"a",0);
2672         addSign(IC_RESULT(ic), MSB16, SPEC_USIGN(getSpec(operandType(IC_RESULT(ic)))));
2673     }
2674 }
2675
2676 /*-----------------------------------------------------------------*/
2677 /* genMinus - generates code for subtraction                       */
2678 /*-----------------------------------------------------------------*/
2679 static void genMinus (iCode *ic)
2680 {
2681     int size, offset = 0;
2682     unsigned long lit = 0L;
2683
2684     aopOp (IC_LEFT(ic),ic,FALSE);
2685     aopOp (IC_RIGHT(ic),ic,FALSE);
2686     aopOp (IC_RESULT(ic),ic,TRUE);
2687
2688     /* special cases :- */
2689     /* if both left & right are in bit space */
2690     if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2691         AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2692         genMinusBits (ic);
2693         goto release ;
2694     }
2695
2696     /* if I can do an decrement instead
2697     of subtract then GOOD for ME */
2698     if (genMinusDec (ic) == TRUE)
2699         goto release;   
2700
2701     size = getDataSize(IC_RESULT(ic));   
2702
2703     if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
2704         CLRC;
2705     }
2706     else{
2707         lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
2708         lit = - (long)lit;
2709     }
2710
2711     /* if literal, add a,#-lit, else normal subb */
2712     while (size--) {
2713         MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));    
2714         if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)  
2715             emitcode("subb","a,%s",
2716                      aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2717         else{
2718             /* first add without previous c */
2719             if(!offset)
2720                 emitcode("add","a,#0x%02x",
2721                          (unsigned int)(lit & 0x0FFL));
2722             else
2723                 emitcode("addc","a,#0x%02x",
2724                          (unsigned int)((lit >> (offset*8)) & 0x0FFL));
2725         }
2726         aopPut(AOP(IC_RESULT(ic)),"a",offset++);      
2727     }
2728
2729     adjustArithmeticResult(ic);
2730         
2731 release:
2732     freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2733     freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2734     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2735 }
2736
2737
2738 /*-----------------------------------------------------------------*/
2739 /* genMultbits :- multiplication of bits                           */
2740 /*-----------------------------------------------------------------*/
2741 static void genMultbits (operand *left, 
2742                          operand *right, 
2743                          operand *result)
2744 {
2745     emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
2746     emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
2747     outBitC(result);
2748 }
2749
2750
2751 /*-----------------------------------------------------------------*/
2752 /* genMultOneByte : 8 bit multiplication & division                */
2753 /*-----------------------------------------------------------------*/
2754 static void genMultOneByte (operand *left,
2755                             operand *right,
2756                             operand *result)
2757 {
2758     link *opetype = operandType(result);
2759     char *l ;
2760     symbol *lbl ;
2761     int size,offset;
2762
2763     /* (if two literals, the value is computed before) */
2764     /* if one literal, literal on the right */
2765     if (AOP_TYPE(left) == AOP_LIT){
2766         operand *t = right;
2767         right = left;
2768         left = t;
2769     }
2770
2771     size = AOP_SIZE(result);
2772     /* signed or unsigned */
2773     emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
2774     l = aopGet(AOP(left),0,FALSE,FALSE);
2775     MOVA(l);       
2776     emitcode("mul","ab");
2777     /* if result size = 1, mul signed = mul unsigned */
2778     aopPut(AOP(result),"a",0);
2779     if (size > 1){
2780         if (SPEC_USIGN(opetype)){
2781             aopPut(AOP(result),"b",1);
2782             if (size > 2)
2783                 /* for filling the MSBs */
2784                 emitcode("clr","a");
2785         }
2786         else{
2787             emitcode("mov","a,b");
2788
2789             /* adjust the MSB if left or right neg */
2790
2791             /* if one literal */
2792             if (AOP_TYPE(right) == AOP_LIT){
2793                 /* AND literal negative */
2794                 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
2795                     /* adjust MSB (c==0 after mul) */
2796                     emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
2797                 }
2798             }
2799             else{
2800                 lbl = newiTempLabel(NULL);
2801                 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
2802                 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
2803                 emitcode("","%05d$:",(lbl->key+100));
2804                 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
2805                 lbl = newiTempLabel(NULL);      
2806                 emitcode("jc","%05d$",(lbl->key+100));          
2807                 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
2808                 emitcode("","%05d$:",(lbl->key+100));
2809             }
2810
2811             lbl = newiTempLabel(NULL);
2812             emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
2813             emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
2814             emitcode("","%05d$:",(lbl->key+100));
2815             emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
2816             lbl = newiTempLabel(NULL);      
2817             emitcode("jc","%05d$",(lbl->key+100));          
2818             emitcode("subb","a,%s", aopGet(AOP(right),0,FALSE,FALSE));
2819             emitcode("","%05d$:",(lbl->key+100));
2820
2821             aopPut(AOP(result),"a",1);
2822             if(size > 2){
2823                 /* get the sign */
2824                 emitcode("rlc","a");
2825                 emitcode("subb","a,acc");
2826             }
2827         }
2828         size -= 2;   
2829         offset = 2;
2830         if (size > 0)
2831             while (size--)
2832                 aopPut(AOP(result),"a",offset++);
2833     }
2834 }
2835
2836 /*-----------------------------------------------------------------*/
2837 /* genMult - generates code for multiplication                     */
2838 /*-----------------------------------------------------------------*/
2839 static void genMult (iCode *ic)
2840 {
2841     operand *left = IC_LEFT(ic);
2842     operand *right = IC_RIGHT(ic);
2843     operand *result= IC_RESULT(ic);   
2844
2845     /* assign the amsops */
2846     aopOp (left,ic,FALSE);
2847     aopOp (right,ic,FALSE);
2848     aopOp (result,ic,TRUE);
2849
2850     /* special cases first */
2851     /* both are bits */
2852     if (AOP_TYPE(left) == AOP_CRY &&
2853         AOP_TYPE(right)== AOP_CRY) {
2854         genMultbits(left,right,result);
2855         goto release ;
2856     }
2857
2858     /* if both are of size == 1 */
2859     if (AOP_SIZE(left) == 1 &&
2860         AOP_SIZE(right) == 1 ) {
2861         genMultOneByte(left,right,result);
2862         goto release ;
2863     }
2864
2865     /* should have been converted to function call */       
2866     assert(1) ;
2867
2868 release :
2869     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2870     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2871     freeAsmop(result,NULL,ic,TRUE); 
2872 }
2873
2874 /*-----------------------------------------------------------------*/
2875 /* genDivbits :- division of bits                                  */
2876 /*-----------------------------------------------------------------*/
2877 static void genDivbits (operand *left, 
2878                         operand *right, 
2879                         operand *result)
2880 {
2881
2882     char *l;
2883
2884     /* the result must be bit */    
2885     emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
2886     l = aopGet(AOP(left),0,FALSE,FALSE);
2887
2888     MOVA(l);    
2889
2890     emitcode("div","ab");
2891     emitcode("rrc","a");
2892     aopPut(AOP(result),"c",0);
2893 }
2894
2895 /*-----------------------------------------------------------------*/
2896 /* genDivOneByte : 8 bit division                                  */
2897 /*-----------------------------------------------------------------*/
2898 static void genDivOneByte (operand *left,
2899                            operand *right,
2900                            operand *result)
2901 {
2902     link *opetype = operandType(result);
2903     char *l ;
2904     symbol *lbl ;
2905     int size,offset;
2906
2907     size = AOP_SIZE(result) - 1;
2908     offset = 1;
2909     /* signed or unsigned */
2910     if (SPEC_USIGN(opetype)) {
2911         /* unsigned is easy */
2912         emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
2913         l = aopGet(AOP(left),0,FALSE,FALSE);
2914         MOVA(l);        
2915         emitcode("div","ab");
2916         aopPut(AOP(result),"a",0);
2917         while (size--)
2918             aopPut(AOP(result),zero,offset++);
2919         return ;
2920     }
2921
2922     /* signed is a little bit more difficult */
2923
2924     /* save the signs of the operands */
2925     l = aopGet(AOP(left),0,FALSE,FALSE);    
2926     MOVA(l);    
2927     emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE));
2928     emitcode("push","acc"); /* save it on the stack */
2929
2930     /* now sign adjust for both left & right */
2931     l =  aopGet(AOP(right),0,FALSE,FALSE);    
2932     MOVA(l);       
2933     lbl = newiTempLabel(NULL);
2934     emitcode("jnb","acc.7,%05d$",(lbl->key+100));   
2935     emitcode("cpl","a");   
2936     emitcode("inc","a");
2937     emitcode("","%05d$:",(lbl->key+100));
2938     emitcode("mov","b,a");
2939
2940     /* sign adjust left side */
2941     l =  aopGet(AOP(left),0,FALSE,FALSE);    
2942     MOVA(l);
2943
2944     lbl = newiTempLabel(NULL);
2945     emitcode("jnb","acc.7,%05d$",(lbl->key+100));
2946     emitcode("cpl","a");
2947     emitcode("inc","a");
2948     emitcode("","%05d$:",(lbl->key+100));
2949
2950     /* now the division */
2951     emitcode("div","ab");
2952     /* we are interested in the lower order
2953     only */
2954     emitcode("mov","b,a");
2955     lbl = newiTempLabel(NULL);
2956     emitcode("pop","acc");   
2957     /* if there was an over flow we don't 
2958     adjust the sign of the result */
2959     emitcode("jb","ov,%05d$",(lbl->key+100));
2960     emitcode("jnb","acc.7,%05d$",(lbl->key+100));
2961     CLRC;
2962     emitcode("clr","a");
2963     emitcode("subb","a,b");
2964     emitcode("mov","b,a");
2965     emitcode("","%05d$:",(lbl->key+100));
2966
2967     /* now we are done */
2968     aopPut(AOP(result),"b",0);
2969     if(size > 0){
2970         emitcode("mov","c,b.7");
2971         emitcode("subb","a,acc");   
2972     }
2973     while (size--)
2974         aopPut(AOP(result),"a",offset++);
2975
2976 }
2977
2978 /*-----------------------------------------------------------------*/
2979 /* genDiv - generates code for division                            */
2980 /*-----------------------------------------------------------------*/
2981 static void genDiv (iCode *ic)
2982 {
2983     operand *left = IC_LEFT(ic);
2984     operand *right = IC_RIGHT(ic);
2985     operand *result= IC_RESULT(ic);   
2986
2987     /* assign the amsops */
2988     aopOp (left,ic,FALSE);
2989     aopOp (right,ic,FALSE);
2990     aopOp (result,ic,TRUE);
2991
2992     /* special cases first */
2993     /* both are bits */
2994     if (AOP_TYPE(left) == AOP_CRY &&
2995         AOP_TYPE(right)== AOP_CRY) {
2996         genDivbits(left,right,result);
2997         goto release ;
2998     }
2999
3000     /* if both are of size == 1 */
3001     if (AOP_SIZE(left) == 1 &&
3002         AOP_SIZE(right) == 1 ) {
3003         genDivOneByte(left,right,result);
3004         goto release ;
3005     }
3006
3007     /* should have been converted to function call */
3008     assert(1);
3009 release :
3010     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3011     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3012     freeAsmop(result,NULL,ic,TRUE); 
3013 }
3014
3015 /*-----------------------------------------------------------------*/
3016 /* genModbits :- modulus of bits                                   */
3017 /*-----------------------------------------------------------------*/
3018 static void genModbits (operand *left, 
3019                         operand *right, 
3020                         operand *result)
3021 {
3022
3023     char *l;
3024
3025     /* the result must be bit */    
3026     emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3027     l = aopGet(AOP(left),0,FALSE,FALSE);
3028
3029     MOVA(l);       
3030
3031     emitcode("div","ab");
3032     emitcode("mov","a,b");
3033     emitcode("rrc","a");
3034     aopPut(AOP(result),"c",0);
3035 }
3036
3037 /*-----------------------------------------------------------------*/
3038 /* genModOneByte : 8 bit modulus                                   */
3039 /*-----------------------------------------------------------------*/
3040 static void genModOneByte (operand *left,
3041                            operand *right,
3042                            operand *result)
3043 {
3044     link *opetype = operandType(result);
3045     char *l ;
3046     symbol *lbl ;
3047
3048     /* signed or unsigned */
3049     if (SPEC_USIGN(opetype)) {
3050         /* unsigned is easy */
3051         emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3052         l = aopGet(AOP(left),0,FALSE,FALSE);
3053         MOVA(l);    
3054         emitcode("div","ab");
3055         aopPut(AOP(result),"b",0);
3056         return ;
3057     }
3058
3059     /* signed is a little bit more difficult */
3060
3061     /* save the signs of the operands */
3062     l = aopGet(AOP(left),0,FALSE,FALSE);    
3063     MOVA(l);
3064
3065     emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3066     emitcode("push","acc"); /* save it on the stack */
3067
3068     /* now sign adjust for both left & right */
3069     l =  aopGet(AOP(right),0,FALSE,FALSE);    
3070     MOVA(l);
3071
3072     lbl = newiTempLabel(NULL);
3073     emitcode("jnb","acc.7,%05d$",(lbl->key+100));  
3074     emitcode("cpl","a");   
3075     emitcode("inc","a");
3076     emitcode("","%05d$:",(lbl->key+100));
3077     emitcode("mov","b,a"); 
3078
3079     /* sign adjust left side */
3080     l =  aopGet(AOP(left),0,FALSE,FALSE);    
3081     MOVA(l);
3082
3083     lbl = newiTempLabel(NULL);
3084     emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3085     emitcode("cpl","a");   
3086     emitcode("inc","a");
3087     emitcode("","%05d$:",(lbl->key+100));
3088
3089     /* now the multiplication */
3090     emitcode("div","ab");
3091     /* we are interested in the lower order
3092     only */
3093     lbl = newiTempLabel(NULL);
3094     emitcode("pop","acc");   
3095     /* if there was an over flow we don't 
3096     adjust the sign of the result */
3097     emitcode("jb","ov,%05d$",(lbl->key+100));
3098     emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3099     CLRC ;
3100     emitcode("clr","a");
3101     emitcode("subb","a,b");
3102     emitcode("mov","b,a");
3103     emitcode("","%05d$:",(lbl->key+100));
3104
3105     /* now we are done */
3106     aopPut(AOP(result),"b",0);
3107
3108 }
3109
3110 /*-----------------------------------------------------------------*/
3111 /* genMod - generates code for division                            */
3112 /*-----------------------------------------------------------------*/
3113 static void genMod (iCode *ic)
3114 {
3115     operand *left = IC_LEFT(ic);
3116     operand *right = IC_RIGHT(ic);
3117     operand *result= IC_RESULT(ic);  
3118
3119     /* assign the amsops */
3120     aopOp (left,ic,FALSE);
3121     aopOp (right,ic,FALSE);
3122     aopOp (result,ic,TRUE);
3123
3124     /* special cases first */
3125     /* both are bits */
3126     if (AOP_TYPE(left) == AOP_CRY &&
3127         AOP_TYPE(right)== AOP_CRY) {
3128         genModbits(left,right,result);
3129         goto release ;
3130     }
3131
3132     /* if both are of size == 1 */
3133     if (AOP_SIZE(left) == 1 &&
3134         AOP_SIZE(right) == 1 ) {
3135         genModOneByte(left,right,result);
3136         goto release ;
3137     }
3138
3139     /* should have been converted to function call */
3140     assert(1);
3141
3142 release :
3143     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3144     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3145     freeAsmop(result,NULL,ic,TRUE); 
3146 }
3147
3148 /*-----------------------------------------------------------------*/
3149 /* genIfxJump :- will create a jump depending on the ifx           */
3150 /*-----------------------------------------------------------------*/
3151 static void genIfxJump (iCode *ic, char *jval)
3152 {
3153     symbol *jlbl ;
3154     symbol *tlbl = newiTempLabel(NULL);
3155     char *inst;
3156
3157     /* if true label then we jump if condition
3158     supplied is true */
3159     if ( IC_TRUE(ic) ) {
3160         jlbl = IC_TRUE(ic);
3161         inst = ((strcmp(jval,"a") == 0 ? "jz" :
3162                  (strcmp(jval,"c") == 0 ? "jnc" : "jnb" )));
3163     }
3164     else {
3165         /* false label is present */
3166         jlbl = IC_FALSE(ic) ;
3167         inst = ((strcmp(jval,"a") == 0 ? "jnz" :
3168                  (strcmp(jval,"c") == 0 ? "jc" : "jb" )));              
3169     }
3170     if (strcmp(inst,"jb") == 0 || strcmp(inst,"jnb") == 0) 
3171         emitcode(inst,"%s,%05d$",jval,(tlbl->key+100));
3172     else
3173         emitcode(inst,"%05d$",tlbl->key+100);
3174     emitcode("ljmp","%05d$",jlbl->key+100);
3175     emitcode("","%05d$:",tlbl->key+100);                
3176
3177     /* mark the icode as generated */
3178     ic->generated = 1;
3179 }
3180
3181 /*-----------------------------------------------------------------*/
3182 /* genCmp :- greater or less than comparison                       */
3183 /*-----------------------------------------------------------------*/
3184 static void genCmp (operand *left,operand *right,
3185                     operand *result, iCode *ifx, int sign)
3186 {
3187     int size, offset = 0 ;
3188     unsigned long lit = 0L;
3189
3190     /* if left & right are bit variables */
3191     if (AOP_TYPE(left) == AOP_CRY &&
3192         AOP_TYPE(right) == AOP_CRY ) {
3193         emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3194         emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3195     } else {
3196         /* subtract right from left if at the
3197         end the carry flag is set then we know that
3198         left is greater than right */
3199         size = max(AOP_SIZE(left),AOP_SIZE(right));
3200
3201         /* if unsigned char cmp with lit, do cjne left,#right,zz */
3202         if((size == 1) && !sign &&
3203            (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
3204             symbol *lbl  = newiTempLabel(NULL);
3205             emitcode("cjne","%s,%s,%05d$",
3206                      aopGet(AOP(left),offset,FALSE,FALSE),
3207                      aopGet(AOP(right),offset,FALSE,FALSE),
3208                      lbl->key+100);
3209             emitcode("","%05d$:",lbl->key+100);
3210         } else {
3211             if(AOP_TYPE(right) == AOP_LIT){
3212                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3213                 /* optimize if(x < 0) or if(x >= 0) */
3214                 if(lit == 0L){
3215                     if(!sign){
3216                         CLRC;
3217                     }
3218                     else{
3219                         MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE,FALSE));
3220                         if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx){
3221                             genIfxJump (ifx,"acc.7");
3222                             return;
3223                         }
3224                         else    
3225                             emitcode("rlc","a");
3226                     }
3227                     goto release;
3228                 }
3229             }
3230             CLRC;
3231             while (size--) {
3232                 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
3233                 if (sign && size == 0) {
3234                     emitcode("xrl","a,#0x80");
3235                     if (AOP_TYPE(right) == AOP_LIT){
3236                         unsigned long lit = (unsigned long)
3237                             floatFromVal(AOP(right)->aopu.aop_lit);
3238                         emitcode("subb","a,#0x%02x",
3239                                  0x80 ^ (unsigned int)((lit >> (offset*8)) & 0x0FFL));                       
3240                     } else {
3241                         emitcode("mov","b,%s",aopGet(AOP(right),offset++,FALSE,FALSE));
3242                         emitcode("xrl","b,#0x80");
3243                         emitcode("subb","a,b");
3244                     }
3245                 } else      
3246                     emitcode("subb","a,%s",aopGet(AOP(right),offset++,FALSE,FALSE));
3247             }
3248         }
3249     }
3250
3251 release:
3252     if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
3253         outBitC(result);
3254     } else {
3255         /* if the result is used in the next
3256         ifx conditional branch then generate
3257         code a little differently */
3258         if (ifx )
3259             genIfxJump (ifx,"c");
3260         else
3261             outBitC(result);
3262         /* leave the result in acc */
3263     }
3264 }
3265
3266 /*-----------------------------------------------------------------*/
3267 /* genCmpGt :- greater than comparison                             */
3268 /*-----------------------------------------------------------------*/
3269 static void genCmpGt (iCode *ic, iCode *ifx)
3270 {
3271     operand *left, *right, *result;
3272     link *letype , *retype;
3273     int sign ;
3274
3275     left = IC_LEFT(ic);
3276     right= IC_RIGHT(ic);
3277     result = IC_RESULT(ic);
3278
3279     letype = getSpec(operandType(left));
3280     retype =getSpec(operandType(right));
3281     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3282     /* assign the amsops */
3283     aopOp (left,ic,FALSE);
3284     aopOp (right,ic,FALSE);
3285     aopOp (result,ic,TRUE);
3286
3287     genCmp(right, left, result, ifx, sign);
3288
3289     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3290     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3291     freeAsmop(result,NULL,ic,TRUE); 
3292 }
3293
3294 /*-----------------------------------------------------------------*/
3295 /* genCmpLt - less than comparisons                                */
3296 /*-----------------------------------------------------------------*/
3297 static void genCmpLt (iCode *ic, iCode *ifx)
3298 {
3299     operand *left, *right, *result;
3300     link *letype , *retype;
3301     int sign ;
3302
3303     left = IC_LEFT(ic);
3304     right= IC_RIGHT(ic);
3305     result = IC_RESULT(ic);
3306
3307     letype = getSpec(operandType(left));
3308     retype =getSpec(operandType(right));
3309     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3310
3311     /* assign the amsops */
3312     aopOp (left,ic,FALSE);
3313     aopOp (right,ic,FALSE);
3314     aopOp (result,ic,TRUE);
3315
3316     genCmp(left, right, result, ifx, sign);
3317
3318     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3319     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3320     freeAsmop(result,NULL,ic,TRUE); 
3321 }
3322
3323 /*-----------------------------------------------------------------*/
3324 /* gencjneshort - compare and jump if not equal                    */
3325 /*-----------------------------------------------------------------*/
3326 static void gencjneshort(operand *left, operand *right, symbol *lbl)
3327 {
3328     int size = max(AOP_SIZE(left),AOP_SIZE(right));
3329     int offset = 0;
3330     unsigned long lit = 0L;
3331
3332     /* if the left side is a literal or 
3333     if the right is in a pointer register and left 
3334     is not */
3335     if ((AOP_TYPE(left) == AOP_LIT) || 
3336         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
3337         operand *t = right;
3338         right = left;
3339         left = t;
3340     }
3341     if(AOP_TYPE(right) == AOP_LIT)
3342         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3343
3344     /* if the right side is a literal then anything goes */
3345     if (AOP_TYPE(right) == AOP_LIT &&
3346         AOP_TYPE(left) != AOP_DIR ) {
3347         while (size--) {
3348             emitcode("cjne","%s,%s,%05d$",
3349                      aopGet(AOP(left),offset,FALSE,FALSE),
3350                      aopGet(AOP(right),offset,FALSE,FALSE),
3351                      lbl->key+100);
3352             offset++;
3353         }
3354     }
3355
3356     /* if the right side is in a register or in direct space or
3357     if the left is a pointer register & right is not */    
3358     else if (AOP_TYPE(right) == AOP_REG ||
3359              AOP_TYPE(right) == AOP_DIR || 
3360              (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
3361              (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
3362         while (size--) {
3363             MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
3364             if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
3365                ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
3366                 emitcode("jnz","%05d$",lbl->key+100);
3367             else
3368                 emitcode("cjne","a,%s,%05d$",
3369                          aopGet(AOP(right),offset,FALSE,TRUE),
3370                          lbl->key+100);
3371             offset++;
3372         }
3373     } else {
3374         /* right is a pointer reg need both a & b */
3375         while(size--) {
3376             char *l = aopGet(AOP(left),offset,FALSE,FALSE);
3377             if(strcmp(l,"b"))
3378                 emitcode("mov","b,%s",l);
3379             MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3380             emitcode("cjne","a,b,%05d$",lbl->key+100);    
3381             offset++;
3382         }
3383     }
3384 }
3385
3386 /*-----------------------------------------------------------------*/
3387 /* gencjne - compare and jump if not equal                         */
3388 /*-----------------------------------------------------------------*/
3389 static void gencjne(operand *left, operand *right, symbol *lbl)
3390 {
3391     symbol *tlbl  = newiTempLabel(NULL);
3392
3393     gencjneshort(left, right, lbl);
3394
3395     emitcode("mov","a,%s",one);
3396     emitcode("sjmp","%05d$",tlbl->key+100);
3397     emitcode("","%05d$:",lbl->key+100);
3398     emitcode("clr","a");
3399     emitcode("","%05d$:",tlbl->key+100);
3400 }
3401
3402 /*-----------------------------------------------------------------*/
3403 /* genCmpEq - generates code for equal to                          */
3404 /*-----------------------------------------------------------------*/
3405 static void genCmpEq (iCode *ic, iCode *ifx)
3406 {
3407     operand *left, *right, *result;
3408
3409     aopOp((left=IC_LEFT(ic)),ic,FALSE);
3410     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3411     aopOp((result=IC_RESULT(ic)),ic,TRUE);
3412
3413     /* if literal, literal on the right or 
3414     if the right is in a pointer register and left 
3415     is not */
3416     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
3417         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
3418         operand *t = IC_RIGHT(ic);
3419         IC_RIGHT(ic) = IC_LEFT(ic);
3420         IC_LEFT(ic) = t;
3421     }
3422
3423     if(ifx && !AOP_SIZE(result)){
3424         symbol *tlbl;
3425         /* if they are both bit variables */
3426         if (AOP_TYPE(left) == AOP_CRY &&
3427             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
3428             if(AOP_TYPE(right) == AOP_LIT){
3429                 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3430                 if(lit == 0L){
3431                     emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3432                     emitcode("cpl","c");
3433                 } else if(lit == 1L) {
3434                     emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3435                 } else {
3436                     emitcode("clr","c");
3437                 }
3438                 /* AOP_TYPE(right) == AOP_CRY */
3439             } else {
3440                 symbol *lbl = newiTempLabel(NULL);
3441                 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3442                 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
3443                 emitcode("cpl","c");
3444                 emitcode("","%05d$:",(lbl->key+100));
3445             }
3446             /* if true label then we jump if condition
3447             supplied is true */
3448             tlbl = newiTempLabel(NULL);
3449             if ( IC_TRUE(ifx) ) {
3450                 emitcode("jnc","%05d$",tlbl->key+100);
3451                 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
3452             } else {
3453                 emitcode("jc","%05d$",tlbl->key+100);
3454                 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
3455             }
3456             emitcode("","%05d$:",tlbl->key+100);                
3457         } else {
3458             tlbl = newiTempLabel(NULL);
3459             gencjneshort(left, right, tlbl);
3460             if ( IC_TRUE(ifx) ) {
3461                 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
3462                 emitcode("","%05d$:",tlbl->key+100);                
3463             } else {
3464                 symbol *lbl = newiTempLabel(NULL);
3465                 emitcode("sjmp","%05d$",lbl->key+100);
3466                 emitcode("","%05d$:",tlbl->key+100);                
3467                 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
3468                 emitcode("","%05d$:",lbl->key+100);             
3469             }
3470         }
3471         /* mark the icode as generated */
3472         ifx->generated = 1;
3473         goto release ;
3474     }
3475
3476     /* if they are both bit variables */
3477     if (AOP_TYPE(left) == AOP_CRY &&
3478         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
3479         if(AOP_TYPE(right) == AOP_LIT){
3480             unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3481             if(lit == 0L){
3482                 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3483                 emitcode("cpl","c");
3484             } else if(lit == 1L) {
3485                 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3486             } else {
3487                 emitcode("clr","c");
3488             }
3489             /* AOP_TYPE(right) == AOP_CRY */
3490         } else {
3491             symbol *lbl = newiTempLabel(NULL);
3492             emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3493             emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
3494             emitcode("cpl","c");
3495             emitcode("","%05d$:",(lbl->key+100));
3496         }
3497         /* c = 1 if egal */
3498         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
3499             outBitC(result);
3500             goto release ;
3501         }
3502         if (ifx) {
3503             genIfxJump (ifx,"c");
3504             goto release ;
3505         }
3506         /* if the result is used in an arithmetic operation
3507         then put the result in place */
3508         outBitC(result);
3509     } else {
3510         gencjne(left,right,newiTempLabel(NULL));    
3511         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
3512             aopPut(AOP(result),"a",0);
3513             goto release ;
3514         }
3515         if (ifx) {
3516             genIfxJump (ifx,"a");
3517             goto release ;
3518         }
3519         /* if the result is used in an arithmetic operation
3520         then put the result in place */
3521         if (AOP_TYPE(result) != AOP_CRY) 
3522             outAcc(result);
3523         /* leave the result in acc */
3524     }
3525
3526 release:
3527     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3528     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3529     freeAsmop(result,NULL,ic,TRUE);
3530 }
3531
3532 /*-----------------------------------------------------------------*/
3533 /* ifxForOp - returns the icode containing the ifx for operand     */
3534 /*-----------------------------------------------------------------*/
3535 static iCode *ifxForOp ( operand *op, iCode *ic )
3536 {
3537     /* if true symbol then needs to be assigned */
3538     if (IS_TRUE_SYMOP(op))
3539         return NULL ;
3540
3541     /* if this has register type condition and
3542     the next instruction is ifx with the same operand
3543     and live to of the operand is upto the ifx only then */
3544     if (ic->next &&
3545         ic->next->op == IFX &&
3546         IC_COND(ic->next)->key == op->key &&
3547         OP_SYMBOL(op)->liveTo <= ic->next->seq )
3548         return ic->next;
3549
3550     return NULL;
3551 }
3552 /*-----------------------------------------------------------------*/
3553 /* genAndOp - for && operation                                     */
3554 /*-----------------------------------------------------------------*/
3555 static void genAndOp (iCode *ic)
3556 {
3557     operand *left,*right, *result;
3558     symbol *tlbl;
3559
3560     /* note here that && operations that are in an
3561     if statement are taken away by backPatchLabels
3562     only those used in arthmetic operations remain */
3563     aopOp((left=IC_LEFT(ic)),ic,FALSE);
3564     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3565     aopOp((result=IC_RESULT(ic)),ic,FALSE);
3566
3567     /* if both are bit variables */
3568     if (AOP_TYPE(left) == AOP_CRY &&
3569         AOP_TYPE(right) == AOP_CRY ) {
3570         emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3571         emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
3572         outBitC(result);
3573     } else {
3574         tlbl = newiTempLabel(NULL);
3575         toBoolean(left);    
3576         emitcode("jz","%05d$",tlbl->key+100);
3577         toBoolean(right);
3578         emitcode("","%05d$:",tlbl->key+100);
3579         outBitAcc(result);
3580     }
3581
3582     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3583     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3584     freeAsmop(result,NULL,ic,TRUE);
3585 }
3586
3587
3588 /*-----------------------------------------------------------------*/
3589 /* genOrOp - for || operation                                      */
3590 /*-----------------------------------------------------------------*/
3591 static void genOrOp (iCode *ic)
3592 {
3593     operand *left,*right, *result;
3594     symbol *tlbl;
3595
3596     /* note here that || operations that are in an
3597     if statement are taken away by backPatchLabels
3598     only those used in arthmetic operations remain */
3599     aopOp((left=IC_LEFT(ic)),ic,FALSE);
3600     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3601     aopOp((result=IC_RESULT(ic)),ic,FALSE);
3602
3603     /* if both are bit variables */
3604     if (AOP_TYPE(left) == AOP_CRY &&
3605         AOP_TYPE(right) == AOP_CRY ) {
3606         emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3607         emitcode("orl","c,%s",AOP(right)->aopu.aop_dir);
3608         outBitC(result);
3609     } else {
3610         tlbl = newiTempLabel(NULL);
3611         toBoolean(left);
3612         emitcode("jnz","%05d$",tlbl->key+100);
3613         toBoolean(right);
3614         emitcode("","%05d$:",tlbl->key+100);
3615         outBitAcc(result);
3616     }
3617
3618     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3619     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3620     freeAsmop(result,NULL,ic,TRUE);            
3621 }
3622
3623 /*-----------------------------------------------------------------*/
3624 /* isLiteralBit - test if lit == 2^n                               */
3625 /*-----------------------------------------------------------------*/
3626 static int isLiteralBit(unsigned long lit)
3627 {
3628     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
3629     0x100L,0x200L,0x400L,0x800L,
3630     0x1000L,0x2000L,0x4000L,0x8000L,
3631     0x10000L,0x20000L,0x40000L,0x80000L,
3632     0x100000L,0x200000L,0x400000L,0x800000L,
3633     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
3634     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
3635     int idx;
3636     
3637     for(idx = 0; idx < 32; idx++)
3638         if(lit == pw[idx])
3639             return idx+1;
3640     return 0;
3641 }
3642
3643 /*-----------------------------------------------------------------*/
3644 /* continueIfTrue -                                                */
3645 /*-----------------------------------------------------------------*/
3646 static void continueIfTrue (iCode *ic)
3647 {
3648     if(IC_TRUE(ic))
3649         emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
3650     ic->generated = 1;
3651 }
3652
3653 /*-----------------------------------------------------------------*/
3654 /* jmpIfTrue -                                                     */
3655 /*-----------------------------------------------------------------*/
3656 static void jumpIfTrue (iCode *ic)
3657 {
3658     if(!IC_TRUE(ic))
3659         emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
3660     ic->generated = 1;
3661 }
3662
3663 /*-----------------------------------------------------------------*/
3664 /* jmpTrueOrFalse -                                                */
3665 /*-----------------------------------------------------------------*/
3666 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
3667 {
3668     // ugly but optimized by peephole
3669     if(IC_TRUE(ic)){
3670         symbol *nlbl = newiTempLabel(NULL);
3671         emitcode("sjmp","%05d$",nlbl->key+100);                 
3672         emitcode("","%05d$:",tlbl->key+100);
3673         emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
3674         emitcode("","%05d$:",nlbl->key+100);
3675     }
3676     else{
3677         emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
3678         emitcode("","%05d$:",tlbl->key+100);
3679     }
3680     ic->generated = 1;
3681 }
3682
3683 /*-----------------------------------------------------------------*/
3684 /* genAnd  - code for and                                          */
3685 /*-----------------------------------------------------------------*/
3686 static void genAnd (iCode *ic, iCode *ifx)
3687 {
3688     operand *left, *right, *result;
3689     int size, offset=0;  
3690     unsigned long lit = 0L;
3691     int bytelit = 0;
3692     char buffer[10];
3693
3694     aopOp((left = IC_LEFT(ic)),ic,FALSE);
3695     aopOp((right= IC_RIGHT(ic)),ic,FALSE);
3696     aopOp((result=IC_RESULT(ic)),ic,TRUE);
3697
3698 #ifdef DEBUG_TYPE
3699     emitcode("","; Type res[%d] = l[%d]&r[%d]",
3700              AOP_TYPE(result),
3701              AOP_TYPE(left), AOP_TYPE(right));
3702     emitcode("","; Size res[%d] = l[%d]&r[%d]",
3703              AOP_SIZE(result),
3704              AOP_SIZE(left), AOP_SIZE(right));
3705 #endif
3706
3707     /* if left is a literal & right is not then exchange them */
3708     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
3709         AOP_NEEDSACC(left)) {
3710         operand *tmp = right ;
3711         right = left;
3712         left = tmp;
3713     }
3714
3715     /* if result = right then exchange them */
3716     if(sameRegs(AOP(result),AOP(right))){
3717         operand *tmp = right ;
3718         right = left;
3719         left = tmp;
3720     }
3721
3722     /* if right is bit then exchange them */
3723     if (AOP_TYPE(right) == AOP_CRY &&
3724         AOP_TYPE(left) != AOP_CRY){
3725         operand *tmp = right ;
3726         right = left;
3727         left = tmp;
3728     }
3729     if(AOP_TYPE(right) == AOP_LIT)
3730         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
3731
3732     size = AOP_SIZE(result);
3733
3734     // if(bit & yy)
3735     // result = bit & yy;
3736     if (AOP_TYPE(left) == AOP_CRY){
3737         // c = bit & literal;
3738         if(AOP_TYPE(right) == AOP_LIT){
3739             if(lit & 1) {
3740                 if(size && sameRegs(AOP(result),AOP(left)))
3741                     // no change
3742                     goto release;
3743                 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3744             } else {
3745                 // bit(result) = 0;
3746                 if(size && (AOP_TYPE(result) == AOP_CRY)){
3747                     emitcode("clr","%s",AOP(result)->aopu.aop_dir);
3748                     goto release;
3749                 }
3750                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
3751                     jumpIfTrue(ifx);
3752                     goto release;
3753                 }
3754                 emitcode("clr","c");
3755             }
3756         } else {
3757             if (AOP_TYPE(right) == AOP_CRY){
3758                 // c = bit & bit;
3759                 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3760                 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
3761             } else {
3762                 // c = bit & val;
3763                 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
3764                 // c = lsb
3765                 emitcode("rrc","a");
3766                 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
3767             }
3768         }
3769         // bit = c
3770         // val = c
3771         if(size)
3772             outBitC(result);
3773         // if(bit & ...)
3774         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
3775             genIfxJump(ifx, "c");           
3776         goto release ;
3777     }
3778
3779     // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
3780     // bit = val & 0xZZ     - size = 1, ifx = FALSE -
3781     if((AOP_TYPE(right) == AOP_LIT) &&
3782        (AOP_TYPE(result) == AOP_CRY) &&
3783        (AOP_TYPE(left) != AOP_CRY)){
3784         int posbit = isLiteralBit(lit);
3785         /* left &  2^n */
3786         if(posbit){
3787             posbit--;
3788             MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
3789             // bit = left & 2^n
3790             if(size)
3791                 emitcode("mov","c,acc.%d",posbit&0x07);
3792             // if(left &  2^n)
3793             else{
3794                 if(ifx){
3795                     sprintf(buffer,"acc.%d",posbit&0x07);
3796                     genIfxJump(ifx, buffer);
3797                 }
3798                 goto release;
3799             }
3800         } else {
3801             symbol *tlbl = newiTempLabel(NULL);
3802             int sizel = AOP_SIZE(left);
3803             if(size)
3804                 emitcode("setb","c");
3805             while(sizel--){
3806                 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
3807                     MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
3808                     // byte ==  2^n ?
3809                     if((posbit = isLiteralBit(bytelit)) != 0)
3810                         emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
3811                     else{
3812                         if(bytelit != 0x0FFL)
3813                             emitcode("anl","a,%s",
3814                                      aopGet(AOP(right),offset,FALSE,TRUE));
3815                         emitcode("jnz","%05d$",tlbl->key+100);
3816                     }
3817                 }
3818                 offset++;
3819             }
3820             // bit = left & literal
3821             if(size){
3822                 emitcode("clr","c");
3823                 emitcode("","%05d$:",tlbl->key+100);
3824             }
3825             // if(left & literal)
3826             else{
3827                 if(ifx)
3828                     jmpTrueOrFalse(ifx, tlbl);
3829                 goto release ;
3830             }
3831         }
3832         outBitC(result);
3833         goto release ;
3834     }
3835
3836     /* if left is same as result */
3837     if(sameRegs(AOP(result),AOP(left))){
3838         for(;size--; offset++) {
3839             if(AOP_TYPE(right) == AOP_LIT){
3840                 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
3841                     continue;
3842                 else 
3843                     if (bytelit == 0)
3844                         aopPut(AOP(result),zero,offset);
3845                     else 
3846                         if (IS_AOP_PREG(result)) {
3847                             MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3848                             emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
3849                             aopPut(AOP(result),"a",offset);
3850                         } else
3851                             emitcode("anl","%s,%s",
3852                                      aopGet(AOP(left),offset,FALSE,TRUE),
3853                                      aopGet(AOP(right),offset,FALSE,FALSE));
3854             } else {
3855                 if (AOP_TYPE(left) == AOP_ACC)
3856                     emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
3857                 else {
3858                     MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3859                     if (IS_AOP_PREG(result)) {
3860                         emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
3861                         aopPut(AOP(result),"a",offset);
3862
3863                     } else
3864                         emitcode("anl","%s,a",
3865                                  aopGet(AOP(left),offset,FALSE,TRUE));
3866                 }
3867             }
3868         }
3869     } else {
3870         // left & result in different registers
3871         if(AOP_TYPE(result) == AOP_CRY){
3872             // result = bit
3873             // if(size), result in bit
3874             // if(!size && ifx), conditional oper: if(left & right)
3875             symbol *tlbl = newiTempLabel(NULL);
3876             int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
3877             if(size)
3878                 emitcode("setb","c");
3879             while(sizer--){
3880                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3881                 emitcode("anl","a,%s",
3882                          aopGet(AOP(left),offset,FALSE,FALSE));
3883                 emitcode("jnz","%05d$",tlbl->key+100);
3884                 offset++;
3885             }
3886             if(size){
3887                 CLRC;
3888                 emitcode("","%05d$:",tlbl->key+100);
3889                 outBitC(result);
3890             } else if(ifx)
3891                 jmpTrueOrFalse(ifx, tlbl);
3892         } else {
3893             for(;(size--);offset++) {
3894                 // normal case
3895                 // result = left & right
3896                 if(AOP_TYPE(right) == AOP_LIT){
3897                     if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
3898                         aopPut(AOP(result),
3899                                aopGet(AOP(left),offset,FALSE,FALSE),
3900                                offset);
3901                         continue;
3902                     } else if(bytelit == 0){
3903                         aopPut(AOP(result),zero,offset);
3904                         continue;
3905                     }
3906                 }
3907                 // faster than result <- left, anl result,right
3908                 // and better if result is SFR
3909                 if (AOP_TYPE(left) == AOP_ACC) 
3910                     emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
3911                 else {
3912                     MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3913                     emitcode("anl","a,%s",
3914                              aopGet(AOP(left),offset,FALSE,FALSE));
3915                 }
3916                 aopPut(AOP(result),"a",offset);
3917             }
3918         }
3919     }
3920
3921 release :
3922     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3923     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3924     freeAsmop(result,NULL,ic,TRUE);     
3925 }
3926
3927 /*-----------------------------------------------------------------*/
3928 /* genOr  - code for or                                            */
3929 /*-----------------------------------------------------------------*/
3930 static void genOr (iCode *ic, iCode *ifx)
3931 {
3932     operand *left, *right, *result;
3933     int size, offset=0;
3934     unsigned long lit = 0L;
3935
3936     aopOp((left = IC_LEFT(ic)),ic,FALSE);
3937     aopOp((right= IC_RIGHT(ic)),ic,FALSE);
3938     aopOp((result=IC_RESULT(ic)),ic,TRUE);
3939
3940 #ifdef DEBUG_TYPE
3941     emitcode("","; Type res[%d] = l[%d]&r[%d]",
3942              AOP_TYPE(result),
3943              AOP_TYPE(left), AOP_TYPE(right));
3944     emitcode("","; Size res[%d] = l[%d]&r[%d]",
3945              AOP_SIZE(result),
3946              AOP_SIZE(left), AOP_SIZE(right));
3947 #endif
3948
3949     /* if left is a literal & right is not then exchange them */
3950     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
3951         AOP_NEEDSACC(left)) {
3952         operand *tmp = right ;
3953         right = left;
3954         left = tmp;
3955     }
3956
3957     /* if result = right then exchange them */
3958     if(sameRegs(AOP(result),AOP(right))){
3959         operand *tmp = right ;
3960         right = left;
3961         left = tmp;
3962     }
3963
3964     /* if right is bit then exchange them */
3965     if (AOP_TYPE(right) == AOP_CRY &&
3966         AOP_TYPE(left) != AOP_CRY){
3967         operand *tmp = right ;
3968         right = left;
3969         left = tmp;
3970     }
3971     if(AOP_TYPE(right) == AOP_LIT)
3972         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
3973
3974     size = AOP_SIZE(result);
3975
3976     // if(bit | yy)
3977     // xx = bit | yy;
3978     if (AOP_TYPE(left) == AOP_CRY){
3979         if(AOP_TYPE(right) == AOP_LIT){
3980             // c = bit & literal;
3981             if(lit){
3982                 // lit != 0 => result = 1
3983                 if(AOP_TYPE(result) == AOP_CRY){
3984                     if(size)
3985                         emitcode("setb","%s",AOP(result)->aopu.aop_dir);
3986                     else if(ifx)
3987                         continueIfTrue(ifx);
3988                     goto release;
3989                 }
3990                 emitcode("setb","c");
3991             } else {
3992                 // lit == 0 => result = left
3993                 if(size && sameRegs(AOP(result),AOP(left)))
3994                     goto release;
3995                 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3996             }
3997         } else {
3998             if (AOP_TYPE(right) == AOP_CRY){
3999                 // c = bit | bit;
4000                 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4001                 emitcode("orl","c,%s",AOP(left)->aopu.aop_dir);
4002             }
4003             else{
4004                 // c = bit | val;
4005                 symbol *tlbl = newiTempLabel(NULL);
4006                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
4007                     emitcode("setb","c");
4008                 emitcode("jb","%s,%05d$",
4009                          AOP(left)->aopu.aop_dir,tlbl->key+100);
4010                 toBoolean(right);
4011                 emitcode("jnz","%05d$",tlbl->key+100);
4012                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4013                     jmpTrueOrFalse(ifx, tlbl);
4014                     goto release;
4015                 } else {
4016                     CLRC;
4017                     emitcode("","%05d$:",tlbl->key+100);
4018                 }
4019             }
4020         }
4021         // bit = c
4022         // val = c
4023         if(size)
4024             outBitC(result);
4025         // if(bit | ...)
4026         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4027             genIfxJump(ifx, "c");           
4028         goto release ;
4029     }
4030
4031     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
4032     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
4033     if((AOP_TYPE(right) == AOP_LIT) &&
4034        (AOP_TYPE(result) == AOP_CRY) &&
4035        (AOP_TYPE(left) != AOP_CRY)){
4036         if(lit){
4037             // result = 1
4038             if(size)
4039                 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4040             else 
4041                 continueIfTrue(ifx);
4042             goto release;
4043         } else {
4044             // lit = 0, result = boolean(left)
4045             if(size)
4046                 emitcode("setb","c");
4047             toBoolean(right);
4048             if(size){
4049                 symbol *tlbl = newiTempLabel(NULL);
4050                 emitcode("jnz","%05d$",tlbl->key+100);
4051                 CLRC;
4052                 emitcode("","%05d$:",tlbl->key+100);
4053             } else {
4054                 genIfxJump (ifx,"a");
4055                 goto release;
4056             }
4057         }
4058         outBitC(result);
4059         goto release ;
4060     }
4061
4062     /* if left is same as result */
4063     if(sameRegs(AOP(result),AOP(left))){
4064         for(;size--; offset++) {
4065             if(AOP_TYPE(right) == AOP_LIT){
4066                 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4067                     continue;
4068                 else 
4069                     if (IS_AOP_PREG(left)) {
4070                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4071                         emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4072                         aopPut(AOP(result),"a",offset);
4073                     } else
4074                         emitcode("orl","%s,%s",
4075                                  aopGet(AOP(left),offset,FALSE,TRUE),
4076                                  aopGet(AOP(right),offset,FALSE,FALSE));
4077             } else {
4078                 if (AOP_TYPE(left) == AOP_ACC) 
4079                     emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4080                 else {              
4081                     MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4082                     if (IS_AOP_PREG(left)) {
4083                         emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4084                         aopPut(AOP(result),"a",offset);
4085                     } else
4086                         emitcode("orl","%s,a",
4087                                  aopGet(AOP(left),offset,FALSE,TRUE));
4088                 }
4089             }
4090         }
4091     } else {
4092         // left & result in different registers
4093         if(AOP_TYPE(result) == AOP_CRY){
4094             // result = bit
4095             // if(size), result in bit
4096             // if(!size && ifx), conditional oper: if(left | right)
4097             symbol *tlbl = newiTempLabel(NULL);
4098             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4099             if(size)
4100                 emitcode("setb","c");
4101             while(sizer--){
4102                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4103                 emitcode("orl","a,%s",
4104                          aopGet(AOP(left),offset,FALSE,FALSE));
4105                 emitcode("jnz","%05d$",tlbl->key+100);
4106                 offset++;
4107             }
4108             if(size){
4109                 CLRC;
4110                 emitcode("","%05d$:",tlbl->key+100);
4111                 outBitC(result);
4112             } else if(ifx)
4113                 jmpTrueOrFalse(ifx, tlbl);
4114         } else for(;(size--);offset++){
4115             // normal case
4116             // result = left & right
4117             if(AOP_TYPE(right) == AOP_LIT){
4118                 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4119                     aopPut(AOP(result),
4120                            aopGet(AOP(left),offset,FALSE,FALSE),
4121                            offset);
4122                     continue;
4123                 }
4124             }
4125             // faster than result <- left, anl result,right
4126             // and better if result is SFR
4127             if (AOP_TYPE(left) == AOP_ACC) 
4128                 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4129             else {
4130                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4131                 emitcode("orl","a,%s",
4132                          aopGet(AOP(left),offset,FALSE,FALSE));
4133             }
4134             aopPut(AOP(result),"a",offset);                     
4135         }
4136     }
4137
4138 release :
4139     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4140     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4141     freeAsmop(result,NULL,ic,TRUE);     
4142 }
4143
4144 /*-----------------------------------------------------------------*/
4145 /* genXor - code for xclusive or                                   */
4146 /*-----------------------------------------------------------------*/
4147 static void genXor (iCode *ic, iCode *ifx)
4148 {
4149     operand *left, *right, *result;
4150     int size, offset=0;
4151     unsigned long lit = 0L;
4152
4153     aopOp((left = IC_LEFT(ic)),ic,FALSE);
4154     aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4155     aopOp((result=IC_RESULT(ic)),ic,TRUE);
4156
4157 #ifdef DEBUG_TYPE
4158     emitcode("","; Type res[%d] = l[%d]&r[%d]",
4159              AOP_TYPE(result),
4160              AOP_TYPE(left), AOP_TYPE(right));
4161     emitcode("","; Size res[%d] = l[%d]&r[%d]",
4162              AOP_SIZE(result),
4163              AOP_SIZE(left), AOP_SIZE(right));
4164 #endif
4165
4166     /* if left is a literal & right is not ||
4167        if left needs acc & right does not */
4168     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4169         (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
4170         operand *tmp = right ;
4171         right = left;
4172         left = tmp;
4173     }
4174
4175     /* if result = right then exchange them */
4176     if(sameRegs(AOP(result),AOP(right))){
4177         operand *tmp = right ;
4178         right = left;
4179         left = tmp;
4180     }
4181
4182     /* if right is bit then exchange them */
4183     if (AOP_TYPE(right) == AOP_CRY &&
4184         AOP_TYPE(left) != AOP_CRY){
4185         operand *tmp = right ;
4186         right = left;
4187         left = tmp;
4188     }
4189     if(AOP_TYPE(right) == AOP_LIT)
4190         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4191
4192     size = AOP_SIZE(result);
4193
4194     // if(bit ^ yy)
4195     // xx = bit ^ yy;
4196     if (AOP_TYPE(left) == AOP_CRY){
4197         if(AOP_TYPE(right) == AOP_LIT){
4198             // c = bit & literal;
4199             if(lit>>1){
4200                 // lit>>1  != 0 => result = 1
4201                 if(AOP_TYPE(result) == AOP_CRY){
4202                     if(size)
4203                         emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4204                     else if(ifx)
4205                         continueIfTrue(ifx);
4206                     goto release;
4207                 }
4208                 emitcode("setb","c");
4209             } else{
4210                 // lit == (0 or 1)
4211                 if(lit == 0){
4212                     // lit == 0, result = left
4213                     if(size && sameRegs(AOP(result),AOP(left)))
4214                         goto release;
4215                     emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4216                 } else{
4217                     // lit == 1, result = not(left)
4218                     if(size && sameRegs(AOP(result),AOP(left))){
4219                         emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
4220                         goto release;
4221                     } else {
4222                         emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4223                         emitcode("cpl","c");
4224                     }
4225                 }
4226             }
4227
4228         } else {
4229             // right != literal
4230             symbol *tlbl = newiTempLabel(NULL);
4231             if (AOP_TYPE(right) == AOP_CRY){
4232                 // c = bit ^ bit;
4233                 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4234             }
4235             else{
4236                 int sizer = AOP_SIZE(right);
4237                 // c = bit ^ val
4238                 // if val>>1 != 0, result = 1
4239                 emitcode("setb","c");
4240                 while(sizer){
4241                     MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
4242                     if(sizer == 1)
4243                         // test the msb of the lsb
4244                         emitcode("anl","a,#0xfe");
4245                     emitcode("jnz","%05d$",tlbl->key+100);
4246                     sizer--;
4247                 }
4248                 // val = (0,1)
4249                 emitcode("rrc","a");
4250             }
4251             emitcode("jnb","%s,%05d$",AOP(left)->aopu.aop_dir,(tlbl->key+100));
4252             emitcode("cpl","c");
4253             emitcode("","%05d$:",(tlbl->key+100));
4254         }
4255         // bit = c
4256         // val = c
4257         if(size)
4258             outBitC(result);
4259         // if(bit | ...)
4260         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4261             genIfxJump(ifx, "c");           
4262         goto release ;
4263     }
4264
4265     if(sameRegs(AOP(result),AOP(left))){
4266         /* if left is same as result */
4267         for(;size--; offset++) {
4268             if(AOP_TYPE(right) == AOP_LIT){
4269                 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4270                     continue;
4271                 else
4272                     if (IS_AOP_PREG(left)) {
4273                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4274                         emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4275                         aopPut(AOP(result),"a",offset);
4276                     } else 
4277                         emitcode("xrl","%s,%s",
4278                                  aopGet(AOP(left),offset,FALSE,TRUE),
4279                                  aopGet(AOP(right),offset,FALSE,FALSE));
4280             } else {
4281                 if (AOP_TYPE(left) == AOP_ACC)
4282                     emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4283                 else {
4284                     MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4285                     if (IS_AOP_PREG(left)) {
4286                         emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4287                         aopPut(AOP(result),"a",offset);
4288                     } else
4289                         emitcode("xrl","%s,a",
4290                                  aopGet(AOP(left),offset,FALSE,TRUE));
4291                 }
4292             }
4293         }
4294     } else {
4295         // left & result in different registers
4296         if(AOP_TYPE(result) == AOP_CRY){
4297             // result = bit
4298             // if(size), result in bit
4299             // if(!size && ifx), conditional oper: if(left ^ right)
4300             symbol *tlbl = newiTempLabel(NULL);
4301             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4302             if(size)
4303                 emitcode("setb","c");
4304             while(sizer--){
4305                 if((AOP_TYPE(right) == AOP_LIT) &&
4306                    (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
4307                     MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
4308                 } else {
4309                     MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4310                     emitcode("xrl","a,%s",
4311                              aopGet(AOP(left),offset,FALSE,FALSE));
4312                 }
4313                 emitcode("jnz","%05d$",tlbl->key+100);
4314                 offset++;
4315             }
4316             if(size){
4317                 CLRC;
4318                 emitcode("","%05d$:",tlbl->key+100);
4319                 outBitC(result);
4320             } else if(ifx)
4321                 jmpTrueOrFalse(ifx, tlbl);
4322         } else for(;(size--);offset++){
4323             // normal case
4324             // result = left & right
4325             if(AOP_TYPE(right) == AOP_LIT){
4326                 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4327                     aopPut(AOP(result),
4328                            aopGet(AOP(left),offset,FALSE,FALSE),
4329                            offset);
4330                     continue;
4331                 }
4332             }
4333             // faster than result <- left, anl result,right
4334             // and better if result is SFR
4335             if (AOP_TYPE(left) == AOP_ACC)
4336                 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4337             else {
4338                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4339                 emitcode("xrl","a,%s",
4340                          aopGet(AOP(left),offset,FALSE,TRUE));
4341             }
4342             aopPut(AOP(result),"a",offset);
4343         }
4344     }
4345
4346 release :
4347     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4348     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4349     freeAsmop(result,NULL,ic,TRUE);     
4350 }
4351
4352 /*-----------------------------------------------------------------*/
4353 /* genInline - write the inline code out                           */
4354 /*-----------------------------------------------------------------*/
4355 static void genInline (iCode *ic)
4356 {
4357     char buffer[MAX_INLINEASM];
4358     char *bp = buffer;
4359     char *bp1= buffer;
4360     
4361     _G.inLine += (!options.asmpeep);
4362     strcpy(buffer,IC_INLINE(ic));
4363
4364     /* emit each line as a code */
4365     while (*bp) {
4366         if (*bp == '\n') {
4367             *bp++ = '\0';
4368             emitcode(bp1,"");
4369             bp1 = bp;
4370         } else {
4371             if (*bp == ':') {
4372                 bp++;
4373                 *bp = '\0';
4374                 bp++;
4375                 emitcode(bp1,"");
4376                 bp1 = bp;
4377             } else
4378                 bp++;
4379         }
4380     }
4381     if (bp1 != bp)
4382         emitcode(bp1,"");
4383     /*     emitcode("",buffer); */
4384     _G.inLine -= (!options.asmpeep);
4385 }
4386
4387 /*-----------------------------------------------------------------*/
4388 /* genRRC - rotate right with carry                                */
4389 /*-----------------------------------------------------------------*/
4390 static void genRRC (iCode *ic)
4391 {
4392     operand *left , *result ;
4393     int size, offset = 0;
4394     char *l;    
4395
4396     /* rotate right with carry */
4397     left = IC_LEFT(ic);
4398     result=IC_RESULT(ic);
4399     aopOp (left,ic,FALSE);
4400     aopOp (result,ic,FALSE);
4401
4402     /* move it to the result */
4403     size = AOP_SIZE(result);    
4404     offset = size - 1 ;
4405     CLRC;
4406     while (size--) {
4407         l = aopGet(AOP(left),offset,FALSE,FALSE);
4408         MOVA(l);
4409         emitcode("rrc","a");
4410         if (AOP_SIZE(result) > 1)
4411             aopPut(AOP(result),"a",offset--);
4412     }
4413     /* now we need to put the carry into the
4414     highest order byte of the result */
4415     if (AOP_SIZE(result) > 1) {
4416         l = aopGet(AOP(result),AOP_SIZE(result)-1,FALSE,FALSE);
4417         MOVA(l);
4418     }
4419     emitcode("mov","acc.7,c");
4420     aopPut(AOP(result),"a",AOP_SIZE(result)-1);
4421     freeAsmop(left,NULL,ic,TRUE);
4422     freeAsmop(result,NULL,ic,TRUE);
4423 }
4424
4425 /*-----------------------------------------------------------------*/
4426 /* genRLC - generate code for rotate left with carry               */
4427 /*-----------------------------------------------------------------*/
4428 static void genRLC (iCode *ic)
4429 {    
4430     operand *left , *result ;
4431     int size, offset = 0;
4432     char *l;    
4433
4434     /* rotate right with carry */
4435     left = IC_LEFT(ic);
4436     result=IC_RESULT(ic);
4437     aopOp (left,ic,FALSE);
4438     aopOp (result,ic,FALSE);
4439
4440     /* move it to the result */
4441     size = AOP_SIZE(result);    
4442     offset = 0 ;
4443     if (size--) {
4444         l = aopGet(AOP(left),offset,FALSE,FALSE);
4445         MOVA(l);
4446         emitcode("add","a,acc");
4447         if (AOP_SIZE(result) > 1)
4448             aopPut(AOP(result),"a",offset++);
4449         while (size--) {
4450             l = aopGet(AOP(left),offset,FALSE,FALSE);
4451             MOVA(l);
4452             emitcode("rlc","a");
4453             if (AOP_SIZE(result) > 1)
4454                 aopPut(AOP(result),"a",offset++);
4455         }
4456     }
4457     /* now we need to put the carry into the
4458     highest order byte of the result */
4459     if (AOP_SIZE(result) > 1) {
4460         l = aopGet(AOP(result),0,FALSE,FALSE);
4461         MOVA(l);
4462     }
4463     emitcode("mov","acc.0,c");
4464     aopPut(AOP(result),"a",0);
4465     freeAsmop(left,NULL,ic,TRUE);
4466     freeAsmop(result,NULL,ic,TRUE);
4467 }
4468
4469 /*-----------------------------------------------------------------*/
4470 /* genGetHbit - generates code get highest order bit               */
4471 /*-----------------------------------------------------------------*/
4472 static void genGetHbit (iCode *ic)
4473 {
4474     operand *left, *result;
4475     left = IC_LEFT(ic);
4476     result=IC_RESULT(ic);
4477     aopOp (left,ic,FALSE);
4478     aopOp (result,ic,FALSE);
4479
4480     /* get the highest order byte into a */
4481     MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
4482     if(AOP_TYPE(result) == AOP_CRY){
4483         emitcode("rlc","a");
4484         outBitC(result);
4485     }
4486     else{
4487         emitcode("rl","a");
4488         emitcode("anl","a,#0x01");
4489         outAcc(result);
4490     }
4491
4492
4493     freeAsmop(left,NULL,ic,TRUE);
4494     freeAsmop(result,NULL,ic,TRUE);
4495 }
4496
4497 /*-----------------------------------------------------------------*/
4498 /* AccRol - rotate left accumulator by known count                 */
4499 /*-----------------------------------------------------------------*/
4500 static void AccRol (int shCount)
4501 {
4502     shCount &= 0x0007;              // shCount : 0..7
4503     switch(shCount){
4504         case 0 :
4505             break;
4506         case 1 :
4507             emitcode("rl","a");
4508             break;
4509         case 2 :
4510             emitcode("rl","a");
4511             emitcode("rl","a");
4512             break;
4513         case 3 :
4514             emitcode("swap","a");
4515             emitcode("rr","a");
4516             break;
4517         case 4 :
4518             emitcode("swap","a");
4519             break;
4520         case 5 :
4521             emitcode("swap","a");
4522             emitcode("rl","a");
4523             break;
4524         case 6 :
4525             emitcode("rr","a");
4526             emitcode("rr","a");
4527             break;
4528         case 7 :
4529             emitcode("rr","a");
4530             break;
4531     }
4532 }
4533
4534 /*-----------------------------------------------------------------*/
4535 /* AccLsh - left shift accumulator by known count                  */
4536 /*-----------------------------------------------------------------*/
4537 static void AccLsh (int shCount)
4538 {
4539     if(shCount != 0){
4540         if(shCount == 1)
4541             emitcode("add","a,acc");
4542         else 
4543             if(shCount == 2) {
4544             emitcode("add","a,acc");
4545             emitcode("add","a,acc");
4546         } else {
4547             /* rotate left accumulator */
4548             AccRol(shCount);
4549             /* and kill the lower order bits */
4550             emitcode("anl","a,#0x%02x", SLMask[shCount]);
4551         }
4552     }
4553 }
4554
4555 /*-----------------------------------------------------------------*/
4556 /* AccRsh - right shift accumulator by known count                 */
4557 /*-----------------------------------------------------------------*/
4558 static void AccRsh (int shCount)
4559 {
4560     if(shCount != 0){
4561         if(shCount == 1){
4562             CLRC;
4563             emitcode("rrc","a");
4564         } else {
4565             /* rotate right accumulator */
4566             AccRol(8 - shCount);
4567             /* and kill the higher order bits */
4568             emitcode("anl","a,#0x%02x", SRMask[shCount]);
4569         }
4570     }
4571 }
4572
4573 /*-----------------------------------------------------------------*/
4574 /* AccSRsh - signed right shift accumulator by known count                 */
4575 /*-----------------------------------------------------------------*/
4576 static void AccSRsh (int shCount)
4577 {
4578     symbol *tlbl ;
4579     if(shCount != 0){
4580         if(shCount == 1){
4581             emitcode("mov","c,acc.7");
4582             emitcode("rrc","a");
4583         } else if(shCount == 2){
4584             emitcode("mov","c,acc.7");
4585             emitcode("rrc","a");
4586             emitcode("mov","c,acc.7");
4587             emitcode("rrc","a");
4588         } else {
4589             tlbl = newiTempLabel(NULL);
4590             /* rotate right accumulator */
4591             AccRol(8 - shCount);
4592             /* and kill the higher order bits */
4593             emitcode("anl","a,#0x%02x", SRMask[shCount]);
4594             emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
4595             emitcode("orl","a,#0x%02x",
4596                      (unsigned char)~SRMask[shCount]);
4597             emitcode("","%05d$:",tlbl->key+100);
4598         }
4599     }
4600 }
4601
4602 /*-----------------------------------------------------------------*/
4603 /* shiftR1Left2Result - shift right one byte from left to result   */
4604 /*-----------------------------------------------------------------*/
4605 static void shiftR1Left2Result (operand *left, int offl,
4606                                 operand *result, int offr,
4607                                 int shCount, int sign)
4608 {
4609     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
4610     /* shift right accumulator */
4611     if(sign)
4612         AccSRsh(shCount);
4613     else
4614         AccRsh(shCount);
4615     aopPut(AOP(result),"a",offr);
4616 }
4617
4618 /*-----------------------------------------------------------------*/
4619 /* shiftL1Left2Result - shift left one byte from left to result    */
4620 /*-----------------------------------------------------------------*/
4621 static void shiftL1Left2Result (operand *left, int offl,
4622                                 operand *result, int offr, int shCount)
4623 {
4624     char *l;
4625     l = aopGet(AOP(left),offl,FALSE,FALSE);
4626     MOVA(l);
4627     /* shift left accumulator */
4628     AccLsh(shCount);
4629     aopPut(AOP(result),"a",offr);
4630 }
4631
4632 /*-----------------------------------------------------------------*/
4633 /* movLeft2Result - move byte from left to result                  */
4634 /*-----------------------------------------------------------------*/
4635 static void movLeft2Result (operand *left, int offl,
4636                             operand *result, int offr, int sign)
4637 {
4638     char *l;
4639     if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
4640         l = aopGet(AOP(left),offl,FALSE,FALSE);
4641
4642         if (*l == '@' && (IS_AOP_PREG(result))) {
4643             emitcode("mov","a,%s",l);
4644             aopPut(AOP(result),"a",offr);
4645         } else {
4646             if(!sign)
4647                 aopPut(AOP(result),l,offr);
4648             else{
4649                 /* MSB sign in acc.7 ! */
4650                 if(getDataSize(left) == offl+1){
4651                     emitcode("mov","a,%s",l);
4652                     aopPut(AOP(result),"a",offr);
4653                 }
4654             }
4655         }
4656     }
4657 }
4658
4659 /*-----------------------------------------------------------------*/
4660 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
4661 /*-----------------------------------------------------------------*/
4662 static void AccAXRrl1 (char *x)
4663 {
4664     emitcode("rrc","a");
4665     emitcode("xch","a,%s", x);
4666     emitcode("rrc","a");
4667     emitcode("xch","a,%s", x);
4668 }
4669
4670 /*-----------------------------------------------------------------*/
4671 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
4672 /*-----------------------------------------------------------------*/
4673 static void AccAXLrl1 (char *x)
4674 {
4675     emitcode("xch","a,%s",x);
4676     emitcode("rlc","a");
4677     emitcode("xch","a,%s",x);
4678     emitcode("rlc","a");
4679 }
4680
4681 /*-----------------------------------------------------------------*/
4682 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
4683 /*-----------------------------------------------------------------*/
4684 static void AccAXLsh1 (char *x)
4685 {
4686     emitcode("xch","a,%s",x);
4687     emitcode("add","a,acc");
4688     emitcode("xch","a,%s",x);
4689     emitcode("rlc","a");
4690 }
4691
4692 /*-----------------------------------------------------------------*/
4693 /* AccAXLsh - left shift a:x by known count (0..7)                 */
4694 /*-----------------------------------------------------------------*/
4695 static void AccAXLsh (char *x, int shCount)
4696 {
4697     switch(shCount){
4698         case 0 :
4699             break;
4700         case 1 :
4701             AccAXLsh1(x);
4702             break;
4703         case 2 :
4704             AccAXLsh1(x);
4705             AccAXLsh1(x);
4706             break;
4707         case 3 :
4708         case 4 :
4709         case 5 :                        // AAAAABBB:CCCCCDDD
4710             AccRol(shCount);            // BBBAAAAA:CCCCCDDD
4711             emitcode("anl","a,#0x%02x",
4712                      SLMask[shCount]);  // BBB00000:CCCCCDDD
4713             emitcode("xch","a,%s",x);   // CCCCCDDD:BBB00000
4714             AccRol(shCount);            // DDDCCCCC:BBB00000
4715             emitcode("xch","a,%s",x);   // BBB00000:DDDCCCCC
4716             emitcode("xrl","a,%s",x);   // (BBB^DDD)CCCCC:DDDCCCCC
4717             emitcode("xch","a,%s",x);   // DDDCCCCC:(BBB^DDD)CCCCC
4718             emitcode("anl","a,#0x%02x",
4719                      SLMask[shCount]);  // DDD00000:(BBB^DDD)CCCCC
4720             emitcode("xch","a,%s",x);   // (BBB^DDD)CCCCC:DDD00000
4721             emitcode("xrl","a,%s",x);   // BBBCCCCC:DDD00000            
4722             break;
4723         case 6 :                        // AAAAAABB:CCCCCCDD
4724             emitcode("anl","a,#0x%02x",
4725                      SRMask[shCount]);  // 000000BB:CCCCCCDD
4726             emitcode("mov","c,acc.0");  // c = B
4727             emitcode("xch","a,%s",x);   // CCCCCCDD:000000BB
4728             AccAXRrl1(x);               // BCCCCCCD:D000000B
4729             AccAXRrl1(x);               // BBCCCCCC:DD000000
4730             break;
4731         case 7 :                        // a:x <<= 7
4732             emitcode("anl","a,#0x%02x",
4733                      SRMask[shCount]);  // 0000000B:CCCCCCCD
4734             emitcode("mov","c,acc.0");  // c = B
4735             emitcode("xch","a,%s",x);   // CCCCCCCD:0000000B
4736             AccAXRrl1(x);               // BCCCCCCC:D0000000
4737             break;
4738         default :
4739             break;
4740     }
4741 }
4742
4743 /*-----------------------------------------------------------------*/
4744 /* AccAXRsh - right shift a:x known count (0..7)                   */
4745 /*-----------------------------------------------------------------*/
4746 static void AccAXRsh (char *x, int shCount)
4747 {   
4748     switch(shCount){
4749         case 0 :
4750             break;
4751         case 1 :
4752             CLRC;
4753             AccAXRrl1(x);               // 0->a:x
4754             break;
4755         case 2 :
4756             CLRC;
4757             AccAXRrl1(x);               // 0->a:x
4758             CLRC;
4759             AccAXRrl1(x);               // 0->a:x
4760             break;
4761         case 3 :
4762         case 4 :
4763         case 5 :                        // AAAAABBB:CCCCCDDD = a:x
4764             AccRol(8 - shCount);        // BBBAAAAA:DDDCCCCC
4765             emitcode("xch","a,%s",x);   // CCCCCDDD:BBBAAAAA
4766             AccRol(8 - shCount);        // DDDCCCCC:BBBAAAAA
4767             emitcode("anl","a,#0x%02x",
4768                      SRMask[shCount]);  // 000CCCCC:BBBAAAAA
4769             emitcode("xrl","a,%s",x);   // BBB(CCCCC^AAAAA):BBBAAAAA
4770             emitcode("xch","a,%s",x);   // BBBAAAAA:BBB(CCCCC^AAAAA)
4771             emitcode("anl","a,#0x%02x",
4772                      SRMask[shCount]);  // 000AAAAA:BBB(CCCCC^AAAAA)
4773             emitcode("xch","a,%s",x);   // BBB(CCCCC^AAAAA):000AAAAA
4774             emitcode("xrl","a,%s",x);   // BBBCCCCC:000AAAAA
4775             emitcode("xch","a,%s",x);   // 000AAAAA:BBBCCCCC
4776             break;
4777         case 6 :                        // AABBBBBB:CCDDDDDD
4778             emitcode("mov","c,acc.7");
4779             AccAXLrl1(x);               // ABBBBBBC:CDDDDDDA
4780             AccAXLrl1(x);               // BBBBBBCC:DDDDDDAA
4781             emitcode("xch","a,%s",x);   // DDDDDDAA:BBBBBBCC
4782             emitcode("anl","a,#0x%02x",
4783                      SRMask[shCount]);  // 000000AA:BBBBBBCC
4784             break;
4785         case 7 :                        // ABBBBBBB:CDDDDDDD
4786             emitcode("mov","c,acc.7");  // c = A
4787             AccAXLrl1(x);               // BBBBBBBC:DDDDDDDA
4788             emitcode("xch","a,%s",x);   // DDDDDDDA:BBBBBBCC
4789             emitcode("anl","a,#0x%02x",
4790                      SRMask[shCount]);  // 0000000A:BBBBBBBC
4791             break;
4792         default :
4793             break;
4794     }
4795 }
4796
4797 /*-----------------------------------------------------------------*/
4798 /* AccAXRshS - right shift signed a:x known count (0..7)           */
4799 /*-----------------------------------------------------------------*/
4800 static void AccAXRshS (char *x, int shCount)
4801 {   
4802     symbol *tlbl ;
4803     switch(shCount){
4804         case 0 :
4805             break;
4806         case 1 :
4807             emitcode("mov","c,acc.7");
4808             AccAXRrl1(x);               // s->a:x
4809             break;
4810         case 2 :
4811             emitcode("mov","c,acc.7");
4812             AccAXRrl1(x);               // s->a:x
4813             emitcode("mov","c,acc.7");
4814             AccAXRrl1(x);               // s->a:x
4815             break;
4816         case 3 :
4817         case 4 :
4818         case 5 :                        // AAAAABBB:CCCCCDDD = a:x
4819             tlbl = newiTempLabel(NULL);
4820             AccRol(8 - shCount);        // BBBAAAAA:CCCCCDDD
4821             emitcode("xch","a,%s",x);   // CCCCCDDD:BBBAAAAA
4822             AccRol(8 - shCount);        // DDDCCCCC:BBBAAAAA
4823             emitcode("anl","a,#0x%02x",
4824                      SRMask[shCount]);  // 000CCCCC:BBBAAAAA
4825             emitcode("xrl","a,%s",x);   // BBB(CCCCC^AAAAA):BBBAAAAA
4826             emitcode("xch","a,%s",x);   // BBBAAAAA:BBB(CCCCC^AAAAA)
4827             emitcode("anl","a,#0x%02x",
4828                      SRMask[shCount]);  // 000AAAAA:BBB(CCCCC^AAAAA)
4829             emitcode("xch","a,%s",x);   // BBB(CCCCC^AAAAA):000AAAAA
4830             emitcode("xrl","a,%s",x);   // BBBCCCCC:000AAAAA
4831             emitcode("xch","a,%s",x);   // 000SAAAA:BBBCCCCC
4832             emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100); 
4833             emitcode("orl","a,#0x%02x",
4834                      (unsigned char)~SRMask[shCount]);  // 111AAAAA:BBBCCCCC
4835             emitcode("","%05d$:",tlbl->key+100);
4836             break;                      // SSSSAAAA:BBBCCCCC
4837         case 6 :                        // AABBBBBB:CCDDDDDD
4838             tlbl = newiTempLabel(NULL);
4839             emitcode("mov","c,acc.7");
4840             AccAXLrl1(x);               // ABBBBBBC:CDDDDDDA
4841             AccAXLrl1(x);               // BBBBBBCC:DDDDDDAA
4842             emitcode("xch","a,%s",x);   // DDDDDDAA:BBBBBBCC
4843             emitcode("anl","a,#0x%02x",
4844                      SRMask[shCount]);  // 000000AA:BBBBBBCC
4845             emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100); 
4846             emitcode("orl","a,#0x%02x",
4847                      (unsigned char)~SRMask[shCount]);  // 111111AA:BBBBBBCC
4848             emitcode("","%05d$:",tlbl->key+100);
4849             break;
4850         case 7 :                        // ABBBBBBB:CDDDDDDD
4851             tlbl = newiTempLabel(NULL);
4852             emitcode("mov","c,acc.7");  // c = A
4853             AccAXLrl1(x);               // BBBBBBBC:DDDDDDDA
4854             emitcode("xch","a,%s",x);   // DDDDDDDA:BBBBBBCC
4855             emitcode("anl","a,#0x%02x",
4856                      SRMask[shCount]);  // 0000000A:BBBBBBBC
4857             emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100); 
4858             emitcode("orl","a,#0x%02x",
4859                      (unsigned char)~SRMask[shCount]);  // 1111111A:BBBBBBBC
4860             emitcode("","%05d$:",tlbl->key+100);
4861             break;
4862         default :
4863             break;
4864     }
4865 }
4866
4867 /*-----------------------------------------------------------------*/
4868 /* shiftL2Left2Result - shift left two bytes from left to result   */
4869 /*-----------------------------------------------------------------*/
4870 static void shiftL2Left2Result (operand *left, int offl,
4871                                 operand *result, int offr, int shCount)
4872 {
4873     if(sameRegs(AOP(result), AOP(left)) &&
4874        ((offl + MSB16) == offr)){
4875         /* don't crash result[offr] */
4876         MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
4877         emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
4878     } else {
4879         movLeft2Result(left,offl, result, offr, 0);
4880         MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
4881     }
4882     /* ax << shCount (x = lsb(result))*/
4883     AccAXLsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
4884     aopPut(AOP(result),"a",offr+MSB16);
4885 }
4886
4887
4888 /*-----------------------------------------------------------------*/
4889 /* shiftR2Left2Result - shift right two bytes from left to result  */
4890 /*-----------------------------------------------------------------*/
4891 static void shiftR2Left2Result (operand *left, int offl,
4892                                 operand *result, int offr,
4893                                 int shCount, int sign)
4894 {
4895     if(sameRegs(AOP(result), AOP(left)) &&
4896        ((offl + MSB16) == offr)){
4897         /* don't crash result[offr] */
4898         MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
4899         emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
4900     } else {
4901         movLeft2Result(left,offl, result, offr, 0);
4902         MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
4903     }
4904     /* a:x >> shCount (x = lsb(result))*/
4905     if(sign)
4906         AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
4907     else
4908         AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
4909     if(getDataSize(result) > 1)
4910         aopPut(AOP(result),"a",offr+MSB16);
4911 }
4912
4913 /*-----------------------------------------------------------------*/
4914 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
4915 /*-----------------------------------------------------------------*/
4916 static void shiftLLeftOrResult (operand *left, int offl,
4917                                 operand *result, int offr, int shCount)
4918 {
4919     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
4920     /* shift left accumulator */
4921     AccLsh(shCount);
4922     /* or with result */
4923     emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
4924     /* back to result */
4925     aopPut(AOP(result),"a",offr);
4926 }
4927
4928 /*-----------------------------------------------------------------*/
4929 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
4930 /*-----------------------------------------------------------------*/
4931 static void shiftRLeftOrResult (operand *left, int offl,
4932                                 operand *result, int offr, int shCount)
4933 {
4934     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
4935     /* shift right accumulator */
4936     AccRsh(shCount);
4937     /* or with result */
4938     emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
4939     /* back to result */
4940     aopPut(AOP(result),"a",offr);
4941 }
4942
4943 /*-----------------------------------------------------------------*/
4944 /* genlshOne - left shift a one byte quantity by known count       */
4945 /*-----------------------------------------------------------------*/
4946 static void genlshOne (operand *result, operand *left, int shCount)
4947 {       
4948     shiftL1Left2Result(left, LSB, result, LSB, shCount);
4949 }
4950
4951 /*-----------------------------------------------------------------*/
4952 /* genlshTwo - left shift two bytes by known amount != 0           */
4953 /*-----------------------------------------------------------------*/
4954 static void genlshTwo (operand *result,operand *left, int shCount)
4955 {
4956     int size;
4957     
4958     size = getDataSize(result);
4959
4960     /* if shCount >= 8 */
4961     if (shCount >= 8) {
4962         shCount -= 8 ;
4963
4964         if (size > 1){
4965             if (shCount)
4966                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
4967             else 
4968                 movLeft2Result(left, LSB, result, MSB16, 0);
4969         }
4970         aopPut(AOP(result),zero,LSB);   
4971     }
4972
4973     /*  1 <= shCount <= 7 */
4974     else {  
4975         if(size == 1)
4976             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
4977         else 
4978             shiftL2Left2Result(left, LSB, result, LSB, shCount);
4979     }
4980 }
4981
4982 /*-----------------------------------------------------------------*/
4983 /* shiftLLong - shift left one long from left to result            */
4984 /* offl = LSB or MSB16                                             */
4985 /*-----------------------------------------------------------------*/
4986 static void shiftLLong (operand *left, operand *result, int offr )
4987 {
4988     char *l;
4989     int size = AOP_SIZE(result);
4990
4991     if(size >= LSB+offr){
4992         l = aopGet(AOP(left),LSB,FALSE,FALSE);
4993         MOVA(l);
4994         emitcode("add","a,acc");
4995         if (sameRegs(AOP(left),AOP(result)) && 
4996             size >= MSB16+offr && offr != LSB )
4997             emitcode("xch","a,%s",
4998                      aopGet(AOP(left),LSB+offr,FALSE,FALSE));
4999         else        
5000             aopPut(AOP(result),"a",LSB+offr);
5001     }
5002
5003     if(size >= MSB16+offr){
5004         if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
5005             l = aopGet(AOP(left),MSB16,FALSE,FALSE);
5006             MOVA(l);
5007         }
5008         emitcode("rlc","a");
5009         if (sameRegs(AOP(left),AOP(result)) && 
5010             size >= MSB24+offr && offr != LSB)
5011             emitcode("xch","a,%s",
5012                      aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
5013         else        
5014             aopPut(AOP(result),"a",MSB16+offr);
5015     }
5016
5017     if(size >= MSB24+offr){
5018         if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
5019             l = aopGet(AOP(left),MSB24,FALSE,FALSE);
5020             MOVA(l);
5021         }
5022         emitcode("rlc","a");
5023         if (sameRegs(AOP(left),AOP(result)) && 
5024             size >= MSB32+offr && offr != LSB )
5025             emitcode("xch","a,%s",
5026                      aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
5027         else        
5028             aopPut(AOP(result),"a",MSB24+offr);
5029     }
5030
5031     if(size > MSB32+offr){
5032         if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
5033             l = aopGet(AOP(left),MSB32,FALSE,FALSE);
5034             MOVA(l);    
5035         }
5036         emitcode("rlc","a");
5037         aopPut(AOP(result),"a",MSB32+offr);
5038     }
5039     if(offr != LSB)
5040         aopPut(AOP(result),zero,LSB);       
5041 }
5042
5043 /*-----------------------------------------------------------------*/
5044 /* genlshFour - shift four byte by a known amount != 0             */
5045 /*-----------------------------------------------------------------*/
5046 static void genlshFour (operand *result, operand *left, int shCount)
5047 {
5048     int size;
5049
5050     size = AOP_SIZE(result);
5051
5052     /* if shifting more that 3 bytes */
5053     if (shCount >= 24 ) {
5054         shCount -= 24;
5055         if (shCount)
5056             /* lowest order of left goes to the highest
5057             order of the destination */
5058             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
5059         else
5060             movLeft2Result(left, LSB, result, MSB32, 0);
5061         aopPut(AOP(result),zero,LSB);
5062         aopPut(AOP(result),zero,MSB16);
5063         aopPut(AOP(result),zero,MSB32);
5064         return;
5065     }
5066
5067     /* more than two bytes */
5068     else if ( shCount >= 16 ) {
5069         /* lower order two bytes goes to higher order two bytes */
5070         shCount -= 16;
5071         /* if some more remaining */
5072         if (shCount)
5073             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
5074         else {
5075             movLeft2Result(left, MSB16, result, MSB32, 0);
5076             movLeft2Result(left, LSB, result, MSB24, 0);
5077         }
5078         aopPut(AOP(result),zero,MSB16);
5079         aopPut(AOP(result),zero,LSB);
5080         return;
5081     }    
5082
5083     /* if more than 1 byte */
5084     else if ( shCount >= 8 ) {
5085         /* lower order three bytes goes to higher order  three bytes */
5086         shCount -= 8;
5087         if(size == 2){
5088             if(shCount)
5089                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5090             else
5091                 movLeft2Result(left, LSB, result, MSB16, 0);
5092         }
5093         else{   /* size = 4 */
5094             if(shCount == 0){
5095                 movLeft2Result(left, MSB24, result, MSB32, 0);
5096                 movLeft2Result(left, MSB16, result, MSB24, 0);
5097                 movLeft2Result(left, LSB, result, MSB16, 0);
5098                 aopPut(AOP(result),zero,LSB);
5099             }
5100             else if(shCount == 1)
5101                 shiftLLong(left, result, MSB16);
5102             else{
5103                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
5104                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5105                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
5106                 aopPut(AOP(result),zero,LSB);
5107             }
5108         }
5109     }
5110
5111     /* 1 <= shCount <= 7 */
5112     else if(shCount <= 2){
5113         shiftLLong(left, result, LSB);
5114         if(shCount == 2)
5115             shiftLLong(result, result, LSB);
5116     }
5117     /* 3 <= shCount <= 7, optimize */
5118     else{
5119         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
5120         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
5121         shiftL2Left2Result(left, LSB, result, LSB, shCount);
5122     }
5123 }
5124
5125 /*-----------------------------------------------------------------*/
5126 /* genLeftShiftLiteral - left shifting by known count              */
5127 /*-----------------------------------------------------------------*/
5128 static void genLeftShiftLiteral (operand *left,
5129                                  operand *right,
5130                                  operand *result,
5131                                  iCode *ic)
5132 {    
5133     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
5134     int size;
5135
5136     freeAsmop(right,NULL,ic,TRUE);
5137
5138     aopOp(left,ic,FALSE);
5139     aopOp(result,ic,FALSE);
5140
5141     size = getSize(operandType(result));
5142
5143 #if VIEW_SIZE
5144     emitcode("; shift left ","result %d, left %d",size,
5145              AOP_SIZE(left));
5146 #endif
5147
5148     /* I suppose that the left size >= result size */
5149     if(shCount == 0){
5150         while(size--){
5151             movLeft2Result(left, size, result, size, 0);
5152         }
5153     }
5154
5155     else if(shCount >= (size * 8))
5156         while(size--)
5157             aopPut(AOP(result),zero,size);
5158     else{
5159         switch (size) {
5160             case 1:
5161                 genlshOne (result,left,shCount);
5162                 break;
5163
5164             case 2:
5165             case 3:
5166                 genlshTwo (result,left,shCount);
5167                 break;
5168
5169             case 4:
5170                 genlshFour (result,left,shCount);
5171                 break;
5172         }
5173     }
5174     freeAsmop(left,NULL,ic,TRUE);
5175     freeAsmop(result,NULL,ic,TRUE);
5176 }
5177
5178 /*-----------------------------------------------------------------*/
5179 /* genLeftShift - generates code for left shifting                 */
5180 /*-----------------------------------------------------------------*/
5181 static void genLeftShift (iCode *ic)
5182 {
5183     operand *left,*right, *result;
5184     int size, offset;
5185     char *l;
5186     symbol *tlbl , *tlbl1;
5187
5188     right = IC_RIGHT(ic);
5189     left  = IC_LEFT(ic);
5190     result = IC_RESULT(ic);
5191
5192     aopOp(right,ic,FALSE);
5193
5194     /* if the shift count is known then do it 
5195     as efficiently as possible */
5196     if (AOP_TYPE(right) == AOP_LIT) {
5197         genLeftShiftLiteral (left,right,result,ic);
5198         return ;
5199     }
5200
5201     /* shift count is unknown then we have to form 
5202     a loop get the loop count in B : Note: we take
5203     only the lower order byte since shifting
5204     more that 32 bits make no sense anyway, ( the
5205     largest size of an object can be only 32 bits ) */  
5206
5207     emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
5208     emitcode("inc","b");
5209     freeAsmop (right,NULL,ic,TRUE);
5210     aopOp(left,ic,FALSE);
5211     aopOp(result,ic,FALSE);
5212
5213     /* now move the left to the result if they are not the
5214     same */
5215     if (!sameRegs(AOP(left),AOP(result)) && 
5216         AOP_SIZE(result) > 1) {
5217
5218         size = AOP_SIZE(result);
5219         offset=0;
5220         while (size--) {
5221             l = aopGet(AOP(left),offset,FALSE,TRUE);
5222             if (*l == '@' && (IS_AOP_PREG(result))) {
5223
5224                 emitcode("mov","a,%s",l);
5225                 aopPut(AOP(result),"a",offset);
5226             } else
5227                 aopPut(AOP(result),l,offset);
5228             offset++;
5229         }
5230     }
5231
5232     tlbl = newiTempLabel(NULL);
5233     size = AOP_SIZE(result);
5234     offset = 0 ;   
5235     tlbl1 = newiTempLabel(NULL);
5236
5237     /* if it is only one byte then */
5238     if (size == 1) {
5239         symbol *tlbl1 = newiTempLabel(NULL);
5240
5241         l = aopGet(AOP(left),0,FALSE,FALSE);
5242         MOVA(l);
5243         emitcode("sjmp","%05d$",tlbl1->key+100); 
5244         emitcode("","%05d$:",tlbl->key+100);
5245         emitcode("add","a,acc");
5246         emitcode("","%05d$:",tlbl1->key+100);
5247         emitcode("djnz","b,%05d$",tlbl->key+100);      
5248         aopPut(AOP(result),"a",0);
5249         goto release ;
5250     }
5251     
5252     reAdjustPreg(AOP(result));    
5253     
5254     emitcode("sjmp","%05d$",tlbl1->key+100); 
5255     emitcode("","%05d$:",tlbl->key+100);    
5256     l = aopGet(AOP(result),offset,FALSE,FALSE);
5257     MOVA(l);
5258     emitcode("add","a,acc");         
5259     aopPut(AOP(result),"a",offset++);
5260     while (--size) {
5261         l = aopGet(AOP(result),offset,FALSE,FALSE);
5262         MOVA(l);
5263         emitcode("rlc","a");         
5264         aopPut(AOP(result),"a",offset++);
5265     }
5266     reAdjustPreg(AOP(result));
5267
5268     emitcode("","%05d$:",tlbl1->key+100);
5269     emitcode("djnz","b,%05d$",tlbl->key+100);
5270 release:
5271     freeAsmop(left,NULL,ic,TRUE);
5272     freeAsmop(result,NULL,ic,TRUE);
5273 }
5274
5275 /*-----------------------------------------------------------------*/
5276 /* genrshOne - right shift a one byte quantity by known count      */
5277 /*-----------------------------------------------------------------*/
5278 static void genrshOne (operand *result, operand *left,
5279                        int shCount, int sign)
5280 {
5281     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
5282 }
5283
5284 /*-----------------------------------------------------------------*/
5285 /* genrshTwo - right shift two bytes by known amount != 0          */
5286 /*-----------------------------------------------------------------*/
5287 static void genrshTwo (operand *result,operand *left,
5288                        int shCount, int sign)
5289 {
5290     /* if shCount >= 8 */
5291     if (shCount >= 8) {
5292         shCount -= 8 ;
5293         if (shCount)
5294             shiftR1Left2Result(left, MSB16, result, LSB,
5295                                shCount, sign);
5296         else 
5297             movLeft2Result(left, MSB16, result, LSB, sign);
5298         addSign(result, MSB16, sign);
5299     }
5300
5301     /*  1 <= shCount <= 7 */
5302     else
5303         shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
5304 }
5305
5306 /*-----------------------------------------------------------------*/
5307 /* shiftRLong - shift right one long from left to result           */
5308 /* offl = LSB or MSB16                                             */
5309 /*-----------------------------------------------------------------*/
5310 static void shiftRLong (operand *left, int offl,
5311                         operand *result, int sign)
5312 {
5313     if(!sign)
5314         emitcode("clr","c");
5315     MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE));
5316     if(sign)
5317         emitcode("mov","c,acc.7");
5318     emitcode("rrc","a");
5319     aopPut(AOP(result),"a",MSB32-offl);
5320     if(offl == MSB16)
5321         /* add sign of "a" */
5322         addSign(result, MSB32, sign);
5323
5324     MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE));
5325     emitcode("rrc","a");
5326     aopPut(AOP(result),"a",MSB24-offl);
5327
5328     MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE));
5329     emitcode("rrc","a");
5330     aopPut(AOP(result),"a",MSB16-offl);
5331
5332     if(offl == LSB){
5333         MOVA(aopGet(AOP(left),LSB,FALSE,FALSE));
5334         emitcode("rrc","a");
5335         aopPut(AOP(result),"a",LSB);
5336     }
5337 }
5338
5339 /*-----------------------------------------------------------------*/
5340 /* genrshFour - shift four byte by a known amount != 0             */
5341 /*-----------------------------------------------------------------*/
5342 static void genrshFour (operand *result, operand *left,
5343                         int shCount, int sign)
5344 {
5345     /* if shifting more that 3 bytes */
5346     if(shCount >= 24 ) {
5347         shCount -= 24;
5348         if(shCount)
5349             shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
5350         else
5351             movLeft2Result(left, MSB32, result, LSB, sign);
5352         addSign(result, MSB16, sign);
5353     }
5354     else if(shCount >= 16){
5355         shCount -= 16;
5356         if(shCount)
5357             shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
5358         else{
5359             movLeft2Result(left, MSB24, result, LSB, 0);
5360             movLeft2Result(left, MSB32, result, MSB16, sign);
5361         }
5362         addSign(result, MSB24, sign);
5363     }
5364     else if(shCount >= 8){
5365         shCount -= 8;
5366         if(shCount == 1)
5367             shiftRLong(left, MSB16, result, sign);
5368         else if(shCount == 0){
5369             movLeft2Result(left, MSB16, result, LSB, 0);
5370             movLeft2Result(left, MSB24, result, MSB16, 0);
5371             movLeft2Result(left, MSB32, result, MSB24, sign);
5372             addSign(result, MSB32, sign);
5373         }
5374         else{
5375             shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
5376             shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
5377             /* the last shift is signed */
5378             shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
5379             addSign(result, MSB32, sign);
5380         }
5381     }
5382     else{   /* 1 <= shCount <= 7 */
5383         if(shCount <= 2){
5384             shiftRLong(left, LSB, result, sign);
5385             if(shCount == 2)
5386                 shiftRLong(result, LSB, result, sign);
5387         }
5388         else{
5389             shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
5390             shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
5391             shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
5392         }
5393     }
5394 }
5395
5396 /*-----------------------------------------------------------------*/
5397 /* genRightShiftLiteral - right shifting by known count            */
5398 /*-----------------------------------------------------------------*/
5399 static void genRightShiftLiteral (operand *left,
5400                                   operand *right,
5401                                   operand *result,
5402                                   iCode *ic,
5403                                   int sign)
5404 {    
5405     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
5406     int size;
5407
5408     freeAsmop(right,NULL,ic,TRUE);
5409
5410     aopOp(left,ic,FALSE);
5411     aopOp(result,ic,FALSE);
5412
5413 #if VIEW_SIZE
5414     emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
5415              AOP_SIZE(left));
5416 #endif
5417
5418     size = getDataSize(left);
5419     /* test the LEFT size !!! */
5420
5421     /* I suppose that the left size >= result size */
5422     if(shCount == 0){
5423         size = getDataSize(result);
5424         while(size--)
5425             movLeft2Result(left, size, result, size, 0);
5426     }
5427
5428     else if(shCount >= (size * 8)){
5429         if(sign)
5430             /* get sign in acc.7 */
5431             MOVA(aopGet(AOP(left),size-1,FALSE,FALSE));
5432         addSign(result, LSB, sign);
5433     } else{
5434         switch (size) {
5435             case 1:
5436                 genrshOne (result,left,shCount,sign);
5437                 break;
5438
5439             case 2:
5440                 genrshTwo (result,left,shCount,sign);
5441                 break;
5442
5443             case 4:
5444                 genrshFour (result,left,shCount,sign);
5445                 break;
5446             default :
5447                 break;
5448         }
5449
5450         freeAsmop(left,NULL,ic,TRUE);
5451         freeAsmop(result,NULL,ic,TRUE);
5452     }
5453 }
5454
5455 /*-----------------------------------------------------------------*/
5456 /* genSignedRightShift - right shift of signed number              */
5457 /*-----------------------------------------------------------------*/
5458 static void genSignedRightShift (iCode *ic)
5459 {
5460     operand *right, *left, *result;
5461     int size, offset;
5462     char *l;
5463     symbol *tlbl, *tlbl1 ;
5464
5465     /* we do it the hard way put the shift count in b
5466     and loop thru preserving the sign */
5467
5468     right = IC_RIGHT(ic);
5469     left  = IC_LEFT(ic);
5470     result = IC_RESULT(ic);
5471
5472     aopOp(right,ic,FALSE);  
5473
5474
5475     if ( AOP_TYPE(right) == AOP_LIT) {
5476         genRightShiftLiteral (left,right,result,ic,1);
5477         return ;
5478     }
5479         /* shift count is unknown then we have to form 
5480        a loop get the loop count in B : Note: we take
5481        only the lower order byte since shifting
5482        more that 32 bits make no sense anyway, ( the
5483        largest size of an object can be only 32 bits ) */  
5484
5485     emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
5486     emitcode("inc","b");
5487     freeAsmop (right,NULL,ic,TRUE);
5488     aopOp(left,ic,FALSE);
5489     aopOp(result,ic,FALSE);
5490
5491     /* now move the left to the result if they are not the
5492     same */
5493     if (!sameRegs(AOP(left),AOP(result)) && 
5494         AOP_SIZE(result) > 1) {
5495
5496         size = AOP_SIZE(result);
5497         offset=0;
5498         while (size--) {
5499             l = aopGet(AOP(left),offset,FALSE,TRUE);
5500             if (*l == '@' && IS_AOP_PREG(result)) {
5501
5502                 emitcode("mov","a,%s",l);
5503                 aopPut(AOP(result),"a",offset);
5504             } else
5505                 aopPut(AOP(result),l,offset);
5506             offset++;
5507         }
5508     }
5509
5510     /* mov the highest order bit to OVR */    
5511     tlbl = newiTempLabel(NULL);
5512     tlbl1= newiTempLabel(NULL);
5513
5514     size = AOP_SIZE(result);
5515     offset = size - 1;
5516     emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
5517     emitcode("rlc","a");
5518     emitcode("mov","ov,c");
5519     /* if it is only one byte then */
5520     if (size == 1) {
5521         l = aopGet(AOP(left),0,FALSE,FALSE);
5522         MOVA(l);
5523         emitcode("sjmp","%05d$",tlbl1->key+100);
5524         emitcode("","%05d$:",tlbl->key+100);
5525         emitcode("mov","c,ov");
5526         emitcode("rrc","a");
5527         emitcode("","%05d$:",tlbl1->key+100);
5528         emitcode("djnz","b,%05d$",tlbl->key+100);
5529         aopPut(AOP(result),"a",0);
5530         goto release ;
5531     }
5532
5533     reAdjustPreg(AOP(result));
5534     emitcode("sjmp","%05d$",tlbl1->key+100);
5535     emitcode("","%05d$:",tlbl->key+100);    
5536     emitcode("mov","c,ov");
5537     while (size--) {
5538         l = aopGet(AOP(result),offset,FALSE,FALSE);
5539         MOVA(l);
5540         emitcode("rrc","a");         
5541         aopPut(AOP(result),"a",offset--);
5542     }
5543     reAdjustPreg(AOP(result));
5544     emitcode("","%05d$:",tlbl1->key+100);
5545     emitcode("djnz","b,%05d$",tlbl->key+100);
5546
5547 release:
5548     freeAsmop(left,NULL,ic,TRUE);
5549     freeAsmop(result,NULL,ic,TRUE);
5550 }
5551
5552 /*-----------------------------------------------------------------*/
5553 /* genRightShift - generate code for right shifting                */
5554 /*-----------------------------------------------------------------*/
5555 static void genRightShift (iCode *ic)
5556 {
5557     operand *right, *left, *result;
5558     link *retype ;
5559     int size, offset;
5560     char *l;
5561     symbol *tlbl, *tlbl1 ;
5562
5563     /* if signed then we do it the hard way preserve the
5564     sign bit moving it inwards */
5565     retype = getSpec(operandType(IC_RESULT(ic)));
5566
5567     if (!SPEC_USIGN(retype)) {
5568         genSignedRightShift (ic);
5569         return ;
5570     }
5571
5572     /* signed & unsigned types are treated the same : i.e. the
5573     signed is NOT propagated inwards : quoting from the
5574     ANSI - standard : "for E1 >> E2, is equivalent to division
5575     by 2**E2 if unsigned or if it has a non-negative value,
5576     otherwise the result is implementation defined ", MY definition
5577     is that the sign does not get propagated */
5578
5579     right = IC_RIGHT(ic);
5580     left  = IC_LEFT(ic);
5581     result = IC_RESULT(ic);
5582
5583     aopOp(right,ic,FALSE);
5584
5585     /* if the shift count is known then do it 
5586     as efficiently as possible */
5587     if (AOP_TYPE(right) == AOP_LIT) {
5588         genRightShiftLiteral (left,right,result,ic, 0);
5589         return ;
5590     }
5591
5592     /* shift count is unknown then we have to form 
5593     a loop get the loop count in B : Note: we take
5594     only the lower order byte since shifting
5595     more that 32 bits make no sense anyway, ( the
5596     largest size of an object can be only 32 bits ) */  
5597
5598     emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
5599     emitcode("inc","b");
5600     freeAsmop (right,NULL,ic,TRUE);
5601     aopOp(left,ic,FALSE);
5602     aopOp(result,ic,FALSE);
5603
5604     /* now move the left to the result if they are not the
5605     same */
5606     if (!sameRegs(AOP(left),AOP(result)) && 
5607         AOP_SIZE(result) > 1) {
5608
5609         size = AOP_SIZE(result);
5610         offset=0;
5611         while (size--) {
5612             l = aopGet(AOP(left),offset,FALSE,TRUE);
5613             if (*l == '@' && IS_AOP_PREG(result)) {
5614
5615                 emitcode("mov","a,%s",l);
5616                 aopPut(AOP(result),"a",offset);
5617             } else
5618                 aopPut(AOP(result),l,offset);
5619             offset++;
5620         }
5621     }
5622
5623     tlbl = newiTempLabel(NULL);
5624     tlbl1= newiTempLabel(NULL);
5625     size = AOP_SIZE(result);
5626     offset = size - 1;
5627
5628     /* if it is only one byte then */
5629     if (size == 1) {
5630         l = aopGet(AOP(left),0,FALSE,FALSE);
5631         MOVA(l);
5632         emitcode("sjmp","%05d$",tlbl1->key+100);
5633         emitcode("","%05d$:",tlbl->key+100);
5634         CLRC;
5635         emitcode("rrc","a");
5636         emitcode("","%05d$:",tlbl1->key+100);
5637         emitcode("djnz","b,%05d$",tlbl->key+100);
5638         aopPut(AOP(result),"a",0);
5639         goto release ;
5640     }
5641
5642     reAdjustPreg(AOP(result));
5643     emitcode("sjmp","%05d$",tlbl1->key+100);
5644     emitcode("","%05d$:",tlbl->key+100);    
5645     CLRC;
5646     while (size--) {
5647         l = aopGet(AOP(result),offset,FALSE,FALSE);
5648         MOVA(l);
5649         emitcode("rrc","a");         
5650         aopPut(AOP(result),"a",offset--);
5651     }
5652     reAdjustPreg(AOP(result));
5653
5654     emitcode("","%05d$:",tlbl1->key+100);
5655     emitcode("djnz","b,%05d$",tlbl->key+100);
5656
5657 release:
5658     freeAsmop(left,NULL,ic,TRUE);
5659     freeAsmop(result,NULL,ic,TRUE);
5660 }
5661
5662 /*-----------------------------------------------------------------*/
5663 /* genUnpackBits - generates code for unpacking bits               */
5664 /*-----------------------------------------------------------------*/
5665 static void genUnpackBits (operand *result, char *rname, int ptype)
5666 {    
5667     int shCnt ;
5668     int rlen = 0 ;
5669     link *etype;
5670     int offset = 0 ;
5671
5672     etype = getSpec(operandType(result));
5673
5674     /* read the first byte  */
5675     switch (ptype) {
5676
5677     case POINTER:
5678     case IPOINTER:
5679         emitcode("mov","a,@%s",rname);
5680         break;
5681         
5682     case PPOINTER:
5683         emitcode("movx","a,@%s",rname);
5684         break;
5685         
5686     case FPOINTER:
5687         emitcode("movx","a,@dptr");
5688         break;
5689
5690     case CPOINTER:
5691         emitcode("clr","a");
5692         emitcode("movc","a","@a+dptr");
5693         break;
5694
5695     case GPOINTER:
5696         emitcode("lcall","__gptrget");
5697         break;
5698     }
5699
5700     /* if we have bitdisplacement then it fits   */
5701     /* into this byte completely or if length is */
5702     /* less than a byte                          */
5703     if ((shCnt = SPEC_BSTR(etype)) || 
5704         (SPEC_BLEN(etype) <= 8))  {
5705
5706         /* shift right acc */
5707         AccRsh(shCnt);
5708
5709         emitcode("anl","a,#0x%02x",
5710                  ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
5711         aopPut(AOP(result),"a",offset);
5712         return ;
5713     }
5714
5715     /* bit field did not fit in a byte  */
5716     rlen = SPEC_BLEN(etype) - 8;
5717     aopPut(AOP(result),"a",offset++);
5718
5719     while (1)  {
5720
5721         switch (ptype) {
5722         case POINTER:
5723         case IPOINTER:
5724             emitcode("inc","%s",rname);
5725             emitcode("mov","a,@%s",rname);
5726             break;
5727             
5728         case PPOINTER:
5729             emitcode("inc","%s",rname);
5730             emitcode("movx","a,@%s",rname);
5731             break;
5732
5733         case FPOINTER:
5734             emitcode("inc","dptr");
5735             emitcode("movx","a,@dptr");
5736             break;
5737             
5738         case CPOINTER:
5739             emitcode("clr","a");
5740             emitcode("inc","dptr");
5741             emitcode("movc","a","@a+dptr");
5742             break;
5743             
5744         case GPOINTER:
5745             emitcode("inc","dptr");
5746             emitcode("lcall","__gptrget");
5747             break;
5748         }
5749
5750         rlen -= 8;            
5751         /* if we are done */
5752         if ( rlen <= 0 )
5753             break ;
5754         
5755         aopPut(AOP(result),"a",offset++);
5756                               
5757     }
5758     
5759     if (rlen) {
5760         emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
5761         aopPut(AOP(result),"a",offset);        
5762     }
5763     
5764     return ;
5765 }
5766
5767
5768 /*-----------------------------------------------------------------*/
5769 /* genDataPointerGet - generates code when ptr offset is known     */
5770 /*-----------------------------------------------------------------*/
5771 static void genDataPointerGet (operand *left, 
5772                                operand *result, 
5773                                iCode *ic)
5774 {
5775     char *l;
5776     char buffer[256];
5777     int size , offset = 0;
5778     aopOp(result,ic,TRUE);
5779
5780     /* get the string representation of the name */
5781     l = aopGet(AOP(left),0,FALSE,TRUE);
5782     size = AOP_SIZE(result);
5783     while (size--) {
5784         if (offset)
5785             sprintf(buffer,"(%s + %d)",l+1,offset);
5786         else
5787             sprintf(buffer,"%s",l+1);
5788         aopPut(AOP(result),buffer,offset++);
5789     }
5790
5791     freeAsmop(left,NULL,ic,TRUE);
5792     freeAsmop(result,NULL,ic,TRUE);
5793 }
5794
5795 /*-----------------------------------------------------------------*/
5796 /* genNearPointerGet - emitcode for near pointer fetch             */
5797 /*-----------------------------------------------------------------*/
5798 static void genNearPointerGet (operand *left, 
5799                                operand *result, 
5800                                iCode *ic)
5801 {
5802     asmop *aop = NULL;
5803     regs *preg = NULL ;
5804     char *rname ;
5805     link *rtype, *retype;
5806     link *ltype = operandType(left);    
5807     char buffer[80];
5808
5809     rtype = operandType(result);
5810     retype= getSpec(rtype);
5811     
5812     aopOp(left,ic,FALSE);
5813     
5814     /* if left is rematerialisable and
5815        result is not bit variable type and
5816        the left is pointer to data space i.e
5817        lower 128 bytes of space */
5818     if (AOP_TYPE(left) == AOP_IMMD &&
5819         !IS_BITVAR(retype)         &&
5820         DCL_TYPE(ltype) == POINTER) {
5821         genDataPointerGet (left,result,ic);
5822         return ;
5823     }
5824     
5825         /* if the value is already in a pointer register
5826        then don't need anything more */
5827     if (!AOP_INPREG(AOP(left))) {
5828         /* otherwise get a free pointer register */
5829         aop = newAsmop(0);
5830         preg = getFreePtr(ic,&aop,FALSE);
5831         emitcode("mov","%s,%s",
5832                 preg->name,
5833                 aopGet(AOP(left),0,FALSE,TRUE));
5834         rname = preg->name ;
5835     } else
5836         rname = aopGet(AOP(left),0,FALSE,FALSE);
5837     
5838     freeAsmop(left,NULL,ic,TRUE);
5839     aopOp (result,ic,FALSE);
5840     
5841       /* if bitfield then unpack the bits */
5842     if (IS_BITVAR(retype)) 
5843         genUnpackBits (result,rname,POINTER);
5844     else {
5845         /* we have can just get the values */
5846         int size = AOP_SIZE(result);
5847         int offset = 0 ;        
5848         
5849         while (size--) {
5850             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
5851
5852                 emitcode("mov","a,@%s",rname);
5853                 aopPut(AOP(result),"a",offset);
5854             } else {
5855                 sprintf(buffer,"@%s",rname);
5856                 aopPut(AOP(result),buffer,offset);
5857             }
5858             offset++ ;
5859             if (size)
5860                 emitcode("inc","%s",rname);
5861         }
5862     }
5863
5864     /* now some housekeeping stuff */
5865     if (aop) {
5866         /* we had to allocate for this iCode */
5867         freeAsmop(NULL,aop,ic,TRUE);
5868     } else { 
5869         /* we did not allocate which means left
5870            already in a pointer register, then
5871            if size > 0 && this could be used again
5872            we have to point it back to where it 
5873            belongs */
5874         if (AOP_SIZE(result) > 1 &&
5875             !OP_SYMBOL(left)->remat &&
5876             ( OP_SYMBOL(left)->liveTo > ic->seq ||
5877               ic->depth )) {
5878             int size = AOP_SIZE(result) - 1;
5879             while (size--)
5880                 emitcode("dec","%s",rname);
5881         }
5882     }
5883
5884     /* done */
5885     freeAsmop(result,NULL,ic,TRUE);
5886      
5887 }
5888
5889 /*-----------------------------------------------------------------*/
5890 /* genPagedPointerGet - emitcode for paged pointer fetch           */
5891 /*-----------------------------------------------------------------*/
5892 static void genPagedPointerGet (operand *left, 
5893                                operand *result, 
5894                                iCode *ic)
5895 {
5896     asmop *aop = NULL;
5897     regs *preg = NULL ;
5898     char *rname ;
5899     link *rtype, *retype;    
5900
5901     rtype = operandType(result);
5902     retype= getSpec(rtype);
5903     
5904     aopOp(left,ic,FALSE);
5905
5906   /* if the value is already in a pointer register
5907        then don't need anything more */
5908     if (!AOP_INPREG(AOP(left))) {
5909         /* otherwise get a free pointer register */
5910         aop = newAsmop(0);
5911         preg = getFreePtr(ic,&aop,FALSE);
5912         emitcode("mov","%s,%s",
5913                 preg->name,
5914                 aopGet(AOP(left),0,FALSE,TRUE));
5915         rname = preg->name ;
5916     } else
5917         rname = aopGet(AOP(left),0,FALSE,FALSE);
5918     
5919     freeAsmop(left,NULL,ic,TRUE);
5920     aopOp (result,ic,FALSE);
5921
5922     /* if bitfield then unpack the bits */
5923     if (IS_BITVAR(retype)) 
5924         genUnpackBits (result,rname,PPOINTER);
5925     else {
5926         /* we have can just get the values */
5927         int size = AOP_SIZE(result);
5928         int offset = 0 ;        
5929         
5930         while (size--) {
5931             
5932             emitcode("movx","a,@%s",rname);
5933             aopPut(AOP(result),"a",offset);
5934             
5935             offset++ ;
5936             
5937             if (size)
5938                 emitcode("inc","%s",rname);
5939         }
5940     }
5941
5942     /* now some housekeeping stuff */
5943     if (aop) {
5944         /* we had to allocate for this iCode */
5945         freeAsmop(NULL,aop,ic,TRUE);
5946     } else { 
5947         /* we did not allocate which means left
5948            already in a pointer register, then
5949            if size > 0 && this could be used again
5950            we have to point it back to where it 
5951            belongs */
5952         if (AOP_SIZE(result) > 1 &&
5953             !OP_SYMBOL(left)->remat &&
5954             ( OP_SYMBOL(left)->liveTo > ic->seq ||
5955               ic->depth )) {
5956             int size = AOP_SIZE(result) - 1;
5957             while (size--)
5958                 emitcode("dec","%s",rname);
5959         }
5960     }
5961
5962     /* done */
5963     freeAsmop(result,NULL,ic,TRUE);
5964     
5965         
5966 }
5967
5968 /*-----------------------------------------------------------------*/
5969 /* genFarPointerGet - gget value from far space                    */
5970 /*-----------------------------------------------------------------*/
5971 static void genFarPointerGet (operand *left,
5972                               operand *result, iCode *ic)
5973 {
5974     int size, offset ;
5975     link *retype = getSpec(operandType(result));
5976
5977     aopOp(left,ic,FALSE);
5978
5979     /* if the operand is already in dptr 
5980     then we do nothing else we move the value to dptr */
5981     if (AOP_TYPE(left) != AOP_STR) {
5982         /* if this is remateriazable */
5983         if (AOP_TYPE(left) == AOP_IMMD)
5984             emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
5985         else { /* we need to get it byte by byte */
5986             emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
5987             emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
5988             if (options.model == MODEL_FLAT24)
5989             {
5990                emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
5991             }
5992         }
5993     }
5994     /* so dptr know contains the address */
5995     freeAsmop(left,NULL,ic,TRUE);
5996     aopOp(result,ic,FALSE);
5997
5998     /* if bit then unpack */
5999     if (IS_BITVAR(retype)) 
6000         genUnpackBits(result,"dptr",FPOINTER);
6001     else {
6002         size = AOP_SIZE(result);
6003         offset = 0 ;
6004
6005         while (size--) {
6006             emitcode("movx","a,@dptr");
6007             aopPut(AOP(result),"a",offset++);
6008             if (size)
6009                 emitcode("inc","dptr");
6010         }
6011     }
6012
6013     freeAsmop(result,NULL,ic,TRUE);
6014 }
6015
6016 /*-----------------------------------------------------------------*/
6017 /* emitcodePointerGet - gget value from code space                  */
6018 /*-----------------------------------------------------------------*/
6019 static void emitcodePointerGet (operand *left,
6020                                 operand *result, iCode *ic)
6021 {
6022     int size, offset ;
6023     link *retype = getSpec(operandType(result));
6024
6025     aopOp(left,ic,FALSE);
6026
6027     /* if the operand is already in dptr 
6028     then we do nothing else we move the value to dptr */
6029     if (AOP_TYPE(left) != AOP_STR) {
6030         /* if this is remateriazable */
6031         if (AOP_TYPE(left) == AOP_IMMD)
6032             emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6033         else { /* we need to get it byte by byte */
6034             emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6035             emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6036             if (options.model == MODEL_FLAT24)
6037             {
6038                emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6039             }
6040         }
6041     }
6042     /* so dptr know contains the address */
6043     freeAsmop(left,NULL,ic,TRUE);
6044     aopOp(result,ic,FALSE);
6045
6046     /* if bit then unpack */
6047     if (IS_BITVAR(retype)) 
6048         genUnpackBits(result,"dptr",CPOINTER);
6049     else {
6050         size = AOP_SIZE(result);
6051         offset = 0 ;
6052
6053         while (size--) {
6054             emitcode("clr","a");
6055             emitcode("movc","a,@a+dptr");
6056             aopPut(AOP(result),"a",offset++);
6057             if (size)
6058                 emitcode("inc","dptr");
6059         }
6060     }
6061
6062     freeAsmop(result,NULL,ic,TRUE);
6063 }
6064
6065 /*-----------------------------------------------------------------*/
6066 /* genGenPointerGet - gget value from generic pointer space        */
6067 /*-----------------------------------------------------------------*/
6068 static void genGenPointerGet (operand *left,
6069                               operand *result, iCode *ic)
6070 {
6071     int size, offset ;
6072     link *retype = getSpec(operandType(result));
6073
6074     aopOp(left,ic,FALSE);
6075
6076     /* if the operand is already in dptr 
6077     then we do nothing else we move the value to dptr */
6078     if (AOP_TYPE(left) != AOP_STR) {
6079         /* if this is remateriazable */
6080         if (AOP_TYPE(left) == AOP_IMMD) {
6081             emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6082             emitcode("mov","b,#%d",pointerCode(retype));
6083         }
6084         else { /* we need to get it byte by byte */
6085             emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6086             emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6087             if (options.model == MODEL_FLAT24)
6088             {
6089                emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6090                emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE));
6091             }
6092             else
6093             {
6094                 emitcode("mov","b,%s",aopGet(AOP(left),2,FALSE,FALSE));
6095             }
6096         }
6097     }
6098     /* so dptr know contains the address */
6099     freeAsmop(left,NULL,ic,TRUE);
6100     aopOp(result,ic,FALSE);
6101
6102     /* if bit then unpack */
6103     if (IS_BITVAR(retype)) 
6104         genUnpackBits(result,"dptr",GPOINTER);
6105     else {
6106         size = AOP_SIZE(result);
6107         offset = 0 ;
6108
6109         while (size--) {
6110             emitcode("lcall","__gptrget");
6111             aopPut(AOP(result),"a",offset++);
6112             if (size)
6113                 emitcode("inc","dptr");
6114         }
6115     }
6116
6117     freeAsmop(result,NULL,ic,TRUE);
6118 }
6119
6120 /*-----------------------------------------------------------------*/
6121 /* genPointerGet - generate code for pointer get                   */
6122 /*-----------------------------------------------------------------*/
6123 static void genPointerGet (iCode *ic)
6124 {
6125     operand *left, *result ;
6126     link *type, *etype;
6127     int p_type;
6128
6129     left = IC_LEFT(ic);
6130     result = IC_RESULT(ic) ;
6131
6132     /* depending on the type of pointer we need to
6133     move it to the correct pointer register */
6134     type = operandType(left);
6135     etype = getSpec(type);
6136     /* if left is of type of pointer then it is simple */
6137     if (IS_PTR(type) && !IS_FUNC(type->next)) 
6138         p_type = DCL_TYPE(type);
6139     else {
6140         /* we have to go by the storage class */
6141         p_type = PTR_TYPE(SPEC_OCLS(etype));
6142
6143 /*      if (SPEC_OCLS(etype)->codesp ) { */
6144 /*          p_type = CPOINTER ;  */
6145 /*      } */
6146 /*      else */
6147 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
6148 /*              p_type = FPOINTER ; */
6149 /*          else */
6150 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
6151 /*                  p_type = PPOINTER; */
6152 /*              else */
6153 /*                  if (SPEC_OCLS(etype) == idata ) */
6154 /*                      p_type = IPOINTER; */
6155 /*                  else */
6156 /*                      p_type = POINTER ; */
6157     }
6158
6159     /* now that we have the pointer type we assign
6160     the pointer values */
6161     switch (p_type) {
6162
6163     case POINTER:       
6164     case IPOINTER:
6165         genNearPointerGet (left,result,ic);
6166         break;
6167
6168     case PPOINTER:
6169         genPagedPointerGet(left,result,ic);
6170         break;
6171
6172     case FPOINTER:
6173         genFarPointerGet (left,result,ic);
6174         break;
6175
6176     case CPOINTER:
6177         emitcodePointerGet (left,result,ic);
6178         break;
6179
6180     case GPOINTER:
6181         genGenPointerGet (left,result,ic);
6182         break;
6183     }
6184
6185 }
6186
6187 /*-----------------------------------------------------------------*/
6188 /* genPackBits - generates code for packed bit storage             */
6189 /*-----------------------------------------------------------------*/
6190 static void genPackBits (link    *etype ,
6191                          operand *right ,
6192                          char *rname, int p_type)
6193 {
6194     int shCount = 0 ;
6195     int offset = 0  ;
6196     int rLen = 0 ;
6197     int blen, bstr ;   
6198     char *l ;
6199
6200     blen = SPEC_BLEN(etype);
6201     bstr = SPEC_BSTR(etype);
6202
6203     l = aopGet(AOP(right),offset++,FALSE,FALSE);
6204     MOVA(l);   
6205
6206     /* if the bit lenth is less than or    */
6207     /* it exactly fits a byte then         */
6208     if (SPEC_BLEN(etype) <= 8 )  {
6209         shCount = SPEC_BSTR(etype) ;
6210
6211         /* shift left acc */
6212         AccLsh(shCount);
6213
6214         if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
6215
6216
6217             switch (p_type) {
6218                 case POINTER:
6219                     emitcode ("mov","b,a");
6220                     emitcode("mov","a,@%s",rname);
6221                     break;
6222
6223                 case FPOINTER:
6224                     emitcode ("mov","b,a");
6225                     emitcode("movx","a,@dptr");
6226                     break;
6227
6228                 case GPOINTER:
6229                     emitcode ("push","b");
6230                     emitcode ("push","acc");
6231                     emitcode ("lcall","__gptrget");
6232                     emitcode ("pop","b");
6233                     break;
6234             }
6235
6236             emitcode ("anl","a,#0x%02x",(unsigned char)
6237                       ((unsigned char)(0xFF << (blen+bstr)) | 
6238                        (unsigned char)(0xFF >> (8-bstr)) ) );
6239             emitcode ("orl","a,b");
6240             if (p_type == GPOINTER)
6241                 emitcode("pop","b");
6242         }
6243     }
6244
6245     switch (p_type) {
6246         case POINTER:
6247             emitcode("mov","@%s,a",rname);
6248             break;
6249
6250         case FPOINTER:
6251             emitcode("movx","@dptr,a");
6252             break;
6253
6254         case GPOINTER:
6255             emitcode("lcall","__gptrput");
6256             break;
6257     }
6258
6259     /* if we r done */
6260     if ( SPEC_BLEN(etype) <= 8 )
6261         return ;
6262
6263     emitcode("inc","%s",rname);
6264     rLen = SPEC_BLEN(etype) ;     
6265
6266     /* now generate for lengths greater than one byte */
6267     while (1) {
6268
6269         l = aopGet(AOP(right),offset++,FALSE,TRUE);
6270
6271         rLen -= 8 ;
6272         if (rLen <= 0 )
6273             break ;
6274
6275         switch (p_type) {
6276             case POINTER:
6277                 if (*l == '@') {
6278                     MOVA(l);
6279                     emitcode("mov","@%s,a",rname);
6280                 } else
6281                     emitcode("mov","@%s,%s",rname,l);
6282                 break;
6283
6284             case FPOINTER:
6285                 MOVA(l);
6286                 emitcode("movx","@dptr,a");
6287                 break;
6288
6289             case GPOINTER:
6290                 MOVA(l);
6291                 emitcode("lcall","__gptrput");
6292                 break;  
6293         }   
6294         emitcode ("inc","%s",rname);
6295     }
6296
6297     MOVA(l);
6298
6299     /* last last was not complete */
6300     if (rLen)   {
6301         /* save the byte & read byte */
6302         switch (p_type) {
6303             case POINTER:
6304                 emitcode ("mov","b,a");
6305                 emitcode("mov","a,@%s",rname);
6306                 break;
6307
6308             case FPOINTER:
6309                 emitcode ("mov","b,a");
6310                 emitcode("movx","a,@dptr");
6311                 break;
6312
6313             case GPOINTER:
6314                 emitcode ("push","b");
6315                 emitcode ("push","acc");
6316                 emitcode ("lcall","__gptrget");
6317                 emitcode ("pop","b");
6318                 break;
6319         }
6320
6321         emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
6322         emitcode ("orl","a,b");
6323     }
6324
6325     if (p_type == GPOINTER)
6326         emitcode("pop","b");
6327
6328     switch (p_type) {
6329
6330     case POINTER:
6331         emitcode("mov","@%s,a",rname);
6332         break;
6333         
6334     case FPOINTER:
6335         emitcode("movx","@dptr,a");
6336         break;
6337         
6338     case GPOINTER:
6339         emitcode("lcall","__gptrput");
6340         break;                  
6341     }
6342 }
6343 /*-----------------------------------------------------------------*/
6344 /* genDataPointerSet - remat pointer to data space                 */
6345 /*-----------------------------------------------------------------*/
6346 static void genDataPointerSet(operand *right,
6347                               operand *result,
6348                               iCode *ic)
6349 {
6350     int size, offset = 0 ;
6351     char *l, buffer[256];
6352
6353     aopOp(right,ic,FALSE);
6354     
6355     l = aopGet(AOP(result),0,FALSE,TRUE);
6356     size = AOP_SIZE(right);
6357     while (size--) {
6358         if (offset)
6359             sprintf(buffer,"(%s + %d)",l+1,offset);
6360         else
6361             sprintf(buffer,"%s",l+1);
6362         emitcode("mov","%s,%s",buffer,
6363                  aopGet(AOP(right),offset++,FALSE,FALSE));
6364     }
6365
6366     freeAsmop(right,NULL,ic,TRUE);
6367     freeAsmop(result,NULL,ic,TRUE);
6368 }
6369
6370 /*-----------------------------------------------------------------*/
6371 /* genNearPointerSet - emitcode for near pointer put                */
6372 /*-----------------------------------------------------------------*/
6373 static void genNearPointerSet (operand *right,
6374                                operand *result, 
6375                                iCode *ic)
6376 {
6377     asmop *aop = NULL;
6378     regs *preg = NULL ;
6379     char *rname , *l;
6380     link *retype;
6381     link *ptype = operandType(result);
6382     
6383     retype= getSpec(operandType(right));
6384
6385     aopOp(result,ic,FALSE);
6386     
6387     /* if the result is rematerializable &
6388        in data space & not a bit variable */
6389     if (AOP_TYPE(result) == AOP_IMMD &&
6390         DCL_TYPE(ptype) == POINTER   &&
6391         !IS_BITVAR(retype)) {
6392         genDataPointerSet (right,result,ic);
6393         return;
6394     }
6395
6396     /* if the value is already in a pointer register
6397     then don't need anything more */
6398     if (!AOP_INPREG(AOP(result))) {
6399         /* otherwise get a free pointer register */
6400         aop = newAsmop(0);
6401         preg = getFreePtr(ic,&aop,FALSE);
6402         emitcode("mov","%s,%s",
6403                  preg->name,
6404                  aopGet(AOP(result),0,FALSE,TRUE));
6405         rname = preg->name ;
6406     } else
6407         rname = aopGet(AOP(result),0,FALSE,FALSE);
6408
6409     freeAsmop(result,NULL,ic,TRUE);
6410     aopOp (right,ic,FALSE);
6411
6412     /* if bitfield then unpack the bits */
6413     if (IS_BITVAR(retype)) 
6414         genPackBits (retype,right,rname,POINTER);
6415     else {
6416         /* we have can just get the values */
6417         int size = AOP_SIZE(right);
6418         int offset = 0 ;    
6419
6420         while (size--) {
6421             l = aopGet(AOP(right),offset,FALSE,TRUE);
6422             if (*l == '@' ) {
6423                 MOVA(l);
6424                 emitcode("mov","@%s,a",rname);
6425             } else
6426                 emitcode("mov","@%s,%s",rname,l);
6427             if (size)
6428                 emitcode("inc","%s",rname);
6429             offset++;
6430         }
6431     }
6432
6433     /* now some housekeeping stuff */
6434     if (aop) {
6435         /* we had to allocate for this iCode */
6436         freeAsmop(NULL,aop,ic,TRUE);
6437     } else { 
6438         /* we did not allocate which means left
6439         already in a pointer register, then
6440         if size > 0 && this could be used again
6441         we have to point it back to where it 
6442         belongs */
6443         if (AOP_SIZE(right) > 1 &&
6444             !OP_SYMBOL(result)->remat &&
6445             ( OP_SYMBOL(result)->liveTo > ic->seq ||
6446               ic->depth )) {
6447             int size = AOP_SIZE(right) - 1;
6448             while (size--)
6449                 emitcode("dec","%s",rname);
6450         }
6451     }
6452
6453     /* done */
6454     freeAsmop(right,NULL,ic,TRUE);
6455
6456
6457 }
6458
6459 /*-----------------------------------------------------------------*/
6460 /* genPagedPointerSet - emitcode for Paged pointer put             */
6461 /*-----------------------------------------------------------------*/
6462 static void genPagedPointerSet (operand *right,
6463                                operand *result, 
6464                                iCode *ic)
6465 {
6466     asmop *aop = NULL;
6467     regs *preg = NULL ;
6468     char *rname , *l;
6469     link *retype;
6470        
6471     retype= getSpec(operandType(right));
6472     
6473     aopOp(result,ic,FALSE);
6474     
6475     /* if the value is already in a pointer register
6476        then don't need anything more */
6477     if (!AOP_INPREG(AOP(result))) {
6478         /* otherwise get a free pointer register */
6479         aop = newAsmop(0);
6480         preg = getFreePtr(ic,&aop,FALSE);
6481         emitcode("mov","%s,%s",
6482                 preg->name,
6483                 aopGet(AOP(result),0,FALSE,TRUE));
6484         rname = preg->name ;
6485     } else
6486         rname = aopGet(AOP(result),0,FALSE,FALSE);
6487     
6488     freeAsmop(result,NULL,ic,TRUE);
6489     aopOp (right,ic,FALSE);
6490
6491     /* if bitfield then unpack the bits */
6492     if (IS_BITVAR(retype)) 
6493         genPackBits (retype,right,rname,PPOINTER);
6494     else {
6495         /* we have can just get the values */
6496         int size = AOP_SIZE(right);
6497         int offset = 0 ;        
6498         
6499         while (size--) {
6500             l = aopGet(AOP(right),offset,FALSE,TRUE);
6501             
6502             MOVA(l);
6503             emitcode("movx","@%s,a",rname);
6504
6505             if (size)
6506                 emitcode("inc","%s",rname);
6507
6508             offset++;
6509         }
6510     }
6511     
6512     /* now some housekeeping stuff */
6513     if (aop) {
6514         /* we had to allocate for this iCode */
6515         freeAsmop(NULL,aop,ic,TRUE);
6516     } else { 
6517         /* we did not allocate which means left
6518            already in a pointer register, then
6519            if size > 0 && this could be used again
6520            we have to point it back to where it 
6521            belongs */
6522         if (AOP_SIZE(right) > 1 &&
6523             !OP_SYMBOL(result)->remat &&
6524             ( OP_SYMBOL(result)->liveTo > ic->seq ||
6525               ic->depth )) {
6526             int size = AOP_SIZE(right) - 1;
6527             while (size--)
6528                 emitcode("dec","%s",rname);
6529         }
6530     }
6531
6532     /* done */
6533     freeAsmop(right,NULL,ic,TRUE);
6534     
6535         
6536 }
6537
6538 /*-----------------------------------------------------------------*/
6539 /* genFarPointerSet - set value from far space                     */
6540 /*-----------------------------------------------------------------*/
6541 static void genFarPointerSet (operand *right,
6542                               operand *result, iCode *ic)
6543 {
6544     int size, offset ;
6545     link *retype = getSpec(operandType(right));
6546
6547     aopOp(result,ic,FALSE);
6548
6549     /* if the operand is already in dptr 
6550     then we do nothing else we move the value to dptr */
6551     if (AOP_TYPE(result) != AOP_STR) {
6552         /* if this is remateriazable */
6553         if (AOP_TYPE(result) == AOP_IMMD)
6554             emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
6555         else { /* we need to get it byte by byte */
6556             emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
6557             emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
6558             if (options.model == MODEL_FLAT24)
6559             {
6560                emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
6561             }
6562         }
6563     }
6564     /* so dptr know contains the address */
6565     freeAsmop(result,NULL,ic,TRUE);
6566     aopOp(right,ic,FALSE);
6567
6568     /* if bit then unpack */
6569     if (IS_BITVAR(retype)) 
6570         genPackBits(retype,right,"dptr",FPOINTER);
6571     else {
6572         size = AOP_SIZE(right);
6573         offset = 0 ;
6574
6575         while (size--) {
6576             char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
6577             MOVA(l);
6578             emitcode("movx","@dptr,a");
6579             if (size)
6580                 emitcode("inc","dptr");
6581         }
6582     }
6583
6584     freeAsmop(right,NULL,ic,TRUE);
6585 }
6586
6587 /*-----------------------------------------------------------------*/
6588 /* genGenPointerSet - set value from generic pointer space         */
6589 /*-----------------------------------------------------------------*/
6590 static void genGenPointerSet (operand *right,
6591                               operand *result, iCode *ic)
6592 {
6593     int size, offset ;
6594     link *retype = getSpec(operandType(right));
6595
6596     aopOp(result,ic,FALSE);
6597
6598     /* if the operand is already in dptr 
6599     then we do nothing else we move the value to dptr */
6600     if (AOP_TYPE(result) != AOP_STR) {
6601         /* if this is remateriazable */
6602         if (AOP_TYPE(result) == AOP_IMMD) {
6603             emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
6604             emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
6605         }
6606         else { /* we need to get it byte by byte */
6607             emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
6608             emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
6609             if (options.model == MODEL_FLAT24)
6610             {
6611                emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
6612                emitcode("mov","b,%s",aopGet(AOP(result),3,FALSE,FALSE));
6613             }
6614             else
6615             {
6616                 emitcode("mov","b,%s",aopGet(AOP(result),2,FALSE,FALSE));
6617             }
6618         }
6619     }
6620     /* so dptr know contains the address */
6621     freeAsmop(result,NULL,ic,TRUE);
6622     aopOp(right,ic,FALSE);
6623
6624     /* if bit then unpack */
6625     if (IS_BITVAR(retype)) 
6626         genPackBits(retype,right,"dptr",GPOINTER);
6627     else {
6628         size = AOP_SIZE(right);
6629         offset = 0 ;
6630
6631         while (size--) {
6632             char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
6633             MOVA(l);
6634             emitcode("lcall","__gptrput");
6635             if (size)
6636                 emitcode("inc","dptr");
6637         }
6638     }
6639
6640     freeAsmop(right,NULL,ic,TRUE);
6641 }
6642
6643 /*-----------------------------------------------------------------*/
6644 /* genPointerSet - stores the value into a pointer location        */
6645 /*-----------------------------------------------------------------*/
6646 static void genPointerSet (iCode *ic)
6647 {    
6648     operand *right, *result ;
6649     link *type, *etype;
6650     int p_type;
6651
6652     right = IC_RIGHT(ic);
6653     result = IC_RESULT(ic) ;
6654
6655     /* depending on the type of pointer we need to
6656     move it to the correct pointer register */
6657     type = operandType(result);
6658     etype = getSpec(type);
6659     /* if left is of type of pointer then it is simple */
6660     if (IS_PTR(type) && !IS_FUNC(type->next)) {
6661         p_type = DCL_TYPE(type);
6662     }
6663     else {
6664         /* we have to go by the storage class */
6665         p_type = PTR_TYPE(SPEC_OCLS(etype));
6666
6667 /*      if (SPEC_OCLS(etype)->codesp ) { */
6668 /*          p_type = CPOINTER ;  */
6669 /*      } */
6670 /*      else */
6671 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
6672 /*              p_type = FPOINTER ; */
6673 /*          else */
6674 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
6675 /*                  p_type = PPOINTER ; */
6676 /*              else */
6677 /*                  if (SPEC_OCLS(etype) == idata ) */
6678 /*                      p_type = IPOINTER ; */
6679 /*                  else */
6680 /*                      p_type = POINTER ; */
6681     }
6682
6683     /* now that we have the pointer type we assign
6684     the pointer values */
6685     switch (p_type) {
6686
6687     case POINTER:
6688     case IPOINTER:
6689         genNearPointerSet (right,result,ic);
6690         break;
6691
6692     case PPOINTER:
6693         genPagedPointerSet (right,result,ic);
6694         break;
6695
6696     case FPOINTER:
6697         genFarPointerSet (right,result,ic);
6698         break;
6699
6700     case GPOINTER:
6701         genGenPointerSet (right,result,ic);
6702         break;
6703     }
6704
6705 }
6706
6707 /*-----------------------------------------------------------------*/
6708 /* genIfx - generate code for Ifx statement                        */
6709 /*-----------------------------------------------------------------*/
6710 static void genIfx (iCode *ic, iCode *popIc)
6711 {
6712     operand *cond = IC_COND(ic);
6713     int isbit =0;
6714
6715     aopOp(cond,ic,FALSE);
6716
6717     /* get the value into acc */
6718     if (AOP_TYPE(cond) != AOP_CRY)
6719         toBoolean(cond);
6720     else
6721         isbit = 1;
6722     /* the result is now in the accumulator */
6723     freeAsmop(cond,NULL,ic,TRUE);
6724
6725     /* if there was something to be popped then do it */
6726     if (popIc)
6727         genIpop(popIc);
6728
6729     /* if the condition is  a bit variable */
6730     if (isbit && IS_ITEMP(cond) && 
6731         SPIL_LOC(cond))
6732         genIfxJump(ic,SPIL_LOC(cond)->rname);
6733     else
6734         if (isbit && !IS_ITEMP(cond))
6735             genIfxJump(ic,OP_SYMBOL(cond)->rname);
6736         else
6737             genIfxJump(ic,"a");
6738
6739     ic->generated = 1;
6740 }
6741
6742 /*-----------------------------------------------------------------*/
6743 /* genAddrOf - generates code for address of                       */
6744 /*-----------------------------------------------------------------*/
6745 static void genAddrOf (iCode *ic)
6746 {
6747     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
6748     int size, offset ;
6749
6750     aopOp(IC_RESULT(ic),ic,FALSE);
6751
6752     /* if the operand is on the stack then we 
6753     need to get the stack offset of this
6754     variable */
6755     if (sym->onStack) {
6756         /* if it has an offset then we need to compute
6757         it */
6758         if (sym->stack) {
6759             emitcode("mov","a,_bp");
6760             emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
6761             aopPut(AOP(IC_RESULT(ic)),"a",0);       
6762         } else 
6763             /* we can just move _bp */
6764             aopPut(AOP(IC_RESULT(ic)),"_bp",0);
6765         /* fill the result with zero */
6766         size = AOP_SIZE(IC_RESULT(ic)) - 1;
6767         offset = 1;
6768         while (size--) 
6769             aopPut(AOP(IC_RESULT(ic)),zero,offset++);
6770
6771         goto release;
6772     }
6773
6774     /* object not on stack then we need the name */
6775     size = AOP_SIZE(IC_RESULT(ic));
6776     offset = 0;
6777
6778     while (size--) {
6779         char s[SDCC_NAME_MAX];
6780         if (offset) 
6781             sprintf(s,"#(%s >> %d)",
6782                     sym->rname,
6783                     offset*8);
6784         else
6785             sprintf(s,"#%s",sym->rname);
6786         aopPut(AOP(IC_RESULT(ic)),s,offset++);
6787     }
6788
6789 release:
6790     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
6791
6792 }
6793
6794 /*-----------------------------------------------------------------*/
6795 /* genFarFarAssign - assignment when both are in far space         */
6796 /*-----------------------------------------------------------------*/
6797 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
6798 {
6799     int size = AOP_SIZE(right);
6800     int offset = 0;
6801     char *l ;
6802     /* first push the right side on to the stack */
6803     while (size--) {
6804         l = aopGet(AOP(right),offset++,FALSE,FALSE);
6805         MOVA(l);
6806         emitcode ("push","acc");
6807     }
6808     
6809     freeAsmop(right,NULL,ic,FALSE);
6810     /* now assign DPTR to result */
6811     aopOp(result,ic,FALSE);
6812     size = AOP_SIZE(result);
6813     while (size--) {
6814         emitcode ("pop","acc");
6815         aopPut(AOP(result),"a",--offset);
6816     }
6817     freeAsmop(result,NULL,ic,FALSE);
6818         
6819 }
6820
6821 /*-----------------------------------------------------------------*/
6822 /* genAssign - generate code for assignment                        */
6823 /*-----------------------------------------------------------------*/
6824 static void genAssign (iCode *ic)
6825 {
6826     operand *result, *right;
6827     int size, offset ;
6828         unsigned long lit = 0L;
6829
6830     result = IC_RESULT(ic);
6831     right  = IC_RIGHT(ic) ;
6832
6833     /* if they are the same */
6834     if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
6835         return ;
6836
6837     aopOp(right,ic,FALSE);
6838     
6839     /* special case both in far space */
6840     if (AOP_TYPE(right) == AOP_DPTR &&
6841         IS_TRUE_SYMOP(result)       &&
6842         isOperandInFarSpace(result)) {
6843
6844         genFarFarAssign (result,right,ic);
6845         return ;
6846     }
6847
6848     aopOp(result,ic,TRUE);
6849
6850     /* if they are the same registers */
6851     if (sameRegs(AOP(right),AOP(result)))
6852         goto release;
6853
6854     /* if the result is a bit */
6855     if (AOP_TYPE(result) == AOP_CRY) {
6856
6857         /* if the right size is a literal then
6858         we know what the value is */
6859         if (AOP_TYPE(right) == AOP_LIT) {
6860             if (((int) operandLitValue(right))) 
6861                 aopPut(AOP(result),one,0);
6862             else
6863                 aopPut(AOP(result),zero,0);
6864             goto release;
6865         }
6866
6867         /* the right is also a bit variable */
6868         if (AOP_TYPE(right) == AOP_CRY) {
6869             emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6870             aopPut(AOP(result),"c",0);
6871             goto release ;
6872         }
6873
6874         /* we need to or */
6875         toBoolean(right);
6876         aopPut(AOP(result),"a",0);
6877         goto release ;
6878     }
6879
6880     /* bit variables done */
6881     /* general case */
6882     size = AOP_SIZE(result);
6883     offset = 0 ;
6884     if(AOP_TYPE(right) == AOP_LIT)
6885         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6886     if((size > 1) &&
6887        (AOP_TYPE(result) != AOP_REG) &&
6888        (AOP_TYPE(right) == AOP_LIT) &&
6889        !IS_FLOAT(operandType(right)) &&
6890        (lit < 256L)){
6891         emitcode("clr","a");
6892         while (size--) {
6893             if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
6894                 aopPut(AOP(result),"a",size);
6895             else
6896                 aopPut(AOP(result),
6897                        aopGet(AOP(right),size,FALSE,FALSE),
6898                        size);
6899         }
6900     } else {
6901         while (size--) {
6902             aopPut(AOP(result),
6903                    aopGet(AOP(right),offset,FALSE,FALSE),
6904                    offset);
6905             offset++;
6906         }
6907     }
6908     
6909 release:
6910     freeAsmop (right,NULL,ic,FALSE);
6911     freeAsmop (result,NULL,ic,TRUE);
6912 }   
6913
6914 /*-----------------------------------------------------------------*/
6915 /* genJumpTab - genrates code for jump table                       */
6916 /*-----------------------------------------------------------------*/
6917 static void genJumpTab (iCode *ic)
6918 {
6919     symbol *jtab;
6920     char *l;
6921
6922     aopOp(IC_JTCOND(ic),ic,FALSE);
6923     /* get the condition into accumulator */
6924     l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
6925     MOVA(l);
6926     /* multiply by three */
6927     emitcode("add","a,acc");
6928     emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
6929     freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
6930
6931     jtab = newiTempLabel(NULL);
6932     emitcode("mov","dptr,#%05d$",jtab->key+100);
6933     emitcode("jmp","@a+dptr");
6934     emitcode("","%05d$:",jtab->key+100);
6935     /* now generate the jump labels */
6936     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
6937          jtab = setNextItem(IC_JTLABELS(ic)))
6938         emitcode("ljmp","%05d$",jtab->key+100);
6939
6940 }
6941
6942 /*-----------------------------------------------------------------*/
6943 /* genCast - gen code for casting                                  */
6944 /*-----------------------------------------------------------------*/
6945 static void genCast (iCode *ic)
6946 {
6947     operand *result = IC_RESULT(ic);
6948     link *ctype = operandType(IC_LEFT(ic));
6949     operand *right = IC_RIGHT(ic);
6950     int size, offset ;
6951
6952     /* if they are equivalent then do nothing */
6953     if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
6954         return ;
6955
6956     aopOp(right,ic,FALSE) ;
6957     aopOp(result,ic,FALSE);
6958
6959     /* if the result is a bit */
6960     if (AOP_TYPE(result) == AOP_CRY) {
6961         /* if the right size is a literal then
6962         we know what the value is */
6963         if (AOP_TYPE(right) == AOP_LIT) {
6964             if (((int) operandLitValue(right))) 
6965                 aopPut(AOP(result),one,0);
6966             else
6967                 aopPut(AOP(result),zero,0);
6968
6969             goto release;
6970         }
6971
6972         /* the right is also a bit variable */
6973         if (AOP_TYPE(right) == AOP_CRY) {
6974             emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6975             aopPut(AOP(result),"c",0);
6976             goto release ;
6977         }
6978
6979         /* we need to or */
6980         toBoolean(right);
6981         aopPut(AOP(result),"a",0);
6982         goto release ;
6983     }
6984
6985     /* if they are the same size : or less */
6986     if (AOP_SIZE(result) <= AOP_SIZE(right)) {
6987
6988         /* if they are in the same place */
6989         if (sameRegs(AOP(right),AOP(result)))
6990             goto release;
6991
6992         /* if they in different places then copy */
6993         size = AOP_SIZE(result);
6994         offset = 0 ;
6995         while (size--) {
6996             aopPut(AOP(result),
6997                    aopGet(AOP(right),offset,FALSE,FALSE),
6998                    offset);
6999             offset++;
7000         }
7001         goto release;
7002     }
7003
7004
7005     /* if the result is of type pointer */
7006     if (IS_PTR(ctype)) {
7007
7008         int p_type;
7009         link *type = operandType(right);
7010         link *etype = getSpec(type);
7011
7012         /* pointer to generic pointer */
7013         if (IS_GENPTR(ctype)) {
7014             char *l = zero;
7015             
7016             if (IS_PTR(type)) 
7017                 p_type = DCL_TYPE(type);
7018             else {
7019                 /* we have to go by the storage class */
7020                 p_type = PTR_TYPE(SPEC_OCLS(etype));
7021
7022 /*              if (SPEC_OCLS(etype)->codesp )  */
7023 /*                  p_type = CPOINTER ;  */
7024 /*              else */
7025 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
7026 /*                      p_type = FPOINTER ; */
7027 /*                  else */
7028 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
7029 /*                          p_type = PPOINTER; */
7030 /*                      else */
7031 /*                          if (SPEC_OCLS(etype) == idata ) */
7032 /*                              p_type = IPOINTER ; */
7033 /*                          else */
7034 /*                              p_type = POINTER ; */
7035             }
7036                 
7037             /* the first two bytes are known */
7038             size = GPTRSIZE - 1; 
7039             offset = 0 ;
7040             while (size--) {
7041                 aopPut(AOP(result),
7042                        aopGet(AOP(right),offset,FALSE,FALSE),
7043                        offset);
7044                 offset++;
7045             }
7046             /* the last byte depending on type */
7047             switch (p_type) {
7048             case IPOINTER:
7049             case POINTER:
7050                 l = zero;
7051                 break;
7052             case FPOINTER:
7053                 l = one;
7054                 break;
7055             case CPOINTER:
7056                 l = "#0x02";
7057                 break;                          
7058             case PPOINTER:
7059                 l = "#0x03";
7060                 break;
7061                 
7062             default:
7063                 /* this should never happen */
7064                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
7065                        "got unknown pointer type");
7066                 exit(1);
7067             }
7068             aopPut(AOP(result),l, GPTRSIZE - 1);            
7069             goto release ;
7070         }
7071         
7072         /* just copy the pointers */
7073         size = AOP_SIZE(result);
7074         offset = 0 ;
7075         while (size--) {
7076             aopPut(AOP(result),
7077                    aopGet(AOP(right),offset,FALSE,FALSE),
7078                    offset);
7079             offset++;
7080         }
7081         goto release ;
7082     }
7083     
7084     /* so we now know that the size of destination is greater
7085     than the size of the source */
7086     /* we move to result for the size of source */
7087     size = AOP_SIZE(right);
7088     offset = 0 ;
7089     while (size--) {
7090         aopPut(AOP(result),
7091                aopGet(AOP(right),offset,FALSE,FALSE),
7092                offset);
7093         offset++;
7094     }
7095
7096     /* now depending on the sign of the destination */
7097     size = AOP_SIZE(result) - AOP_SIZE(right);
7098     /* if unsigned or not an integral type */
7099     if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) {
7100         while (size--)
7101             aopPut(AOP(result),zero,offset++);
7102     } else {
7103         /* we need to extend the sign :{ */
7104         char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
7105                          FALSE,FALSE);
7106         MOVA(l);
7107         emitcode("rlc","a");
7108         emitcode("subb","a,acc");
7109         while (size--)
7110             aopPut(AOP(result),"a",offset++);   
7111     }
7112
7113     /* we are done hurray !!!! */
7114
7115 release:
7116     freeAsmop(right,NULL,ic,TRUE);
7117     freeAsmop(result,NULL,ic,TRUE);
7118
7119 }
7120
7121 /*-----------------------------------------------------------------*/
7122 /* genDjnz - generate decrement & jump if not zero instrucion      */
7123 /*-----------------------------------------------------------------*/
7124 static int genDjnz (iCode *ic, iCode *ifx)
7125 {
7126     symbol *lbl, *lbl1;
7127     if (!ifx)
7128         return 0;
7129     
7130     /* if the if condition has a false label
7131        then we cannot save */
7132     if (IC_FALSE(ifx))
7133         return 0;
7134
7135     /* if the minus is not of the form 
7136        a = a - 1 */
7137     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
7138         !IS_OP_LITERAL(IC_RIGHT(ic)))
7139         return 0;
7140
7141     if (operandLitValue(IC_RIGHT(ic)) != 1)
7142         return 0;
7143
7144     /* if the size of this greater than one then no
7145        saving */
7146     if (getSize(operandType(IC_RESULT(ic))) > 1)
7147         return 0;
7148
7149     /* otherwise we can save BIG */
7150     lbl = newiTempLabel(NULL);
7151     lbl1= newiTempLabel(NULL);
7152
7153     aopOp(IC_RESULT(ic),ic,FALSE);
7154     
7155     if (IS_AOP_PREG(IC_RESULT(ic))) {
7156         emitcode("dec","%s",
7157                  aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
7158         emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
7159         emitcode("jnz","%05d$",lbl->key+100);
7160     } else {    
7161         emitcode ("djnz","%s,%05d$",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
7162                   lbl->key+100);
7163     }
7164     emitcode ("sjmp","%05d$",lbl1->key+100);
7165     emitcode ("","%05d$:",lbl->key+100);
7166     emitcode ("ljmp","%05d$",IC_TRUE(ifx)->key+100);
7167     emitcode ("","%05d$:",lbl1->key+100);
7168     
7169     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7170     ifx->generated = 1;
7171     return 1;
7172 }
7173
7174 /*-----------------------------------------------------------------*/
7175 /* genReceive - generate code for a receive iCode                  */
7176 /*-----------------------------------------------------------------*/
7177 static void genReceive (iCode *ic)
7178 {    
7179     if (isOperandInFarSpace(IC_RESULT(ic)) && 
7180         ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
7181           IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
7182
7183         int size = getSize(operandType(IC_RESULT(ic)));
7184         int offset =  fReturnSize - size;
7185         while (size--) {
7186             emitcode ("push","%s", (strcmp(fReturn[fReturnSize - offset - 1],"a") ?
7187                                     fReturn[fReturnSize - offset - 1] : "acc"));
7188             offset++;
7189         }
7190         aopOp(IC_RESULT(ic),ic,FALSE);  
7191         size = AOP_SIZE(IC_RESULT(ic));
7192         offset = 0;
7193         while (size--) {
7194             emitcode ("pop","acc");
7195             aopPut (AOP(IC_RESULT(ic)),"a",offset++);
7196         }
7197         
7198     } else {
7199         _G.accInUse++;
7200         aopOp(IC_RESULT(ic),ic,FALSE);  
7201         _G.accInUse--;
7202         assignResultValue(IC_RESULT(ic));       
7203     }
7204
7205     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7206 }
7207
7208 /*-----------------------------------------------------------------*/
7209 /* gen51Code - generate code for 8051 based controllers            */
7210 /*-----------------------------------------------------------------*/
7211 void gen51Code (iCode *lic)
7212 {
7213     iCode *ic;
7214     int cln = 0;
7215
7216     /* Hack-o-matic: change fReturn based on model. */
7217     if (options.model == MODEL_FLAT24)
7218     {
7219         fReturn = fReturn390;
7220         fReturnSize = 5;
7221     }
7222
7223     lineHead = lineCurr = NULL;
7224
7225     /* if debug information required */
7226 /*     if (options.debug && currFunc) { */
7227     if (currFunc) {
7228         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
7229         _G.debugLine = 1;
7230         if (IS_STATIC(currFunc->etype))
7231             emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name); 
7232         else
7233             emitcode("","G$%s$0$0 ==.",currFunc->name);
7234         _G.debugLine = 0;
7235     }
7236     /* stack pointer name */
7237     if (options.useXstack)
7238         spname = "_spx";
7239     else
7240         spname = "sp";
7241     
7242  
7243     for (ic = lic ; ic ; ic = ic->next ) {
7244         
7245         if ( cln != ic->lineno ) {
7246             if ( options.debug ) {
7247                 _G.debugLine = 1;
7248                 emitcode("","C$%s$%d$%d$%d ==.",
7249                          ic->filename,ic->lineno,
7250                          ic->level,ic->block);
7251                 _G.debugLine = 0;
7252             }
7253             emitcode(";","%s %d",ic->filename,ic->lineno);
7254             cln = ic->lineno ;
7255         }
7256         /* if the result is marked as
7257            spilt and rematerializable or code for
7258            this has already been generated then
7259            do nothing */
7260         if (resultRemat(ic) || ic->generated ) 
7261             continue ;
7262         
7263         /* depending on the operation */
7264         switch (ic->op) {
7265         case '!' :
7266             genNot(ic);
7267             break;
7268             
7269         case '~' :
7270             genCpl(ic);
7271             break;
7272             
7273         case UNARYMINUS:
7274             genUminus (ic);
7275             break;
7276             
7277         case IPUSH:
7278             genIpush (ic);
7279             break;
7280             
7281         case IPOP:
7282             /* IPOP happens only when trying to restore a 
7283                spilt live range, if there is an ifx statement
7284                following this pop then the if statement might
7285                be using some of the registers being popped which
7286                would destory the contents of the register so
7287                we need to check for this condition and handle it */
7288             if (ic->next            && 
7289                 ic->next->op == IFX &&
7290                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
7291                 genIfx (ic->next,ic);
7292             else
7293                 genIpop (ic);
7294             break; 
7295             
7296         case CALL:
7297             genCall (ic);
7298             break;
7299             
7300         case PCALL:
7301             genPcall (ic);
7302             break;
7303             
7304         case FUNCTION:
7305             genFunction (ic);
7306             break;
7307             
7308         case ENDFUNCTION:
7309             genEndFunction (ic);
7310             break;
7311             
7312         case RETURN:
7313             genRet (ic);
7314             break;
7315             
7316         case LABEL:
7317             genLabel (ic);
7318             break;
7319             
7320         case GOTO:
7321             genGoto (ic);
7322             break;
7323             
7324         case '+' :
7325             genPlus (ic) ;
7326             break;
7327             
7328         case '-' :
7329             if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
7330                 genMinus (ic);
7331             break;
7332             
7333         case '*' :
7334             genMult (ic);
7335             break;
7336             
7337         case '/' :
7338             genDiv (ic) ;
7339             break;
7340             
7341         case '%' :
7342             genMod (ic);
7343             break;
7344             
7345         case '>' :
7346             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
7347             break;
7348             
7349         case '<' :
7350             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
7351             break;
7352             
7353         case LE_OP:
7354         case GE_OP:
7355         case NE_OP:
7356             
7357             /* note these two are xlated by algebraic equivalence
7358                during parsing SDCC.y */
7359             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
7360                    "got '>=' or '<=' shouldn't have come here");
7361             break;      
7362             
7363         case EQ_OP:
7364             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
7365             break;          
7366             
7367         case AND_OP:
7368             genAndOp (ic);
7369             break;
7370             
7371         case OR_OP:
7372             genOrOp (ic);
7373             break;
7374             
7375         case '^' :
7376             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
7377             break;
7378             
7379         case '|' :
7380                 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
7381             break;
7382             
7383         case BITWISEAND:
7384             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
7385             break;
7386             
7387         case INLINEASM:
7388             genInline (ic);
7389             break;
7390             
7391         case RRC:
7392             genRRC (ic);
7393             break;
7394             
7395         case RLC:
7396             genRLC (ic);
7397             break;
7398             
7399         case GETHBIT:
7400             genGetHbit (ic);
7401             break;
7402             
7403         case LEFT_OP:
7404             genLeftShift (ic);
7405             break;
7406             
7407         case RIGHT_OP:
7408             genRightShift (ic);
7409             break;
7410             
7411         case GET_VALUE_AT_ADDRESS:
7412             genPointerGet(ic);
7413             break;
7414             
7415         case '=' :
7416             if (POINTER_SET(ic))
7417                 genPointerSet(ic);
7418             else
7419                 genAssign(ic);
7420             break;
7421             
7422         case IFX:
7423             genIfx (ic,NULL);
7424             break;
7425             
7426         case ADDRESS_OF:
7427             genAddrOf (ic);
7428             break;
7429             
7430         case JUMPTABLE:
7431             genJumpTab (ic);
7432             break;
7433             
7434         case CAST:
7435             genCast (ic);
7436             break;
7437             
7438         case RECEIVE:
7439             genReceive(ic);
7440             break;
7441             
7442         case SEND:
7443             addSet(&_G.sendSet,ic);
7444             break;
7445
7446         default :
7447             ic = ic;
7448             /*      piCode(ic,stdout); */
7449             
7450         }
7451     }
7452     
7453
7454     /* now we are ready to call the 
7455        peep hole optimizer */
7456     if (!options.nopeep)
7457         peepHole (&lineHead);
7458
7459     /* now do the actual printing */
7460     printLine (lineHead,codeOutFile);
7461     return;
7462 }