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