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