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