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