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