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