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