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