fix AOP_OP_3_NOFATAL
[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     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
2973         isOperandInFarSpace(IC_RESULT(ic))) \
2974     { \
2975        /* No can do; DPTR & DPTR2 in use, and we need another. */ \
2976        rc = TRUE; \
2977     }  \
2978     else \
2979     { \
2980        aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
2981                                      (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
2982        rc = FALSE; \
2983        if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
2984            AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
2985        { \
2986             /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
2987             fprintf(stderr,                                  \
2988                     "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno);   \
2989        } \
2990     }
2991
2992 #define AOP_OP_2(ic) \
2993     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
2994     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
2995     
2996 #endif
2997
2998
2999 #define AOP_SET_LOCALS(ic) \
3000     left = IC_LEFT(ic); \
3001     right = IC_RIGHT(ic); \
3002     result = IC_RESULT(ic);
3003
3004 /*-----------------------------------------------------------------*/
3005 /* genPlus - generates code for addition                           */
3006 /*-----------------------------------------------------------------*/
3007 static void genPlus (iCode *ic)
3008 {
3009     int size, offset = 0;
3010     bool pushResult = FALSE;
3011     int  rSize;
3012
3013     D(emitcode(";", "genPlus "););
3014
3015     /* special cases :- */
3016
3017 #if 0
3018     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE);
3019     aopOp (IC_LEFT(ic),ic,FALSE, 
3020            (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3021     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2) &&
3022         (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR))
3023     {
3024         pushResult = TRUE;
3025     }
3026     else
3027     {
3028         aopOp (IC_RESULT(ic),ic,TRUE, 
3029                ((AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)
3030              || (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR)));
3031     }
3032 #else
3033     AOP_OP_3_NOFATAL(ic, pushResult);
3034     if (pushResult)
3035     {
3036         D(emitcode(";", "genPlus: must push result: 3 ops in far space"););
3037     }
3038 #endif    
3039
3040     if (!pushResult)
3041     {
3042     /* if literal, literal on the right or
3043        if left requires ACC or right is already
3044        in ACC */
3045     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT)
3046         || ((AOP_NEEDSACC(IC_LEFT(ic))) && !(AOP_NEEDSACC(IC_RIGHT(ic)))) 
3047         || AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC )
3048     {
3049         operand *t = IC_RIGHT(ic);
3050         IC_RIGHT(ic) = IC_LEFT(ic);
3051         IC_LEFT(ic) = t;
3052         emitcode(";", "Swapped plus args.");
3053     }
3054
3055     /* if both left & right are in bit
3056     space */
3057     if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
3058         AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
3059         genPlusBits (ic);
3060         goto release ;
3061     }
3062
3063     /* if left in bit space & right literal */
3064     if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
3065         AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
3066         emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
3067         /* if result in bit space */
3068         if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
3069             if((unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit) != 0L)
3070                 emitcode("cpl","c");
3071             outBitC(IC_RESULT(ic));
3072         } else {
3073             size = getDataSize(IC_RESULT(ic));
3074             _startLazyDPSEvaluation();
3075             while (size--) {
3076                 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,TRUE));
3077                 emitcode("addc","a,#00");
3078                 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
3079             }
3080             _endLazyDPSEvaluation();
3081         }
3082         goto release ;
3083     }
3084
3085     /* if I can do an increment instead
3086     of add then GOOD for ME */
3087     if (genPlusIncr (ic) == TRUE)
3088     {
3089         emitcode(";", "did genPlusIncr");
3090         goto release;   
3091     }
3092
3093     }
3094     size = getDataSize(pushResult ? IC_LEFT(ic) : IC_RESULT(ic));
3095
3096     _startLazyDPSEvaluation();
3097     while(size--)
3098     {
3099         if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) 
3100         {
3101             MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,TRUE));
3102             if(offset == 0)
3103                 emitcode("add","a,%s",
3104                          aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,FALSE));
3105             else
3106                 emitcode("addc","a,%s",
3107                          aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,FALSE));
3108         } else {
3109             MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,TRUE));
3110             if(offset == 0)
3111                 emitcode("add","a,%s",
3112                          aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,FALSE));
3113             else
3114                 emitcode("addc","a,%s",
3115                          aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,FALSE));
3116         }
3117         if (!pushResult)
3118         {
3119             aopPut(AOP(IC_RESULT(ic)),"a",offset);
3120         }
3121         else
3122         {
3123             emitcode("push", "acc");
3124         }
3125         offset++;
3126     }
3127     _endLazyDPSEvaluation();
3128    
3129     if (pushResult)
3130     {
3131         aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
3132
3133         size = getDataSize(IC_LEFT(ic));
3134         rSize = getDataSize(IC_RESULT(ic));
3135         
3136         /* If the pushed data is bigger than the result,
3137          * simply discard unused bytes. Icky, but works.
3138          *
3139          * Should we throw a warning here? We're losing data...
3140          */
3141         while (size > rSize)
3142         {
3143            D(emitcode(";", "discarding unused result byte."););
3144            emitcode("pop", "acc");
3145            size--;
3146            offset--; 
3147         }
3148         if (size < rSize)
3149         {
3150             emitcode("clr", "a");
3151             /* Conversly, we haven't pushed enough here.
3152              * just zero-pad, and all is well. 
3153              */
3154             while (size < rSize)
3155             {
3156                 emitcode("push", "acc");
3157                 size++;
3158                 offset++;
3159             }
3160         }
3161
3162         _startLazyDPSEvaluation();
3163         while(size--)
3164         {
3165             emitcode("pop", "acc");
3166             aopPut(AOP(IC_RESULT(ic)), "a", --offset);
3167         }
3168         _endLazyDPSEvaluation();
3169     }
3170
3171     adjustArithmeticResult(ic);
3172
3173 release:
3174     freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3175     freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3176     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3177 }
3178
3179 /*-----------------------------------------------------------------*/
3180 /* genMinusDec :- does subtraction with deccrement if possible     */
3181 /*-----------------------------------------------------------------*/
3182 static bool genMinusDec (iCode *ic)
3183 {
3184     unsigned int icount ;
3185     unsigned int size = getDataSize(IC_RESULT(ic));
3186
3187     /* will try to generate an increment */
3188     /* if the right side is not a literal 
3189     we cannot */
3190     if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
3191         return FALSE ;
3192
3193     /* if the literal value of the right hand side
3194     is greater than 4 then it is not worth it */
3195     if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
3196         return FALSE ;
3197
3198     /* if decrement 16 bits in register */
3199     if (AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
3200         AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
3201         sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
3202         (size > 1) &&
3203         (icount == 1)) {
3204             symbol *tlbl;
3205             int emitTlbl;
3206             int labelRange;
3207
3208             /* If the next instruction is a goto and the goto target
3209          * is <= 5 instructions previous to this, we can generate
3210              * jumps straight to that target.
3211              */
3212             if (ic->next && ic->next->op == GOTO
3213                 && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
3214                 && labelRange <= 5 )
3215             {        
3216                emitcode(";", "tail decrement optimized (range %d)", labelRange);
3217                tlbl = IC_LABEL(ic->next);
3218                emitTlbl = 0;
3219             }
3220             else
3221             {
3222                 tlbl = newiTempLabel(NULL);
3223                 emitTlbl = 1;
3224             }
3225         
3226                 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE));
3227                 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
3228                    AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR ||
3229                    IS_AOP_PREG(IC_RESULT(ic)))
3230                         emitcode("cjne","%s,#0xff,%05d$"
3231                                          ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE)
3232                                          ,tlbl->key+100);
3233                 else{
3234                         emitcode("mov","a,#0xff");
3235                         emitcode("cjne","a,%s,%05d$"
3236                                          ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE)
3237                                          ,tlbl->key+100);
3238                 }
3239                 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE));
3240                 if (size > 2)
3241                 {
3242                         if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
3243                            AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR ||
3244                            IS_AOP_PREG(IC_RESULT(ic)))
3245                                 emitcode("cjne","%s,#0xff,%05d$"
3246                                                  ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE)
3247                                                  ,tlbl->key+100);
3248                         else{
3249                                 emitcode("cjne","a,%s,%05d$"
3250                                                  ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE)
3251                                                  ,tlbl->key+100);
3252                         }
3253                         emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE));
3254                 }
3255                 if (size > 3)
3256                 {
3257                         if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
3258                            AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR ||
3259                            IS_AOP_PREG(IC_RESULT(ic)))
3260                                 emitcode("cjne","%s,#0xff,%05d$"
3261                                                  ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE)
3262                                                  ,tlbl->key+100);
3263                         else{
3264                                 emitcode("cjne","a,%s,%05d$"
3265                                                  ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE)
3266                                                  ,tlbl->key+100);
3267                         }
3268                         emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE,FALSE));
3269                 }
3270                 if (emitTlbl)
3271                 {
3272                     emitcode("","%05d$:",tlbl->key+100);
3273                 }
3274         return TRUE;
3275     }
3276
3277     /* if the sizes are greater than 1 then we cannot */
3278     if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
3279         AOP_SIZE(IC_LEFT(ic)) > 1   )
3280         return FALSE ;
3281
3282     /* we can if the aops of the left & result match or
3283     if they are in registers and the registers are the
3284     same */
3285     if (
3286         AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
3287         AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
3288         sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
3289
3290         _startLazyDPSEvaluation();
3291         while (icount--) 
3292         {
3293             emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
3294         }
3295         _endLazyDPSEvaluation();
3296
3297         return TRUE ;
3298     }
3299
3300     return FALSE ;
3301 }
3302
3303 /*-----------------------------------------------------------------*/
3304 /* addSign - complete with sign                                    */
3305 /*-----------------------------------------------------------------*/
3306 static void addSign(operand *result, int offset, int sign)
3307 {
3308     int size = (getDataSize(result) - offset);
3309     if(size > 0){
3310         if(sign){
3311             emitcode("rlc","a");
3312             emitcode("subb","a,acc");
3313             while(size--)
3314                 aopPut(AOP(result),"a",offset++); 
3315         } else
3316             while(size--)
3317                 aopPut(AOP(result),zero,offset++);
3318     }
3319 }
3320
3321 /*-----------------------------------------------------------------*/
3322 /* genMinusBits - generates code for subtraction  of two bits      */
3323 /*-----------------------------------------------------------------*/
3324 static void genMinusBits (iCode *ic)
3325 {
3326     symbol *lbl = newiTempLabel(NULL);
3327     
3328     D(emitcode(";", "genMinusBits "););    
3329
3330     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
3331         emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
3332         emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
3333         emitcode("cpl","c");
3334         emitcode("","%05d$:",(lbl->key+100));
3335         outBitC(IC_RESULT(ic));
3336     }
3337     else{
3338         emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
3339         emitcode("subb","a,acc");
3340         emitcode("jnb","%s,%05d$",AOP(IC_LEFT(ic))->aopu.aop_dir,(lbl->key+100));
3341         emitcode("inc","a");
3342         emitcode("","%05d$:",(lbl->key+100));
3343         aopPut(AOP(IC_RESULT(ic)),"a",0);
3344         addSign(IC_RESULT(ic), MSB16, SPEC_USIGN(getSpec(operandType(IC_RESULT(ic)))));
3345     }
3346 }
3347
3348 /*-----------------------------------------------------------------*/
3349 /* genMinus - generates code for subtraction                       */
3350 /*-----------------------------------------------------------------*/
3351 static void genMinus (iCode *ic)
3352 {
3353     int size, offset = 0;
3354     int rSize;
3355     unsigned long lit = 0L;
3356     bool pushResult = FALSE;
3357
3358     D(emitcode(";", "genMinus "););
3359
3360     aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
3361     aopOp (IC_RIGHT(ic),ic,FALSE, TRUE);
3362     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) &&
3363         (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR2))
3364     {
3365         pushResult = TRUE;
3366     }
3367     else
3368     {
3369         aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
3370
3371     /* special cases :- */
3372     /* if both left & right are in bit space */
3373     if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
3374         AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
3375         genMinusBits (ic);
3376         goto release ;
3377     }
3378
3379     /* if I can do an decrement instead
3380     of subtract then GOOD for ME */
3381     if (genMinusDec (ic) == TRUE)
3382         goto release;
3383
3384     }
3385
3386     size = getDataSize(pushResult ? IC_LEFT(ic) : IC_RESULT(ic));
3387
3388     if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
3389         CLRC;
3390     }
3391     else{
3392         lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3393         lit = - (long)lit;
3394     }
3395
3396
3397     /* if literal, add a,#-lit, else normal subb */
3398     _startLazyDPSEvaluation();
3399     while (size--) {
3400         MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,TRUE));
3401         if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)  
3402             emitcode("subb","a,%s",
3403                      aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,FALSE));
3404         else{
3405             /* first add without previous c */
3406             if(!offset)
3407                 emitcode("add","a,#0x%02x",
3408                          (unsigned int)(lit & 0x0FFL));
3409             else
3410                 emitcode("addc","a,#0x%02x",
3411                          (unsigned int)((lit >> (offset*8)) & 0x0FFL));
3412         }
3413
3414         if (pushResult)
3415         {
3416             emitcode("push", "acc");
3417         }
3418         else
3419         {
3420             aopPut(AOP(IC_RESULT(ic)),"a",offset);
3421         }
3422         offset++;
3423     }
3424     _endLazyDPSEvaluation();
3425
3426     if (pushResult)
3427     {
3428         aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
3429
3430         size = getDataSize(IC_LEFT(ic));
3431         rSize = getDataSize(IC_RESULT(ic));
3432
3433         /* If the pushed data is bigger than the result,
3434          * simply discard unused bytes. Icky, but works.
3435          *
3436          * Should we throw a warning here? We're losing data...
3437          */
3438         while (size > getDataSize(IC_RESULT(ic)))
3439         {
3440            emitcode(";", "discarding unused result byte.");
3441            emitcode("pop", "acc");
3442            size--;
3443            offset--; 
3444         }
3445         if (size < rSize)
3446         {
3447             emitcode("clr", "a");
3448             /* Conversly, we haven't pushed enough here.
3449              * just zero-pad, and all is well. 
3450              */
3451             while (size < rSize)
3452             {
3453                 emitcode("push", "acc");
3454                 size++;
3455                 offset++;
3456             }
3457         }
3458
3459         while(size--)
3460         {
3461             emitcode("pop", "acc");
3462             aopPut(AOP(IC_RESULT(ic)), "a", --offset);
3463         }
3464     }
3465
3466     adjustArithmeticResult(ic);
3467         
3468 release:
3469     freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3470     freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3471     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3472 }
3473
3474
3475 /*-----------------------------------------------------------------*/
3476 /* genMultbits :- multiplication of bits                           */
3477 /*-----------------------------------------------------------------*/
3478 static void genMultbits (operand *left, 
3479                          operand *right, 
3480                          operand *result)
3481 {
3482     emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3483     emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
3484     outBitC(result);
3485 }
3486
3487
3488 /*-----------------------------------------------------------------*/
3489 /* genMultOneByte : 8 bit multiplication & division                */
3490 /*-----------------------------------------------------------------*/
3491 static void genMultOneByte (operand *left,
3492                             operand *right,
3493                             operand *result)
3494 {
3495     sym_link *opetype = operandType(result);
3496     char *l ;
3497     symbol *lbl ;
3498     int size,offset;
3499
3500     /* (if two literals, the value is computed before) */
3501     /* if one literal, literal on the right */
3502     if (AOP_TYPE(left) == AOP_LIT){
3503         operand *t = right;
3504         right = left;
3505         left = t;
3506     }
3507
3508     size = AOP_SIZE(result);
3509     /* signed or unsigned */
3510     emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3511     l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3512     MOVA(l);       
3513     emitcode("mul","ab");
3514     /* if result size = 1, mul signed = mul unsigned */
3515     aopPut(AOP(result),"a",0);
3516     if (size > 1){
3517         if (SPEC_USIGN(opetype)){
3518             aopPut(AOP(result),"b",1);
3519             if (size > 2)
3520                 /* for filling the MSBs */
3521                 emitcode("clr","a");
3522         }
3523         else{
3524             emitcode("mov","a,b");
3525
3526             /* adjust the MSB if left or right neg */
3527
3528             /* if one literal */
3529             if (AOP_TYPE(right) == AOP_LIT){
3530                 /* AND literal negative */
3531                 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3532                     /* adjust MSB (c==0 after mul) */
3533                     emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3534                 }
3535             }
3536             else{
3537                 lbl = newiTempLabel(NULL);
3538                 emitcode("xch","a,%s",aopGet(AOP(right),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(right),0,FALSE,FALSE,FALSE));
3542                 lbl = newiTempLabel(NULL);      
3543                 emitcode("jc","%05d$",(lbl->key+100));          
3544                 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3545                 emitcode("","%05d$:",(lbl->key+100));
3546             }
3547
3548             lbl = newiTempLabel(NULL);
3549             emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3550             emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
3551             emitcode("","%05d$:",(lbl->key+100));
3552             emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3553             lbl = newiTempLabel(NULL);      
3554             emitcode("jc","%05d$",(lbl->key+100));          
3555             emitcode("subb","a,%s", aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3556             emitcode("","%05d$:",(lbl->key+100));
3557
3558             aopPut(AOP(result),"a",1);
3559             if(size > 2){
3560                 /* get the sign */
3561                 emitcode("rlc","a");
3562                 emitcode("subb","a,acc");
3563             }
3564         }
3565         size -= 2;   
3566         offset = 2;
3567         if (size > 0)
3568             while (size--)
3569                 aopPut(AOP(result),"a",offset++);
3570     }
3571 }
3572
3573 /*-----------------------------------------------------------------*/
3574 /* genMult - generates code for multiplication                     */
3575 /*-----------------------------------------------------------------*/
3576 static void genMult (iCode *ic)
3577 {
3578     operand *left = IC_LEFT(ic);
3579     operand *right = IC_RIGHT(ic);
3580     operand *result= IC_RESULT(ic);   
3581
3582     D(emitcode(";", "genMult "););
3583
3584     /* assign the amsops */
3585     AOP_OP_3(ic);
3586 #if 0
3587     aopOp (left,ic,FALSE, FALSE);
3588     aopOp (right,ic,FALSE, TRUE);
3589     aopOp (result,ic,TRUE, FALSE);
3590 #endif
3591
3592     /* special cases first */
3593     /* both are bits */
3594     if (AOP_TYPE(left) == AOP_CRY &&
3595         AOP_TYPE(right)== AOP_CRY) {
3596         genMultbits(left,right,result);
3597         goto release ;
3598     }
3599
3600     /* if both are of size == 1 */
3601     if (AOP_SIZE(left) == 1 &&
3602         AOP_SIZE(right) == 1 ) {
3603         genMultOneByte(left,right,result);
3604         goto release ;
3605     }
3606
3607     /* should have been converted to function call */       
3608     assert(1) ;
3609
3610 release :
3611     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3612     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3613     freeAsmop(result,NULL,ic,TRUE); 
3614 }
3615
3616 /*-----------------------------------------------------------------*/
3617 /* genDivbits :- division of bits                                  */
3618 /*-----------------------------------------------------------------*/
3619 static void genDivbits (operand *left, 
3620                         operand *right, 
3621                         operand *result)
3622 {
3623
3624     char *l;
3625
3626     /* the result must be bit */
3627     LOAD_AB_FOR_DIV(left, right, l);
3628     emitcode("div","ab");
3629     emitcode("rrc","a");
3630     aopPut(AOP(result),"c",0);
3631 }
3632
3633 /*-----------------------------------------------------------------*/
3634 /* genDivOneByte : 8 bit division                                  */
3635 /*-----------------------------------------------------------------*/
3636 static void genDivOneByte (operand *left,
3637                            operand *right,
3638                            operand *result)
3639 {
3640     sym_link *opetype = operandType(result);
3641     char *l ;
3642     symbol *lbl ;
3643     int size,offset;
3644
3645     size = AOP_SIZE(result) - 1;
3646     offset = 1;
3647     /* signed or unsigned */
3648     if (SPEC_USIGN(opetype)) {
3649         /* unsigned is easy */
3650         LOAD_AB_FOR_DIV(left, right, l);
3651         emitcode("div","ab");
3652         aopPut(AOP(result),"a",0);
3653         while (size--)
3654             aopPut(AOP(result),zero,offset++);
3655         return ;
3656     }
3657
3658     /* signed is a little bit more difficult */
3659
3660     /* save the signs of the operands */
3661     l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);    
3662     MOVA(l);    
3663     emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE,FALSE));
3664     emitcode("push","acc"); /* save it on the stack */
3665
3666     /* now sign adjust for both left & right */
3667     l =  aopGet(AOP(right),0,FALSE,FALSE,TRUE);
3668     MOVA(l);       
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     emitcode("mov","b,a");
3675
3676     /* sign adjust left side */
3677     l =  aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3678     MOVA(l);
3679
3680     lbl = newiTempLabel(NULL);
3681     emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3682     emitcode("cpl","a");
3683     emitcode("inc","a");
3684     emitcode("","%05d$:",(lbl->key+100));
3685
3686     /* now the division */
3687     emitcode("nop", "; workaround for DS80C390 div bug.");
3688     emitcode("div","ab");
3689     /* we are interested in the lower order
3690     only */
3691     emitcode("mov","b,a");
3692     lbl = newiTempLabel(NULL);
3693     emitcode("pop","acc");   
3694     /* if there was an over flow we don't 
3695     adjust the sign of the result */
3696     emitcode("jb","ov,%05d$",(lbl->key+100));
3697     emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3698     CLRC;
3699     emitcode("clr","a");
3700     emitcode("subb","a,b");
3701     emitcode("mov","b,a");
3702     emitcode("","%05d$:",(lbl->key+100));
3703
3704     /* now we are done */
3705     aopPut(AOP(result),"b",0);
3706     if(size > 0){
3707         emitcode("mov","c,b.7");
3708         emitcode("subb","a,acc");   
3709     }
3710     while (size--)
3711         aopPut(AOP(result),"a",offset++);
3712
3713 }
3714
3715 /*-----------------------------------------------------------------*/
3716 /* genDiv - generates code for division                            */
3717 /*-----------------------------------------------------------------*/
3718 static void genDiv (iCode *ic)
3719 {
3720     operand *left = IC_LEFT(ic);
3721     operand *right = IC_RIGHT(ic);
3722     operand *result= IC_RESULT(ic);   
3723
3724     D(emitcode(";", "genDiv "););
3725
3726     /* assign the amsops */
3727     AOP_OP_3(ic);
3728 #if 0
3729     aopOp (left,ic,FALSE, FALSE);
3730     aopOp (right,ic,FALSE, TRUE);
3731     aopOp (result,ic,TRUE, FALSE);
3732 #endif
3733
3734     /* special cases first */
3735     /* both are bits */
3736     if (AOP_TYPE(left) == AOP_CRY &&
3737         AOP_TYPE(right)== AOP_CRY) {
3738         genDivbits(left,right,result);
3739         goto release ;
3740     }
3741
3742     /* if both are of size == 1 */
3743     if (AOP_SIZE(left) == 1 &&
3744         AOP_SIZE(right) == 1 ) {
3745         genDivOneByte(left,right,result);
3746         goto release ;
3747     }
3748
3749     /* should have been converted to function call */
3750     assert(1);
3751 release :
3752     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3753     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3754     freeAsmop(result,NULL,ic,TRUE); 
3755 }
3756
3757 /*-----------------------------------------------------------------*/
3758 /* genModbits :- modulus of bits                                   */
3759 /*-----------------------------------------------------------------*/
3760 static void genModbits (operand *left, 
3761                         operand *right, 
3762                         operand *result)
3763 {
3764
3765     char *l;
3766
3767     /* the result must be bit */    
3768     LOAD_AB_FOR_DIV(left, right, l);
3769     emitcode("div","ab");
3770     emitcode("mov","a,b");
3771     emitcode("rrc","a");
3772     aopPut(AOP(result),"c",0);
3773 }
3774
3775 /*-----------------------------------------------------------------*/
3776 /* genModOneByte : 8 bit modulus                                   */
3777 /*-----------------------------------------------------------------*/
3778 static void genModOneByte (operand *left,
3779                            operand *right,
3780                            operand *result)
3781 {
3782     sym_link *opetype = operandType(result);
3783     char *l ;
3784     symbol *lbl ;
3785
3786     /* signed or unsigned */
3787     if (SPEC_USIGN(opetype)) {
3788         /* unsigned is easy */
3789         LOAD_AB_FOR_DIV(left, right, l);
3790         emitcode("div","ab");
3791         aopPut(AOP(result),"b",0);
3792         return ;
3793     }
3794
3795     /* signed is a little bit more difficult */
3796
3797     /* save the signs of the operands */
3798     l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3799     MOVA(l);
3800
3801     emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3802     emitcode("push","acc"); /* save it on the stack */
3803
3804     /* now sign adjust for both left & right */
3805     l =  aopGet(AOP(right),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     emitcode("mov","b,a"); 
3814
3815     /* sign adjust left side */
3816     l =  aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3817     MOVA(l);
3818
3819     lbl = newiTempLabel(NULL);
3820     emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3821     emitcode("cpl","a");   
3822     emitcode("inc","a");
3823     emitcode("","%05d$:",(lbl->key+100));
3824
3825     /* now the multiplication */
3826     emitcode("nop", "; workaround for DS80C390 div bug.");
3827     emitcode("div","ab");
3828     /* we are interested in the lower order
3829     only */
3830     lbl = newiTempLabel(NULL);
3831     emitcode("pop","acc");   
3832     /* if there was an over flow we don't 
3833     adjust the sign of the result */
3834     emitcode("jb","ov,%05d$",(lbl->key+100));
3835     emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3836     CLRC ;
3837     emitcode("clr","a");
3838     emitcode("subb","a,b");
3839     emitcode("mov","b,a");
3840     emitcode("","%05d$:",(lbl->key+100));
3841
3842     /* now we are done */
3843     aopPut(AOP(result),"b",0);
3844
3845 }
3846
3847 /*-----------------------------------------------------------------*/
3848 /* genMod - generates code for division                            */
3849 /*-----------------------------------------------------------------*/
3850 static void genMod (iCode *ic)
3851 {
3852     operand *left = IC_LEFT(ic);
3853     operand *right = IC_RIGHT(ic);
3854     operand *result= IC_RESULT(ic);  
3855
3856     D(emitcode(";", "genMod "););
3857
3858     /* assign the amsops */
3859     AOP_OP_3(ic);
3860 #if 0
3861     aopOp (left,ic,FALSE, FALSE);
3862     aopOp (right,ic,FALSE, TRUE);
3863     aopOp (result,ic,TRUE, FALSE);
3864 #endif
3865
3866     /* special cases first */
3867     /* both are bits */
3868     if (AOP_TYPE(left) == AOP_CRY &&
3869         AOP_TYPE(right)== AOP_CRY) {
3870         genModbits(left,right,result);
3871         goto release ;
3872     }
3873
3874     /* if both are of size == 1 */
3875     if (AOP_SIZE(left) == 1 &&
3876         AOP_SIZE(right) == 1 ) {
3877         genModOneByte(left,right,result);
3878         goto release ;
3879     }
3880
3881     /* should have been converted to function call */
3882     assert(1);
3883
3884 release :
3885     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3886     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3887     freeAsmop(result,NULL,ic,TRUE); 
3888 }
3889
3890 /*-----------------------------------------------------------------*/
3891 /* genIfxJump :- will create a jump depending on the ifx           */
3892 /*-----------------------------------------------------------------*/
3893 static void genIfxJump (iCode *ic, char *jval)
3894 {
3895     symbol *jlbl ;
3896     symbol *tlbl = newiTempLabel(NULL);
3897     char *inst;
3898
3899     D(emitcode(";", "genIfxJump "););
3900
3901     /* if true label then we jump if condition
3902     supplied is true */
3903     if ( IC_TRUE(ic) ) {
3904         jlbl = IC_TRUE(ic);
3905         inst = ((strcmp(jval,"a") == 0 ? "jz" :
3906                  (strcmp(jval,"c") == 0 ? "jnc" : "jnb" )));
3907     }
3908     else {
3909         /* false label is present */
3910         jlbl = IC_FALSE(ic) ;
3911         inst = ((strcmp(jval,"a") == 0 ? "jnz" :
3912                  (strcmp(jval,"c") == 0 ? "jc" : "jb" )));              
3913     }
3914     if (strcmp(inst,"jb") == 0 || strcmp(inst,"jnb") == 0) 
3915         emitcode(inst,"%s,%05d$",jval,(tlbl->key+100));
3916     else
3917         emitcode(inst,"%05d$",tlbl->key+100);
3918     emitcode("ljmp","%05d$",jlbl->key+100);
3919     emitcode("","%05d$:",tlbl->key+100);                
3920
3921     /* mark the icode as generated */
3922     ic->generated = 1;
3923 }
3924
3925 /*-----------------------------------------------------------------*/
3926 /* genCmp :- greater or less than comparison                       */
3927 /*-----------------------------------------------------------------*/
3928 static void genCmp (operand *left,operand *right,
3929                     iCode *ic, iCode *ifx, int sign)
3930 {
3931     int                 size, offset = 0 ;
3932     unsigned long       lit = 0L;
3933     operand             *result;
3934
3935     D(emitcode(";", "genCmp"););
3936
3937     result = IC_RESULT(ic);
3938
3939     /* if left & right are bit variables */
3940     if (AOP_TYPE(left) == AOP_CRY &&
3941         AOP_TYPE(right) == AOP_CRY ) {
3942         emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3943         emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3944     } else {
3945         /* subtract right from left if at the
3946         end the carry flag is set then we know that
3947         left is greater than right */
3948         size = max(AOP_SIZE(left),AOP_SIZE(right));
3949
3950         /* if unsigned char cmp with lit, do cjne left,#right,zz */
3951         if((size == 1) && !sign &&
3952            (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
3953             symbol *lbl  = newiTempLabel(NULL);
3954             emitcode("cjne","%s,%s,%05d$",
3955                      aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
3956                      aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
3957                      lbl->key+100);
3958             emitcode("","%05d$:",lbl->key+100);
3959         } else {
3960             if (AOP_TYPE(right) == AOP_LIT)
3961             {
3962                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3963                 /* optimize if(x < 0) or if(x >= 0) */
3964                 if(lit == 0L)
3965                 {
3966                     if(!sign)
3967                     {
3968                         CLRC;
3969                     }
3970                     else
3971                     {
3972                         MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE,FALSE,TRUE));
3973                         
3974                         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3975                         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3976                         
3977                         aopOp(result,ic,FALSE, FALSE);
3978                         
3979                         if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx)
3980                         {
3981                             freeAsmop(result,NULL,ic,TRUE);
3982                             genIfxJump (ifx,"acc.7");
3983                             return;
3984                         }
3985                         else
3986                         {
3987                             emitcode("rlc","a");
3988                         }
3989                         goto release_freedLR;
3990                     }
3991                     goto release;
3992                 }
3993             }
3994             CLRC;
3995             while (size--)
3996             {
3997                 emitcode(";", "genCmp #1: %d/%d/%d", size, sign, offset);
3998                 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
3999                 emitcode(";", "genCmp #2");
4000                 if (sign && (size == 0))
4001                 {
4002                     emitcode(";", "genCmp #3");
4003                     emitcode("xrl","a,#0x80");
4004                     if (AOP_TYPE(right) == AOP_LIT)
4005                     {
4006                         unsigned long lit = (unsigned long)
4007                             floatFromVal(AOP(right)->aopu.aop_lit);
4008                         emitcode(";", "genCmp #3.1");
4009                         emitcode("subb","a,#0x%02x",
4010                             0x80 ^ (unsigned int)((lit >> (offset*8)) & 0x0FFL));
4011                     }
4012                     else
4013                     {
4014                         emitcode(";", "genCmp #3.2");
4015                         if (AOP_NEEDSACC(right))
4016                         {
4017                             emitcode("push", "acc");
4018                         }
4019                         emitcode("mov","b,%s",aopGet(AOP(right),offset++,
4020                                   FALSE,FALSE,FALSE));
4021                         emitcode("xrl","b,#0x80");
4022                         if (AOP_NEEDSACC(right))
4023                         {
4024                             emitcode("pop", "acc");
4025                         }
4026                         emitcode("subb","a,b");
4027                     }
4028                 }
4029                 else
4030                 {
4031                     const char *s;
4032
4033                     emitcode(";", "genCmp #4");
4034                     if (AOP_NEEDSACC(right))
4035                     {
4036                         /* Yuck!! */
4037                         emitcode(";", "genCmp #4.1");
4038                         emitcode("xch", "a, b");
4039                         MOVA(aopGet(AOP(right),offset++,FALSE,FALSE,TRUE));
4040                         emitcode("xch", "a, b");
4041                         s = "b";
4042                     }
4043                     else
4044                     {
4045                         emitcode(";", "genCmp #4.2");
4046                         s = aopGet(AOP(right),offset++,FALSE,FALSE,FALSE);
4047                     }
4048
4049                     emitcode("subb","a,%s",s);
4050                 }
4051             }
4052         }
4053     }
4054
4055 release:
4056 /* Don't need the left & right operands any more; do need the result. */
4057     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4058     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4059                         
4060     aopOp(result,ic,FALSE, FALSE);
4061
4062 release_freedLR:
4063
4064     if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) 
4065     {
4066         outBitC(result);
4067     } 
4068     else 
4069     {
4070         /* if the result is used in the next
4071         ifx conditional branch then generate
4072         code a little differently */
4073         if (ifx )
4074         {
4075             genIfxJump (ifx,"c");
4076         }
4077         else
4078         {
4079             outBitC(result);
4080         }
4081         /* leave the result in acc */
4082     }
4083     freeAsmop(result,NULL,ic,TRUE);
4084 }
4085
4086 /*-----------------------------------------------------------------*/
4087 /* genCmpGt :- greater than comparison                             */
4088 /*-----------------------------------------------------------------*/
4089 static void genCmpGt (iCode *ic, iCode *ifx)
4090 {
4091     operand *left, *right;
4092     sym_link *letype , *retype;
4093     int sign ;
4094
4095     D(emitcode(";", "genCmpGt "););
4096
4097     left = IC_LEFT(ic);
4098     right= IC_RIGHT(ic);
4099
4100     letype = getSpec(operandType(left));
4101     retype =getSpec(operandType(right));
4102     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4103
4104     /* assign the left & right amsops */
4105     AOP_OP_2(ic);
4106
4107     genCmp(right, left, ic, ifx, sign);
4108 }
4109
4110 /*-----------------------------------------------------------------*/
4111 /* genCmpLt - less than comparisons                                */
4112 /*-----------------------------------------------------------------*/
4113 static void genCmpLt (iCode *ic, iCode *ifx)
4114 {
4115     operand *left, *right;
4116     sym_link *letype , *retype;
4117     int sign ;
4118
4119     D(emitcode(";", "genCmpLt "););
4120
4121     left = IC_LEFT(ic);
4122     right= IC_RIGHT(ic);
4123
4124     letype = getSpec(operandType(left));
4125     retype =getSpec(operandType(right));
4126     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4127
4128     /* assign the left & right amsops */
4129     AOP_OP_2(ic);
4130
4131     genCmp(left, right, ic, ifx, sign);
4132 }
4133
4134 /*-----------------------------------------------------------------*/
4135 /* gencjneshort - compare and jump if not equal                    */
4136 /*-----------------------------------------------------------------*/
4137 static void gencjneshort(operand *left, operand *right, symbol *lbl)
4138 {
4139     int size = max(AOP_SIZE(left),AOP_SIZE(right));
4140     int offset = 0;
4141     unsigned long lit = 0L;
4142
4143     D(emitcode(";", "gencjneshort"););
4144
4145     /* if the left side is a literal or 
4146     if the right is in a pointer register and left 
4147     is not */
4148     if ((AOP_TYPE(left) == AOP_LIT) || 
4149         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4150         operand *t = right;
4151         right = left;
4152         left = t;
4153     }
4154     
4155     if(AOP_TYPE(right) == AOP_LIT)
4156         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4157         
4158     if (opIsGptr(left) || opIsGptr(right))
4159     {
4160         /* We are comparing a generic pointer to something.
4161          * Exclude the generic type byte from the comparison.
4162          */
4163         size--;
4164         D(emitcode(";", "cjneshort: generic ptr special case.");) 
4165     }
4166          
4167
4168     /* if the right side is a literal then anything goes */
4169     if (AOP_TYPE(right) == AOP_LIT &&
4170         AOP_TYPE(left) != AOP_DIR ) {
4171         while (size--) {
4172             char *l = aopGet(AOP(left), offset, FALSE, FALSE,TRUE);
4173             MOVA(l);
4174             emitcode("cjne","a,%s,%05d$",
4175                      aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
4176                      lbl->key+100);
4177             offset++;
4178         }
4179     }
4180
4181     /* if the right side is in a register or in direct space or
4182     if the left is a pointer register & right is not */    
4183     else if (AOP_TYPE(right) == AOP_REG ||
4184              AOP_TYPE(right) == AOP_DIR || 
4185              (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4186              (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) 
4187     {
4188         while (size--) 
4189         {
4190             MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
4191             if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
4192                ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
4193                 emitcode("jnz","%05d$",lbl->key+100);
4194             else
4195                 emitcode("cjne","a,%s,%05d$",
4196                          aopGet(AOP(right),offset,FALSE,TRUE,FALSE),
4197                          lbl->key+100);
4198             offset++;
4199         }
4200     } else {
4201         /* right is a pointer reg need both a & b */
4202         while(size--) {
4203             char *l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
4204             if(strcmp(l,"b"))
4205                 emitcode("mov","b,%s",l);
4206             MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4207             emitcode("cjne","a,b,%05d$",lbl->key+100);    
4208             offset++;
4209         }
4210     }
4211 }
4212
4213 /*-----------------------------------------------------------------*/
4214 /* gencjne - compare and jump if not equal                         */
4215 /*-----------------------------------------------------------------*/
4216 static void gencjne(operand *left, operand *right, symbol *lbl)
4217 {
4218     symbol *tlbl  = newiTempLabel(NULL);
4219
4220     D(emitcode(";", "gencjne"););
4221
4222     gencjneshort(left, right, lbl);
4223
4224     emitcode("mov","a,%s",one);
4225     emitcode("sjmp","%05d$",tlbl->key+100);
4226     emitcode("","%05d$:",lbl->key+100);
4227     emitcode("clr","a");
4228     emitcode("","%05d$:",tlbl->key+100);
4229 }
4230
4231 /*-----------------------------------------------------------------*/
4232 /* genCmpEq - generates code for equal to                          */
4233 /*-----------------------------------------------------------------*/
4234 static void genCmpEq (iCode *ic, iCode *ifx)
4235 {
4236     operand *left, *right, *result;
4237
4238     D(emitcode(";", "genCmpEq "););
4239
4240     AOP_OP_2(ic);
4241     AOP_SET_LOCALS(ic);
4242 #if 0
4243     aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
4244     aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
4245     aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4246 #endif
4247
4248     /* if literal, literal on the right or 
4249     if the right is in a pointer register and left 
4250     is not */
4251     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
4252         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4253         operand *t = IC_RIGHT(ic);
4254         IC_RIGHT(ic) = IC_LEFT(ic);
4255         IC_LEFT(ic) = t;
4256     }
4257
4258     if (ifx && /* !AOP_SIZE(result) */ 
4259        OP_SYMBOL(result) && 
4260        OP_SYMBOL(result)->regType == REG_CND)
4261     {
4262         symbol *tlbl;
4263         /* if they are both bit variables */
4264         if (AOP_TYPE(left) == AOP_CRY &&
4265             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4266             if(AOP_TYPE(right) == AOP_LIT){
4267                 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4268                 if(lit == 0L){
4269                     emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4270                     emitcode("cpl","c");
4271                 } else if(lit == 1L) {
4272                     emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4273                 } else {
4274                     emitcode("clr","c");
4275                 }
4276                 /* AOP_TYPE(right) == AOP_CRY */
4277             } else {
4278                 symbol *lbl = newiTempLabel(NULL);
4279                 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4280                 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
4281                 emitcode("cpl","c");
4282                 emitcode("","%05d$:",(lbl->key+100));
4283             }
4284             /* if true label then we jump if condition
4285             supplied is true */
4286             tlbl = newiTempLabel(NULL);
4287             if ( IC_TRUE(ifx) ) {
4288                 emitcode("jnc","%05d$",tlbl->key+100);
4289                 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
4290             } else {
4291                 emitcode("jc","%05d$",tlbl->key+100);
4292                 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
4293             }
4294             emitcode("","%05d$:",tlbl->key+100);                
4295         } else {
4296             tlbl = newiTempLabel(NULL);
4297             gencjneshort(left, right, tlbl);
4298             if ( IC_TRUE(ifx) ) {
4299                 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
4300                 emitcode("","%05d$:",tlbl->key+100);                
4301             } else {
4302                 symbol *lbl = newiTempLabel(NULL);
4303                 emitcode("sjmp","%05d$",lbl->key+100);
4304                 emitcode("","%05d$:",tlbl->key+100);                
4305                 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
4306                 emitcode("","%05d$:",lbl->key+100);             
4307             }
4308         }
4309         /* mark the icode as generated */
4310         ifx->generated = 1;
4311         
4312         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4313         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4314         return ;
4315     }
4316
4317     /* if they are both bit variables */
4318     if (AOP_TYPE(left) == AOP_CRY &&
4319         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4320         if(AOP_TYPE(right) == AOP_LIT){
4321             unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4322             if(lit == 0L){
4323                 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4324                 emitcode("cpl","c");
4325             } else if(lit == 1L) {
4326                 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4327             } else {
4328                 emitcode("clr","c");
4329             }
4330             /* AOP_TYPE(right) == AOP_CRY */
4331         } else {
4332             symbol *lbl = newiTempLabel(NULL);
4333             emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4334             emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
4335             emitcode("cpl","c");
4336             emitcode("","%05d$:",(lbl->key+100));
4337         }
4338         
4339         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4340         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4341                
4342         aopOp(result,ic,TRUE, FALSE);
4343                
4344         /* c = 1 if egal */
4345         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
4346             outBitC(result);
4347             goto release ;
4348         }
4349         if (ifx) {
4350             genIfxJump (ifx,"c");
4351             goto release ;
4352         }
4353         /* if the result is used in an arithmetic operation
4354         then put the result in place */
4355         outBitC(result);
4356     } else {
4357         gencjne(left,right,newiTempLabel(NULL));
4358         
4359         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4360         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4361                
4362         aopOp(result,ic,TRUE, FALSE);
4363         
4364         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4365             aopPut(AOP(result),"a",0);
4366             goto release ;
4367         }
4368         if (ifx) {
4369             genIfxJump (ifx,"a");
4370             goto release ;
4371         }
4372         /* if the result is used in an arithmetic operation
4373         then put the result in place */
4374         if (AOP_TYPE(result) != AOP_CRY) 
4375             outAcc(result);
4376         /* leave the result in acc */
4377     }
4378
4379 release:
4380     freeAsmop(result,NULL,ic,TRUE);
4381 }
4382
4383 /*-----------------------------------------------------------------*/
4384 /* ifxForOp - returns the icode containing the ifx for operand     */
4385 /*-----------------------------------------------------------------*/
4386 static iCode *ifxForOp ( operand *op, iCode *ic )
4387 {
4388     /* if true symbol then needs to be assigned */
4389     if (IS_TRUE_SYMOP(op))
4390         return NULL ;
4391
4392     /* if this has register type condition and
4393     the next instruction is ifx with the same operand
4394     and live to of the operand is upto the ifx only then */
4395     if (ic->next &&
4396         ic->next->op == IFX &&
4397         IC_COND(ic->next)->key == op->key &&
4398         OP_SYMBOL(op)->liveTo <= ic->next->seq )
4399         return ic->next;
4400
4401     return NULL;
4402 }
4403 /*-----------------------------------------------------------------*/
4404 /* genAndOp - for && operation                                     */
4405 /*-----------------------------------------------------------------*/
4406 static void genAndOp (iCode *ic)
4407 {
4408     operand *left,*right, *result;
4409     symbol *tlbl;
4410
4411     D(emitcode(";", "genAndOp "););
4412
4413     /* note here that && operations that are in an
4414     if statement are taken away by backPatchLabels
4415     only those used in arthmetic operations remain */
4416     AOP_OP_3(ic);
4417     AOP_SET_LOCALS(ic);
4418 #if 0
4419     aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
4420     aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
4421     aopOp((result=IC_RESULT(ic)),ic,FALSE, FALSE);
4422 #endif
4423
4424     /* if both are bit variables */
4425     if (AOP_TYPE(left) == AOP_CRY &&
4426         AOP_TYPE(right) == AOP_CRY ) {
4427         emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4428         emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
4429         outBitC(result);
4430     } else {
4431         tlbl = newiTempLabel(NULL);
4432         toBoolean(left);    
4433         emitcode("jz","%05d$",tlbl->key+100);
4434         toBoolean(right);
4435         emitcode("","%05d$:",tlbl->key+100);
4436         outBitAcc(result);
4437     }
4438
4439     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4440     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4441     freeAsmop(result,NULL,ic,TRUE);
4442 }
4443
4444
4445 /*-----------------------------------------------------------------*/
4446 /* genOrOp - for || operation                                      */
4447 /*-----------------------------------------------------------------*/
4448 static void genOrOp (iCode *ic)
4449 {
4450     operand *left,*right, *result;
4451     symbol *tlbl;
4452
4453     D(emitcode(";", "genOrOp "););
4454
4455     /* note here that || operations that are in an
4456     if statement are taken away by backPatchLabels
4457     only those used in arthmetic operations remain */
4458     AOP_OP_3(ic);
4459     AOP_SET_LOCALS(ic);
4460 #if 0
4461     aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
4462     aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
4463     aopOp((result=IC_RESULT(ic)),ic,FALSE, FALSE);
4464 #endif
4465
4466     /* if both are bit variables */
4467     if (AOP_TYPE(left) == AOP_CRY &&
4468         AOP_TYPE(right) == AOP_CRY ) {
4469         emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4470         emitcode("orl","c,%s",AOP(right)->aopu.aop_dir);
4471         outBitC(result);
4472     } else {
4473         tlbl = newiTempLabel(NULL);
4474         toBoolean(left);
4475         emitcode("jnz","%05d$",tlbl->key+100);
4476         toBoolean(right);
4477         emitcode("","%05d$:",tlbl->key+100);
4478         outBitAcc(result);
4479     }
4480
4481     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4482     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4483     freeAsmop(result,NULL,ic,TRUE);            
4484 }
4485
4486 /*-----------------------------------------------------------------*/
4487 /* isLiteralBit - test if lit == 2^n                               */
4488 /*-----------------------------------------------------------------*/
4489 static int isLiteralBit(unsigned long lit)
4490 {
4491     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
4492     0x100L,0x200L,0x400L,0x800L,
4493     0x1000L,0x2000L,0x4000L,0x8000L,
4494     0x10000L,0x20000L,0x40000L,0x80000L,
4495     0x100000L,0x200000L,0x400000L,0x800000L,
4496     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
4497     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
4498     int idx;
4499     
4500     for(idx = 0; idx < 32; idx++)
4501         if(lit == pw[idx])
4502             return idx+1;
4503     return 0;
4504 }
4505
4506 /*-----------------------------------------------------------------*/
4507 /* continueIfTrue -                                                */
4508 /*-----------------------------------------------------------------*/
4509 static void continueIfTrue (iCode *ic)
4510 {
4511     if(IC_TRUE(ic))
4512         emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
4513     ic->generated = 1;
4514 }
4515
4516 /*-----------------------------------------------------------------*/
4517 /* jmpIfTrue -                                                     */
4518 /*-----------------------------------------------------------------*/
4519 static void jumpIfTrue (iCode *ic)
4520 {
4521     if(!IC_TRUE(ic))
4522         emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
4523     ic->generated = 1;
4524 }
4525
4526 /*-----------------------------------------------------------------*/
4527 /* jmpTrueOrFalse -                                                */
4528 /*-----------------------------------------------------------------*/
4529 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
4530 {
4531     // ugly but optimized by peephole
4532     if(IC_TRUE(ic)){
4533         symbol *nlbl = newiTempLabel(NULL);
4534         emitcode("sjmp","%05d$",nlbl->key+100);                 
4535         emitcode("","%05d$:",tlbl->key+100);
4536         emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
4537         emitcode("","%05d$:",nlbl->key+100);
4538     }
4539     else{
4540         emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
4541         emitcode("","%05d$:",tlbl->key+100);
4542     }
4543     ic->generated = 1;
4544 }
4545
4546 /*-----------------------------------------------------------------*/
4547 /* genAnd  - code for and                                          */
4548 /*-----------------------------------------------------------------*/
4549 static void genAnd (iCode *ic, iCode *ifx)
4550 {
4551     operand *left, *right, *result;
4552     int size, offset=0;  
4553     unsigned long lit = 0L;
4554     int bytelit = 0;
4555     char buffer[10];
4556
4557     D(emitcode(";", "genAnd "););
4558
4559     AOP_OP_3(ic);
4560     AOP_SET_LOCALS(ic);
4561 #if 0
4562     aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
4563     aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
4564     aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4565 #endif
4566
4567 #ifdef DEBUG_TYPE
4568     emitcode("","; Type res[%d] = l[%d]&r[%d]",
4569              AOP_TYPE(result),
4570              AOP_TYPE(left), AOP_TYPE(right));
4571     emitcode("","; Size res[%d] = l[%d]&r[%d]",
4572              AOP_SIZE(result),
4573              AOP_SIZE(left), AOP_SIZE(right));
4574 #endif
4575
4576     /* if left is a literal & right is not then exchange them */
4577     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4578         AOP_NEEDSACC(left)) {
4579         operand *tmp = right ;
4580         right = left;
4581         left = tmp;
4582     }
4583
4584     /* if result = right then exchange them */
4585     if(sameRegs(AOP(result),AOP(right))){
4586         operand *tmp = right ;
4587         right = left;
4588         left = tmp;
4589     }
4590
4591     /* if right is bit then exchange them */
4592     if (AOP_TYPE(right) == AOP_CRY &&
4593         AOP_TYPE(left) != AOP_CRY){
4594         operand *tmp = right ;
4595         right = left;
4596         left = tmp;
4597     }
4598     if(AOP_TYPE(right) == AOP_LIT)
4599         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4600
4601     size = AOP_SIZE(result);
4602
4603     // if(bit & yy)
4604     // result = bit & yy;
4605     if (AOP_TYPE(left) == AOP_CRY){
4606         // c = bit & literal;
4607         if(AOP_TYPE(right) == AOP_LIT){
4608             if(lit & 1) {
4609                 if(size && sameRegs(AOP(result),AOP(left)))
4610                     // no change
4611                     goto release;
4612                 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4613             } else {
4614                 // bit(result) = 0;
4615                 if(size && (AOP_TYPE(result) == AOP_CRY)){
4616                     emitcode("clr","%s",AOP(result)->aopu.aop_dir);
4617                     goto release;
4618                 }
4619                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4620                     jumpIfTrue(ifx);
4621                     goto release;
4622                 }
4623                 emitcode("clr","c");
4624             }
4625         } else {
4626             if (AOP_TYPE(right) == AOP_CRY){
4627                 // c = bit & bit;
4628                 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4629                 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4630             } else {
4631                 // c = bit & val;
4632                 MOVA(aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4633                 // c = lsb
4634                 emitcode("rrc","a");
4635                 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4636             }
4637         }
4638         // bit = c
4639         // val = c
4640         if(size)
4641             outBitC(result);
4642         // if(bit & ...)
4643         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4644             genIfxJump(ifx, "c");           
4645         goto release ;
4646     }
4647
4648     // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
4649     // bit = val & 0xZZ     - size = 1, ifx = FALSE -
4650     if((AOP_TYPE(right) == AOP_LIT) &&
4651        (AOP_TYPE(result) == AOP_CRY) &&
4652        (AOP_TYPE(left) != AOP_CRY)){
4653         int posbit = isLiteralBit(lit);
4654         /* left &  2^n */
4655         if(posbit){
4656             posbit--;
4657             MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE,TRUE));
4658             // bit = left & 2^n
4659             if(size)
4660                 emitcode("mov","c,acc.%d",posbit&0x07);
4661             // if(left &  2^n)
4662             else{
4663                 if(ifx){
4664                     sprintf(buffer,"acc.%d",posbit&0x07);
4665                     genIfxJump(ifx, buffer);
4666                 }
4667                 goto release;
4668             }
4669         } else {
4670             symbol *tlbl = newiTempLabel(NULL);
4671             int sizel = AOP_SIZE(left);
4672             if(size)
4673                 emitcode("setb","c");
4674             while(sizel--){
4675                 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
4676                     MOVA( aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
4677                     // byte ==  2^n ?
4678                     if((posbit = isLiteralBit(bytelit)) != 0)
4679                         emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
4680                     else{
4681                         if(bytelit != 0x0FFL)
4682                             emitcode("anl","a,%s",
4683                                      aopGet(AOP(right),offset,FALSE,TRUE,FALSE));
4684                         emitcode("jnz","%05d$",tlbl->key+100);
4685                     }
4686                 }
4687                 offset++;
4688             }
4689             // bit = left & literal
4690             if(size){
4691                 emitcode("clr","c");
4692                 emitcode("","%05d$:",tlbl->key+100);
4693             }
4694             // if(left & literal)
4695             else{
4696                 if(ifx)
4697                     jmpTrueOrFalse(ifx, tlbl);
4698                 goto release ;
4699             }
4700         }
4701         outBitC(result);
4702         goto release ;
4703     }
4704
4705     /* if left is same as result */
4706     if(sameRegs(AOP(result),AOP(left))){
4707         for(;size--; offset++) {
4708             if(AOP_TYPE(right) == AOP_LIT){
4709                 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
4710                     continue;
4711                 else 
4712                     if (bytelit == 0)
4713                         aopPut(AOP(result),zero,offset);
4714                     else 
4715                         if (IS_AOP_PREG(result)) {
4716                             MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4717                             emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4718                             aopPut(AOP(result),"a",offset);
4719                         } else
4720                             emitcode("anl","%s,%s",
4721                                      aopGet(AOP(left),offset,FALSE,TRUE,FALSE),
4722                                      aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4723             } else {
4724                 if (AOP_TYPE(left) == AOP_ACC)
4725                     emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4726                 else {
4727                     MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4728                     if (IS_AOP_PREG(result)) {
4729                         emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4730                         aopPut(AOP(result),"a",offset);
4731
4732                     } else
4733                         emitcode("anl","%s,a",
4734                                  aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4735                 }
4736             }
4737         }
4738     } else {
4739         // left & result in different registers
4740         if(AOP_TYPE(result) == AOP_CRY){
4741             // result = bit
4742             // if(size), result in bit
4743             // if(!size && ifx), conditional oper: if(left & right)
4744             symbol *tlbl = newiTempLabel(NULL);
4745             int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
4746             if(size)
4747                 emitcode("setb","c");
4748             while(sizer--){
4749                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4750                 emitcode("anl","a,%s",
4751                          aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4752                 emitcode("jnz","%05d$",tlbl->key+100);
4753                 offset++;
4754             }
4755             if(size){
4756                 CLRC;
4757                 emitcode("","%05d$:",tlbl->key+100);
4758                 outBitC(result);
4759             } else if(ifx)
4760                 jmpTrueOrFalse(ifx, tlbl);
4761         } else 
4762         {
4763             for(;(size--);offset++) 
4764             {
4765                 // normal case
4766                 // result = left & right
4767                 if(AOP_TYPE(right) == AOP_LIT)
4768                 {
4769                     if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
4770                     {
4771                         aopPut(AOP(result),
4772                                aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
4773                                offset);
4774                         continue;
4775                     } 
4776                     else if (bytelit == 0)
4777                     {
4778                         aopPut(AOP(result),zero,offset);
4779                         continue;
4780                     }
4781                     D(emitcode(";", "better literal AND."););
4782                     MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
4783                     emitcode("anl", "a, %s", aopGet(AOP(right),offset,
4784                                                 FALSE,FALSE,FALSE));
4785                     
4786                 }
4787                 else
4788                 {
4789                     // faster than result <- left, anl result,right
4790                     // and better if result is SFR
4791                     if (AOP_TYPE(left) == AOP_ACC) 
4792                     {
4793                         emitcode("anl","a,%s",aopGet(AOP(right),offset,
4794                                                      FALSE,FALSE,FALSE));
4795                     }
4796                     else 
4797                     {
4798                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4799                         emitcode("anl","a,%s",
4800                                  aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4801                     }
4802                 }
4803                 aopPut(AOP(result),"a",offset);
4804             }
4805         }
4806     }
4807
4808 release :
4809     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4810     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4811     freeAsmop(result,NULL,ic,TRUE);     
4812 }
4813
4814 /*-----------------------------------------------------------------*/
4815 /* genOr  - code for or                                            */
4816 /*-----------------------------------------------------------------*/
4817 static void genOr (iCode *ic, iCode *ifx)
4818 {
4819     operand *left, *right, *result;
4820     int size, offset=0;
4821     unsigned long lit = 0L;
4822
4823     D(emitcode(";", "genOr "););
4824
4825     AOP_OP_3(ic);
4826     AOP_SET_LOCALS(ic);
4827 #if 0
4828     aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
4829     aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
4830     aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4831 #endif
4832
4833 #ifdef DEBUG_TYPE
4834     emitcode("","; Type res[%d] = l[%d]&r[%d]",
4835              AOP_TYPE(result),
4836              AOP_TYPE(left), AOP_TYPE(right));
4837     emitcode("","; Size res[%d] = l[%d]&r[%d]",
4838              AOP_SIZE(result),
4839              AOP_SIZE(left), AOP_SIZE(right));
4840 #endif
4841
4842     /* if left is a literal & right is not then exchange them */
4843     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4844         AOP_NEEDSACC(left)) {
4845         operand *tmp = right ;
4846         right = left;
4847         left = tmp;
4848     }
4849
4850     /* if result = right then exchange them */
4851     if(sameRegs(AOP(result),AOP(right))){
4852         operand *tmp = right ;
4853         right = left;
4854         left = tmp;
4855     }
4856
4857     /* if right is bit then exchange them */
4858     if (AOP_TYPE(right) == AOP_CRY &&
4859         AOP_TYPE(left) != AOP_CRY){
4860         operand *tmp = right ;
4861         right = left;
4862         left = tmp;
4863     }
4864     if(AOP_TYPE(right) == AOP_LIT)
4865         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4866
4867     size = AOP_SIZE(result);
4868
4869     // if(bit | yy)
4870     // xx = bit | yy;
4871     if (AOP_TYPE(left) == AOP_CRY){
4872         if(AOP_TYPE(right) == AOP_LIT){
4873             // c = bit & literal;
4874             if(lit){
4875                 // lit != 0 => result = 1
4876                 if(AOP_TYPE(result) == AOP_CRY){
4877                     if(size)
4878                         emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4879                     else if(ifx)
4880                         continueIfTrue(ifx);
4881                     goto release;
4882                 }
4883                 emitcode("setb","c");
4884             } else {
4885                 // lit == 0 => result = left
4886                 if(size && sameRegs(AOP(result),AOP(left)))
4887                     goto release;
4888                 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4889             }
4890         } else {
4891             if (AOP_TYPE(right) == AOP_CRY){
4892                 // c = bit | bit;
4893                 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4894                 emitcode("orl","c,%s",AOP(left)->aopu.aop_dir);
4895             }
4896             else{
4897                 // c = bit | val;
4898                 symbol *tlbl = newiTempLabel(NULL);
4899                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
4900                     emitcode("setb","c");
4901                 emitcode("jb","%s,%05d$",
4902                          AOP(left)->aopu.aop_dir,tlbl->key+100);
4903                 toBoolean(right);
4904                 emitcode("jnz","%05d$",tlbl->key+100);
4905                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4906                     jmpTrueOrFalse(ifx, tlbl);
4907                     goto release;
4908                 } else {
4909                     CLRC;
4910                     emitcode("","%05d$:",tlbl->key+100);
4911                 }
4912             }
4913         }
4914         // bit = c
4915         // val = c
4916         if(size)
4917             outBitC(result);
4918         // if(bit | ...)
4919         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4920             genIfxJump(ifx, "c");           
4921         goto release ;
4922     }
4923
4924     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
4925     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
4926     if((AOP_TYPE(right) == AOP_LIT) &&
4927        (AOP_TYPE(result) == AOP_CRY) &&
4928        (AOP_TYPE(left) != AOP_CRY)){
4929         if(lit){
4930             // result = 1
4931             if(size)
4932                 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4933             else 
4934                 continueIfTrue(ifx);
4935             goto release;
4936         } else {
4937             // lit = 0, result = boolean(left)
4938             if(size)
4939                 emitcode("setb","c");
4940             toBoolean(right);
4941             if(size){
4942                 symbol *tlbl = newiTempLabel(NULL);
4943                 emitcode("jnz","%05d$",tlbl->key+100);
4944                 CLRC;
4945                 emitcode("","%05d$:",tlbl->key+100);
4946             } else {
4947                 genIfxJump (ifx,"a");
4948                 goto release;
4949             }
4950         }
4951         outBitC(result);
4952         goto release ;
4953     }
4954
4955     /* if left is same as result */
4956     if(sameRegs(AOP(result),AOP(left)))
4957     {
4958         for(;size--; offset++) 
4959         {
4960             if(AOP_TYPE(right) == AOP_LIT){
4961                 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4962                 {
4963                     continue;
4964                 }
4965                 else 
4966                 {
4967                     if (IS_AOP_PREG(left)) 
4968                     {
4969                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4970                         emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4971                         aopPut(AOP(result),"a",offset);
4972                     } 
4973                     else
4974                     {
4975                         emitcode("orl","%s,%s",
4976                                  aopGet(AOP(left),offset,FALSE,TRUE,FALSE),
4977                                  aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4978                     }
4979                 }
4980             } 
4981             else 
4982             {
4983                 if (AOP_TYPE(left) == AOP_ACC)
4984                 { 
4985                     emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4986                 }
4987                 else 
4988                 {                   
4989                     MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4990                     if (IS_AOP_PREG(left)) 
4991                     {
4992                         emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4993                         aopPut(AOP(result),"a",offset);
4994                     } 
4995                     else
4996                     {
4997                         emitcode("orl","%s,a",
4998                                  aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4999                     }
5000                 }
5001             }
5002         }
5003     }
5004     else
5005     {
5006         // left & result in different registers
5007         if(AOP_TYPE(result) == AOP_CRY)
5008         {
5009             // result = bit
5010             // if(size), result in bit
5011             // if(!size && ifx), conditional oper: if(left | right)
5012             symbol *tlbl = newiTempLabel(NULL);
5013             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5014             if(size)
5015                 emitcode("setb","c");
5016             while(sizer--){
5017                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5018                 emitcode("orl","a,%s",
5019                          aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
5020                 emitcode("jnz","%05d$",tlbl->key+100);
5021                 offset++;
5022             }
5023             if(size){
5024                 CLRC;
5025                 emitcode("","%05d$:",tlbl->key+100);
5026                 outBitC(result);
5027             } else if(ifx)
5028                 jmpTrueOrFalse(ifx, tlbl);
5029         } 
5030         else 
5031         {
5032             for(;(size--);offset++)
5033             {
5034                 // normal case
5035                 // result = left & right
5036                 if(AOP_TYPE(right) == AOP_LIT)
5037                 {
5038                     if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
5039                     {
5040                         aopPut(AOP(result),
5041                                aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
5042                                offset);
5043                         continue;
5044                     }
5045                     D(emitcode(";", "better literal OR."););
5046                     MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
5047                     emitcode("orl", "a, %s", aopGet(AOP(right),offset,
5048                                                 FALSE,FALSE,FALSE));
5049                      
5050                 }
5051                 else
5052                 {
5053                     // faster than result <- left, anl result,right
5054                     // and better if result is SFR
5055                     if (AOP_TYPE(left) == AOP_ACC) 
5056                     {
5057                         emitcode("orl","a,%s",aopGet(AOP(right),offset,
5058                                                      FALSE,FALSE,FALSE));
5059                     }
5060                     else 
5061                     {
5062                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5063                         emitcode("orl","a,%s",
5064                                  aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
5065                     }
5066                 }
5067                 aopPut(AOP(result),"a",offset);                 
5068             }
5069         }
5070     }
5071
5072 release :
5073     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5074     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5075     freeAsmop(result,NULL,ic,TRUE);     
5076 }
5077
5078 /*-----------------------------------------------------------------*/
5079 /* genXor - code for xclusive or                                   */
5080 /*-----------------------------------------------------------------*/
5081 static void genXor (iCode *ic, iCode *ifx)
5082 {
5083     operand *left, *right, *result;
5084     int size, offset=0;
5085     unsigned long lit = 0L;
5086
5087     D(emitcode(";", "genXor "););
5088
5089     AOP_OP_3(ic);
5090     AOP_SET_LOCALS(ic);
5091 #if 0
5092     aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
5093     aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
5094     aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
5095 #endif
5096
5097 #ifdef DEBUG_TYPE
5098     emitcode("","; Type res[%d] = l[%d]&r[%d]",
5099              AOP_TYPE(result),
5100              AOP_TYPE(left), AOP_TYPE(right));
5101     emitcode("","; Size res[%d] = l[%d]&r[%d]",
5102              AOP_SIZE(result),
5103              AOP_SIZE(left), AOP_SIZE(right));
5104 #endif
5105
5106     /* if left is a literal & right is not ||
5107        if left needs acc & right does not */
5108     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5109         (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
5110         operand *tmp = right ;
5111         right = left;
5112         left = tmp;
5113     }
5114
5115     /* if result = right then exchange them */
5116     if(sameRegs(AOP(result),AOP(right))){
5117         operand *tmp = right ;
5118         right = left;
5119         left = tmp;
5120     }
5121
5122     /* if right is bit then exchange them */
5123     if (AOP_TYPE(right) == AOP_CRY &&
5124         AOP_TYPE(left) != AOP_CRY){
5125         operand *tmp = right ;
5126         right = left;
5127         left = tmp;
5128     }
5129     if(AOP_TYPE(right) == AOP_LIT)
5130         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5131
5132     size = AOP_SIZE(result);
5133
5134     // if(bit ^ yy)
5135     // xx = bit ^ yy;
5136     if (AOP_TYPE(left) == AOP_CRY){
5137         if(AOP_TYPE(right) == AOP_LIT){
5138             // c = bit & literal;
5139             if(lit>>1){
5140                 // lit>>1  != 0 => result = 1
5141                 if(AOP_TYPE(result) == AOP_CRY){
5142                     if(size)
5143                         emitcode("setb","%s",AOP(result)->aopu.aop_dir);
5144                     else if(ifx)
5145                         continueIfTrue(ifx);
5146                     goto release;
5147                 }
5148                 emitcode("setb","c");
5149             } else{
5150                 // lit == (0 or 1)
5151                 if(lit == 0){
5152                     // lit == 0, result = left
5153                     if(size && sameRegs(AOP(result),AOP(left)))
5154                         goto release;
5155                     emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5156                 } else{
5157                     // lit == 1, result = not(left)
5158                     if(size && sameRegs(AOP(result),AOP(left))){
5159                         emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
5160                         goto release;
5161                     } else {
5162                         emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5163                         emitcode("cpl","c");
5164                     }
5165                 }
5166             }
5167
5168         } else {
5169             // right != literal
5170             symbol *tlbl = newiTempLabel(NULL);
5171             if (AOP_TYPE(right) == AOP_CRY){
5172                 // c = bit ^ bit;
5173                 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5174             }
5175             else{
5176                 int sizer = AOP_SIZE(right);
5177                 // c = bit ^ val
5178                 // if val>>1 != 0, result = 1
5179                 emitcode("setb","c");
5180                 while(sizer){
5181                     MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE,TRUE));
5182                     if(sizer == 1)
5183                         // test the msb of the lsb
5184                         emitcode("anl","a,#0xfe");
5185                     emitcode("jnz","%05d$",tlbl->key+100);
5186                     sizer--;
5187                 }
5188                 // val = (0,1)
5189                 emitcode("rrc","a");
5190             }
5191             emitcode("jnb","%s,%05d$",AOP(left)->aopu.aop_dir,(tlbl->key+100));
5192             emitcode("cpl","c");
5193             emitcode("","%05d$:",(tlbl->key+100));
5194         }
5195         // bit = c
5196         // val = c
5197         if(size)
5198             outBitC(result);
5199         // if(bit | ...)
5200         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5201             genIfxJump(ifx, "c");           
5202         goto release ;
5203     }
5204
5205     if(sameRegs(AOP(result),AOP(left))){
5206         /* if left is same as result */
5207         for(;size--; offset++) {
5208             if(AOP_TYPE(right) == AOP_LIT){
5209                 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
5210                     continue;
5211                 else
5212                     if (IS_AOP_PREG(left)) {
5213                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5214                         emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5215                         aopPut(AOP(result),"a",offset);
5216                     } else 
5217                         emitcode("xrl","%s,%s",
5218                                  aopGet(AOP(left),offset,FALSE,TRUE,FALSE),
5219                                  aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
5220             } else {
5221                 if (AOP_TYPE(left) == AOP_ACC)
5222                     emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
5223                 else {
5224                     MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5225                     if (IS_AOP_PREG(left)) {
5226                         emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5227                         aopPut(AOP(result),"a",offset);
5228                     } else
5229                         emitcode("xrl","%s,a",
5230                                  aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5231                 }
5232             }
5233         }
5234     } else {
5235         // left & result in different registers
5236         if(AOP_TYPE(result) == AOP_CRY){
5237             // result = bit
5238             // if(size), result in bit
5239             // if(!size && ifx), conditional oper: if(left ^ right)
5240             symbol *tlbl = newiTempLabel(NULL);
5241             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5242             if(size)
5243                 emitcode("setb","c");
5244             while(sizer--){
5245                 if((AOP_TYPE(right) == AOP_LIT) &&
5246                    (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
5247                     MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
5248                 } else {
5249                     MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5250                     emitcode("xrl","a,%s",
5251                              aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
5252                 }
5253                 emitcode("jnz","%05d$",tlbl->key+100);
5254                 offset++;
5255             }
5256             if(size){
5257                 CLRC;
5258                 emitcode("","%05d$:",tlbl->key+100);
5259                 outBitC(result);
5260             } else if(ifx)
5261                 jmpTrueOrFalse(ifx, tlbl);
5262         } else for(;(size--);offset++)
5263         {
5264             // normal case
5265             // result = left & right
5266             if(AOP_TYPE(right) == AOP_LIT)
5267             {
5268                 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
5269                 {
5270                     aopPut(AOP(result),
5271                            aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
5272                            offset);
5273                     continue;
5274                 }
5275                 D(emitcode(";", "better literal XOR."););
5276                 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
5277                 emitcode("xrl", "a, %s", aopGet(AOP(right),offset,
5278                                                 FALSE,FALSE,FALSE));                
5279             }
5280             else
5281             {
5282                 // faster than result <- left, anl result,right
5283                 // and better if result is SFR
5284                 if (AOP_TYPE(left) == AOP_ACC)
5285                 {
5286                     emitcode("xrl","a,%s",aopGet(AOP(right),offset,
5287                              FALSE,FALSE,FALSE));
5288                 }
5289                 else 
5290                 {
5291                     MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5292                     emitcode("xrl","a,%s",
5293                              aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5294                 }
5295             }
5296             aopPut(AOP(result),"a",offset);
5297         }
5298     }
5299
5300 release :
5301     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5302     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5303     freeAsmop(result,NULL,ic,TRUE);     
5304 }
5305
5306 /*-----------------------------------------------------------------*/
5307 /* genInline - write the inline code out                           */
5308 /*-----------------------------------------------------------------*/
5309 static void genInline (iCode *ic)
5310 {
5311     char buffer[MAX_INLINEASM];
5312     char *bp = buffer;
5313     char *bp1= buffer;
5314     
5315     D(emitcode(";", "genInline "););
5316
5317     _G.inLine += (!options.asmpeep);
5318     strcpy(buffer,IC_INLINE(ic));
5319
5320     /* emit each line as a code */
5321     while (*bp) {
5322         if (*bp == '\n') {
5323             *bp++ = '\0';
5324             emitcode(bp1,"");
5325             bp1 = bp;
5326         } else {
5327             if (*bp == ':') {
5328                 bp++;
5329                 *bp = '\0';
5330                 bp++;
5331                 emitcode(bp1,"");
5332                 bp1 = bp;
5333             } else
5334                 bp++;
5335         }
5336     }
5337     if (bp1 != bp)
5338         emitcode(bp1,"");
5339     /*     emitcode("",buffer); */
5340     _G.inLine -= (!options.asmpeep);
5341 }
5342
5343 /*-----------------------------------------------------------------*/
5344 /* genRRC - rotate right with carry                                */
5345 /*-----------------------------------------------------------------*/
5346 static void genRRC (iCode *ic)
5347 {
5348     operand *left , *result ;
5349     int size, offset = 0;
5350     char *l;    
5351
5352     D(emitcode(";", "genRRC "););
5353
5354     /* rotate right with carry */
5355     left = IC_LEFT(ic);
5356     result=IC_RESULT(ic);
5357     aopOp (left,ic,FALSE, FALSE);
5358     aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5359
5360     /* move it to the result */
5361     size = AOP_SIZE(result);    
5362     offset = size - 1 ;
5363     CLRC;
5364     
5365     _startLazyDPSEvaluation();
5366     while (size--) {
5367         l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
5368         MOVA(l);
5369         emitcode("rrc","a");
5370         if (AOP_SIZE(result) > 1)
5371             aopPut(AOP(result),"a",offset--);
5372     }
5373     _endLazyDPSEvaluation();
5374     
5375     /* now we need to put the carry into the
5376     highest order byte of the result */
5377     if (AOP_SIZE(result) > 1) {
5378         l = aopGet(AOP(result),AOP_SIZE(result)-1,FALSE,FALSE,TRUE);
5379         MOVA(l);
5380     }
5381     emitcode("mov","acc.7,c");
5382     aopPut(AOP(result),"a",AOP_SIZE(result)-1);
5383     freeAsmop(left,NULL,ic,TRUE);
5384     freeAsmop(result,NULL,ic,TRUE);
5385 }
5386
5387 /*-----------------------------------------------------------------*/
5388 /* genRLC - generate code for rotate left with carry               */
5389 /*-----------------------------------------------------------------*/
5390 static void genRLC (iCode *ic)
5391 {    
5392     operand *left , *result ;
5393     int size, offset = 0;
5394     char *l;    
5395
5396     D(emitcode(";", "genRLC "););
5397
5398     /* rotate right with carry */
5399     left = IC_LEFT(ic);
5400     result=IC_RESULT(ic);
5401     aopOp (left,ic,FALSE, FALSE);
5402     aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5403
5404     /* move it to the result */
5405     size = AOP_SIZE(result);    
5406     offset = 0 ;
5407     if (size--) {
5408         l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
5409         MOVA(l);
5410         emitcode("add","a,acc");
5411         if (AOP_SIZE(result) > 1)
5412         {
5413             aopPut(AOP(result),"a",offset++);
5414         }
5415             
5416         _startLazyDPSEvaluation();
5417         while (size--) {
5418             l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
5419             MOVA(l);
5420             emitcode("rlc","a");
5421             if (AOP_SIZE(result) > 1)
5422                 aopPut(AOP(result),"a",offset++);
5423         }
5424         _endLazyDPSEvaluation();
5425     }
5426     /* now we need to put the carry into the
5427     highest order byte of the result */
5428     if (AOP_SIZE(result) > 1) {
5429         l = aopGet(AOP(result),0,FALSE,FALSE,TRUE);
5430         MOVA(l);
5431     }
5432     emitcode("mov","acc.0,c");
5433     aopPut(AOP(result),"a",0);
5434     freeAsmop(left,NULL,ic,TRUE);
5435     freeAsmop(result,NULL,ic,TRUE);
5436 }
5437
5438 /*-----------------------------------------------------------------*/
5439 /* genGetHbit - generates code get highest order bit               */
5440 /*-----------------------------------------------------------------*/
5441 static void genGetHbit (iCode *ic)
5442 {
5443     operand *left, *result;
5444     left = IC_LEFT(ic);
5445     result=IC_RESULT(ic);
5446     aopOp (left,ic,FALSE, FALSE);
5447     aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5448
5449     D(emitcode(";", "genGetHbit "););
5450
5451     /* get the highest order byte into a */
5452     MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE,TRUE));
5453     if(AOP_TYPE(result) == AOP_CRY){
5454         emitcode("rlc","a");
5455         outBitC(result);
5456     }
5457     else{
5458         emitcode("rl","a");
5459         emitcode("anl","a,#0x01");
5460         outAcc(result);
5461     }
5462
5463
5464     freeAsmop(left,NULL,ic,TRUE);
5465     freeAsmop(result,NULL,ic,TRUE);
5466 }
5467
5468 /*-----------------------------------------------------------------*/
5469 /* AccRol - rotate left accumulator by known count                 */
5470 /*-----------------------------------------------------------------*/
5471 static void AccRol (int shCount)
5472 {
5473     shCount &= 0x0007;              // shCount : 0..7
5474     switch(shCount){
5475         case 0 :
5476             break;
5477         case 1 :
5478             emitcode("rl","a");
5479             break;
5480         case 2 :
5481             emitcode("rl","a");
5482             emitcode("rl","a");
5483             break;
5484         case 3 :
5485             emitcode("swap","a");
5486             emitcode("rr","a");
5487             break;
5488         case 4 :
5489             emitcode("swap","a");
5490             break;
5491         case 5 :
5492             emitcode("swap","a");
5493             emitcode("rl","a");
5494             break;
5495         case 6 :
5496             emitcode("rr","a");
5497             emitcode("rr","a");
5498             break;
5499         case 7 :
5500             emitcode("rr","a");
5501             break;
5502     }
5503 }
5504
5505 /*-----------------------------------------------------------------*/
5506 /* AccLsh - left shift accumulator by known count                  */
5507 /*-----------------------------------------------------------------*/
5508 static void AccLsh (int shCount)
5509 {
5510     if(shCount != 0){
5511         if(shCount == 1)
5512             emitcode("add","a,acc");
5513         else 
5514             if(shCount == 2) {
5515             emitcode("add","a,acc");
5516             emitcode("add","a,acc");
5517         } else {
5518             /* rotate left accumulator */
5519             AccRol(shCount);
5520             /* and kill the lower order bits */
5521             emitcode("anl","a,#0x%02x", SLMask[shCount]);
5522         }
5523     }
5524 }
5525
5526 /*-----------------------------------------------------------------*/
5527 /* AccRsh - right shift accumulator by known count                 */
5528 /*-----------------------------------------------------------------*/
5529 static void AccRsh (int shCount)
5530 {
5531     if(shCount != 0){
5532         if(shCount == 1){
5533             CLRC;
5534             emitcode("rrc","a");
5535         } else {
5536             /* rotate right accumulator */
5537             AccRol(8 - shCount);
5538             /* and kill the higher order bits */
5539             emitcode("anl","a,#0x%02x", SRMask[shCount]);
5540         }
5541     }
5542 }
5543
5544 #if 0
5545 //REMOVE ME!!!
5546 /*-----------------------------------------------------------------*/
5547 /* AccSRsh - signed right shift accumulator by known count                 */
5548 /*-----------------------------------------------------------------*/
5549 static void AccSRsh (int shCount)
5550 {
5551     symbol *tlbl ;
5552     if(shCount != 0){
5553         if(shCount == 1){
5554             emitcode("mov","c,acc.7");
5555             emitcode("rrc","a");
5556         } else if(shCount == 2){
5557             emitcode("mov","c,acc.7");
5558             emitcode("rrc","a");
5559             emitcode("mov","c,acc.7");
5560             emitcode("rrc","a");
5561         } else {
5562             tlbl = newiTempLabel(NULL);
5563             /* rotate right accumulator */
5564             AccRol(8 - shCount);
5565             /* and kill the higher order bits */
5566             emitcode("anl","a,#0x%02x", SRMask[shCount]);
5567             emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5568             emitcode("orl","a,#0x%02x",
5569                      (unsigned char)~SRMask[shCount]);
5570             emitcode("","%05d$:",tlbl->key+100);
5571         }
5572     }
5573 }
5574 #endif
5575
5576 #if 0
5577 //REMOVE ME!!!
5578 /*-----------------------------------------------------------------*/
5579 /* shiftR1Left2Result - shift right one byte from left to result   */
5580 /*-----------------------------------------------------------------*/
5581 static void shiftR1Left2Result (operand *left, int offl,
5582                                 operand *result, int offr,
5583                                 int shCount, int sign)
5584 {
5585     MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5586     /* shift right accumulator */
5587     if(sign)
5588         AccSRsh(shCount);
5589     else
5590         AccRsh(shCount);
5591     aopPut(AOP(result),"a",offr);
5592 }
5593 #endif
5594
5595 #if 0
5596 //REMOVE ME!!!
5597 /*-----------------------------------------------------------------*/
5598 /* shiftL1Left2Result - shift left one byte from left to result    */
5599 /*-----------------------------------------------------------------*/
5600 static void shiftL1Left2Result (operand *left, int offl,
5601                                 operand *result, int offr, int shCount)
5602 {
5603     char *l;
5604     l = aopGet(AOP(left),offl,FALSE,FALSE,TRUE);
5605     MOVA(l);
5606     /* shift left accumulator */
5607     AccLsh(shCount);
5608     aopPut(AOP(result),"a",offr);
5609 }
5610 #endif
5611
5612 #if 0
5613 //REMOVE ME!!!
5614 /*-----------------------------------------------------------------*/
5615 /* movLeft2Result - move byte from left to result                  */
5616 /*-----------------------------------------------------------------*/
5617 static void movLeft2Result (operand *left, int offl,
5618                             operand *result, int offr, int sign)
5619 {
5620     char *l;
5621     if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
5622         l = aopGet(AOP(left),offl,FALSE,FALSE,FALSE);
5623
5624         if (*l == '@' && (IS_AOP_PREG(result))) {
5625             emitcode("mov","a,%s",l);
5626             aopPut(AOP(result),"a",offr);
5627         } else {
5628             if(!sign)
5629                 aopPut(AOP(result),l,offr);
5630             else{
5631                 /* MSB sign in acc.7 ! */
5632                 if(getDataSize(left) == offl+1){
5633                     emitcode("mov","a,%s",l);
5634                     aopPut(AOP(result),"a",offr);
5635                 }
5636             }
5637         }
5638     }
5639 }
5640 #endif
5641
5642 #if 0
5643 //REMOVE ME!!!
5644 /*-----------------------------------------------------------------*/
5645 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
5646 /*-----------------------------------------------------------------*/
5647 static void AccAXRrl1 (char *x)
5648 {
5649     emitcode("rrc","a");
5650     emitcode("xch","a,%s", x);
5651     emitcode("rrc","a");
5652     emitcode("xch","a,%s", x);
5653 }
5654 #endif
5655
5656 #if 0
5657 //REMOVE ME!!!
5658 /*-----------------------------------------------------------------*/
5659 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
5660 /*-----------------------------------------------------------------*/
5661 static void AccAXLrl1 (char *x)
5662 {
5663     emitcode("xch","a,%s",x);
5664     emitcode("rlc","a");
5665     emitcode("xch","a,%s",x);
5666     emitcode("rlc","a");
5667 }
5668 #endif
5669
5670 #if 0
5671 //REMOVE ME!!!
5672 /*-----------------------------------------------------------------*/
5673 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
5674 /*-----------------------------------------------------------------*/
5675 static void AccAXLsh1 (char *x)
5676 {
5677     emitcode("xch","a,%s",x);
5678     emitcode("add","a,acc");
5679     emitcode("xch","a,%s",x);
5680     emitcode("rlc","a");
5681 }
5682 #endif
5683
5684 #if 0
5685 //REMOVE ME!!!
5686 /*-----------------------------------------------------------------*/
5687 /* AccAXLsh - left shift a:x by known count (0..7)                 */
5688 /*-----------------------------------------------------------------*/
5689 static void AccAXLsh (char *x, int shCount)
5690 {
5691     switch(shCount){
5692         case 0 :
5693             break;
5694         case 1 :
5695             AccAXLsh1(x);
5696             break;
5697         case 2 :
5698             AccAXLsh1(x);
5699             AccAXLsh1(x);
5700             break;
5701         case 3 :
5702         case 4 :
5703         case 5 :                        // AAAAABBB:CCCCCDDD
5704             AccRol(shCount);            // BBBAAAAA:CCCCCDDD
5705             emitcode("anl","a,#0x%02x",
5706                      SLMask[shCount]);  // BBB00000:CCCCCDDD
5707             emitcode("xch","a,%s",x);   // CCCCCDDD:BBB00000
5708             AccRol(shCount);            // DDDCCCCC:BBB00000
5709             emitcode("xch","a,%s",x);   // BBB00000:DDDCCCCC
5710             emitcode("xrl","a,%s",x);   // (BBB^DDD)CCCCC:DDDCCCCC
5711             emitcode("xch","a,%s",x);   // DDDCCCCC:(BBB^DDD)CCCCC
5712             emitcode("anl","a,#0x%02x",
5713                      SLMask[shCount]);  // DDD00000:(BBB^DDD)CCCCC
5714             emitcode("xch","a,%s",x);   // (BBB^DDD)CCCCC:DDD00000
5715             emitcode("xrl","a,%s",x);   // BBBCCCCC:DDD00000            
5716             break;
5717         case 6 :                        // AAAAAABB:CCCCCCDD
5718             emitcode("anl","a,#0x%02x",
5719                      SRMask[shCount]);  // 000000BB:CCCCCCDD
5720             emitcode("mov","c,acc.0");  // c = B
5721             emitcode("xch","a,%s",x);   // CCCCCCDD:000000BB
5722             AccAXRrl1(x);               // BCCCCCCD:D000000B
5723             AccAXRrl1(x);               // BBCCCCCC:DD000000
5724             break;
5725         case 7 :                        // a:x <<= 7
5726             emitcode("anl","a,#0x%02x",
5727                      SRMask[shCount]);  // 0000000B:CCCCCCCD
5728             emitcode("mov","c,acc.0");  // c = B
5729             emitcode("xch","a,%s",x);   // CCCCCCCD:0000000B
5730             AccAXRrl1(x);               // BCCCCCCC:D0000000
5731             break;
5732         default :
5733             break;
5734     }
5735 }
5736 #endif
5737
5738 #if 0
5739 //REMOVE ME!!!
5740 /*-----------------------------------------------------------------*/
5741 /* AccAXRsh - right shift a:x known count (0..7)                   */
5742 /*-----------------------------------------------------------------*/
5743 static void AccAXRsh (char *x, int shCount)
5744 {   
5745     switch(shCount){
5746         case 0 :
5747             break;
5748         case 1 :
5749             CLRC;
5750             AccAXRrl1(x);               // 0->a:x
5751             break;
5752         case 2 :
5753             CLRC;
5754             AccAXRrl1(x);               // 0->a:x
5755             CLRC;
5756             AccAXRrl1(x);               // 0->a:x
5757             break;
5758         case 3 :
5759         case 4 :
5760         case 5 :                        // AAAAABBB:CCCCCDDD = a:x
5761             AccRol(8 - shCount);        // BBBAAAAA:DDDCCCCC
5762             emitcode("xch","a,%s",x);   // CCCCCDDD:BBBAAAAA
5763             AccRol(8 - shCount);        // DDDCCCCC:BBBAAAAA
5764             emitcode("anl","a,#0x%02x",
5765                      SRMask[shCount]);  // 000CCCCC:BBBAAAAA
5766             emitcode("xrl","a,%s",x);   // BBB(CCCCC^AAAAA):BBBAAAAA
5767             emitcode("xch","a,%s",x);   // BBBAAAAA:BBB(CCCCC^AAAAA)
5768             emitcode("anl","a,#0x%02x",
5769                      SRMask[shCount]);  // 000AAAAA:BBB(CCCCC^AAAAA)
5770             emitcode("xch","a,%s",x);   // BBB(CCCCC^AAAAA):000AAAAA
5771             emitcode("xrl","a,%s",x);   // BBBCCCCC:000AAAAA
5772             emitcode("xch","a,%s",x);   // 000AAAAA:BBBCCCCC
5773             break;
5774         case 6 :                        // AABBBBBB:CCDDDDDD
5775             emitcode("mov","c,acc.7");
5776             AccAXLrl1(x);               // ABBBBBBC:CDDDDDDA
5777             AccAXLrl1(x);               // BBBBBBCC:DDDDDDAA
5778             emitcode("xch","a,%s",x);   // DDDDDDAA:BBBBBBCC
5779             emitcode("anl","a,#0x%02x",
5780                      SRMask[shCount]);  // 000000AA:BBBBBBCC
5781             break;
5782         case 7 :                        // ABBBBBBB:CDDDDDDD
5783             emitcode("mov","c,acc.7");  // c = A
5784             AccAXLrl1(x);               // BBBBBBBC:DDDDDDDA
5785             emitcode("xch","a,%s",x);   // DDDDDDDA:BBBBBBCC
5786             emitcode("anl","a,#0x%02x",
5787                      SRMask[shCount]);  // 0000000A:BBBBBBBC
5788             break;
5789         default :
5790             break;
5791     }
5792 }
5793 #endif
5794
5795 #if 0
5796 //REMOVE ME!!!
5797 /*-----------------------------------------------------------------*/
5798 /* AccAXRshS - right shift signed a:x known count (0..7)           */
5799 /*-----------------------------------------------------------------*/
5800 static void AccAXRshS (char *x, int shCount)
5801 {   
5802     symbol *tlbl ;
5803     switch(shCount){
5804         case 0 :
5805             break;
5806         case 1 :
5807             emitcode("mov","c,acc.7");
5808             AccAXRrl1(x);               // s->a:x
5809             break;
5810         case 2 :
5811             emitcode("mov","c,acc.7");
5812             AccAXRrl1(x);               // s->a:x
5813             emitcode("mov","c,acc.7");
5814             AccAXRrl1(x);               // s->a:x
5815             break;
5816         case 3 :
5817         case 4 :
5818         case 5 :                        // AAAAABBB:CCCCCDDD = a:x
5819             tlbl = newiTempLabel(NULL);
5820             AccRol(8 - shCount);        // BBBAAAAA:CCCCCDDD
5821             emitcode("xch","a,%s",x);   // CCCCCDDD:BBBAAAAA
5822             AccRol(8 - shCount);        // DDDCCCCC:BBBAAAAA
5823             emitcode("anl","a,#0x%02x",
5824                      SRMask[shCount]);  // 000CCCCC:BBBAAAAA
5825             emitcode("xrl","a,%s",x);   // BBB(CCCCC^AAAAA):BBBAAAAA
5826             emitcode("xch","a,%s",x);   // BBBAAAAA:BBB(CCCCC^AAAAA)
5827             emitcode("anl","a,#0x%02x",
5828                      SRMask[shCount]);  // 000AAAAA:BBB(CCCCC^AAAAA)
5829             emitcode("xch","a,%s",x);   // BBB(CCCCC^AAAAA):000AAAAA
5830             emitcode("xrl","a,%s",x);   // BBBCCCCC:000AAAAA
5831             emitcode("xch","a,%s",x);   // 000SAAAA:BBBCCCCC
5832             emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100); 
5833             emitcode("orl","a,#0x%02x",
5834                      (unsigned char)~SRMask[shCount]);  // 111AAAAA:BBBCCCCC
5835             emitcode("","%05d$:",tlbl->key+100);
5836             break;                      // SSSSAAAA:BBBCCCCC
5837         case 6 :                        // AABBBBBB:CCDDDDDD
5838             tlbl = newiTempLabel(NULL);
5839             emitcode("mov","c,acc.7");
5840             AccAXLrl1(x);               // ABBBBBBC:CDDDDDDA
5841             AccAXLrl1(x);               // BBBBBBCC:DDDDDDAA
5842             emitcode("xch","a,%s",x);   // DDDDDDAA:BBBBBBCC
5843             emitcode("anl","a,#0x%02x",
5844                      SRMask[shCount]);  // 000000AA:BBBBBBCC
5845             emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100); 
5846             emitcode("orl","a,#0x%02x",
5847                      (unsigned char)~SRMask[shCount]);  // 111111AA:BBBBBBCC
5848             emitcode("","%05d$:",tlbl->key+100);
5849             break;
5850         case 7 :                        // ABBBBBBB:CDDDDDDD
5851             tlbl = newiTempLabel(NULL);
5852             emitcode("mov","c,acc.7");  // c = A
5853             AccAXLrl1(x);               // BBBBBBBC:DDDDDDDA
5854             emitcode("xch","a,%s",x);   // DDDDDDDA:BBBBBBCC
5855             emitcode("anl","a,#0x%02x",
5856                      SRMask[shCount]);  // 0000000A:BBBBBBBC
5857             emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100); 
5858             emitcode("orl","a,#0x%02x",
5859                      (unsigned char)~SRMask[shCount]);  // 1111111A:BBBBBBBC
5860             emitcode("","%05d$:",tlbl->key+100);
5861             break;
5862         default :
5863             break;
5864     }
5865 }
5866 #endif
5867
5868 #if 0
5869 //REMOVE ME!!!
5870 /*-----------------------------------------------------------------*/
5871 /* shiftL2Left2Result - shift left two bytes from left to result   */
5872 /*-----------------------------------------------------------------*/
5873 static void shiftL2Left2Result (operand *left, int offl,
5874                                 operand *result, int offr, int shCount)
5875 {
5876     if(sameRegs(AOP(result), AOP(left)) &&
5877        ((offl + MSB16) == offr)){
5878         /* don't crash result[offr] */
5879         MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5880         emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE,FALSE));
5881     } else {
5882         movLeft2Result(left,offl, result, offr, 0);
5883         MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE,TRUE));
5884     }
5885     /* ax << shCount (x = lsb(result))*/
5886     AccAXLsh( aopGet(AOP(result),offr,FALSE,FALSE,FALSE), shCount);
5887     aopPut(AOP(result),"a",offr+MSB16);
5888 }
5889 #endif
5890
5891 #if 0
5892 //REMOVE ME!!!
5893 /*-----------------------------------------------------------------*/
5894 /* shiftR2Left2Result - shift right two bytes from left to result  */
5895 /*-----------------------------------------------------------------*/
5896 static void shiftR2Left2Result (operand *left, int offl,
5897                                 operand *result, int offr,
5898                                 int shCount, int sign)
5899 {
5900     if(sameRegs(AOP(result), AOP(left)) &&
5901        ((offl + MSB16) == offr)){
5902         /* don't crash result[offr] */
5903         MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5904         emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE,FALSE));
5905     } else {
5906         movLeft2Result(left,offl, result, offr, 0);
5907         MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE,TRUE));
5908     }
5909     /* a:x >> shCount (x = lsb(result))*/
5910     if(sign)
5911         AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE,FALSE) , shCount);
5912     else
5913         AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE,FALSE) , shCount);
5914     if(getDataSize(result) > 1)
5915         aopPut(AOP(result),"a",offr+MSB16);
5916 }
5917 #endif
5918
5919 #if 0
5920 //REMOVE ME!!!
5921 /*-----------------------------------------------------------------*/
5922 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
5923 /*-----------------------------------------------------------------*/
5924 static void shiftLLeftOrResult (operand *left, int offl,
5925                                 operand *result, int offr, int shCount)
5926 {
5927     MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5928     /* shift left accumulator */
5929     AccLsh(shCount);
5930     /* or with result */
5931     emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE,FALSE));
5932     /* back to result */
5933     aopPut(AOP(result),"a",offr);
5934 }
5935 #endif
5936
5937 #if 0
5938 //REMOVE ME!!!
5939 /*-----------------------------------------------------------------*/
5940 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
5941 /*-----------------------------------------------------------------*/
5942 static void shiftRLeftOrResult (operand *left, int offl,
5943                                 operand *result, int offr, int shCount)
5944 {
5945     MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5946     /* shift right accumulator */
5947     AccRsh(shCount);
5948     /* or with result */
5949     emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE,FALSE));
5950     /* back to result */
5951     aopPut(AOP(result),"a",offr);
5952 }
5953 #endif
5954
5955 #if 0
5956 //REMOVE ME!!!
5957 /*-----------------------------------------------------------------*/
5958 /* genlshOne - left shift a one byte quantity by known count       */
5959 /*-----------------------------------------------------------------*/
5960 static void genlshOne (operand *result, operand *left, int shCount)
5961 {       
5962     D(emitcode(";", "genlshOne "););
5963     shiftL1Left2Result(left, LSB, result, LSB, shCount);
5964 }
5965 #endif
5966
5967 #if 0
5968 //REMOVE ME!!!
5969 /*-----------------------------------------------------------------*/
5970 /* genlshTwo - left shift two bytes by known amount != 0           */
5971 /*-----------------------------------------------------------------*/
5972 static void genlshTwo (operand *result,operand *left, int shCount)
5973 {
5974     int size;
5975     
5976     D(emitcode(";", "genlshTwo "););
5977
5978     size = getDataSize(result);
5979
5980     /* if shCount >= 8 */
5981     if (shCount >= 8) {
5982         shCount -= 8 ;
5983
5984         if (size > 1){
5985             if (shCount)
5986                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5987             else 
5988                 movLeft2Result(left, LSB, result, MSB16, 0);
5989         }
5990         aopPut(AOP(result),zero,LSB);   
5991     }
5992
5993     /*  1 <= shCount <= 7 */
5994     else {  
5995         if(size == 1)
5996             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
5997         else 
5998             shiftL2Left2Result(left, LSB, result, LSB, shCount);
5999     }
6000 }
6001 #endif
6002
6003 #if 0
6004 //REMOVE ME!!!
6005 /*-----------------------------------------------------------------*/
6006 /* shiftLLong - shift left one long from left to result            */
6007 /* offl = LSB or MSB16                                             */
6008 /*-----------------------------------------------------------------*/
6009 static void shiftLLong (operand *left, operand *result, int offr )
6010 {
6011     char *l;
6012     int size = AOP_SIZE(result);
6013
6014     if(size >= LSB+offr){
6015         l = aopGet(AOP(left),LSB,FALSE,FALSE,TRUE);
6016         MOVA(l);
6017         emitcode("add","a,acc");
6018         if (sameRegs(AOP(left),AOP(result)) && 
6019             size >= MSB16+offr && offr != LSB )
6020             emitcode("xch","a,%s",
6021                      aopGet(AOP(left),LSB+offr,FALSE,FALSE,FALSE));
6022         else        
6023             aopPut(AOP(result),"a",LSB+offr);
6024     }
6025
6026     if(size >= MSB16+offr){
6027         if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
6028             l = aopGet(AOP(left),MSB16,FALSE,FALSE,TRUE);
6029             MOVA(l);
6030         }
6031         emitcode("rlc","a");
6032         if (sameRegs(AOP(left),AOP(result)) && 
6033             size >= MSB24+offr && offr != LSB)
6034             emitcode("xch","a,%s",
6035                      aopGet(AOP(left),MSB16+offr,FALSE,FALSE,FALSE));
6036         else        
6037             aopPut(AOP(result),"a",MSB16+offr);
6038     }
6039
6040     if(size >= MSB24+offr){
6041         if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
6042             l = aopGet(AOP(left),MSB24,FALSE,FALSE,TRUE);
6043             MOVA(l);
6044         }
6045         emitcode("rlc","a");
6046         if (sameRegs(AOP(left),AOP(result)) && 
6047             size >= MSB32+offr && offr != LSB )
6048             emitcode("xch","a,%s",
6049                      aopGet(AOP(left),MSB24+offr,FALSE,FALSE,FALSE));
6050         else        
6051             aopPut(AOP(result),"a",MSB24+offr);
6052     }
6053
6054     if(size > MSB32+offr){
6055         if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
6056             l = aopGet(AOP(left),MSB32,FALSE,FALSE,TRUE);
6057             MOVA(l);    
6058         }
6059         emitcode("rlc","a");
6060         aopPut(AOP(result),"a",MSB32+offr);
6061     }
6062     if(offr != LSB)
6063         aopPut(AOP(result),zero,LSB);       
6064 }
6065 #endif
6066
6067 #if 0
6068 //REMOVE ME!!!
6069 /*-----------------------------------------------------------------*/
6070 /* genlshFour - shift four byte by a known amount != 0             */
6071 /*-----------------------------------------------------------------*/
6072 static void genlshFour (operand *result, operand *left, int shCount)
6073 {
6074     int size;
6075
6076     D(emitcode(";", "genlshFour "););
6077
6078     size = AOP_SIZE(result);
6079
6080     /* if shifting more that 3 bytes */
6081     if (shCount >= 24 ) {
6082         shCount -= 24;
6083         if (shCount)
6084             /* lowest order of left goes to the highest
6085             order of the destination */
6086             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
6087         else
6088             movLeft2Result(left, LSB, result, MSB32, 0);
6089         aopPut(AOP(result),zero,LSB);
6090         aopPut(AOP(result),zero,MSB16);
6091         aopPut(AOP(result),zero,MSB32);
6092         return;
6093     }
6094
6095     /* more than two bytes */
6096     else if ( shCount >= 16 ) {
6097         /* lower order two bytes goes to higher order two bytes */
6098         shCount -= 16;
6099         /* if some more remaining */
6100         if (shCount)
6101             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
6102         else {
6103             movLeft2Result(left, MSB16, result, MSB32, 0);
6104             movLeft2Result(left, LSB, result, MSB24, 0);
6105         }
6106         aopPut(AOP(result),zero,MSB16);
6107         aopPut(AOP(result),zero,LSB);
6108         return;
6109     }    
6110
6111     /* if more than 1 byte */
6112     else if ( shCount >= 8 ) {
6113         /* lower order three bytes goes to higher order  three bytes */
6114         shCount -= 8;
6115         if(size == 2){
6116             if(shCount)
6117                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6118             else
6119                 movLeft2Result(left, LSB, result, MSB16, 0);
6120         }
6121         else{   /* size = 4 */
6122             if(shCount == 0){
6123                 movLeft2Result(left, MSB24, result, MSB32, 0);
6124                 movLeft2Result(left, MSB16, result, MSB24, 0);
6125                 movLeft2Result(left, LSB, result, MSB16, 0);
6126                 aopPut(AOP(result),zero,LSB);
6127             }
6128             else if(shCount == 1)
6129                 shiftLLong(left, result, MSB16);
6130             else{
6131                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
6132                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6133                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
6134                 aopPut(AOP(result),zero,LSB);
6135             }
6136         }
6137     }
6138
6139     /* 1 <= shCount <= 7 */
6140     else if(shCount <= 2){
6141         shiftLLong(left, result, LSB);
6142         if(shCount == 2)
6143             shiftLLong(result, result, LSB);
6144     }
6145     /* 3 <= shCount <= 7, optimize */
6146     else{
6147         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
6148         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
6149         shiftL2Left2Result(left, LSB, result, LSB, shCount);
6150     }
6151 }
6152 #endif
6153
6154 #if 0
6155 //REMOVE ME!!!
6156 /*-----------------------------------------------------------------*/
6157 /* genLeftShiftLiteral - left shifting by known count              */
6158 /*-----------------------------------------------------------------*/
6159 static void genLeftShiftLiteral (operand *left,
6160                                  operand *right,
6161                                  operand *result,
6162                                  iCode *ic)
6163 {    
6164     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6165     int size;
6166
6167     D(emitcode(";","genLeftShiftLiteral (%d)", shCount););
6168
6169     freeAsmop(right,NULL,ic,TRUE);
6170
6171     aopOp(left,ic,FALSE, FALSE);
6172     aopOp(result,ic,FALSE, TRUE);
6173
6174     size = getSize(operandType(result));
6175
6176 #if VIEW_SIZE
6177     emitcode("; shift left ","result %d, left %d",size,
6178              AOP_SIZE(left));
6179 #endif
6180
6181     /* I suppose that the left size >= result size */
6182     if(shCount == 0){
6183         while(size--){
6184             movLeft2Result(left, size, result, size, 0);
6185         }
6186     }
6187
6188     else if(shCount >= (size * 8))
6189         while(size--)
6190             aopPut(AOP(result),zero,size);
6191     else{
6192         switch (size) {
6193             case 1:
6194                 genlshOne (result,left,shCount);
6195                 break;
6196
6197             case 2:
6198             case 3: /* bug: this is for generic pointers, I bet. */
6199                 genlshTwo (result,left,shCount);
6200                 break;
6201
6202             case 4:
6203                 genlshFour (result,left,shCount);
6204                 break;
6205         }
6206     }
6207     freeAsmop(left,NULL,ic,TRUE);
6208     freeAsmop(result,NULL,ic,TRUE);
6209 }
6210 #endif
6211
6212 /*-----------------------------------------------------------------*/
6213 /* genLeftShift - generates code for left shifting                 */
6214 /*-----------------------------------------------------------------*/
6215 static void genLeftShift (iCode *ic)
6216 {
6217     operand *left,*right, *result;
6218     int size, offset;
6219     char *l;
6220     symbol *tlbl , *tlbl1;
6221
6222     D(emitcode(";", "genLeftShift "););
6223
6224     right = IC_RIGHT(ic);
6225     left  = IC_LEFT(ic);
6226     result = IC_RESULT(ic);
6227
6228     aopOp(right,ic,FALSE, FALSE);
6229
6230 #if 0
6231     /* if the shift count is known then do it 
6232     as efficiently as possible */
6233     if (AOP_TYPE(right) == AOP_LIT) {
6234         genLeftShiftLiteral (left,right,result,ic);
6235         return ;
6236     }
6237 #endif
6238
6239     /* shift count is unknown then we have to form 
6240     a loop get the loop count in B : Note: we take
6241     only the lower order byte since shifting
6242     more that 32 bits make no sense anyway, ( the
6243     largest size of an object can be only 32 bits ) */  
6244
6245     emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
6246     emitcode("inc","b");
6247     freeAsmop (right,NULL,ic,TRUE);
6248     aopOp(left,ic,FALSE, FALSE);
6249     aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6250
6251     /* now move the left to the result if they are not the
6252     same */
6253     if (!sameRegs(AOP(left),AOP(result)) && 
6254         AOP_SIZE(result) > 1) {
6255
6256         size = AOP_SIZE(result);
6257         offset=0;
6258         _startLazyDPSEvaluation();
6259         while (size--) {
6260             l = aopGet(AOP(left),offset,FALSE,TRUE,FALSE);
6261             if (*l == '@' && (IS_AOP_PREG(result))) {
6262
6263                 emitcode("mov","a,%s",l);
6264                 aopPut(AOP(result),"a",offset);
6265             } else
6266                 aopPut(AOP(result),l,offset);
6267             offset++;
6268         }
6269         _endLazyDPSEvaluation();
6270     }
6271
6272     tlbl = newiTempLabel(NULL);
6273     size = AOP_SIZE(result);
6274     offset = 0 ;   
6275     tlbl1 = newiTempLabel(NULL);
6276
6277     /* if it is only one byte then */
6278     if (size == 1) {
6279         symbol *tlbl1 = newiTempLabel(NULL);
6280
6281         l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
6282         MOVA(l);
6283         emitcode("sjmp","%05d$",tlbl1->key+100); 
6284         emitcode("","%05d$:",tlbl->key+100);
6285         emitcode("add","a,acc");
6286         emitcode("","%05d$:",tlbl1->key+100);
6287         emitcode("djnz","b,%05d$",tlbl->key+100);      
6288         aopPut(AOP(result),"a",0);
6289         goto release ;
6290     }
6291     
6292     reAdjustPreg(AOP(result));    
6293     
6294     emitcode("sjmp","%05d$",tlbl1->key+100); 
6295     emitcode("","%05d$:",tlbl->key+100);    
6296     l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6297     MOVA(l);
6298     emitcode("add","a,acc");         
6299     aopPut(AOP(result),"a",offset++);
6300     _startLazyDPSEvaluation();
6301     while (--size) {
6302         l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6303         MOVA(l);
6304         emitcode("rlc","a");         
6305         aopPut(AOP(result),"a",offset++);
6306     }
6307     _endLazyDPSEvaluation();
6308     reAdjustPreg(AOP(result));
6309
6310     emitcode("","%05d$:",tlbl1->key+100);
6311     emitcode("djnz","b,%05d$",tlbl->key+100);
6312 release:
6313     freeAsmop(left,NULL,ic,TRUE);
6314     freeAsmop(result,NULL,ic,TRUE);
6315 }
6316
6317 #if 0
6318 //REMOVE ME!!!
6319 /*-----------------------------------------------------------------*/
6320 /* genrshOne - right shift a one byte quantity by known count      */
6321 /*-----------------------------------------------------------------*/
6322 static void genrshOne (operand *result, operand *left,
6323                        int shCount, int sign)
6324 {
6325     D(emitcode(";", "genrshOne"););
6326     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
6327 }
6328 #endif
6329
6330 #if 0
6331 //REMOVE ME!!!
6332 /*-----------------------------------------------------------------*/
6333 /* genrshTwo - right shift two bytes by known amount != 0          */
6334 /*-----------------------------------------------------------------*/
6335 static void genrshTwo (operand *result,operand *left,
6336                        int shCount, int sign)
6337 {
6338     D(emitcode(";", "genrshTwo"););
6339
6340     /* if shCount >= 8 */
6341     if (shCount >= 8) {
6342         shCount -= 8 ;
6343         if (shCount)
6344             shiftR1Left2Result(left, MSB16, result, LSB,
6345                                shCount, sign);
6346         else 
6347             movLeft2Result(left, MSB16, result, LSB, sign);
6348         addSign(result, MSB16, sign);
6349     }
6350
6351     /*  1 <= shCount <= 7 */
6352     else
6353         shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
6354 }
6355 #endif
6356
6357 #if 0
6358 //REMOVE ME!!!
6359 /*-----------------------------------------------------------------*/
6360 /* shiftRLong - shift right one long from left to result           */
6361 /* offl = LSB or MSB16                                             */
6362 /*-----------------------------------------------------------------*/
6363 static void shiftRLong (operand *left, int offl,
6364                         operand *result, int sign)
6365 {
6366     if(!sign)
6367         emitcode("clr","c");
6368     MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE,TRUE));
6369     if(sign)
6370         emitcode("mov","c,acc.7");
6371     emitcode("rrc","a");
6372     aopPut(AOP(result),"a",MSB32-offl);
6373     if(offl == MSB16)
6374         /* add sign of "a" */
6375         addSign(result, MSB32, sign);
6376
6377     MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE,TRUE));
6378     emitcode("rrc","a");
6379     aopPut(AOP(result),"a",MSB24-offl);
6380
6381     MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE,TRUE));
6382     emitcode("rrc","a");
6383     aopPut(AOP(result),"a",MSB16-offl);
6384
6385     if(offl == LSB){
6386         MOVA(aopGet(AOP(left),LSB,FALSE,FALSE,TRUE));
6387         emitcode("rrc","a");
6388         aopPut(AOP(result),"a",LSB);
6389     }
6390 }
6391 #endif
6392
6393 #if 0
6394 //REMOVE ME!!!
6395 /*-----------------------------------------------------------------*/
6396 /* genrshFour - shift four byte by a known amount != 0             */
6397 /*-----------------------------------------------------------------*/
6398 static void genrshFour (operand *result, operand *left,
6399                         int shCount, int sign)
6400 {
6401     D(emitcode(";", "genrshFour"););
6402     
6403     /* if shifting more that 3 bytes */
6404     if(shCount >= 24 ) {
6405         shCount -= 24;
6406         if(shCount)
6407             shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
6408         else
6409             movLeft2Result(left, MSB32, result, LSB, sign);
6410         addSign(result, MSB16, sign);
6411     }
6412     else if(shCount >= 16){
6413         shCount -= 16;
6414         if(shCount)
6415             shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
6416         else{
6417             movLeft2Result(left, MSB24, result, LSB, 0);
6418             movLeft2Result(left, MSB32, result, MSB16, sign);
6419         }
6420         addSign(result, MSB24, sign);
6421     }
6422     else if(shCount >= 8){
6423         shCount -= 8;
6424         if(shCount == 1)
6425             shiftRLong(left, MSB16, result, sign);
6426         else if(shCount == 0){
6427             movLeft2Result(left, MSB16, result, LSB, 0);
6428             movLeft2Result(left, MSB24, result, MSB16, 0);
6429             movLeft2Result(left, MSB32, result, MSB24, sign);
6430             addSign(result, MSB32, sign);
6431         }
6432         else{
6433             shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
6434             shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
6435             /* the last shift is signed */
6436             shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
6437             addSign(result, MSB32, sign);
6438         }
6439     }
6440     else{   /* 1 <= shCount <= 7 */
6441         if(shCount <= 2){
6442             shiftRLong(left, LSB, result, sign);
6443             if(shCount == 2)
6444                 shiftRLong(result, LSB, result, sign);
6445         }
6446         else{
6447             shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
6448             shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
6449             shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
6450         }
6451     }
6452 }
6453 #endif
6454
6455 #if 0
6456 //REMOVE ME!!!
6457 /*-----------------------------------------------------------------*/
6458 /* genRightShiftLiteral - right shifting by known count            */
6459 /*-----------------------------------------------------------------*/
6460 static void genRightShiftLiteral (operand *left,
6461                                   operand *right,
6462                                   operand *result,
6463                                   iCode *ic,
6464                                   int sign)
6465 {    
6466     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6467     int size;
6468
6469     D(emitcode(";", "genRightShiftLiteral"););
6470
6471     freeAsmop(right,NULL,ic,TRUE);
6472
6473     aopOp(left,ic,FALSE, FALSE);
6474     aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6475
6476 #if VIEW_SIZE
6477     emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
6478              AOP_SIZE(left));
6479 #endif
6480
6481     size = getDataSize(left);
6482     /* test the LEFT size !!! */
6483
6484     /* I suppose that the left size >= result size */
6485     if(shCount == 0){
6486         size = getDataSize(result);
6487         while(size--)
6488             movLeft2Result(left, size, result, size, 0);
6489     }
6490
6491     else if(shCount >= (size * 8)){
6492         if(sign)
6493             /* get sign in acc.7 */
6494             MOVA(aopGet(AOP(left),size-1,FALSE,FALSE,TRUE));
6495         addSign(result, LSB, sign);
6496     } else{
6497         switch (size) {
6498             case 1:
6499                 genrshOne (result,left,shCount,sign);
6500                 break;
6501
6502             case 2:
6503                 genrshTwo (result,left,shCount,sign);
6504                 break;
6505
6506             case 4:
6507                 genrshFour (result,left,shCount,sign);
6508                 break;
6509             default :
6510                 break;
6511         }
6512
6513         freeAsmop(left,NULL,ic,TRUE);
6514         freeAsmop(result,NULL,ic,TRUE);
6515     }
6516 }
6517 #endif
6518
6519 /*-----------------------------------------------------------------*/
6520 /* genSignedRightShift - right shift of signed number              */
6521 /*-----------------------------------------------------------------*/
6522 static void genSignedRightShift (iCode *ic)
6523 {
6524     operand *right, *left, *result;
6525     int size, offset;
6526     char *l;
6527     symbol *tlbl, *tlbl1 ;
6528
6529     D(emitcode(";", "genSignedRightShift "););
6530
6531     /* we do it the hard way put the shift count in b
6532     and loop thru preserving the sign */
6533
6534     right = IC_RIGHT(ic);
6535     left  = IC_LEFT(ic);
6536     result = IC_RESULT(ic);
6537
6538     aopOp(right,ic,FALSE, FALSE);
6539
6540 #if 0
6541     if ( AOP_TYPE(right) == AOP_LIT) {
6542         genRightShiftLiteral (left,right,result,ic,1);
6543         return ;
6544     }
6545 #endif
6546     /* shift count is unknown then we have to form 
6547        a loop get the loop count in B : Note: we take
6548        only the lower order byte since shifting
6549        more that 32 bits make no sense anyway, ( the
6550        largest size of an object can be only 32 bits ) */  
6551
6552     emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
6553     emitcode("inc","b");
6554     freeAsmop (right,NULL,ic,TRUE);
6555     aopOp(left,ic,FALSE, FALSE);
6556     aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6557
6558     /* now move the left to the result if they are not the
6559     same */
6560     if (!sameRegs(AOP(left),AOP(result)) && 
6561         AOP_SIZE(result) > 1) {
6562
6563         size = AOP_SIZE(result);
6564         offset=0;
6565         _startLazyDPSEvaluation();
6566         while (size--) {
6567             l = aopGet(AOP(left),offset,FALSE,TRUE,FALSE);
6568             if (*l == '@' && IS_AOP_PREG(result)) {
6569
6570                 emitcode("mov","a,%s",l);
6571                 aopPut(AOP(result),"a",offset);
6572             } else
6573                 aopPut(AOP(result),l,offset);
6574             offset++;
6575         }
6576         _endLazyDPSEvaluation();
6577     }
6578
6579     /* mov the highest order bit to OVR */    
6580     tlbl = newiTempLabel(NULL);
6581     tlbl1= newiTempLabel(NULL);
6582
6583     size = AOP_SIZE(result);
6584     offset = size - 1;
6585     emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
6586     emitcode("rlc","a");
6587     emitcode("mov","ov,c");
6588     /* if it is only one byte then */
6589     if (size == 1) {
6590         l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
6591         MOVA(l);
6592         emitcode("sjmp","%05d$",tlbl1->key+100);
6593         emitcode("","%05d$:",tlbl->key+100);
6594         emitcode("mov","c,ov");
6595         emitcode("rrc","a");
6596         emitcode("","%05d$:",tlbl1->key+100);
6597         emitcode("djnz","b,%05d$",tlbl->key+100);
6598         aopPut(AOP(result),"a",0);
6599         goto release ;
6600     }
6601
6602     reAdjustPreg(AOP(result));
6603     emitcode("sjmp","%05d$",tlbl1->key+100);
6604     emitcode("","%05d$:",tlbl->key+100);    
6605     emitcode("mov","c,ov");
6606     _startLazyDPSEvaluation();
6607     while (size--) {
6608         l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6609         MOVA(l);
6610         emitcode("rrc","a");         
6611         aopPut(AOP(result),"a",offset--);
6612     }
6613     _endLazyDPSEvaluation();
6614     reAdjustPreg(AOP(result));
6615     emitcode("","%05d$:",tlbl1->key+100);
6616     emitcode("djnz","b,%05d$",tlbl->key+100);
6617
6618 release:
6619     freeAsmop(left,NULL,ic,TRUE);
6620     freeAsmop(result,NULL,ic,TRUE);
6621 }
6622
6623 /*-----------------------------------------------------------------*/
6624 /* genRightShift - generate code for right shifting                */
6625 /*-----------------------------------------------------------------*/
6626 static void genRightShift (iCode *ic)
6627 {
6628     operand *right, *left, *result;
6629     sym_link *retype ;
6630     int size, offset;
6631     char *l;
6632     symbol *tlbl, *tlbl1 ;
6633
6634     D(emitcode(";", "genRightShift "););
6635
6636     /* if signed then we do it the hard way preserve the
6637     sign bit moving it inwards */
6638     retype = getSpec(operandType(IC_RESULT(ic)));
6639
6640     if (!SPEC_USIGN(retype)) {
6641         genSignedRightShift (ic);
6642         return ;
6643     }
6644
6645     /* signed & unsigned types are treated the same : i.e. the
6646     signed is NOT propagated inwards : quoting from the
6647     ANSI - standard : "for E1 >> E2, is equivalent to division
6648     by 2**E2 if unsigned or if it has a non-negative value,
6649     otherwise the result is implementation defined ", MY definition
6650     is that the sign does not get propagated */
6651
6652     right = IC_RIGHT(ic);
6653     left  = IC_LEFT(ic);
6654     result = IC_RESULT(ic);
6655
6656     aopOp(right,ic,FALSE, FALSE);
6657
6658 #if 0
6659     /* if the shift count is known then do it 
6660     as efficiently as possible */
6661     if (AOP_TYPE(right) == AOP_LIT) {
6662         genRightShiftLiteral (left,right,result,ic, 0);
6663         return ;
6664     }
6665 #endif
6666
6667     /* shift count is unknown then we have to form 
6668     a loop get the loop count in B : Note: we take
6669     only the lower order byte since shifting
6670     more that 32 bits make no sense anyway, ( the
6671     largest size of an object can be only 32 bits ) */  
6672
6673     emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
6674     emitcode("inc","b");
6675     freeAsmop (right,NULL,ic,TRUE);
6676     aopOp(left,ic,FALSE, FALSE);
6677     aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6678
6679     /* now move the left to the result if they are not the
6680     same */
6681     if (!sameRegs(AOP(left),AOP(result)) && 
6682         AOP_SIZE(result) > 1) {
6683
6684         size = AOP_SIZE(result);
6685         offset=0;
6686         _startLazyDPSEvaluation();
6687         while (size--) {
6688             l = aopGet(AOP(left),offset,FALSE,TRUE,FALSE);
6689             if (*l == '@' && IS_AOP_PREG(result)) {
6690
6691                 emitcode("mov","a,%s",l);
6692                 aopPut(AOP(result),"a",offset);
6693             } else
6694                 aopPut(AOP(result),l,offset);
6695             offset++;
6696         }
6697         _endLazyDPSEvaluation();
6698     }
6699
6700     tlbl = newiTempLabel(NULL);
6701     tlbl1= newiTempLabel(NULL);
6702     size = AOP_SIZE(result);
6703     offset = size - 1;
6704
6705     /* if it is only one byte then */
6706     if (size == 1) {
6707         l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
6708         MOVA(l);
6709         emitcode("sjmp","%05d$",tlbl1->key+100);
6710         emitcode("","%05d$:",tlbl->key+100);
6711         CLRC;
6712         emitcode("rrc","a");
6713         emitcode("","%05d$:",tlbl1->key+100);
6714         emitcode("djnz","b,%05d$",tlbl->key+100);
6715         aopPut(AOP(result),"a",0);
6716         goto release ;
6717     }
6718
6719     reAdjustPreg(AOP(result));
6720     emitcode("sjmp","%05d$",tlbl1->key+100);
6721     emitcode("","%05d$:",tlbl->key+100);    
6722     CLRC;
6723     _startLazyDPSEvaluation();
6724     while (size--) {
6725         l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6726         MOVA(l);
6727         emitcode("rrc","a");         
6728         aopPut(AOP(result),"a",offset--);
6729     }
6730     _endLazyDPSEvaluation();
6731     reAdjustPreg(AOP(result));
6732
6733     emitcode("","%05d$:",tlbl1->key+100);
6734     emitcode("djnz","b,%05d$",tlbl->key+100);
6735
6736 release:
6737     freeAsmop(left,NULL,ic,TRUE);
6738     freeAsmop(result,NULL,ic,TRUE);
6739 }
6740
6741 /*-----------------------------------------------------------------*/
6742 /* genUnpackBits - generates code for unpacking bits               */
6743 /*-----------------------------------------------------------------*/
6744 static void genUnpackBits (operand *result, char *rname, int ptype)
6745 {    
6746     int shCnt ;
6747     int rlen = 0 ;
6748     sym_link *etype;
6749     int offset = 0 ;
6750
6751     D(emitcode(";", "genUnpackBits "););
6752
6753     etype = getSpec(operandType(result));
6754
6755     /* read the first byte  */
6756     switch (ptype) {
6757
6758     case POINTER:
6759     case IPOINTER:
6760         emitcode("mov","a,@%s",rname);
6761         break;
6762         
6763     case PPOINTER:
6764         emitcode("movx","a,@%s",rname);
6765         break;
6766         
6767     case FPOINTER:
6768         emitcode("movx","a,@dptr");
6769         break;
6770
6771     case CPOINTER:
6772         emitcode("clr","a");
6773         emitcode("movc","a","@a+dptr");
6774         break;
6775
6776     case GPOINTER:
6777         emitcode("lcall","__gptrget");
6778         break;
6779     }
6780
6781     /* if we have bitdisplacement then it fits   */
6782     /* into this byte completely or if length is */
6783     /* less than a byte                          */
6784     if ((shCnt = SPEC_BSTR(etype)) || 
6785         (SPEC_BLEN(etype) <= 8))  {
6786
6787         /* shift right acc */
6788         AccRsh(shCnt);
6789
6790         emitcode("anl","a,#0x%02x",
6791                  ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
6792         aopPut(AOP(result),"a",offset);
6793         return ;
6794     }
6795
6796     /* bit field did not fit in a byte  */
6797     rlen = SPEC_BLEN(etype) - 8;
6798     aopPut(AOP(result),"a",offset++);
6799
6800     while (1)  {
6801
6802         switch (ptype) {
6803         case POINTER:
6804         case IPOINTER:
6805             emitcode("inc","%s",rname);
6806             emitcode("mov","a,@%s",rname);
6807             break;
6808             
6809         case PPOINTER:
6810             emitcode("inc","%s",rname);
6811             emitcode("movx","a,@%s",rname);
6812             break;
6813
6814         case FPOINTER:
6815             emitcode("inc","dptr");
6816             emitcode("movx","a,@dptr");
6817             break;
6818             
6819         case CPOINTER:
6820             emitcode("clr","a");
6821             emitcode("inc","dptr");
6822             emitcode("movc","a","@a+dptr");
6823             break;
6824             
6825         case GPOINTER:
6826             emitcode("inc","dptr");
6827             emitcode("lcall","__gptrget");
6828             break;
6829         }
6830
6831         rlen -= 8;            
6832         /* if we are done */
6833         if ( rlen < 8 )
6834             break ;
6835         
6836         aopPut(AOP(result),"a",offset++);
6837                               
6838     }
6839     
6840     if (rlen) {
6841         emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(rlen));
6842         aopPut(AOP(result),"a",offset);        
6843     }
6844     
6845     return ;
6846 }
6847
6848
6849 /*-----------------------------------------------------------------*/
6850 /* genDataPointerGet - generates code when ptr offset is known     */
6851 /*-----------------------------------------------------------------*/
6852 static void genDataPointerGet (operand *left, 
6853                                operand *result, 
6854                                iCode *ic)
6855 {
6856     char *l;
6857     char buffer[256];
6858     int size , offset = 0;
6859     aopOp(result,ic,TRUE, FALSE);
6860
6861     /* get the string representation of the name */
6862     l = aopGet(AOP(left),0,FALSE,TRUE,FALSE);
6863     size = AOP_SIZE(result);
6864     _startLazyDPSEvaluation();
6865     while (size--) {
6866         if (offset)
6867             sprintf(buffer,"(%s + %d)",l+1,offset);
6868         else
6869             sprintf(buffer,"%s",l+1);
6870         aopPut(AOP(result),buffer,offset++);
6871     }
6872     _endLazyDPSEvaluation();
6873
6874     freeAsmop(left,NULL,ic,TRUE);
6875     freeAsmop(result,NULL,ic,TRUE);
6876 }
6877
6878 /*-----------------------------------------------------------------*/
6879 /* genNearPointerGet - emitcode for near pointer fetch             */
6880 /*-----------------------------------------------------------------*/
6881 static void genNearPointerGet (operand *left, 
6882                                operand *result, 
6883                                iCode *ic)
6884 {
6885     asmop *aop = NULL;
6886     regs *preg = NULL ;
6887     char *rname ;
6888     sym_link *rtype, *retype, *letype;
6889     sym_link *ltype = operandType(left);    
6890     char buffer[80];
6891
6892     rtype = operandType(result);
6893     retype= getSpec(rtype);
6894     letype= getSpec(ltype);
6895
6896     aopOp(left,ic,FALSE, FALSE);
6897     
6898     /* if left is rematerialisable and
6899        result is not bit variable type and
6900        the left is pointer to data space i.e
6901        lower 128 bytes of space */
6902     if (AOP_TYPE(left) == AOP_IMMD &&
6903         !IS_BITVAR(retype)         &&
6904         !IS_BITVAR(letype)         &&
6905         DCL_TYPE(ltype) == POINTER) {
6906         genDataPointerGet (left,result,ic);
6907         return ;
6908     }
6909     
6910         /* if the value is already in a pointer register
6911        then don't need anything more */
6912     if (!AOP_INPREG(AOP(left))) {
6913         /* otherwise get a free pointer register */
6914         aop = newAsmop(0);
6915         preg = getFreePtr(ic,&aop,FALSE);
6916         emitcode("mov","%s,%s",
6917                 preg->name,
6918                 aopGet(AOP(left),0,FALSE,TRUE,FALSE));
6919         rname = preg->name ;
6920     } else
6921         rname = aopGet(AOP(left),0,FALSE,FALSE,FALSE);
6922     
6923     freeAsmop(left,NULL,ic,TRUE);
6924     aopOp (result,ic,FALSE, FALSE);
6925     
6926       /* if bitfield then unpack the bits */
6927     if (IS_BITVAR(retype) || IS_BITVAR(letype)) 
6928         genUnpackBits (result,rname,POINTER);
6929     else {
6930         /* we have can just get the values */
6931         int size = AOP_SIZE(result);
6932         int offset = 0 ;        
6933         
6934         while (size--) {
6935             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
6936
6937                 emitcode("mov","a,@%s",rname);
6938                 aopPut(AOP(result),"a",offset);
6939             } else {
6940                 sprintf(buffer,"@%s",rname);
6941                 aopPut(AOP(result),buffer,offset);
6942             }
6943             offset++ ;
6944             if (size)
6945                 emitcode("inc","%s",rname);
6946         }
6947     }
6948
6949     /* now some housekeeping stuff */
6950     if (aop) {
6951         /* we had to allocate for this iCode */
6952         freeAsmop(NULL,aop,ic,TRUE);
6953     } else { 
6954         /* we did not allocate which means left
6955            already in a pointer register, then
6956            if size > 0 && this could be used again
6957            we have to point it back to where it 
6958            belongs */
6959         if (AOP_SIZE(result) > 1 &&
6960             !OP_SYMBOL(left)->remat &&
6961             ( OP_SYMBOL(left)->liveTo > ic->seq ||
6962               ic->depth )) {
6963             int size = AOP_SIZE(result) - 1;
6964             while (size--)
6965                 emitcode("dec","%s",rname);
6966         }
6967     }
6968
6969     /* done */
6970     freeAsmop(result,NULL,ic,TRUE);
6971      
6972 }
6973
6974 /*-----------------------------------------------------------------*/
6975 /* genPagedPointerGet - emitcode for paged pointer fetch           */
6976 /*-----------------------------------------------------------------*/
6977 static void genPagedPointerGet (operand *left, 
6978                                operand *result, 
6979                                iCode *ic)
6980 {
6981     asmop *aop = NULL;
6982     regs *preg = NULL ;
6983     char *rname;
6984     sym_link *rtype, *retype, *letype;    
6985
6986     rtype = operandType(result);
6987     retype= getSpec(rtype);
6988     letype= getSpec(operandType(left));
6989     aopOp(left,ic,FALSE, FALSE);
6990
6991   /* if the value is already in a pointer register
6992        then don't need anything more */
6993     if (!AOP_INPREG(AOP(left))) {
6994         /* otherwise get a free pointer register */
6995         aop = newAsmop(0);
6996         preg = getFreePtr(ic,&aop,FALSE);
6997         emitcode("mov","%s,%s",
6998                 preg->name,
6999                 aopGet(AOP(left),0,FALSE,TRUE,FALSE));
7000         rname = preg->name ;
7001     } else
7002         rname = aopGet(AOP(left),0,FALSE,FALSE,FALSE);
7003     
7004     freeAsmop(left,NULL,ic,TRUE);
7005     aopOp (result,ic,FALSE, FALSE);
7006
7007     /* if bitfield then unpack the bits */
7008     if (IS_BITVAR(retype) || IS_BITVAR(letype)) 
7009         genUnpackBits (result,rname,PPOINTER);
7010     else {
7011         /* we have can just get the values */
7012         int size = AOP_SIZE(result);
7013         int offset = 0 ;        
7014         
7015         while (size--) {
7016             
7017             emitcode("movx","a,@%s",rname);
7018             aopPut(AOP(result),"a",offset);
7019             
7020             offset++ ;
7021             
7022             if (size)
7023                 emitcode("inc","%s",rname);
7024         }
7025     }
7026
7027     /* now some housekeeping stuff */
7028     if (aop) {
7029         /* we had to allocate for this iCode */
7030         freeAsmop(NULL,aop,ic,TRUE);
7031     } else { 
7032         /* we did not allocate which means left
7033            already in a pointer register, then
7034            if size > 0 && this could be used again
7035            we have to point it back to where it 
7036            belongs */
7037         if (AOP_SIZE(result) > 1 &&
7038             !OP_SYMBOL(left)->remat &&
7039             ( OP_SYMBOL(left)->liveTo > ic->seq ||
7040               ic->depth )) {
7041             int size = AOP_SIZE(result) - 1;
7042             while (size--)
7043                 emitcode("dec","%s",rname);
7044         }
7045     }
7046
7047     /* done */
7048     freeAsmop(result,NULL,ic,TRUE);
7049     
7050         
7051 }
7052
7053 /*-----------------------------------------------------------------*/
7054 /* genFarPointerGet - gget value from far space                    */
7055 /*-----------------------------------------------------------------*/
7056 static void genFarPointerGet (operand *left,
7057                               operand *result, iCode *ic)
7058 {
7059     int size, offset ;
7060     sym_link *retype = getSpec(operandType(result));
7061     sym_link *letype = getSpec(operandType(left));
7062     D(emitcode(";", "genFarPointerGet"););
7063
7064     aopOp(left,ic,FALSE, FALSE);
7065
7066     /* if the operand is already in dptr 
7067     then we do nothing else we move the value to dptr */
7068     if (AOP_TYPE(left) != AOP_STR) {
7069         /* if this is remateriazable */
7070         if (AOP_TYPE(left) == AOP_IMMD)
7071         {
7072             emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE,FALSE));
7073         }
7074         else 
7075         { 
7076             /* we need to get it byte by byte */
7077             _startLazyDPSEvaluation();
7078             if (AOP_TYPE(left) != AOP_DPTR)
7079             {
7080                 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
7081                 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
7082                 emitcode("mov","dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
7083             }
7084             else
7085             {
7086                  /* We need to generate a load to DPTR indirect through DPTR. */
7087                  D(emitcode(";", "genFarPointerGet -- indirection special case."););
7088                  emitcode("push", "%s", aopGet(AOP(left),0,FALSE,TRUE,TRUE));
7089                  emitcode("push", "%s", aopGet(AOP(left),1,FALSE,TRUE,TRUE));
7090                  emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
7091                  emitcode("pop", "dph");
7092                  emitcode("pop", "dpl");
7093             }
7094             _endLazyDPSEvaluation();
7095         }
7096     }
7097     /* so dptr know contains the address */
7098     freeAsmop(left,NULL,ic,TRUE);
7099     aopOp(result,ic,FALSE, TRUE);
7100
7101     /* if bit then unpack */
7102     if (IS_BITVAR(retype) || IS_BITVAR(letype)) 
7103         genUnpackBits(result,"dptr",FPOINTER);
7104     else {
7105         size = AOP_SIZE(result);
7106         offset = 0 ;
7107
7108         _startLazyDPSEvaluation();
7109         while (size--) {
7110             
7111             genSetDPTR(0);
7112             _flushLazyDPS();
7113             
7114             emitcode("movx","a,@dptr");
7115             if (size)
7116                 emitcode("inc","dptr");     
7117
7118             aopPut(AOP(result),"a",offset++);
7119         }
7120         _endLazyDPSEvaluation();
7121     }
7122
7123     freeAsmop(result,NULL,ic,TRUE);
7124 }
7125
7126 /*-----------------------------------------------------------------*/
7127 /* emitcodePointerGet - gget value from code space                  */
7128 /*-----------------------------------------------------------------*/
7129 static void emitcodePointerGet (operand *left,
7130                                 operand *result, iCode *ic)
7131 {
7132     int size, offset ;
7133     sym_link *retype = getSpec(operandType(result));
7134
7135     aopOp(left,ic,FALSE, FALSE);
7136
7137     /* if the operand is already in dptr 
7138     then we do nothing else we move the value to dptr */
7139     if (AOP_TYPE(left) != AOP_STR) {
7140         /* if this is remateriazable */
7141         if (AOP_TYPE(left) == AOP_IMMD)
7142         {
7143             emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE,FALSE));
7144         }
7145         else
7146         { /* we need to get it byte by byte */
7147             _startLazyDPSEvaluation();
7148             if (AOP_TYPE(left) != AOP_DPTR)
7149             {
7150                 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
7151                 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
7152                 emitcode("mov","dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
7153             }
7154             else
7155             {
7156                  /* We need to generate a load to DPTR indirect through DPTR. */
7157                  D(emitcode(";", "gencodePointerGet -- indirection special case."););
7158                  emitcode("push", "%s", aopGet(AOP(left),0,FALSE,TRUE,TRUE));
7159                  emitcode("push", "%s", aopGet(AOP(left),1,FALSE,TRUE,TRUE));
7160                  emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
7161                  emitcode("pop", "dph");
7162                  emitcode("pop", "dpl");
7163             }      
7164             _endLazyDPSEvaluation();        
7165         }
7166     }
7167     /* so dptr know contains the address */
7168     freeAsmop(left,NULL,ic,TRUE);
7169     aopOp(result,ic,FALSE, TRUE);
7170
7171     /* if bit then unpack */
7172     if (IS_BITVAR(retype)) 
7173         genUnpackBits(result,"dptr",CPOINTER);
7174     else {
7175         size = AOP_SIZE(result);
7176         offset = 0 ;
7177
7178         _startLazyDPSEvaluation();
7179         while (size--) 
7180         {
7181             genSetDPTR(0);
7182             _flushLazyDPS();
7183                               
7184             emitcode("clr","a");
7185             emitcode("movc","a,@a+dptr");
7186             if (size)
7187                 emitcode("inc","dptr");            
7188             aopPut(AOP(result),"a",offset++);
7189         }
7190         _endLazyDPSEvaluation();
7191     }
7192
7193     freeAsmop(result,NULL,ic,TRUE);
7194 }
7195
7196 /*-----------------------------------------------------------------*/
7197 /* genGenPointerGet - gget value from generic pointer space        */
7198 /*-----------------------------------------------------------------*/
7199 static void genGenPointerGet (operand *left,
7200                               operand *result, iCode *ic)
7201 {
7202     int size, offset ;
7203     sym_link *retype = getSpec(operandType(result));
7204     sym_link *letype = getSpec(operandType(left));
7205
7206     aopOp(left,ic,FALSE, TRUE);
7207
7208     /* if the operand is already in dptr 
7209     then we do nothing else we move the value to dptr */
7210     if (AOP_TYPE(left) != AOP_STR) {
7211         /* if this is remateriazable */
7212         if (AOP_TYPE(left) == AOP_IMMD) {
7213             emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE,FALSE));
7214             emitcode("mov","b,#%d",pointerCode(retype));
7215         }
7216         else { /* we need to get it byte by byte */
7217             _startLazyDPSEvaluation();
7218             emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
7219             emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
7220             emitcode("mov","dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
7221             emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE,TRUE));
7222             _endLazyDPSEvaluation();
7223         }
7224     }
7225     /* so dptr know contains the address */
7226     freeAsmop(left,NULL,ic,TRUE);
7227     aopOp(result,ic,FALSE, TRUE);
7228
7229     /* if bit then unpack */
7230     if (IS_BITVAR(retype) || IS_BITVAR(letype)) 
7231         genUnpackBits(result,"dptr",GPOINTER);
7232     else {
7233         size = AOP_SIZE(result);
7234         offset = 0 ;
7235
7236         while (size--) {
7237             emitcode("lcall","__gptrget");
7238             aopPut(AOP(result),"a",offset++);
7239             if (size)
7240                 emitcode("inc","dptr");
7241         }
7242     }
7243
7244     freeAsmop(result,NULL,ic,TRUE);
7245 }
7246
7247 /*-----------------------------------------------------------------*/
7248 /* genPointerGet - generate code for pointer get                   */
7249 /*-----------------------------------------------------------------*/
7250 static void genPointerGet (iCode *ic)
7251 {
7252     operand *left, *result ;
7253     sym_link *type, *etype;
7254     int p_type;
7255
7256     D(emitcode(";", "genPointerGet "););
7257
7258     left = IC_LEFT(ic);
7259     result = IC_RESULT(ic) ;
7260
7261     /* depending on the type of pointer we need to
7262     move it to the correct pointer register */
7263     type = operandType(left);
7264     etype = getSpec(type);
7265     /* if left is of type of pointer then it is simple */
7266     if (IS_PTR(type) && !IS_FUNC(type->next)) 
7267         p_type = DCL_TYPE(type);
7268     else {
7269         /* we have to go by the storage class */
7270         p_type = PTR_TYPE(SPEC_OCLS(etype));
7271     }
7272
7273     /* now that we have the pointer type we assign
7274     the pointer values */
7275     switch (p_type) {
7276
7277     case POINTER:       
7278     case IPOINTER:
7279         genNearPointerGet (left,result,ic);
7280         break;
7281
7282     case PPOINTER:
7283         genPagedPointerGet(left,result,ic);
7284         break;
7285
7286     case FPOINTER:
7287         genFarPointerGet (left,result,ic);
7288         break;
7289
7290     case CPOINTER:
7291         emitcodePointerGet (left,result,ic);
7292         break;
7293
7294     case GPOINTER:
7295         genGenPointerGet (left,result,ic);
7296         break;
7297     }
7298
7299 }
7300
7301 /*-----------------------------------------------------------------*/
7302 /* genPackBits - generates code for packed bit storage             */
7303 /*-----------------------------------------------------------------*/
7304 static void genPackBits (sym_link    *etype ,
7305                          operand *right ,
7306                          char *rname, int p_type)
7307 {
7308     int shCount = 0 ;
7309     int offset = 0  ;
7310     int rLen = 0 ;
7311     int blen, bstr ;   
7312     char *l ;
7313
7314     blen = SPEC_BLEN(etype);
7315     bstr = SPEC_BSTR(etype);
7316
7317     l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7318     MOVA(l);   
7319
7320     /* if the bit lenth is less than or    */
7321     /* it exactly fits a byte then         */
7322     if (SPEC_BLEN(etype) <= 8 )  {
7323         shCount = SPEC_BSTR(etype) ;
7324
7325         /* shift left acc */
7326         AccLsh(shCount);
7327
7328         if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
7329
7330
7331             switch (p_type) {
7332                 case POINTER:
7333                     emitcode ("mov","b,a");
7334                     emitcode("mov","a,@%s",rname);
7335                     break;
7336
7337                 case FPOINTER:
7338                     emitcode ("mov","b,a");
7339                     emitcode("movx","a,@dptr");
7340                     break;
7341
7342                 case GPOINTER:
7343                     emitcode ("push","b");
7344                     emitcode ("push","acc");
7345                     emitcode ("lcall","__gptrget");
7346                     emitcode ("pop","b");
7347                     break;
7348             }
7349
7350             emitcode ("anl","a,#0x%02x",(unsigned char)
7351                       ((unsigned char)(0xFF << (blen+bstr)) | 
7352                        (unsigned char)(0xFF >> (8-bstr)) ) );
7353             emitcode ("orl","a,b");
7354             if (p_type == GPOINTER)
7355                 emitcode("pop","b");
7356         }
7357     }
7358
7359     switch (p_type) {
7360         case POINTER:
7361             emitcode("mov","@%s,a",rname);
7362             break;
7363
7364         case FPOINTER:
7365             emitcode("movx","@dptr,a");
7366             break;
7367
7368         case GPOINTER:
7369             emitcode("lcall","__gptrput");
7370             break;
7371     }
7372
7373     /* if we r done */
7374     if ( SPEC_BLEN(etype) <= 8 )
7375         return ;
7376
7377     emitcode("inc","%s",rname);
7378     rLen = SPEC_BLEN(etype) ;     
7379
7380     /* now generate for lengths greater than one byte */
7381     while (1) {
7382
7383         l = aopGet(AOP(right),offset++,FALSE,TRUE,FALSE);
7384
7385         rLen -= 8 ;
7386         if (rLen < 8 )
7387             break ;
7388
7389         switch (p_type) {
7390             case POINTER:
7391                 if (*l == '@') {
7392                     MOVA(l);
7393                     emitcode("mov","@%s,a",rname);
7394                 } else
7395                     emitcode("mov","@%s,%s",rname,l);
7396                 break;
7397
7398             case FPOINTER:
7399                 MOVA(l);
7400                 emitcode("movx","@dptr,a");
7401                 break;
7402
7403             case GPOINTER:
7404                 MOVA(l);
7405                 emitcode("lcall","__gptrput");
7406                 break;  
7407         }   
7408         emitcode ("inc","%s",rname);
7409     }
7410
7411     MOVA(l);
7412
7413     /* last last was not complete */
7414     if (rLen)   {
7415         /* save the byte & read byte */
7416         switch (p_type) {
7417             case POINTER:
7418                 emitcode ("mov","b,a");
7419                 emitcode("mov","a,@%s",rname);
7420                 break;
7421
7422             case FPOINTER:
7423                 emitcode ("mov","b,a");
7424                 emitcode("movx","a,@dptr");
7425                 break;
7426
7427             case GPOINTER:
7428                 emitcode ("push","b");
7429                 emitcode ("push","acc");
7430                 emitcode ("lcall","__gptrget");
7431                 emitcode ("pop","b");
7432                 break;
7433         }
7434
7435         emitcode ("anl","a,#0x%02x",((unsigned char)-1 << rLen) );
7436         emitcode ("orl","a,b");
7437     }
7438
7439     if (p_type == GPOINTER)
7440         emitcode("pop","b");
7441
7442     switch (p_type) {
7443
7444     case POINTER:
7445         emitcode("mov","@%s,a",rname);
7446         break;
7447         
7448     case FPOINTER:
7449         emitcode("movx","@dptr,a");
7450         break;
7451         
7452     case GPOINTER:
7453         emitcode("lcall","__gptrput");
7454         break;                  
7455     }
7456 }
7457 /*-----------------------------------------------------------------*/
7458 /* genDataPointerSet - remat pointer to data space                 */
7459 /*-----------------------------------------------------------------*/
7460 static void genDataPointerSet(operand *right,
7461                               operand *result,
7462                               iCode *ic)
7463 {
7464     int size, offset = 0 ;
7465     char *l, buffer[256];
7466
7467     aopOp(right,ic,FALSE, FALSE);
7468     
7469     l = aopGet(AOP(result),0,FALSE,TRUE,FALSE);
7470     size = AOP_SIZE(right);
7471     while (size--) {
7472         if (offset)
7473             sprintf(buffer,"(%s + %d)",l+1,offset);
7474         else
7475             sprintf(buffer,"%s",l+1);
7476         emitcode("mov","%s,%s",buffer,
7477                  aopGet(AOP(right),offset++,FALSE,FALSE,FALSE));
7478     }
7479
7480     freeAsmop(right,NULL,ic,TRUE);
7481     freeAsmop(result,NULL,ic,TRUE);
7482 }
7483
7484 /*-----------------------------------------------------------------*/
7485 /* genNearPointerSet - emitcode for near pointer put                */
7486 /*-----------------------------------------------------------------*/
7487 static void genNearPointerSet (operand *right,
7488                                operand *result, 
7489                                iCode *ic)
7490 {
7491     asmop *aop = NULL;
7492     regs *preg = NULL ;
7493     char *rname , *l;
7494     sym_link *retype, *letype;
7495     sym_link *ptype = operandType(result);
7496     
7497     retype= getSpec(operandType(right));
7498     letype= getSpec(ptype);
7499
7500     aopOp(result,ic,FALSE, FALSE);
7501     
7502     /* if the result is rematerializable &
7503        in data space & not a bit variable */
7504     if (AOP_TYPE(result) == AOP_IMMD &&
7505         DCL_TYPE(ptype) == POINTER   &&
7506         !IS_BITVAR(retype) &&
7507         !IS_BITVAR(letype)) {
7508         genDataPointerSet (right,result,ic);
7509         return;
7510     }
7511
7512     /* if the value is already in a pointer register
7513     then don't need anything more */
7514     if (!AOP_INPREG(AOP(result))) {
7515         /* otherwise get a free pointer register */
7516         aop = newAsmop(0);
7517         preg = getFreePtr(ic,&aop,FALSE);
7518         emitcode("mov","%s,%s",
7519                  preg->name,
7520                  aopGet(AOP(result),0,FALSE,TRUE,FALSE));
7521         rname = preg->name ;
7522     } else
7523         rname = aopGet(AOP(result),0,FALSE,FALSE,FALSE);
7524
7525     freeAsmop(result,NULL,ic,TRUE);
7526     aopOp (right,ic,FALSE, FALSE);
7527
7528     /* if bitfield then unpack the bits */
7529     if (IS_BITVAR(retype) || IS_BITVAR(letype)) 
7530         genPackBits ((IS_BITVAR(retype) ? retype : letype),right,rname,POINTER);
7531     else {
7532         /* we have can just get the values */
7533         int size = AOP_SIZE(right);
7534         int offset = 0 ;    
7535
7536         while (size--) {
7537             l = aopGet(AOP(right),offset,FALSE,TRUE,FALSE);
7538             if (*l == '@' ) {
7539                 MOVA(l);
7540                 emitcode("mov","@%s,a",rname);
7541             } else
7542                 emitcode("mov","@%s,%s",rname,l);
7543             if (size)
7544                 emitcode("inc","%s",rname);
7545             offset++;
7546         }
7547     }
7548
7549     /* now some housekeeping stuff */
7550     if (aop) {
7551         /* we had to allocate for this iCode */
7552         freeAsmop(NULL,aop,ic,TRUE);
7553     } else { 
7554         /* we did not allocate which means left
7555         already in a pointer register, then
7556         if size > 0 && this could be used again
7557         we have to point it back to where it 
7558         belongs */
7559         if (AOP_SIZE(right) > 1 &&
7560             !OP_SYMBOL(result)->remat &&
7561             ( OP_SYMBOL(result)->liveTo > ic->seq ||
7562               ic->depth )) {
7563             int size = AOP_SIZE(right) - 1;
7564             while (size--)
7565                 emitcode("dec","%s",rname);
7566         }
7567     }
7568
7569     /* done */
7570     freeAsmop(right,NULL,ic,TRUE);
7571
7572
7573 }
7574
7575 /*-----------------------------------------------------------------*/
7576 /* genPagedPointerSet - emitcode for Paged pointer put             */
7577 /*-----------------------------------------------------------------*/
7578 static void genPagedPointerSet (operand *right,
7579                                operand *result, 
7580                                iCode *ic)
7581 {
7582     asmop *aop = NULL;
7583     regs *preg = NULL ;
7584     char *rname , *l;
7585     sym_link *retype, *letype;
7586        
7587     retype= getSpec(operandType(right));
7588     letype= getSpec(operandType(result));
7589     
7590     aopOp(result,ic,FALSE, FALSE);
7591     
7592     /* if the value is already in a pointer register
7593        then don't need anything more */
7594     if (!AOP_INPREG(AOP(result))) {
7595         /* otherwise get a free pointer register */
7596         aop = newAsmop(0);
7597         preg = getFreePtr(ic,&aop,FALSE);
7598         emitcode("mov","%s,%s",
7599                 preg->name,
7600                 aopGet(AOP(result),0,FALSE,TRUE,FALSE));
7601         rname = preg->name ;
7602     } else
7603         rname = aopGet(AOP(result),0,FALSE,FALSE,FALSE);
7604     
7605     freeAsmop(result,NULL,ic,TRUE);
7606     aopOp (right,ic,FALSE, FALSE);
7607
7608     /* if bitfield then unpack the bits */
7609     if (IS_BITVAR(retype) || IS_BITVAR(letype)) 
7610         genPackBits ((IS_BITVAR(retype) ? retype : letype) ,right,rname,PPOINTER);
7611     else {
7612         /* we have can just get the values */
7613         int size = AOP_SIZE(right);
7614         int offset = 0 ;        
7615         
7616         while (size--) {
7617             l = aopGet(AOP(right),offset,FALSE,TRUE,TRUE);
7618             
7619             MOVA(l);
7620             emitcode("movx","@%s,a",rname);
7621
7622             if (size)
7623                 emitcode("inc","%s",rname);
7624
7625             offset++;
7626         }
7627     }
7628     
7629     /* now some housekeeping stuff */
7630     if (aop) {
7631         /* we had to allocate for this iCode */
7632         freeAsmop(NULL,aop,ic,TRUE);
7633     } else { 
7634         /* we did not allocate which means left
7635            already in a pointer register, then
7636            if size > 0 && this could be used again
7637            we have to point it back to where it 
7638            belongs */
7639         if (AOP_SIZE(right) > 1 &&
7640             !OP_SYMBOL(result)->remat &&
7641             ( OP_SYMBOL(result)->liveTo > ic->seq ||
7642               ic->depth )) {
7643             int size = AOP_SIZE(right) - 1;
7644             while (size--)
7645                 emitcode("dec","%s",rname);
7646         }
7647     }
7648
7649     /* done */
7650     freeAsmop(right,NULL,ic,TRUE);
7651     
7652         
7653 }
7654
7655 /*-----------------------------------------------------------------*/
7656 /* genFarPointerSet - set value from far space                     */
7657 /*-----------------------------------------------------------------*/
7658 static void genFarPointerSet (operand *right,
7659                               operand *result, iCode *ic)
7660 {
7661     int size, offset ;
7662     sym_link *retype = getSpec(operandType(right));
7663     sym_link *letype = getSpec(operandType(result));
7664
7665     aopOp(result,ic,FALSE, FALSE);
7666
7667     /* if the operand is already in dptr 
7668     then we do nothing else we move the value to dptr */
7669     if (AOP_TYPE(result) != AOP_STR) {
7670         /* if this is remateriazable */
7671         if (AOP_TYPE(result) == AOP_IMMD)
7672             emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE,FALSE));
7673         else 
7674         {
7675             /* we need to get it byte by byte */
7676             _startLazyDPSEvaluation();
7677             if (AOP_TYPE(result) != AOP_DPTR)
7678             {
7679                 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE,TRUE));
7680                 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE,TRUE));
7681                 emitcode("mov","dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7682             }
7683             else
7684             {
7685                  /* We need to generate a load to DPTR indirect through DPTR. */
7686                  D(emitcode(";", "genFarPointerSet -- indirection special case."););
7687                  emitcode("push", "%s", aopGet(AOP(result),0,FALSE,TRUE,TRUE));
7688                  emitcode("push", "%s", aopGet(AOP(result),1,FALSE,TRUE,TRUE));
7689                  emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7690                  emitcode("pop", "dph");
7691                  emitcode("pop", "dpl");
7692             }
7693             _endLazyDPSEvaluation();
7694         }
7695     }
7696     /* so dptr know contains the address */
7697     freeAsmop(result,NULL,ic,TRUE);
7698     aopOp(right,ic,FALSE, TRUE);
7699
7700     /* if bit then unpack */
7701     if (IS_BITVAR(retype) || IS_BITVAR(letype)) 
7702         genPackBits((IS_BITVAR(retype)?retype:letype),right,"dptr",FPOINTER);
7703     else {
7704         size = AOP_SIZE(right);
7705         offset = 0 ;
7706
7707         _startLazyDPSEvaluation();
7708         while (size--) {
7709             char *l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7710             MOVA(l);
7711             
7712             genSetDPTR(0);
7713             _flushLazyDPS();
7714             
7715             emitcode("movx","@dptr,a");
7716             if (size)
7717                 emitcode("inc","dptr");
7718         }
7719         _endLazyDPSEvaluation();
7720     }
7721
7722     freeAsmop(right,NULL,ic,TRUE);
7723 }
7724
7725 /*-----------------------------------------------------------------*/
7726 /* genGenPointerSet - set value from generic pointer space         */
7727 /*-----------------------------------------------------------------*/
7728 static void genGenPointerSet (operand *right,
7729                               operand *result, iCode *ic)
7730 {
7731     int size, offset ;
7732     sym_link *retype = getSpec(operandType(right));
7733     sym_link *letype = getSpec(operandType(result));
7734
7735     aopOp(result,ic,FALSE, TRUE);
7736
7737     /* if the operand is already in dptr 
7738     then we do nothing else we move the value to dptr */
7739     if (AOP_TYPE(result) != AOP_STR) {
7740         _startLazyDPSEvaluation();
7741         /* if this is remateriazable */
7742         if (AOP_TYPE(result) == AOP_IMMD) {
7743             emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE,FALSE));
7744             emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE,FALSE));
7745         }
7746         else { /* we need to get it byte by byte */
7747             emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE,TRUE));
7748             emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE,TRUE));
7749             emitcode("mov","dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7750             emitcode("mov","b,%s",aopGet(AOP(result),3,FALSE,FALSE,TRUE));
7751         }
7752         _endLazyDPSEvaluation();
7753     }
7754     /* so dptr know contains the address */
7755     freeAsmop(result,NULL,ic,TRUE);
7756     aopOp(right,ic,FALSE, TRUE);
7757
7758     /* if bit then unpack */
7759     if (IS_BITVAR(retype) || IS_BITVAR(letype)) 
7760         genPackBits((IS_BITVAR(retype)?retype:letype),right,"dptr",GPOINTER);
7761     else {
7762         size = AOP_SIZE(right);
7763         offset = 0 ;
7764
7765         _startLazyDPSEvaluation();
7766         while (size--) {
7767             char *l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7768             MOVA(l);
7769             
7770             genSetDPTR(0);
7771             _flushLazyDPS();
7772             
7773             emitcode("lcall","__gptrput");
7774             if (size)
7775                 emitcode("inc","dptr");
7776         }
7777         _endLazyDPSEvaluation();
7778     }
7779
7780     freeAsmop(right,NULL,ic,TRUE);
7781 }
7782
7783 /*-----------------------------------------------------------------*/
7784 /* genPointerSet - stores the value into a pointer location        */
7785 /*-----------------------------------------------------------------*/
7786 static void genPointerSet (iCode *ic)
7787 {    
7788     operand *right, *result ;
7789     sym_link *type, *etype;
7790     int p_type;
7791
7792     D(emitcode(";", "genPointerSet "););
7793
7794     right = IC_RIGHT(ic);
7795     result = IC_RESULT(ic) ;
7796
7797     /* depending on the type of pointer we need to
7798     move it to the correct pointer register */
7799     type = operandType(result);
7800     etype = getSpec(type);
7801     /* if left is of type of pointer then it is simple */
7802     if (IS_PTR(type) && !IS_FUNC(type->next)) {
7803         p_type = DCL_TYPE(type);
7804     }
7805     else {
7806         /* we have to go by the storage class */
7807         p_type = PTR_TYPE(SPEC_OCLS(etype));
7808     }
7809
7810     /* now that we have the pointer type we assign
7811     the pointer values */
7812     switch (p_type) {
7813
7814     case POINTER:
7815     case IPOINTER:
7816         genNearPointerSet (right,result,ic);
7817         break;
7818
7819     case PPOINTER:
7820         genPagedPointerSet (right,result,ic);
7821         break;
7822
7823     case FPOINTER:
7824         genFarPointerSet (right,result,ic);
7825         break;
7826
7827     case GPOINTER:
7828         genGenPointerSet (right,result,ic);
7829         break;
7830     }
7831
7832 }
7833
7834 /*-----------------------------------------------------------------*/
7835 /* genIfx - generate code for Ifx statement                        */
7836 /*-----------------------------------------------------------------*/
7837 static void genIfx (iCode *ic, iCode *popIc)
7838 {
7839     operand *cond = IC_COND(ic);
7840     int isbit =0;
7841
7842     D(emitcode(";", "genIfx "););
7843
7844     aopOp(cond,ic,FALSE, FALSE);
7845
7846     /* get the value into acc */
7847     if (AOP_TYPE(cond) != AOP_CRY)
7848         toBoolean(cond);
7849     else
7850         isbit = 1;
7851     /* the result is now in the accumulator */
7852     freeAsmop(cond,NULL,ic,TRUE);
7853
7854     /* if there was something to be popped then do it */
7855     if (popIc)
7856         genIpop(popIc);
7857
7858     /* if the condition is  a bit variable */
7859     if (isbit && IS_ITEMP(cond) && 
7860         SPIL_LOC(cond))
7861         genIfxJump(ic,SPIL_LOC(cond)->rname);
7862     else
7863         if (isbit && !IS_ITEMP(cond))
7864             genIfxJump(ic,OP_SYMBOL(cond)->rname);
7865         else
7866             genIfxJump(ic,"a");
7867
7868     ic->generated = 1;
7869 }
7870
7871 /*-----------------------------------------------------------------*/
7872 /* genAddrOf - generates code for address of                       */
7873 /*-----------------------------------------------------------------*/
7874 static void genAddrOf (iCode *ic)
7875 {
7876     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
7877     int size, offset ;
7878
7879     D(emitcode(";", "genAddrOf "););
7880
7881     aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
7882
7883     /* if the operand is on the stack then we 
7884     need to get the stack offset of this
7885     variable */
7886     if (sym->onStack) {
7887         /* if it has an offset then we need to compute
7888         it */
7889         if (sym->stack) {
7890             emitcode("mov","a,_bp");
7891             emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
7892             aopPut(AOP(IC_RESULT(ic)),"a",0);       
7893         } else {
7894             /* we can just move _bp */
7895             aopPut(AOP(IC_RESULT(ic)),"_bp",0);
7896         }
7897         /* fill the result with zero */
7898         size = AOP_SIZE(IC_RESULT(ic)) - 1;
7899         
7900         
7901         if (options.stack10bit && size < (FPTRSIZE - 1))
7902         {
7903             fprintf(stderr, 
7904                     "*** warning: pointer to stack var truncated.\n");
7905         }
7906         
7907         offset = 1;
7908         while (size--)
7909         {
7910             /* Yuck! */
7911             if (options.stack10bit && offset == 2)
7912             {
7913                 aopPut(AOP(IC_RESULT(ic)),"#0x40", offset++);
7914             }
7915             else
7916             {
7917                 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
7918             }
7919         }
7920
7921         goto release;
7922     }
7923
7924     /* object not on stack then we need the name */
7925     size = AOP_SIZE(IC_RESULT(ic));
7926     offset = 0;
7927
7928     while (size--) {
7929         char s[SDCC_NAME_MAX];
7930         if (offset) 
7931             sprintf(s,"#(%s >> %d)",
7932                     sym->rname,
7933                     offset*8);
7934         else
7935             sprintf(s,"#%s",sym->rname);
7936         aopPut(AOP(IC_RESULT(ic)),s,offset++);
7937     }
7938
7939 release:
7940     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7941
7942 }
7943
7944 /*-----------------------------------------------------------------*/
7945 /* genFarFarAssign - assignment when both are in far space         */
7946 /*-----------------------------------------------------------------*/
7947 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
7948 {
7949     int size = AOP_SIZE(right);
7950     int offset = 0;
7951     char *l;
7952
7953 #ifdef LAZY_DPS_OPT
7954     if (size > 1)
7955     {
7956         /* This is a net loss for size == 1, but a big gain
7957          * otherwise.
7958          */
7959         D(emitcode(";", "genFarFarAssign (improved)"););
7960
7961         aopOp(result,ic,TRUE, TRUE);
7962
7963         _startLazyDPSEvaluation();
7964         while (size--) 
7965         {
7966             aopPut(AOP(result),
7967                    aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
7968                    offset);
7969             offset++;
7970         }
7971         _endLazyDPSEvaluation();    
7972         freeAsmop(result,NULL,ic,FALSE);
7973         freeAsmop(right,NULL,ic,FALSE);
7974     }
7975     else
7976 #endif
7977     {
7978     D(emitcode(";", "genFarFarAssign "););
7979
7980     /* first push the right side on to the stack */
7981     _startLazyDPSEvaluation();
7982     while (size--) {
7983         l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7984         MOVA(l);
7985         emitcode ("push","acc");
7986     }
7987
7988     freeAsmop(right,NULL,ic,FALSE);
7989     /* now assign DPTR to result */
7990     aopOp(result,ic,FALSE, FALSE);
7991     size = AOP_SIZE(result);
7992     while (size--) {
7993         emitcode ("pop","acc");
7994         aopPut(AOP(result),"a",--offset);
7995     }
7996     freeAsmop(result,NULL,ic,FALSE);
7997     _endLazyDPSEvaluation();
7998     }
7999 }
8000
8001 /*-----------------------------------------------------------------*/
8002 /* genAssign - generate code for assignment                        */
8003 /*-----------------------------------------------------------------*/
8004 static void genAssign (iCode *ic)
8005 {
8006     operand *result, *right;
8007     int size, offset ;
8008         unsigned long lit = 0L;
8009
8010     D(emitcode(";", "genAssign "););
8011
8012     result = IC_RESULT(ic);
8013     right  = IC_RIGHT(ic) ;
8014
8015     /* if they are the same */
8016     if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
8017         return ;
8018
8019     aopOp(right,ic,FALSE, FALSE);
8020     
8021     emitcode(";", "genAssign: resultIsFar = %s",
8022              isOperandInFarSpace(result) ?
8023              "TRUE" : "FALSE");
8024
8025     /* special case both in far space */
8026     if ((AOP_TYPE(right) == AOP_DPTR ||
8027          AOP_TYPE(right) == AOP_DPTR2) &&
8028     /* IS_TRUE_SYMOP(result)       && */
8029     isOperandInFarSpace(result)) {
8030         
8031         genFarFarAssign (result,right,ic);
8032         return ;
8033     }
8034
8035     aopOp(result,ic,TRUE, FALSE);
8036
8037     /* if they are the same registers */
8038     if (sameRegs(AOP(right),AOP(result)))
8039         goto release;
8040
8041     /* if the result is a bit */
8042     if (AOP_TYPE(result) == AOP_CRY) {
8043
8044         /* if the right size is a literal then
8045         we know what the value is */
8046         if (AOP_TYPE(right) == AOP_LIT) {
8047             if (((int) operandLitValue(right))) 
8048                 aopPut(AOP(result),one,0);
8049             else
8050                 aopPut(AOP(result),zero,0);
8051             goto release;
8052         }
8053
8054         /* the right is also a bit variable */
8055         if (AOP_TYPE(right) == AOP_CRY) {
8056             emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8057             aopPut(AOP(result),"c",0);
8058             goto release ;
8059         }
8060
8061         /* we need to or */
8062         toBoolean(right);
8063         aopPut(AOP(result),"a",0);
8064         goto release ;
8065     }
8066
8067     /* bit variables done */
8068     /* general case */
8069     size = AOP_SIZE(result);
8070     offset = 0 ;
8071     if(AOP_TYPE(right) == AOP_LIT)
8072         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
8073     
8074     if((size > 1) &&
8075        (AOP_TYPE(result) != AOP_REG) &&
8076        (AOP_TYPE(right) == AOP_LIT) &&
8077        !IS_FLOAT(operandType(right)) 
8078 #ifndef LAZY_DPS_OPT
8079        && (lit < 256L)
8080 #endif       
8081        )
8082     {
8083 #ifdef LAZY_DPS_OPT
8084         D(emitcode(";", "Kevin's better literal load code"););
8085         _startLazyDPSEvaluation();
8086     while (size && ((unsigned int)(lit >> (offset*8)) != 0))
8087         {
8088             aopPut(AOP(result),
8089                    aopGet(AOP(right),offset,FALSE,FALSE,TRUE),
8090                    offset);
8091             offset++;
8092             size--;
8093         }
8094         /* And now fill the rest with zeros. */
8095         if (size)
8096         {
8097             emitcode("clr","a");
8098         }
8099         while (size--)
8100         {
8101             aopPut(AOP(result), "a", offset++);
8102         }
8103         _endLazyDPSEvaluation();
8104 #else
8105         emitcode("clr","a");
8106         
8107         _startLazyDPSEvaluation();
8108         while (size--) 
8109         {
8110             if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
8111                 aopPut(AOP(result),"a",size);
8112             else
8113                 aopPut(AOP(result),
8114                        aopGet(AOP(right),size,FALSE,FALSE,FALSE),
8115                        size);
8116         }
8117         _endLazyDPSEvaluation();
8118 #endif  
8119     } 
8120     else 
8121     {
8122         _startLazyDPSEvaluation();
8123         while (size--) 
8124         {
8125             aopPut(AOP(result),
8126                    aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8127                    offset);
8128             offset++;
8129         }
8130         _endLazyDPSEvaluation();
8131     }
8132     
8133 release:
8134     freeAsmop (right,NULL,ic,FALSE);
8135     freeAsmop (result,NULL,ic,TRUE);
8136 }   
8137
8138 /*-----------------------------------------------------------------*/
8139 /* genJumpTab - generates code for jump table                      */
8140 /*-----------------------------------------------------------------*/
8141 static void genJumpTab (iCode *ic)
8142 {
8143     symbol *jtab;
8144     char *l;
8145
8146     D(emitcode(";", "genJumpTab "););
8147
8148     aopOp(IC_JTCOND(ic),ic,FALSE, FALSE);
8149     /* get the condition into accumulator */
8150     l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE,TRUE);
8151     MOVA(l);
8152     /* multiply by four! */
8153     emitcode("add","a,acc");
8154     emitcode("add","a,acc");
8155     freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
8156
8157     jtab = newiTempLabel(NULL);
8158     emitcode("mov","dptr,#%05d$",jtab->key+100);
8159     emitcode("jmp","@a+dptr");
8160     emitcode("","%05d$:",jtab->key+100);
8161     /* now generate the jump labels */
8162     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
8163          jtab = setNextItem(IC_JTLABELS(ic)))
8164         emitcode("ljmp","%05d$",jtab->key+100);
8165
8166 }
8167
8168 /*-----------------------------------------------------------------*/
8169 /* genCast - gen code for casting                                  */
8170 /*-----------------------------------------------------------------*/
8171 static void genCast (iCode *ic)
8172 {
8173     operand *result = IC_RESULT(ic);
8174     sym_link *ctype = operandType(IC_LEFT(ic));
8175     sym_link *rtype = operandType(IC_RIGHT(ic));
8176     operand *right = IC_RIGHT(ic);
8177     int size, offset ;
8178
8179     D(emitcode(";", "genCast "););
8180
8181     /* if they are equivalent then do nothing */
8182     if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
8183         return ;
8184
8185     aopOp(right,ic,FALSE, FALSE) ;
8186     aopOp(result,ic,FALSE, AOP_TYPE(right) == AOP_DPTR);
8187
8188     /* if the result is a bit */
8189     if (AOP_TYPE(result) == AOP_CRY) {
8190         /* if the right size is a literal then
8191         we know what the value is */
8192         if (AOP_TYPE(right) == AOP_LIT) {
8193             if (((int) operandLitValue(right))) 
8194                 aopPut(AOP(result),one,0);
8195             else
8196                 aopPut(AOP(result),zero,0);
8197
8198             goto release;
8199         }
8200
8201         /* the right is also a bit variable */
8202         if (AOP_TYPE(right) == AOP_CRY) {
8203             emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8204             aopPut(AOP(result),"c",0);
8205             goto release ;
8206         }
8207
8208         /* we need to or */
8209         toBoolean(right);
8210         aopPut(AOP(result),"a",0);
8211         goto release ;
8212     }
8213
8214     /* if they are the same size : or less */
8215     if (AOP_SIZE(result) <= AOP_SIZE(right)) {
8216
8217         /* if they are in the same place */
8218         if (sameRegs(AOP(right),AOP(result)))
8219             goto release;
8220
8221         /* if they in different places then copy */
8222         size = AOP_SIZE(result);
8223         offset = 0 ;
8224         _startLazyDPSEvaluation();
8225         while (size--) {
8226             aopPut(AOP(result),
8227                    aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8228                    offset);
8229             offset++;
8230         }
8231         _endLazyDPSEvaluation();
8232         goto release;
8233     }
8234
8235
8236     /* if the result is of type pointer */
8237     if (IS_PTR(ctype)) {
8238
8239         int p_type;
8240         sym_link *type = operandType(right);
8241
8242         /* pointer to generic pointer */
8243         if (IS_GENPTR(ctype)) {
8244             char *l = zero;
8245             
8246             if (IS_PTR(type)) 
8247             {
8248                 p_type = DCL_TYPE(type);
8249             }
8250             else 
8251             {
8252 #if OLD_CAST_BEHAVIOR
8253                 /* KV: we are converting a non-pointer type to
8254                  * a generic pointer. This (ifdef'd out) code
8255                  * says that the resulting generic pointer 
8256                  * should have the same class as the storage
8257                  * location of the non-pointer variable.
8258                  * 
8259                  * For example, converting an int (which happens
8260                  * to be stored in DATA space) to a pointer results
8261                  * in a DATA generic pointer; if the original int
8262                  * in XDATA space, so will be the resulting pointer.
8263                  *
8264                  * I don't like that behavior, and thus this change:
8265                  * all such conversions will be forced to XDATA and
8266                  * throw a warning. If you want some non-XDATA
8267                  * type, or you want to suppress the warning, you
8268                  * must go through an intermediate cast, like so:
8269                  *
8270                  * char _generic *gp = (char _xdata *)(intVar);
8271                  */
8272                 sym_link *etype = getSpec(type);                 
8273
8274                 /* we have to go by the storage class */
8275                 if (SPEC_OCLS(etype) != generic)
8276                 {
8277                     p_type = PTR_TYPE(SPEC_OCLS(etype));
8278                 }
8279                 else
8280 #endif          
8281                 {
8282                     /* Converting unknown class (i.e. register variable)
8283                      * to generic pointer. This is not good, but
8284                      * we'll make a guess (and throw a warning).
8285                      */
8286                     p_type = FPOINTER;
8287                     werror(W_INT_TO_GEN_PTR_CAST);           
8288                 }
8289             }
8290                 
8291             /* the first two bytes are known */
8292             size = GPTRSIZE - 1; 
8293             offset = 0 ;
8294             _startLazyDPSEvaluation();
8295             while (size--) {
8296                 aopPut(AOP(result),
8297                        aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8298                        offset);
8299                 offset++;
8300             }
8301             _endLazyDPSEvaluation();
8302             
8303             /* the last byte depending on type */
8304             switch (p_type) {
8305             case IPOINTER:
8306             case POINTER:
8307                 l = zero;
8308                 break;
8309             case FPOINTER:
8310                 l = one;
8311                 break;
8312             case CPOINTER:
8313                 l = "#0x02";
8314                 break;                          
8315             case PPOINTER:
8316                 l = "#0x03";
8317                 break;
8318                 
8319             default:
8320                 /* this should never happen */
8321                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8322                        "got unknown pointer type");
8323                 exit(1);
8324             }
8325             aopPut(AOP(result),l, GPTRSIZE - 1);            
8326             goto release ;
8327         }
8328         
8329         /* just copy the pointers */
8330         size = AOP_SIZE(result);
8331         offset = 0 ;
8332         _startLazyDPSEvaluation();
8333         while (size--) {
8334             aopPut(AOP(result),
8335                    aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8336                    offset);
8337             offset++;
8338         }
8339         _endLazyDPSEvaluation();
8340         goto release ;
8341     }
8342     
8343     /* so we now know that the size of destination is greater
8344     than the size of the source */
8345     /* we move to result for the size of source */
8346     size = AOP_SIZE(right);
8347     offset = 0 ;
8348     _startLazyDPSEvaluation();
8349     while (size--) {
8350         aopPut(AOP(result),
8351                aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8352                offset);
8353         offset++;
8354     }
8355     _endLazyDPSEvaluation();
8356
8357     /* now depending on the sign of the source && destination */
8358     size = AOP_SIZE(result) - AOP_SIZE(right);
8359     /* if unsigned or not an integral type */
8360     /* also, if the source is a bit, we don't need to sign extend, because
8361      * it can't possibly have set the sign bit.
8362      */
8363     if (SPEC_USIGN(rtype) || !IS_SPEC(rtype) || AOP_TYPE(right) == AOP_CRY) 
8364     {
8365         while (size--)
8366         {
8367             aopPut(AOP(result),zero,offset++);
8368         }
8369     } 
8370     else 
8371     {
8372         /* we need to extend the sign :{ */
8373         char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
8374                          FALSE,FALSE,TRUE);
8375         MOVA(l);
8376         emitcode("rlc","a");
8377         emitcode("subb","a,acc");
8378         while (size--)
8379             aopPut(AOP(result),"a",offset++);   
8380     }
8381
8382     /* we are done hurray !!!! */
8383
8384 release:
8385     freeAsmop(right,NULL,ic,TRUE);
8386     freeAsmop(result,NULL,ic,TRUE);
8387
8388 }
8389
8390 /*-----------------------------------------------------------------*/
8391 /* genDjnz - generate decrement & jump if not zero instrucion      */
8392 /*-----------------------------------------------------------------*/
8393 static int genDjnz (iCode *ic, iCode *ifx)
8394 {
8395     symbol *lbl, *lbl1;
8396     if (!ifx)
8397         return 0;
8398     
8399     /* if the if condition has a false label
8400        then we cannot save */
8401     if (IC_FALSE(ifx))
8402         return 0;
8403
8404     /* if the minus is not of the form 
8405        a = a - 1 */
8406     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
8407         !IS_OP_LITERAL(IC_RIGHT(ic)))
8408         return 0;
8409
8410     if (operandLitValue(IC_RIGHT(ic)) != 1)
8411         return 0;
8412
8413     /* if the size of this greater than one then no
8414        saving */
8415     if (getSize(operandType(IC_RESULT(ic))) > 1)
8416         return 0;
8417
8418     /* otherwise we can save BIG */
8419     lbl = newiTempLabel(NULL);
8420     lbl1= newiTempLabel(NULL);
8421
8422     aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
8423     
8424     if (IS_AOP_PREG(IC_RESULT(ic))) {
8425         emitcode("dec","%s",
8426                  aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
8427         emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
8428         emitcode("jnz","%05d$",lbl->key+100);
8429     } else {    
8430         emitcode ("djnz","%s,%05d$",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE),
8431                   lbl->key+100);
8432     }
8433     emitcode ("sjmp","%05d$",lbl1->key+100);
8434     emitcode ("","%05d$:",lbl->key+100);
8435     emitcode ("ljmp","%05d$",IC_TRUE(ifx)->key+100);
8436     emitcode ("","%05d$:",lbl1->key+100);
8437     
8438     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8439     ifx->generated = 1;
8440     return 1;
8441 }
8442
8443 /*-----------------------------------------------------------------*/
8444 /* genReceive - generate code for a receive iCode                  */
8445 /*-----------------------------------------------------------------*/
8446 static void genReceive (iCode *ic)
8447 {    
8448
8449     D(emitcode(";", "genReceive "););
8450
8451     if (isOperandInFarSpace(IC_RESULT(ic)) && 
8452         ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
8453           IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
8454         int size = getSize(operandType(IC_RESULT(ic)));
8455         int offset =  fReturnSize_390 - size;
8456         while (size--) {
8457             emitcode ("push","%s", (strcmp(fReturn[fReturnSize_390 - offset - 1],"a") ?
8458                                     fReturn[fReturnSize_390 - offset - 1] : "acc"));
8459             offset++;
8460         }
8461         aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
8462         size = AOP_SIZE(IC_RESULT(ic));
8463         offset = 0;
8464         while (size--) {
8465             emitcode ("pop","acc");
8466             aopPut (AOP(IC_RESULT(ic)),"a",offset++);
8467         }
8468         
8469     } else {
8470         _G.accInUse++;
8471         aopOp(IC_RESULT(ic),ic,FALSE, FALSE);  
8472         _G.accInUse--;
8473         assignResultValue(IC_RESULT(ic));       
8474     }
8475
8476     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8477 }
8478
8479 /*-----------------------------------------------------------------*/
8480 /* gen390Code - generate code for Dallas 390 based controllers     */
8481 /*-----------------------------------------------------------------*/
8482 void gen390Code (iCode *lic)
8483 {
8484     iCode *ic;
8485     int cln = 0;
8486
8487     lineHead = lineCurr = NULL;
8488
8489 #if 0
8490     //REMOVE ME!!!
8491     /* print the allocation information */
8492     if (allocInfo)
8493         printAllocInfo( currFunc, codeOutFile);
8494 #endif
8495     /* if debug information required */
8496     if (options.debug && currFunc) {
8497     //jwk if (currFunc) {
8498         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
8499         _G.debugLine = 1;
8500         if (IS_STATIC(currFunc->etype))
8501             emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name); 
8502         else
8503             emitcode("","G$%s$0$0 ==.",currFunc->name);
8504         _G.debugLine = 0;
8505     }
8506     /* stack pointer name */
8507     if (options.useXstack)
8508         spname = "_spx";
8509     else
8510         spname = "sp";
8511     
8512  
8513     for (ic = lic ; ic ; ic = ic->next ) {
8514         
8515         if ( cln != ic->lineno ) {
8516             if ( options.debug ) {
8517                 _G.debugLine = 1;
8518                 emitcode("","C$%s$%d$%d$%d ==.",
8519                          ic->filename,ic->lineno,
8520                          ic->level,ic->block);
8521                 _G.debugLine = 0;
8522             }
8523             emitcode(";","%s %d",ic->filename,ic->lineno);
8524             cln = ic->lineno ;
8525         }
8526         /* if the result is marked as
8527            spilt and rematerializable or code for
8528            this has already been generated then
8529            do nothing */
8530         if (resultRemat(ic) || ic->generated ) 
8531             continue ;
8532         
8533         /* depending on the operation */
8534         switch (ic->op) {
8535         case '!' :
8536             genNot(ic);
8537             break;
8538             
8539         case '~' :
8540             genCpl(ic);
8541             break;
8542             
8543         case UNARYMINUS:
8544             genUminus (ic);
8545             break;
8546             
8547         case IPUSH:
8548             genIpush (ic);
8549             break;
8550             
8551         case IPOP:
8552             /* IPOP happens only when trying to restore a 
8553                spilt live range, if there is an ifx statement
8554                following this pop then the if statement might
8555                be using some of the registers being popped which
8556                would destory the contents of the register so
8557                we need to check for this condition and handle it */
8558             if (ic->next            && 
8559                 ic->next->op == IFX &&
8560                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
8561                 genIfx (ic->next,ic);
8562             else
8563                 genIpop (ic);
8564             break; 
8565             
8566         case CALL:
8567             genCall (ic);
8568             break;
8569             
8570         case PCALL:
8571             genPcall (ic);
8572             break;
8573             
8574         case FUNCTION:
8575             genFunction (ic);
8576             break;
8577             
8578         case ENDFUNCTION:
8579             genEndFunction (ic);
8580             break;
8581             
8582         case RETURN:
8583             genRet (ic);
8584             break;
8585             
8586         case LABEL:
8587             genLabel (ic);
8588             break;
8589             
8590         case GOTO:
8591             genGoto (ic);
8592             break;
8593             
8594         case '+' :
8595             genPlus (ic) ;
8596             break;
8597             
8598         case '-' :
8599             if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
8600                 genMinus (ic);
8601             break;
8602             
8603         case '*' :
8604             genMult (ic);
8605             break;
8606             
8607         case '/' :
8608             genDiv (ic) ;
8609             break;
8610             
8611         case '%' :
8612             genMod (ic);
8613             break;
8614             
8615         case '>' :
8616             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
8617             break;
8618             
8619         case '<' :
8620             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
8621             break;
8622             
8623         case LE_OP:
8624         case GE_OP:
8625         case NE_OP:
8626             
8627             /* note these two are xlated by algebraic equivalence
8628                during parsing SDCC.y */
8629             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8630                    "got '>=' or '<=' shouldn't have come here");
8631             break;      
8632             
8633         case EQ_OP:
8634             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
8635             break;          
8636             
8637         case AND_OP:
8638             genAndOp (ic);
8639             break;
8640             
8641         case OR_OP:
8642             genOrOp (ic);
8643             break;
8644             
8645         case '^' :
8646             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
8647             break;
8648             
8649         case '|' :
8650                 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
8651             break;
8652             
8653         case BITWISEAND:
8654             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
8655             break;
8656             
8657         case INLINEASM:
8658             genInline (ic);
8659             break;
8660             
8661         case RRC:
8662             genRRC (ic);
8663             break;
8664             
8665         case RLC:
8666             genRLC (ic);
8667             break;
8668             
8669         case GETHBIT:
8670             genGetHbit (ic);
8671             break;
8672             
8673         case LEFT_OP:
8674             genLeftShift (ic);
8675             break;
8676             
8677         case RIGHT_OP:
8678             genRightShift (ic);
8679             break;
8680             
8681         case GET_VALUE_AT_ADDRESS:
8682             genPointerGet(ic);
8683             break;
8684             
8685         case '=' :
8686             if (POINTER_SET(ic))
8687                 genPointerSet(ic);
8688             else
8689                 genAssign(ic);
8690             break;
8691             
8692         case IFX:
8693             genIfx (ic,NULL);
8694             break;
8695             
8696         case ADDRESS_OF:
8697             genAddrOf (ic);
8698             break;
8699             
8700         case JUMPTABLE:
8701             genJumpTab (ic);
8702             break;
8703             
8704         case CAST:
8705             genCast (ic);
8706             break;
8707             
8708         case RECEIVE:
8709             genReceive(ic);
8710             break;
8711             
8712         case SEND:
8713             addSet(&_G.sendSet,ic);
8714             break;
8715
8716         default :
8717             ic = ic;
8718             /*      piCode(ic,stdout); */
8719             
8720         }
8721     }
8722     
8723
8724     /* now we are ready to call the 
8725        peep hole optimizer */
8726     if (!options.nopeep)
8727         peepHole (&lineHead);
8728
8729     /* now do the actual printing */
8730     printLine (lineHead,codeOutFile);    
8731     return;
8732 }