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