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