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