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