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