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