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