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