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