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