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