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