improved bit-wise operations with literal RHS
[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_3(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         symbol *tlbl;
4249         /* if they are both bit variables */
4250         if (AOP_TYPE(left) == AOP_CRY &&
4251             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4252             if(AOP_TYPE(right) == AOP_LIT){
4253                 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4254                 if(lit == 0L){
4255                     emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4256                     emitcode("cpl","c");
4257                 } else if(lit == 1L) {
4258                     emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4259                 } else {
4260                     emitcode("clr","c");
4261                 }
4262                 /* AOP_TYPE(right) == AOP_CRY */
4263             } else {
4264                 symbol *lbl = newiTempLabel(NULL);
4265                 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4266                 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
4267                 emitcode("cpl","c");
4268                 emitcode("","%05d$:",(lbl->key+100));
4269             }
4270             /* if true label then we jump if condition
4271             supplied is true */
4272             tlbl = newiTempLabel(NULL);
4273             if ( IC_TRUE(ifx) ) {
4274                 emitcode("jnc","%05d$",tlbl->key+100);
4275                 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
4276             } else {
4277                 emitcode("jc","%05d$",tlbl->key+100);
4278                 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
4279             }
4280             emitcode("","%05d$:",tlbl->key+100);                
4281         } else {
4282             tlbl = newiTempLabel(NULL);
4283             gencjneshort(left, right, tlbl);
4284             if ( IC_TRUE(ifx) ) {
4285                 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
4286                 emitcode("","%05d$:",tlbl->key+100);                
4287             } else {
4288                 symbol *lbl = newiTempLabel(NULL);
4289                 emitcode("sjmp","%05d$",lbl->key+100);
4290                 emitcode("","%05d$:",tlbl->key+100);                
4291                 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
4292                 emitcode("","%05d$:",lbl->key+100);             
4293             }
4294         }
4295         /* mark the icode as generated */
4296         ifx->generated = 1;
4297         goto release ;
4298     }
4299
4300     /* if they are both bit variables */
4301     if (AOP_TYPE(left) == AOP_CRY &&
4302         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4303         if(AOP_TYPE(right) == AOP_LIT){
4304             unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4305             if(lit == 0L){
4306                 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4307                 emitcode("cpl","c");
4308             } else if(lit == 1L) {
4309                 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4310             } else {
4311                 emitcode("clr","c");
4312             }
4313             /* AOP_TYPE(right) == AOP_CRY */
4314         } else {
4315             symbol *lbl = newiTempLabel(NULL);
4316             emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4317             emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
4318             emitcode("cpl","c");
4319             emitcode("","%05d$:",(lbl->key+100));
4320         }
4321         /* c = 1 if egal */
4322         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
4323             outBitC(result);
4324             goto release ;
4325         }
4326         if (ifx) {
4327             genIfxJump (ifx,"c");
4328             goto release ;
4329         }
4330         /* if the result is used in an arithmetic operation
4331         then put the result in place */
4332         outBitC(result);
4333     } else {
4334         gencjne(left,right,newiTempLabel(NULL));    
4335         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4336             aopPut(AOP(result),"a",0);
4337             goto release ;
4338         }
4339         if (ifx) {
4340             genIfxJump (ifx,"a");
4341             goto release ;
4342         }
4343         /* if the result is used in an arithmetic operation
4344         then put the result in place */
4345         if (AOP_TYPE(result) != AOP_CRY) 
4346             outAcc(result);
4347         /* leave the result in acc */
4348     }
4349
4350 release:
4351     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4352     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4353     freeAsmop(result,NULL,ic,TRUE);
4354 }
4355
4356 /*-----------------------------------------------------------------*/
4357 /* ifxForOp - returns the icode containing the ifx for operand     */
4358 /*-----------------------------------------------------------------*/
4359 static iCode *ifxForOp ( operand *op, iCode *ic )
4360 {
4361     /* if true symbol then needs to be assigned */
4362     if (IS_TRUE_SYMOP(op))
4363         return NULL ;
4364
4365     /* if this has register type condition and
4366     the next instruction is ifx with the same operand
4367     and live to of the operand is upto the ifx only then */
4368     if (ic->next &&
4369         ic->next->op == IFX &&
4370         IC_COND(ic->next)->key == op->key &&
4371         OP_SYMBOL(op)->liveTo <= ic->next->seq )
4372         return ic->next;
4373
4374     return NULL;
4375 }
4376 /*-----------------------------------------------------------------*/
4377 /* genAndOp - for && operation                                     */
4378 /*-----------------------------------------------------------------*/
4379 static void genAndOp (iCode *ic)
4380 {
4381     operand *left,*right, *result;
4382     symbol *tlbl;
4383
4384     D(emitcode(";", "genAndOp "););
4385
4386     /* note here that && operations that are in an
4387     if statement are taken away by backPatchLabels
4388     only those used in arthmetic operations remain */
4389     AOP_OP_3(ic);
4390     AOP_SET_LOCALS(ic);
4391 #if 0
4392     aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
4393     aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
4394     aopOp((result=IC_RESULT(ic)),ic,FALSE, FALSE);
4395 #endif
4396
4397     /* if both are bit variables */
4398     if (AOP_TYPE(left) == AOP_CRY &&
4399         AOP_TYPE(right) == AOP_CRY ) {
4400         emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4401         emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
4402         outBitC(result);
4403     } else {
4404         tlbl = newiTempLabel(NULL);
4405         toBoolean(left);    
4406         emitcode("jz","%05d$",tlbl->key+100);
4407         toBoolean(right);
4408         emitcode("","%05d$:",tlbl->key+100);
4409         outBitAcc(result);
4410     }
4411
4412     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4413     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4414     freeAsmop(result,NULL,ic,TRUE);
4415 }
4416
4417
4418 /*-----------------------------------------------------------------*/
4419 /* genOrOp - for || operation                                      */
4420 /*-----------------------------------------------------------------*/
4421 static void genOrOp (iCode *ic)
4422 {
4423     operand *left,*right, *result;
4424     symbol *tlbl;
4425
4426     D(emitcode(";", "genOrOp "););
4427
4428     /* note here that || operations that are in an
4429     if statement are taken away by backPatchLabels
4430     only those used in arthmetic operations remain */
4431     AOP_OP_3(ic);
4432     AOP_SET_LOCALS(ic);
4433 #if 0
4434     aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
4435     aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
4436     aopOp((result=IC_RESULT(ic)),ic,FALSE, FALSE);
4437 #endif
4438
4439     /* if both are bit variables */
4440     if (AOP_TYPE(left) == AOP_CRY &&
4441         AOP_TYPE(right) == AOP_CRY ) {
4442         emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4443         emitcode("orl","c,%s",AOP(right)->aopu.aop_dir);
4444         outBitC(result);
4445     } else {
4446         tlbl = newiTempLabel(NULL);
4447         toBoolean(left);
4448         emitcode("jnz","%05d$",tlbl->key+100);
4449         toBoolean(right);
4450         emitcode("","%05d$:",tlbl->key+100);
4451         outBitAcc(result);
4452     }
4453
4454     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4455     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4456     freeAsmop(result,NULL,ic,TRUE);            
4457 }
4458
4459 /*-----------------------------------------------------------------*/
4460 /* isLiteralBit - test if lit == 2^n                               */
4461 /*-----------------------------------------------------------------*/
4462 static int isLiteralBit(unsigned long lit)
4463 {
4464     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
4465     0x100L,0x200L,0x400L,0x800L,
4466     0x1000L,0x2000L,0x4000L,0x8000L,
4467     0x10000L,0x20000L,0x40000L,0x80000L,
4468     0x100000L,0x200000L,0x400000L,0x800000L,
4469     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
4470     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
4471     int idx;
4472     
4473     for(idx = 0; idx < 32; idx++)
4474         if(lit == pw[idx])
4475             return idx+1;
4476     return 0;
4477 }
4478
4479 /*-----------------------------------------------------------------*/
4480 /* continueIfTrue -                                                */
4481 /*-----------------------------------------------------------------*/
4482 static void continueIfTrue (iCode *ic)
4483 {
4484     if(IC_TRUE(ic))
4485         emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
4486     ic->generated = 1;
4487 }
4488
4489 /*-----------------------------------------------------------------*/
4490 /* jmpIfTrue -                                                     */
4491 /*-----------------------------------------------------------------*/
4492 static void jumpIfTrue (iCode *ic)
4493 {
4494     if(!IC_TRUE(ic))
4495         emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
4496     ic->generated = 1;
4497 }
4498
4499 /*-----------------------------------------------------------------*/
4500 /* jmpTrueOrFalse -                                                */
4501 /*-----------------------------------------------------------------*/
4502 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
4503 {
4504     // ugly but optimized by peephole
4505     if(IC_TRUE(ic)){
4506         symbol *nlbl = newiTempLabel(NULL);
4507         emitcode("sjmp","%05d$",nlbl->key+100);                 
4508         emitcode("","%05d$:",tlbl->key+100);
4509         emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
4510         emitcode("","%05d$:",nlbl->key+100);
4511     }
4512     else{
4513         emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
4514         emitcode("","%05d$:",tlbl->key+100);
4515     }
4516     ic->generated = 1;
4517 }
4518
4519 /*-----------------------------------------------------------------*/
4520 /* genAnd  - code for and                                          */
4521 /*-----------------------------------------------------------------*/
4522 static void genAnd (iCode *ic, iCode *ifx)
4523 {
4524     operand *left, *right, *result;
4525     int size, offset=0;  
4526     unsigned long lit = 0L;
4527     int bytelit = 0;
4528     char buffer[10];
4529
4530     D(emitcode(";", "genAnd "););
4531
4532     AOP_OP_3(ic);
4533     AOP_SET_LOCALS(ic);
4534 #if 0
4535     aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
4536     aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
4537     aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4538 #endif
4539
4540 #ifdef DEBUG_TYPE
4541     emitcode("","; Type res[%d] = l[%d]&r[%d]",
4542              AOP_TYPE(result),
4543              AOP_TYPE(left), AOP_TYPE(right));
4544     emitcode("","; Size res[%d] = l[%d]&r[%d]",
4545              AOP_SIZE(result),
4546              AOP_SIZE(left), AOP_SIZE(right));
4547 #endif
4548
4549     /* if left is a literal & right is not then exchange them */
4550     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4551         AOP_NEEDSACC(left)) {
4552         operand *tmp = right ;
4553         right = left;
4554         left = tmp;
4555     }
4556
4557     /* if result = right then exchange them */
4558     if(sameRegs(AOP(result),AOP(right))){
4559         operand *tmp = right ;
4560         right = left;
4561         left = tmp;
4562     }
4563
4564     /* if right is bit then exchange them */
4565     if (AOP_TYPE(right) == AOP_CRY &&
4566         AOP_TYPE(left) != AOP_CRY){
4567         operand *tmp = right ;
4568         right = left;
4569         left = tmp;
4570     }
4571     if(AOP_TYPE(right) == AOP_LIT)
4572         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4573
4574     size = AOP_SIZE(result);
4575
4576     // if(bit & yy)
4577     // result = bit & yy;
4578     if (AOP_TYPE(left) == AOP_CRY){
4579         // c = bit & literal;
4580         if(AOP_TYPE(right) == AOP_LIT){
4581             if(lit & 1) {
4582                 if(size && sameRegs(AOP(result),AOP(left)))
4583                     // no change
4584                     goto release;
4585                 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4586             } else {
4587                 // bit(result) = 0;
4588                 if(size && (AOP_TYPE(result) == AOP_CRY)){
4589                     emitcode("clr","%s",AOP(result)->aopu.aop_dir);
4590                     goto release;
4591                 }
4592                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4593                     jumpIfTrue(ifx);
4594                     goto release;
4595                 }
4596                 emitcode("clr","c");
4597             }
4598         } else {
4599             if (AOP_TYPE(right) == AOP_CRY){
4600                 // c = bit & bit;
4601                 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4602                 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4603             } else {
4604                 // c = bit & val;
4605                 MOVA(aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4606                 // c = lsb
4607                 emitcode("rrc","a");
4608                 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4609             }
4610         }
4611         // bit = c
4612         // val = c
4613         if(size)
4614             outBitC(result);
4615         // if(bit & ...)
4616         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4617             genIfxJump(ifx, "c");           
4618         goto release ;
4619     }
4620
4621     // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
4622     // bit = val & 0xZZ     - size = 1, ifx = FALSE -
4623     if((AOP_TYPE(right) == AOP_LIT) &&
4624        (AOP_TYPE(result) == AOP_CRY) &&
4625        (AOP_TYPE(left) != AOP_CRY)){
4626         int posbit = isLiteralBit(lit);
4627         /* left &  2^n */
4628         if(posbit){
4629             posbit--;
4630             MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE,TRUE));
4631             // bit = left & 2^n
4632             if(size)
4633                 emitcode("mov","c,acc.%d",posbit&0x07);
4634             // if(left &  2^n)
4635             else{
4636                 if(ifx){
4637                     sprintf(buffer,"acc.%d",posbit&0x07);
4638                     genIfxJump(ifx, buffer);
4639                 }
4640                 goto release;
4641             }
4642         } else {
4643             symbol *tlbl = newiTempLabel(NULL);
4644             int sizel = AOP_SIZE(left);
4645             if(size)
4646                 emitcode("setb","c");
4647             while(sizel--){
4648                 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
4649                     MOVA( aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
4650                     // byte ==  2^n ?
4651                     if((posbit = isLiteralBit(bytelit)) != 0)
4652                         emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
4653                     else{
4654                         if(bytelit != 0x0FFL)
4655                             emitcode("anl","a,%s",
4656                                      aopGet(AOP(right),offset,FALSE,TRUE,FALSE));
4657                         emitcode("jnz","%05d$",tlbl->key+100);
4658                     }
4659                 }
4660                 offset++;
4661             }
4662             // bit = left & literal
4663             if(size){
4664                 emitcode("clr","c");
4665                 emitcode("","%05d$:",tlbl->key+100);
4666             }
4667             // if(left & literal)
4668             else{
4669                 if(ifx)
4670                     jmpTrueOrFalse(ifx, tlbl);
4671                 goto release ;
4672             }
4673         }
4674         outBitC(result);
4675         goto release ;
4676     }
4677
4678     /* if left is same as result */
4679     if(sameRegs(AOP(result),AOP(left))){
4680         for(;size--; offset++) {
4681             if(AOP_TYPE(right) == AOP_LIT){
4682                 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
4683                     continue;
4684                 else 
4685                     if (bytelit == 0)
4686                         aopPut(AOP(result),zero,offset);
4687                     else 
4688                         if (IS_AOP_PREG(result)) {
4689                             MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4690                             emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4691                             aopPut(AOP(result),"a",offset);
4692                         } else
4693                             emitcode("anl","%s,%s",
4694                                      aopGet(AOP(left),offset,FALSE,TRUE,FALSE),
4695                                      aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4696             } else {
4697                 if (AOP_TYPE(left) == AOP_ACC)
4698                     emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4699                 else {
4700                     MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4701                     if (IS_AOP_PREG(result)) {
4702                         emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4703                         aopPut(AOP(result),"a",offset);
4704
4705                     } else
4706                         emitcode("anl","%s,a",
4707                                  aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4708                 }
4709             }
4710         }
4711     } else {
4712         // left & result in different registers
4713         if(AOP_TYPE(result) == AOP_CRY){
4714             // result = bit
4715             // if(size), result in bit
4716             // if(!size && ifx), conditional oper: if(left & right)
4717             symbol *tlbl = newiTempLabel(NULL);
4718             int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
4719             if(size)
4720                 emitcode("setb","c");
4721             while(sizer--){
4722                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4723                 emitcode("anl","a,%s",
4724                          aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4725                 emitcode("jnz","%05d$",tlbl->key+100);
4726                 offset++;
4727             }
4728             if(size){
4729                 CLRC;
4730                 emitcode("","%05d$:",tlbl->key+100);
4731                 outBitC(result);
4732             } else if(ifx)
4733                 jmpTrueOrFalse(ifx, tlbl);
4734         } else 
4735         {
4736             for(;(size--);offset++) 
4737             {
4738                 // normal case
4739                 // result = left & right
4740                 if(AOP_TYPE(right) == AOP_LIT)
4741                 {
4742                     if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
4743                     {
4744                         aopPut(AOP(result),
4745                                aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
4746                                offset);
4747                         continue;
4748                     } 
4749                     else if (bytelit == 0)
4750                     {
4751                         aopPut(AOP(result),zero,offset);
4752                         continue;
4753                     }
4754                     D(emitcode(";", "better literal AND."););
4755                     MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
4756                     emitcode("anl", "a, %s", aopGet(AOP(right),offset,
4757                                                 FALSE,FALSE,FALSE));
4758                     
4759                 }
4760                 else
4761                 {
4762                     // faster than result <- left, anl result,right
4763                     // and better if result is SFR
4764                     if (AOP_TYPE(left) == AOP_ACC) 
4765                     {
4766                         emitcode("anl","a,%s",aopGet(AOP(right),offset,
4767                                                      FALSE,FALSE,FALSE));
4768                     }
4769                     else 
4770                     {
4771                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4772                         emitcode("anl","a,%s",
4773                                  aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4774                     }
4775                 }
4776                 aopPut(AOP(result),"a",offset);
4777             }
4778         }
4779     }
4780
4781 release :
4782     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4783     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4784     freeAsmop(result,NULL,ic,TRUE);     
4785 }
4786
4787 /*-----------------------------------------------------------------*/
4788 /* genOr  - code for or                                            */
4789 /*-----------------------------------------------------------------*/
4790 static void genOr (iCode *ic, iCode *ifx)
4791 {
4792     operand *left, *right, *result;
4793     int size, offset=0;
4794     unsigned long lit = 0L;
4795
4796     D(emitcode(";", "genOr "););
4797
4798     AOP_OP_3(ic);
4799     AOP_SET_LOCALS(ic);
4800 #if 0
4801     aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
4802     aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
4803     aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4804 #endif
4805
4806 #ifdef DEBUG_TYPE
4807     emitcode("","; Type res[%d] = l[%d]&r[%d]",
4808              AOP_TYPE(result),
4809              AOP_TYPE(left), AOP_TYPE(right));
4810     emitcode("","; Size res[%d] = l[%d]&r[%d]",
4811              AOP_SIZE(result),
4812              AOP_SIZE(left), AOP_SIZE(right));
4813 #endif
4814
4815     /* if left is a literal & right is not then exchange them */
4816     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4817         AOP_NEEDSACC(left)) {
4818         operand *tmp = right ;
4819         right = left;
4820         left = tmp;
4821     }
4822
4823     /* if result = right then exchange them */
4824     if(sameRegs(AOP(result),AOP(right))){
4825         operand *tmp = right ;
4826         right = left;
4827         left = tmp;
4828     }
4829
4830     /* if right is bit then exchange them */
4831     if (AOP_TYPE(right) == AOP_CRY &&
4832         AOP_TYPE(left) != AOP_CRY){
4833         operand *tmp = right ;
4834         right = left;
4835         left = tmp;
4836     }
4837     if(AOP_TYPE(right) == AOP_LIT)
4838         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4839
4840     size = AOP_SIZE(result);
4841
4842     // if(bit | yy)
4843     // xx = bit | yy;
4844     if (AOP_TYPE(left) == AOP_CRY){
4845         if(AOP_TYPE(right) == AOP_LIT){
4846             // c = bit & literal;
4847             if(lit){
4848                 // lit != 0 => result = 1
4849                 if(AOP_TYPE(result) == AOP_CRY){
4850                     if(size)
4851                         emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4852                     else if(ifx)
4853                         continueIfTrue(ifx);
4854                     goto release;
4855                 }
4856                 emitcode("setb","c");
4857             } else {
4858                 // lit == 0 => result = left
4859                 if(size && sameRegs(AOP(result),AOP(left)))
4860                     goto release;
4861                 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4862             }
4863         } else {
4864             if (AOP_TYPE(right) == AOP_CRY){
4865                 // c = bit | bit;
4866                 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4867                 emitcode("orl","c,%s",AOP(left)->aopu.aop_dir);
4868             }
4869             else{
4870                 // c = bit | val;
4871                 symbol *tlbl = newiTempLabel(NULL);
4872                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
4873                     emitcode("setb","c");
4874                 emitcode("jb","%s,%05d$",
4875                          AOP(left)->aopu.aop_dir,tlbl->key+100);
4876                 toBoolean(right);
4877                 emitcode("jnz","%05d$",tlbl->key+100);
4878                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4879                     jmpTrueOrFalse(ifx, tlbl);
4880                     goto release;
4881                 } else {
4882                     CLRC;
4883                     emitcode("","%05d$:",tlbl->key+100);
4884                 }
4885             }
4886         }
4887         // bit = c
4888         // val = c
4889         if(size)
4890             outBitC(result);
4891         // if(bit | ...)
4892         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4893             genIfxJump(ifx, "c");           
4894         goto release ;
4895     }
4896
4897     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
4898     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
4899     if((AOP_TYPE(right) == AOP_LIT) &&
4900        (AOP_TYPE(result) == AOP_CRY) &&
4901        (AOP_TYPE(left) != AOP_CRY)){
4902         if(lit){
4903             // result = 1
4904             if(size)
4905                 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4906             else 
4907                 continueIfTrue(ifx);
4908             goto release;
4909         } else {
4910             // lit = 0, result = boolean(left)
4911             if(size)
4912                 emitcode("setb","c");
4913             toBoolean(right);
4914             if(size){
4915                 symbol *tlbl = newiTempLabel(NULL);
4916                 emitcode("jnz","%05d$",tlbl->key+100);
4917                 CLRC;
4918                 emitcode("","%05d$:",tlbl->key+100);
4919             } else {
4920                 genIfxJump (ifx,"a");
4921                 goto release;
4922             }
4923         }
4924         outBitC(result);
4925         goto release ;
4926     }
4927
4928     /* if left is same as result */
4929     if(sameRegs(AOP(result),AOP(left)))
4930     {
4931         for(;size--; offset++) 
4932         {
4933             if(AOP_TYPE(right) == AOP_LIT){
4934                 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4935                 {
4936                     continue;
4937                 }
4938                 else 
4939                 {
4940                     if (IS_AOP_PREG(left)) 
4941                     {
4942                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4943                         emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4944                         aopPut(AOP(result),"a",offset);
4945                     } 
4946                     else
4947                     {
4948                         emitcode("orl","%s,%s",
4949                                  aopGet(AOP(left),offset,FALSE,TRUE,FALSE),
4950                                  aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4951                     }
4952                 }
4953             } 
4954             else 
4955             {
4956                 if (AOP_TYPE(left) == AOP_ACC)
4957                 { 
4958                     emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4959                 }
4960                 else 
4961                 {                   
4962                     MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4963                     if (IS_AOP_PREG(left)) 
4964                     {
4965                         emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4966                         aopPut(AOP(result),"a",offset);
4967                     } 
4968                     else
4969                     {
4970                         emitcode("orl","%s,a",
4971                                  aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4972                     }
4973                 }
4974             }
4975         }
4976     }
4977     else
4978     {
4979         // left & result in different registers
4980         if(AOP_TYPE(result) == AOP_CRY)
4981         {
4982             // result = bit
4983             // if(size), result in bit
4984             // if(!size && ifx), conditional oper: if(left | right)
4985             symbol *tlbl = newiTempLabel(NULL);
4986             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4987             if(size)
4988                 emitcode("setb","c");
4989             while(sizer--){
4990                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4991                 emitcode("orl","a,%s",
4992                          aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4993                 emitcode("jnz","%05d$",tlbl->key+100);
4994                 offset++;
4995             }
4996             if(size){
4997                 CLRC;
4998                 emitcode("","%05d$:",tlbl->key+100);
4999                 outBitC(result);
5000             } else if(ifx)
5001                 jmpTrueOrFalse(ifx, tlbl);
5002         } 
5003         else 
5004         {
5005             for(;(size--);offset++)
5006             {
5007                 // normal case
5008                 // result = left & right
5009                 if(AOP_TYPE(right) == AOP_LIT)
5010                 {
5011                     if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
5012                     {
5013                         aopPut(AOP(result),
5014                                aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
5015                                offset);
5016                         continue;
5017                     }
5018                     D(emitcode(";", "better literal OR."););
5019                     MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
5020                     emitcode("orl", "a, %s", aopGet(AOP(right),offset,
5021                                                 FALSE,FALSE,FALSE));
5022                      
5023                 }
5024                 else
5025                 {
5026                     // faster than result <- left, anl result,right
5027                     // and better if result is SFR
5028                     if (AOP_TYPE(left) == AOP_ACC) 
5029                     {
5030                         emitcode("orl","a,%s",aopGet(AOP(right),offset,
5031                                                      FALSE,FALSE,FALSE));
5032                     }
5033                     else 
5034                     {
5035                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5036                         emitcode("orl","a,%s",
5037                                  aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
5038                     }
5039                 }
5040                 aopPut(AOP(result),"a",offset);                 
5041             }
5042         }
5043     }
5044
5045 release :
5046     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5047     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5048     freeAsmop(result,NULL,ic,TRUE);     
5049 }
5050
5051 /*-----------------------------------------------------------------*/
5052 /* genXor - code for xclusive or                                   */
5053 /*-----------------------------------------------------------------*/
5054 static void genXor (iCode *ic, iCode *ifx)
5055 {
5056     operand *left, *right, *result;
5057     int size, offset=0;
5058     unsigned long lit = 0L;
5059
5060     D(emitcode(";", "genXor "););
5061
5062     AOP_OP_3(ic);
5063     AOP_SET_LOCALS(ic);
5064 #if 0
5065     aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
5066     aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
5067     aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
5068 #endif
5069
5070 #ifdef DEBUG_TYPE
5071     emitcode("","; Type res[%d] = l[%d]&r[%d]",
5072              AOP_TYPE(result),
5073              AOP_TYPE(left), AOP_TYPE(right));
5074     emitcode("","; Size res[%d] = l[%d]&r[%d]",
5075              AOP_SIZE(result),
5076              AOP_SIZE(left), AOP_SIZE(right));
5077 #endif
5078
5079     /* if left is a literal & right is not ||
5080        if left needs acc & right does not */
5081     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5082         (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
5083         operand *tmp = right ;
5084         right = left;
5085         left = tmp;
5086     }
5087
5088     /* if result = right then exchange them */
5089     if(sameRegs(AOP(result),AOP(right))){
5090         operand *tmp = right ;
5091         right = left;
5092         left = tmp;
5093     }
5094
5095     /* if right is bit then exchange them */
5096     if (AOP_TYPE(right) == AOP_CRY &&
5097         AOP_TYPE(left) != AOP_CRY){
5098         operand *tmp = right ;
5099         right = left;
5100         left = tmp;
5101     }
5102     if(AOP_TYPE(right) == AOP_LIT)
5103         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5104
5105     size = AOP_SIZE(result);
5106
5107     // if(bit ^ yy)
5108     // xx = bit ^ yy;
5109     if (AOP_TYPE(left) == AOP_CRY){
5110         if(AOP_TYPE(right) == AOP_LIT){
5111             // c = bit & literal;
5112             if(lit>>1){
5113                 // lit>>1  != 0 => result = 1
5114                 if(AOP_TYPE(result) == AOP_CRY){
5115                     if(size)
5116                         emitcode("setb","%s",AOP(result)->aopu.aop_dir);
5117                     else if(ifx)
5118                         continueIfTrue(ifx);
5119                     goto release;
5120                 }
5121                 emitcode("setb","c");
5122             } else{
5123                 // lit == (0 or 1)
5124                 if(lit == 0){
5125                     // lit == 0, result = left
5126                     if(size && sameRegs(AOP(result),AOP(left)))
5127                         goto release;
5128                     emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5129                 } else{
5130                     // lit == 1, result = not(left)
5131                     if(size && sameRegs(AOP(result),AOP(left))){
5132                         emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
5133                         goto release;
5134                     } else {
5135                         emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5136                         emitcode("cpl","c");
5137                     }
5138                 }
5139             }
5140
5141         } else {
5142             // right != literal
5143             symbol *tlbl = newiTempLabel(NULL);
5144             if (AOP_TYPE(right) == AOP_CRY){
5145                 // c = bit ^ bit;
5146                 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5147             }
5148             else{
5149                 int sizer = AOP_SIZE(right);
5150                 // c = bit ^ val
5151                 // if val>>1 != 0, result = 1
5152                 emitcode("setb","c");
5153                 while(sizer){
5154                     MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE,TRUE));
5155                     if(sizer == 1)
5156                         // test the msb of the lsb
5157                         emitcode("anl","a,#0xfe");
5158                     emitcode("jnz","%05d$",tlbl->key+100);
5159                     sizer--;
5160                 }
5161                 // val = (0,1)
5162                 emitcode("rrc","a");
5163             }
5164             emitcode("jnb","%s,%05d$",AOP(left)->aopu.aop_dir,(tlbl->key+100));
5165             emitcode("cpl","c");
5166             emitcode("","%05d$:",(tlbl->key+100));
5167         }
5168         // bit = c
5169         // val = c
5170         if(size)
5171             outBitC(result);
5172         // if(bit | ...)
5173         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5174             genIfxJump(ifx, "c");           
5175         goto release ;
5176     }
5177
5178     if(sameRegs(AOP(result),AOP(left))){
5179         /* if left is same as result */
5180         for(;size--; offset++) {
5181             if(AOP_TYPE(right) == AOP_LIT){
5182                 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
5183                     continue;
5184                 else
5185                     if (IS_AOP_PREG(left)) {
5186                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5187                         emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5188                         aopPut(AOP(result),"a",offset);
5189                     } else 
5190                         emitcode("xrl","%s,%s",
5191                                  aopGet(AOP(left),offset,FALSE,TRUE,FALSE),
5192                                  aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
5193             } else {
5194                 if (AOP_TYPE(left) == AOP_ACC)
5195                     emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
5196                 else {
5197                     MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5198                     if (IS_AOP_PREG(left)) {
5199                         emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5200                         aopPut(AOP(result),"a",offset);
5201                     } else
5202                         emitcode("xrl","%s,a",
5203                                  aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5204                 }
5205             }
5206         }
5207     } else {
5208         // left & result in different registers
5209         if(AOP_TYPE(result) == AOP_CRY){
5210             // result = bit
5211             // if(size), result in bit
5212             // if(!size && ifx), conditional oper: if(left ^ right)
5213             symbol *tlbl = newiTempLabel(NULL);
5214             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5215             if(size)
5216                 emitcode("setb","c");
5217             while(sizer--){
5218                 if((AOP_TYPE(right) == AOP_LIT) &&
5219                    (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
5220                     MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
5221                 } else {
5222                     MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5223                     emitcode("xrl","a,%s",
5224                              aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
5225                 }
5226                 emitcode("jnz","%05d$",tlbl->key+100);
5227                 offset++;
5228             }
5229             if(size){
5230                 CLRC;
5231                 emitcode("","%05d$:",tlbl->key+100);
5232                 outBitC(result);
5233             } else if(ifx)
5234                 jmpTrueOrFalse(ifx, tlbl);
5235         } else for(;(size--);offset++)
5236         {
5237             // normal case
5238             // result = left & right
5239             if(AOP_TYPE(right) == AOP_LIT)
5240             {
5241                 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
5242                 {
5243                     aopPut(AOP(result),
5244                            aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
5245                            offset);
5246                     continue;
5247                 }
5248                 D(emitcode(";", "better literal XOR."););
5249                 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
5250                 emitcode("xrl", "a, %s", aopGet(AOP(right),offset,
5251                                                 FALSE,FALSE,FALSE));                
5252             }
5253             else
5254             {
5255                 // faster than result <- left, anl result,right
5256                 // and better if result is SFR
5257                 if (AOP_TYPE(left) == AOP_ACC)
5258                 {
5259                     emitcode("xrl","a,%s",aopGet(AOP(right),offset,
5260                              FALSE,FALSE,FALSE));
5261                 }
5262                 else 
5263                 {
5264                     MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5265                     emitcode("xrl","a,%s",
5266                              aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5267                 }
5268             }
5269             aopPut(AOP(result),"a",offset);
5270         }
5271     }
5272
5273 release :
5274     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5275     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5276     freeAsmop(result,NULL,ic,TRUE);     
5277 }
5278
5279 /*-----------------------------------------------------------------*/
5280 /* genInline - write the inline code out                           */
5281 /*-----------------------------------------------------------------*/
5282 static void genInline (iCode *ic)
5283 {
5284     char buffer[MAX_INLINEASM];
5285     char *bp = buffer;
5286     char *bp1= buffer;
5287     
5288     D(emitcode(";", "genInline "););
5289
5290     _G.inLine += (!options.asmpeep);
5291     strcpy(buffer,IC_INLINE(ic));
5292
5293     /* emit each line as a code */
5294     while (*bp) {
5295         if (*bp == '\n') {
5296             *bp++ = '\0';
5297             emitcode(bp1,"");
5298             bp1 = bp;
5299         } else {
5300             if (*bp == ':') {
5301                 bp++;
5302                 *bp = '\0';
5303                 bp++;
5304                 emitcode(bp1,"");
5305                 bp1 = bp;
5306             } else
5307                 bp++;
5308         }
5309     }
5310     if (bp1 != bp)
5311         emitcode(bp1,"");
5312     /*     emitcode("",buffer); */
5313     _G.inLine -= (!options.asmpeep);
5314 }
5315
5316 /*-----------------------------------------------------------------*/
5317 /* genRRC - rotate right with carry                                */
5318 /*-----------------------------------------------------------------*/
5319 static void genRRC (iCode *ic)
5320 {
5321     operand *left , *result ;
5322     int size, offset = 0;
5323     char *l;    
5324
5325     D(emitcode(";", "genRRC "););
5326
5327     /* rotate right with carry */
5328     left = IC_LEFT(ic);
5329     result=IC_RESULT(ic);
5330     aopOp (left,ic,FALSE, FALSE);
5331     aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5332
5333     /* move it to the result */
5334     size = AOP_SIZE(result);    
5335     offset = size - 1 ;
5336     CLRC;
5337     
5338     _startLazyDPSEvaluation();
5339     while (size--) {
5340         l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
5341         MOVA(l);
5342         emitcode("rrc","a");
5343         if (AOP_SIZE(result) > 1)
5344             aopPut(AOP(result),"a",offset--);
5345     }
5346     _endLazyDPSEvaluation();
5347     
5348     /* now we need to put the carry into the
5349     highest order byte of the result */
5350     if (AOP_SIZE(result) > 1) {
5351         l = aopGet(AOP(result),AOP_SIZE(result)-1,FALSE,FALSE,TRUE);
5352         MOVA(l);
5353     }
5354     emitcode("mov","acc.7,c");
5355     aopPut(AOP(result),"a",AOP_SIZE(result)-1);
5356     freeAsmop(left,NULL,ic,TRUE);
5357     freeAsmop(result,NULL,ic,TRUE);
5358 }
5359
5360 /*-----------------------------------------------------------------*/
5361 /* genRLC - generate code for rotate left with carry               */
5362 /*-----------------------------------------------------------------*/
5363 static void genRLC (iCode *ic)
5364 {    
5365     operand *left , *result ;
5366     int size, offset = 0;
5367     char *l;    
5368
5369     D(emitcode(";", "genRLC "););
5370
5371     /* rotate right with carry */
5372     left = IC_LEFT(ic);
5373     result=IC_RESULT(ic);
5374     aopOp (left,ic,FALSE, FALSE);
5375     aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5376
5377     /* move it to the result */
5378     size = AOP_SIZE(result);    
5379     offset = 0 ;
5380     if (size--) {
5381         l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
5382         MOVA(l);
5383         emitcode("add","a,acc");
5384         if (AOP_SIZE(result) > 1)
5385         {
5386             aopPut(AOP(result),"a",offset++);
5387         }
5388             
5389         _startLazyDPSEvaluation();
5390         while (size--) {
5391             l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
5392             MOVA(l);
5393             emitcode("rlc","a");
5394             if (AOP_SIZE(result) > 1)
5395                 aopPut(AOP(result),"a",offset++);
5396         }
5397         _endLazyDPSEvaluation();
5398     }
5399     /* now we need to put the carry into the
5400     highest order byte of the result */
5401     if (AOP_SIZE(result) > 1) {
5402         l = aopGet(AOP(result),0,FALSE,FALSE,TRUE);
5403         MOVA(l);
5404     }
5405     emitcode("mov","acc.0,c");
5406     aopPut(AOP(result),"a",0);
5407     freeAsmop(left,NULL,ic,TRUE);
5408     freeAsmop(result,NULL,ic,TRUE);
5409 }
5410
5411 /*-----------------------------------------------------------------*/
5412 /* genGetHbit - generates code get highest order bit               */
5413 /*-----------------------------------------------------------------*/
5414 static void genGetHbit (iCode *ic)
5415 {
5416     operand *left, *result;
5417     left = IC_LEFT(ic);
5418     result=IC_RESULT(ic);
5419     aopOp (left,ic,FALSE, FALSE);
5420     aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5421
5422     D(emitcode(";", "genGetHbit "););
5423
5424     /* get the highest order byte into a */
5425     MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE,TRUE));
5426     if(AOP_TYPE(result) == AOP_CRY){
5427         emitcode("rlc","a");
5428         outBitC(result);
5429     }
5430     else{
5431         emitcode("rl","a");
5432         emitcode("anl","a,#0x01");
5433         outAcc(result);
5434     }
5435
5436
5437     freeAsmop(left,NULL,ic,TRUE);
5438     freeAsmop(result,NULL,ic,TRUE);
5439 }
5440
5441 /*-----------------------------------------------------------------*/
5442 /* AccRol - rotate left accumulator by known count                 */
5443 /*-----------------------------------------------------------------*/
5444 static void AccRol (int shCount)
5445 {
5446     shCount &= 0x0007;              // shCount : 0..7
5447     switch(shCount){
5448         case 0 :
5449             break;
5450         case 1 :
5451             emitcode("rl","a");
5452             break;
5453         case 2 :
5454             emitcode("rl","a");
5455             emitcode("rl","a");
5456             break;
5457         case 3 :
5458             emitcode("swap","a");
5459             emitcode("rr","a");
5460             break;
5461         case 4 :
5462             emitcode("swap","a");
5463             break;
5464         case 5 :
5465             emitcode("swap","a");
5466             emitcode("rl","a");
5467             break;
5468         case 6 :
5469             emitcode("rr","a");
5470             emitcode("rr","a");
5471             break;
5472         case 7 :
5473             emitcode("rr","a");
5474             break;
5475     }
5476 }
5477
5478 /*-----------------------------------------------------------------*/
5479 /* AccLsh - left shift accumulator by known count                  */
5480 /*-----------------------------------------------------------------*/
5481 static void AccLsh (int shCount)
5482 {
5483     if(shCount != 0){
5484         if(shCount == 1)
5485             emitcode("add","a,acc");
5486         else 
5487             if(shCount == 2) {
5488             emitcode("add","a,acc");
5489             emitcode("add","a,acc");
5490         } else {
5491             /* rotate left accumulator */
5492             AccRol(shCount);
5493             /* and kill the lower order bits */
5494             emitcode("anl","a,#0x%02x", SLMask[shCount]);
5495         }
5496     }
5497 }
5498
5499 /*-----------------------------------------------------------------*/
5500 /* AccRsh - right shift accumulator by known count                 */
5501 /*-----------------------------------------------------------------*/
5502 static void AccRsh (int shCount)
5503 {
5504     if(shCount != 0){
5505         if(shCount == 1){
5506             CLRC;
5507             emitcode("rrc","a");
5508         } else {
5509             /* rotate right accumulator */
5510             AccRol(8 - shCount);
5511             /* and kill the higher order bits */
5512             emitcode("anl","a,#0x%02x", SRMask[shCount]);
5513         }
5514     }
5515 }
5516
5517 #if 0
5518 //REMOVE ME!!!
5519 /*-----------------------------------------------------------------*/
5520 /* AccSRsh - signed right shift accumulator by known count                 */
5521 /*-----------------------------------------------------------------*/
5522 static void AccSRsh (int shCount)
5523 {
5524     symbol *tlbl ;
5525     if(shCount != 0){
5526         if(shCount == 1){
5527             emitcode("mov","c,acc.7");
5528             emitcode("rrc","a");
5529         } else if(shCount == 2){
5530             emitcode("mov","c,acc.7");
5531             emitcode("rrc","a");
5532             emitcode("mov","c,acc.7");
5533             emitcode("rrc","a");
5534         } else {
5535             tlbl = newiTempLabel(NULL);
5536             /* rotate right accumulator */
5537             AccRol(8 - shCount);
5538             /* and kill the higher order bits */
5539             emitcode("anl","a,#0x%02x", SRMask[shCount]);
5540             emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5541             emitcode("orl","a,#0x%02x",
5542                      (unsigned char)~SRMask[shCount]);
5543             emitcode("","%05d$:",tlbl->key+100);
5544         }
5545     }
5546 }
5547 #endif
5548
5549 #if 0
5550 //REMOVE ME!!!
5551 /*-----------------------------------------------------------------*/
5552 /* shiftR1Left2Result - shift right one byte from left to result   */
5553 /*-----------------------------------------------------------------*/
5554 static void shiftR1Left2Result (operand *left, int offl,
5555                                 operand *result, int offr,
5556                                 int shCount, int sign)
5557 {
5558     MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5559     /* shift right accumulator */
5560     if(sign)
5561         AccSRsh(shCount);
5562     else
5563         AccRsh(shCount);
5564     aopPut(AOP(result),"a",offr);
5565 }
5566 #endif
5567
5568 #if 0
5569 //REMOVE ME!!!
5570 /*-----------------------------------------------------------------*/
5571 /* shiftL1Left2Result - shift left one byte from left to result    */
5572 /*-----------------------------------------------------------------*/
5573 static void shiftL1Left2Result (operand *left, int offl,
5574                                 operand *result, int offr, int shCount)
5575 {
5576     char *l;
5577     l = aopGet(AOP(left),offl,FALSE,FALSE,TRUE);
5578     MOVA(l);
5579     /* shift left accumulator */
5580     AccLsh(shCount);
5581     aopPut(AOP(result),"a",offr);
5582 }
5583 #endif
5584
5585 #if 0
5586 //REMOVE ME!!!
5587 /*-----------------------------------------------------------------*/
5588 /* movLeft2Result - move byte from left to result                  */
5589 /*-----------------------------------------------------------------*/
5590 static void movLeft2Result (operand *left, int offl,
5591                             operand *result, int offr, int sign)
5592 {
5593     char *l;
5594     if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
5595         l = aopGet(AOP(left),offl,FALSE,FALSE,FALSE);
5596
5597         if (*l == '@' && (IS_AOP_PREG(result))) {
5598             emitcode("mov","a,%s",l);
5599             aopPut(AOP(result),"a",offr);
5600         } else {
5601             if(!sign)
5602                 aopPut(AOP(result),l,offr);
5603             else{
5604                 /* MSB sign in acc.7 ! */
5605                 if(getDataSize(left) == offl+1){
5606                     emitcode("mov","a,%s",l);
5607                     aopPut(AOP(result),"a",offr);
5608                 }
5609             }
5610         }
5611     }
5612 }
5613 #endif
5614
5615 #if 0
5616 //REMOVE ME!!!
5617 /*-----------------------------------------------------------------*/
5618 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
5619 /*-----------------------------------------------------------------*/
5620 static void AccAXRrl1 (char *x)
5621 {
5622     emitcode("rrc","a");
5623     emitcode("xch","a,%s", x);
5624     emitcode("rrc","a");
5625     emitcode("xch","a,%s", x);
5626 }
5627 #endif
5628
5629 #if 0
5630 //REMOVE ME!!!
5631 /*-----------------------------------------------------------------*/
5632 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
5633 /*-----------------------------------------------------------------*/
5634 static void AccAXLrl1 (char *x)
5635 {
5636     emitcode("xch","a,%s",x);
5637     emitcode("rlc","a");
5638     emitcode("xch","a,%s",x);
5639     emitcode("rlc","a");
5640 }
5641 #endif
5642
5643 #if 0
5644 //REMOVE ME!!!
5645 /*-----------------------------------------------------------------*/
5646 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
5647 /*-----------------------------------------------------------------*/
5648 static void AccAXLsh1 (char *x)
5649 {
5650     emitcode("xch","a,%s",x);
5651     emitcode("add","a,acc");
5652     emitcode("xch","a,%s",x);
5653     emitcode("rlc","a");
5654 }
5655 #endif
5656
5657 #if 0
5658 //REMOVE ME!!!
5659 /*-----------------------------------------------------------------*/
5660 /* AccAXLsh - left shift a:x by known count (0..7)                 */
5661 /*-----------------------------------------------------------------*/
5662 static void AccAXLsh (char *x, int shCount)
5663 {
5664     switch(shCount){
5665         case 0 :
5666             break;
5667         case 1 :
5668             AccAXLsh1(x);
5669             break;
5670         case 2 :
5671             AccAXLsh1(x);
5672             AccAXLsh1(x);
5673             break;
5674         case 3 :
5675         case 4 :
5676         case 5 :                        // AAAAABBB:CCCCCDDD
5677             AccRol(shCount);            // BBBAAAAA:CCCCCDDD
5678             emitcode("anl","a,#0x%02x",
5679                      SLMask[shCount]);  // BBB00000:CCCCCDDD
5680             emitcode("xch","a,%s",x);   // CCCCCDDD:BBB00000
5681             AccRol(shCount);            // DDDCCCCC:BBB00000
5682             emitcode("xch","a,%s",x);   // BBB00000:DDDCCCCC
5683             emitcode("xrl","a,%s",x);   // (BBB^DDD)CCCCC:DDDCCCCC
5684             emitcode("xch","a,%s",x);   // DDDCCCCC:(BBB^DDD)CCCCC
5685             emitcode("anl","a,#0x%02x",
5686                      SLMask[shCount]);  // DDD00000:(BBB^DDD)CCCCC
5687             emitcode("xch","a,%s",x);   // (BBB^DDD)CCCCC:DDD00000
5688             emitcode("xrl","a,%s",x);   // BBBCCCCC:DDD00000            
5689             break;
5690         case 6 :                        // AAAAAABB:CCCCCCDD
5691             emitcode("anl","a,#0x%02x",
5692                      SRMask[shCount]);  // 000000BB:CCCCCCDD
5693             emitcode("mov","c,acc.0");  // c = B
5694             emitcode("xch","a,%s",x);   // CCCCCCDD:000000BB
5695             AccAXRrl1(x);               // BCCCCCCD:D000000B
5696             AccAXRrl1(x);               // BBCCCCCC:DD000000
5697             break;
5698         case 7 :                        // a:x <<= 7
5699             emitcode("anl","a,#0x%02x",
5700                      SRMask[shCount]);  // 0000000B:CCCCCCCD
5701             emitcode("mov","c,acc.0");  // c = B
5702             emitcode("xch","a,%s",x);   // CCCCCCCD:0000000B
5703             AccAXRrl1(x);               // BCCCCCCC:D0000000
5704             break;
5705         default :
5706             break;
5707     }
5708 }
5709 #endif
5710
5711 #if 0
5712 //REMOVE ME!!!
5713 /*-----------------------------------------------------------------*/
5714 /* AccAXRsh - right shift a:x known count (0..7)                   */
5715 /*-----------------------------------------------------------------*/
5716 static void AccAXRsh (char *x, int shCount)
5717 {   
5718     switch(shCount){
5719         case 0 :
5720             break;
5721         case 1 :
5722             CLRC;
5723             AccAXRrl1(x);               // 0->a:x
5724             break;
5725         case 2 :
5726             CLRC;
5727             AccAXRrl1(x);               // 0->a:x
5728             CLRC;
5729             AccAXRrl1(x);               // 0->a:x
5730             break;
5731         case 3 :
5732         case 4 :
5733         case 5 :                        // AAAAABBB:CCCCCDDD = a:x
5734             AccRol(8 - shCount);        // BBBAAAAA:DDDCCCCC
5735             emitcode("xch","a,%s",x);   // CCCCCDDD:BBBAAAAA
5736             AccRol(8 - shCount);        // DDDCCCCC:BBBAAAAA
5737             emitcode("anl","a,#0x%02x",
5738                      SRMask[shCount]);  // 000CCCCC:BBBAAAAA
5739             emitcode("xrl","a,%s",x);   // BBB(CCCCC^AAAAA):BBBAAAAA
5740             emitcode("xch","a,%s",x);   // BBBAAAAA:BBB(CCCCC^AAAAA)
5741             emitcode("anl","a,#0x%02x",
5742                      SRMask[shCount]);  // 000AAAAA:BBB(CCCCC^AAAAA)
5743             emitcode("xch","a,%s",x);   // BBB(CCCCC^AAAAA):000AAAAA
5744             emitcode("xrl","a,%s",x);   // BBBCCCCC:000AAAAA
5745             emitcode("xch","a,%s",x);   // 000AAAAA:BBBCCCCC
5746             break;
5747         case 6 :                        // AABBBBBB:CCDDDDDD
5748             emitcode("mov","c,acc.7");
5749             AccAXLrl1(x);               // ABBBBBBC:CDDDDDDA
5750             AccAXLrl1(x);               // BBBBBBCC:DDDDDDAA
5751             emitcode("xch","a,%s",x);   // DDDDDDAA:BBBBBBCC
5752             emitcode("anl","a,#0x%02x",
5753                      SRMask[shCount]);  // 000000AA:BBBBBBCC
5754             break;
5755         case 7 :                        // ABBBBBBB:CDDDDDDD
5756             emitcode("mov","c,acc.7");  // c = A
5757             AccAXLrl1(x);               // BBBBBBBC:DDDDDDDA
5758             emitcode("xch","a,%s",x);   // DDDDDDDA:BBBBBBCC
5759             emitcode("anl","a,#0x%02x",
5760                      SRMask[shCount]);  // 0000000A:BBBBBBBC
5761             break;
5762         default :
5763             break;
5764     }
5765 }
5766 #endif
5767
5768 #if 0
5769 //REMOVE ME!!!
5770 /*-----------------------------------------------------------------*/
5771 /* AccAXRshS - right shift signed a:x known count (0..7)           */
5772 /*-----------------------------------------------------------------*/
5773 static void AccAXRshS (char *x, int shCount)
5774 {   
5775     symbol *tlbl ;
5776     switch(shCount){
5777         case 0 :
5778             break;
5779         case 1 :
5780             emitcode("mov","c,acc.7");
5781             AccAXRrl1(x);               // s->a:x
5782             break;
5783         case 2 :
5784             emitcode("mov","c,acc.7");
5785             AccAXRrl1(x);               // s->a:x
5786             emitcode("mov","c,acc.7");
5787             AccAXRrl1(x);               // s->a:x
5788             break;
5789         case 3 :
5790         case 4 :
5791         case 5 :                        // AAAAABBB:CCCCCDDD = a:x
5792             tlbl = newiTempLabel(NULL);
5793             AccRol(8 - shCount);        // BBBAAAAA:CCCCCDDD
5794             emitcode("xch","a,%s",x);   // CCCCCDDD:BBBAAAAA
5795             AccRol(8 - shCount);        // DDDCCCCC:BBBAAAAA
5796             emitcode("anl","a,#0x%02x",
5797                      SRMask[shCount]);  // 000CCCCC:BBBAAAAA
5798             emitcode("xrl","a,%s",x);   // BBB(CCCCC^AAAAA):BBBAAAAA
5799             emitcode("xch","a,%s",x);   // BBBAAAAA:BBB(CCCCC^AAAAA)
5800             emitcode("anl","a,#0x%02x",
5801                      SRMask[shCount]);  // 000AAAAA:BBB(CCCCC^AAAAA)
5802             emitcode("xch","a,%s",x);   // BBB(CCCCC^AAAAA):000AAAAA
5803             emitcode("xrl","a,%s",x);   // BBBCCCCC:000AAAAA
5804             emitcode("xch","a,%s",x);   // 000SAAAA:BBBCCCCC
5805             emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100); 
5806             emitcode("orl","a,#0x%02x",
5807                      (unsigned char)~SRMask[shCount]);  // 111AAAAA:BBBCCCCC
5808             emitcode("","%05d$:",tlbl->key+100);
5809             break;                      // SSSSAAAA:BBBCCCCC
5810         case 6 :                        // AABBBBBB:CCDDDDDD
5811             tlbl = newiTempLabel(NULL);
5812             emitcode("mov","c,acc.7");
5813             AccAXLrl1(x);               // ABBBBBBC:CDDDDDDA
5814             AccAXLrl1(x);               // BBBBBBCC:DDDDDDAA
5815             emitcode("xch","a,%s",x);   // DDDDDDAA:BBBBBBCC
5816             emitcode("anl","a,#0x%02x",
5817                      SRMask[shCount]);  // 000000AA:BBBBBBCC
5818             emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100); 
5819             emitcode("orl","a,#0x%02x",
5820                      (unsigned char)~SRMask[shCount]);  // 111111AA:BBBBBBCC
5821             emitcode("","%05d$:",tlbl->key+100);
5822             break;
5823         case 7 :                        // ABBBBBBB:CDDDDDDD
5824             tlbl = newiTempLabel(NULL);
5825             emitcode("mov","c,acc.7");  // c = A
5826             AccAXLrl1(x);               // BBBBBBBC:DDDDDDDA
5827             emitcode("xch","a,%s",x);   // DDDDDDDA:BBBBBBCC
5828             emitcode("anl","a,#0x%02x",
5829                      SRMask[shCount]);  // 0000000A:BBBBBBBC
5830             emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100); 
5831             emitcode("orl","a,#0x%02x",
5832                      (unsigned char)~SRMask[shCount]);  // 1111111A:BBBBBBBC
5833             emitcode("","%05d$:",tlbl->key+100);
5834             break;
5835         default :
5836             break;
5837     }
5838 }
5839 #endif
5840
5841 #if 0
5842 //REMOVE ME!!!
5843 /*-----------------------------------------------------------------*/
5844 /* shiftL2Left2Result - shift left two bytes from left to result   */
5845 /*-----------------------------------------------------------------*/
5846 static void shiftL2Left2Result (operand *left, int offl,
5847                                 operand *result, int offr, int shCount)
5848 {
5849     if(sameRegs(AOP(result), AOP(left)) &&
5850        ((offl + MSB16) == offr)){
5851         /* don't crash result[offr] */
5852         MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5853         emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE,FALSE));
5854     } else {
5855         movLeft2Result(left,offl, result, offr, 0);
5856         MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE,TRUE));
5857     }
5858     /* ax << shCount (x = lsb(result))*/
5859     AccAXLsh( aopGet(AOP(result),offr,FALSE,FALSE,FALSE), shCount);
5860     aopPut(AOP(result),"a",offr+MSB16);
5861 }
5862 #endif
5863
5864 #if 0
5865 //REMOVE ME!!!
5866 /*-----------------------------------------------------------------*/
5867 /* shiftR2Left2Result - shift right two bytes from left to result  */
5868 /*-----------------------------------------------------------------*/
5869 static void shiftR2Left2Result (operand *left, int offl,
5870                                 operand *result, int offr,
5871                                 int shCount, int sign)
5872 {
5873     if(sameRegs(AOP(result), AOP(left)) &&
5874        ((offl + MSB16) == offr)){
5875         /* don't crash result[offr] */
5876         MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5877         emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE,FALSE));
5878     } else {
5879         movLeft2Result(left,offl, result, offr, 0);
5880         MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE,TRUE));
5881     }
5882     /* a:x >> shCount (x = lsb(result))*/
5883     if(sign)
5884         AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE,FALSE) , shCount);
5885     else
5886         AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE,FALSE) , shCount);
5887     if(getDataSize(result) > 1)
5888         aopPut(AOP(result),"a",offr+MSB16);
5889 }
5890 #endif
5891
5892 #if 0
5893 //REMOVE ME!!!
5894 /*-----------------------------------------------------------------*/
5895 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
5896 /*-----------------------------------------------------------------*/
5897 static void shiftLLeftOrResult (operand *left, int offl,
5898                                 operand *result, int offr, int shCount)
5899 {
5900     MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5901     /* shift left accumulator */
5902     AccLsh(shCount);
5903     /* or with result */
5904     emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE,FALSE));
5905     /* back to result */
5906     aopPut(AOP(result),"a",offr);
5907 }
5908 #endif
5909
5910 #if 0
5911 //REMOVE ME!!!
5912 /*-----------------------------------------------------------------*/
5913 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
5914 /*-----------------------------------------------------------------*/
5915 static void shiftRLeftOrResult (operand *left, int offl,
5916                                 operand *result, int offr, int shCount)
5917 {
5918     MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5919     /* shift right accumulator */
5920     AccRsh(shCount);
5921     /* or with result */
5922     emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE,FALSE));
5923     /* back to result */
5924     aopPut(AOP(result),"a",offr);
5925 }
5926 #endif
5927
5928 #if 0
5929 //REMOVE ME!!!
5930 /*-----------------------------------------------------------------*/
5931 /* genlshOne - left shift a one byte quantity by known count       */
5932 /*-----------------------------------------------------------------*/
5933 static void genlshOne (operand *result, operand *left, int shCount)
5934 {       
5935     D(emitcode(";", "genlshOne "););
5936     shiftL1Left2Result(left, LSB, result, LSB, shCount);
5937 }
5938 #endif
5939
5940 #if 0
5941 //REMOVE ME!!!
5942 /*-----------------------------------------------------------------*/
5943 /* genlshTwo - left shift two bytes by known amount != 0           */
5944 /*-----------------------------------------------------------------*/
5945 static void genlshTwo (operand *result,operand *left, int shCount)
5946 {
5947     int size;
5948     
5949     D(emitcode(";", "genlshTwo "););
5950
5951     size = getDataSize(result);
5952
5953     /* if shCount >= 8 */
5954     if (shCount >= 8) {
5955         shCount -= 8 ;
5956
5957         if (size > 1){
5958             if (shCount)
5959                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5960             else 
5961                 movLeft2Result(left, LSB, result, MSB16, 0);
5962         }
5963         aopPut(AOP(result),zero,LSB);   
5964     }
5965
5966     /*  1 <= shCount <= 7 */
5967     else {  
5968         if(size == 1)
5969             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
5970         else 
5971             shiftL2Left2Result(left, LSB, result, LSB, shCount);
5972     }
5973 }
5974 #endif
5975
5976 #if 0
5977 //REMOVE ME!!!
5978 /*-----------------------------------------------------------------*/
5979 /* shiftLLong - shift left one long from left to result            */
5980 /* offl = LSB or MSB16                                             */
5981 /*-----------------------------------------------------------------*/
5982 static void shiftLLong (operand *left, operand *result, int offr )
5983 {
5984     char *l;
5985     int size = AOP_SIZE(result);
5986
5987     if(size >= LSB+offr){
5988         l = aopGet(AOP(left),LSB,FALSE,FALSE,TRUE);
5989         MOVA(l);
5990         emitcode("add","a,acc");
5991         if (sameRegs(AOP(left),AOP(result)) && 
5992             size >= MSB16+offr && offr != LSB )
5993             emitcode("xch","a,%s",
5994                      aopGet(AOP(left),LSB+offr,FALSE,FALSE,FALSE));
5995         else        
5996             aopPut(AOP(result),"a",LSB+offr);
5997     }
5998
5999     if(size >= MSB16+offr){
6000         if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
6001             l = aopGet(AOP(left),MSB16,FALSE,FALSE,TRUE);
6002             MOVA(l);
6003         }
6004         emitcode("rlc","a");
6005         if (sameRegs(AOP(left),AOP(result)) && 
6006             size >= MSB24+offr && offr != LSB)
6007             emitcode("xch","a,%s",
6008                      aopGet(AOP(left),MSB16+offr,FALSE,FALSE,FALSE));
6009         else        
6010             aopPut(AOP(result),"a",MSB16+offr);
6011     }
6012
6013     if(size >= MSB24+offr){
6014         if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
6015             l = aopGet(AOP(left),MSB24,FALSE,FALSE,TRUE);
6016             MOVA(l);
6017         }
6018         emitcode("rlc","a");
6019         if (sameRegs(AOP(left),AOP(result)) && 
6020             size >= MSB32+offr && offr != LSB )
6021             emitcode("xch","a,%s",
6022                      aopGet(AOP(left),MSB24+offr,FALSE,FALSE,FALSE));
6023         else        
6024             aopPut(AOP(result),"a",MSB24+offr);
6025     }
6026
6027     if(size > MSB32+offr){
6028         if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
6029             l = aopGet(AOP(left),MSB32,FALSE,FALSE,TRUE);
6030             MOVA(l);    
6031         }
6032         emitcode("rlc","a");
6033         aopPut(AOP(result),"a",MSB32+offr);
6034     }
6035     if(offr != LSB)
6036         aopPut(AOP(result),zero,LSB);       
6037 }
6038 #endif
6039
6040 #if 0
6041 //REMOVE ME!!!
6042 /*-----------------------------------------------------------------*/
6043 /* genlshFour - shift four byte by a known amount != 0             */
6044 /*-----------------------------------------------------------------*/
6045 static void genlshFour (operand *result, operand *left, int shCount)
6046 {
6047     int size;
6048
6049     D(emitcode(";", "genlshFour "););
6050
6051     size = AOP_SIZE(result);
6052
6053     /* if shifting more that 3 bytes */
6054     if (shCount >= 24 ) {
6055         shCount -= 24;
6056         if (shCount)
6057             /* lowest order of left goes to the highest
6058             order of the destination */
6059             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
6060         else
6061             movLeft2Result(left, LSB, result, MSB32, 0);
6062         aopPut(AOP(result),zero,LSB);
6063         aopPut(AOP(result),zero,MSB16);
6064         aopPut(AOP(result),zero,MSB32);
6065         return;
6066     }
6067
6068     /* more than two bytes */
6069     else if ( shCount >= 16 ) {
6070         /* lower order two bytes goes to higher order two bytes */
6071         shCount -= 16;
6072         /* if some more remaining */
6073         if (shCount)
6074             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
6075         else {
6076             movLeft2Result(left, MSB16, result, MSB32, 0);
6077             movLeft2Result(left, LSB, result, MSB24, 0);
6078         }
6079         aopPut(AOP(result),zero,MSB16);
6080         aopPut(AOP(result),zero,LSB);
6081         return;
6082     }    
6083
6084     /* if more than 1 byte */
6085     else if ( shCount >= 8 ) {
6086         /* lower order three bytes goes to higher order  three bytes */
6087         shCount -= 8;
6088         if(size == 2){
6089             if(shCount)
6090                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6091             else
6092                 movLeft2Result(left, LSB, result, MSB16, 0);
6093         }
6094         else{   /* size = 4 */
6095             if(shCount == 0){
6096                 movLeft2Result(left, MSB24, result, MSB32, 0);
6097                 movLeft2Result(left, MSB16, result, MSB24, 0);
6098                 movLeft2Result(left, LSB, result, MSB16, 0);
6099                 aopPut(AOP(result),zero,LSB);
6100             }
6101             else if(shCount == 1)
6102                 shiftLLong(left, result, MSB16);
6103             else{
6104                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
6105                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6106                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
6107                 aopPut(AOP(result),zero,LSB);
6108             }
6109         }
6110     }
6111
6112     /* 1 <= shCount <= 7 */
6113     else if(shCount <= 2){
6114         shiftLLong(left, result, LSB);
6115         if(shCount == 2)
6116             shiftLLong(result, result, LSB);
6117     }
6118     /* 3 <= shCount <= 7, optimize */
6119     else{
6120         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
6121         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
6122         shiftL2Left2Result(left, LSB, result, LSB, shCount);
6123     }
6124 }
6125 #endif
6126
6127 #if 0
6128 //REMOVE ME!!!
6129 /*-----------------------------------------------------------------*/
6130 /* genLeftShiftLiteral - left shifting by known count              */
6131 /*-----------------------------------------------------------------*/
6132 static void genLeftShiftLiteral (operand *left,
6133                                  operand *right,
6134                                  operand *result,
6135                                  iCode *ic)
6136 {    
6137     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6138     int size;
6139
6140     D(emitcode(";","genLeftShiftLiteral (%d)", shCount););
6141
6142     freeAsmop(right,NULL,ic,TRUE);
6143
6144     aopOp(left,ic,FALSE, FALSE);
6145     aopOp(result,ic,FALSE, TRUE);
6146
6147     size = getSize(operandType(result));
6148
6149 #if VIEW_SIZE
6150     emitcode("; shift left ","result %d, left %d",size,
6151              AOP_SIZE(left));
6152 #endif
6153
6154     /* I suppose that the left size >= result size */
6155     if(shCount == 0){
6156         while(size--){
6157             movLeft2Result(left, size, result, size, 0);
6158         }
6159     }
6160
6161     else if(shCount >= (size * 8))
6162         while(size--)
6163             aopPut(AOP(result),zero,size);
6164     else{
6165         switch (size) {
6166             case 1:
6167                 genlshOne (result,left,shCount);
6168                 break;
6169
6170             case 2:
6171             case 3: /* bug: this is for generic pointers, I bet. */
6172                 genlshTwo (result,left,shCount);
6173                 break;
6174
6175             case 4:
6176                 genlshFour (result,left,shCount);
6177                 break;
6178         }
6179     }
6180     freeAsmop(left,NULL,ic,TRUE);
6181     freeAsmop(result,NULL,ic,TRUE);
6182 }
6183 #endif
6184
6185 /*-----------------------------------------------------------------*/
6186 /* genLeftShift - generates code for left shifting                 */
6187 /*-----------------------------------------------------------------*/
6188 static void genLeftShift (iCode *ic)
6189 {
6190     operand *left,*right, *result;
6191     int size, offset;
6192     char *l;
6193     symbol *tlbl , *tlbl1;
6194
6195     D(emitcode(";", "genLeftShift "););
6196
6197     right = IC_RIGHT(ic);
6198     left  = IC_LEFT(ic);
6199     result = IC_RESULT(ic);
6200
6201     aopOp(right,ic,FALSE, FALSE);
6202
6203 #if 0
6204     /* if the shift count is known then do it 
6205     as efficiently as possible */
6206     if (AOP_TYPE(right) == AOP_LIT) {
6207         genLeftShiftLiteral (left,right,result,ic);
6208         return ;
6209     }
6210 #endif
6211
6212     /* shift count is unknown then we have to form 
6213     a loop get the loop count in B : Note: we take
6214     only the lower order byte since shifting
6215     more that 32 bits make no sense anyway, ( the
6216     largest size of an object can be only 32 bits ) */  
6217
6218     emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
6219     emitcode("inc","b");
6220     freeAsmop (right,NULL,ic,TRUE);
6221     aopOp(left,ic,FALSE, FALSE);
6222     aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6223
6224     /* now move the left to the result if they are not the
6225     same */
6226     if (!sameRegs(AOP(left),AOP(result)) && 
6227         AOP_SIZE(result) > 1) {
6228
6229         size = AOP_SIZE(result);
6230         offset=0;
6231         _startLazyDPSEvaluation();
6232         while (size--) {
6233             l = aopGet(AOP(left),offset,FALSE,TRUE,FALSE);
6234             if (*l == '@' && (IS_AOP_PREG(result))) {
6235
6236                 emitcode("mov","a,%s",l);
6237                 aopPut(AOP(result),"a",offset);
6238             } else
6239                 aopPut(AOP(result),l,offset);
6240             offset++;
6241         }
6242         _endLazyDPSEvaluation();
6243     }
6244
6245     tlbl = newiTempLabel(NULL);
6246     size = AOP_SIZE(result);
6247     offset = 0 ;   
6248     tlbl1 = newiTempLabel(NULL);
6249
6250     /* if it is only one byte then */
6251     if (size == 1) {
6252         symbol *tlbl1 = newiTempLabel(NULL);
6253
6254         l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
6255         MOVA(l);
6256         emitcode("sjmp","%05d$",tlbl1->key+100); 
6257         emitcode("","%05d$:",tlbl->key+100);
6258         emitcode("add","a,acc");
6259         emitcode("","%05d$:",tlbl1->key+100);
6260         emitcode("djnz","b,%05d$",tlbl->key+100);      
6261         aopPut(AOP(result),"a",0);
6262         goto release ;
6263     }
6264     
6265     reAdjustPreg(AOP(result));    
6266     
6267     emitcode("sjmp","%05d$",tlbl1->key+100); 
6268     emitcode("","%05d$:",tlbl->key+100);    
6269     l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6270     MOVA(l);
6271     emitcode("add","a,acc");         
6272     aopPut(AOP(result),"a",offset++);
6273     _startLazyDPSEvaluation();
6274     while (--size) {
6275         l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6276         MOVA(l);
6277         emitcode("rlc","a");         
6278         aopPut(AOP(result),"a",offset++);
6279     }
6280     _endLazyDPSEvaluation();
6281     reAdjustPreg(AOP(result));
6282
6283     emitcode("","%05d$:",tlbl1->key+100);
6284     emitcode("djnz","b,%05d$",tlbl->key+100);
6285 release:
6286     freeAsmop(left,NULL,ic,TRUE);
6287     freeAsmop(result,NULL,ic,TRUE);
6288 }
6289
6290 #if 0
6291 //REMOVE ME!!!
6292 /*-----------------------------------------------------------------*/
6293 /* genrshOne - right shift a one byte quantity by known count      */
6294 /*-----------------------------------------------------------------*/
6295 static void genrshOne (operand *result, operand *left,
6296                        int shCount, int sign)
6297 {
6298     D(emitcode(";", "genrshOne"););
6299     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
6300 }
6301 #endif
6302
6303 #if 0
6304 //REMOVE ME!!!
6305 /*-----------------------------------------------------------------*/
6306 /* genrshTwo - right shift two bytes by known amount != 0          */
6307 /*-----------------------------------------------------------------*/
6308 static void genrshTwo (operand *result,operand *left,
6309                        int shCount, int sign)
6310 {
6311     D(emitcode(";", "genrshTwo"););
6312
6313     /* if shCount >= 8 */
6314     if (shCount >= 8) {
6315         shCount -= 8 ;
6316         if (shCount)
6317             shiftR1Left2Result(left, MSB16, result, LSB,
6318                                shCount, sign);
6319         else 
6320             movLeft2Result(left, MSB16, result, LSB, sign);
6321         addSign(result, MSB16, sign);
6322     }
6323
6324     /*  1 <= shCount <= 7 */
6325     else
6326         shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
6327 }
6328 #endif
6329
6330 #if 0
6331 //REMOVE ME!!!
6332 /*-----------------------------------------------------------------*/
6333 /* shiftRLong - shift right one long from left to result           */
6334 /* offl = LSB or MSB16                                             */
6335 /*-----------------------------------------------------------------*/
6336 static void shiftRLong (operand *left, int offl,
6337                         operand *result, int sign)
6338 {
6339     if(!sign)
6340         emitcode("clr","c");
6341     MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE,TRUE));
6342     if(sign)
6343         emitcode("mov","c,acc.7");
6344     emitcode("rrc","a");
6345     aopPut(AOP(result),"a",MSB32-offl);
6346     if(offl == MSB16)
6347         /* add sign of "a" */
6348         addSign(result, MSB32, sign);
6349
6350     MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE,TRUE));
6351     emitcode("rrc","a");
6352     aopPut(AOP(result),"a",MSB24-offl);
6353
6354     MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE,TRUE));
6355     emitcode("rrc","a");
6356     aopPut(AOP(result),"a",MSB16-offl);
6357
6358     if(offl == LSB){
6359         MOVA(aopGet(AOP(left),LSB,FALSE,FALSE,TRUE));
6360         emitcode("rrc","a");
6361         aopPut(AOP(result),"a",LSB);
6362     }
6363 }
6364 #endif
6365
6366 #if 0
6367 //REMOVE ME!!!
6368 /*-----------------------------------------------------------------*/
6369 /* genrshFour - shift four byte by a known amount != 0             */
6370 /*-----------------------------------------------------------------*/
6371 static void genrshFour (operand *result, operand *left,
6372                         int shCount, int sign)
6373 {
6374     D(emitcode(";", "genrshFour"););
6375     
6376     /* if shifting more that 3 bytes */
6377     if(shCount >= 24 ) {
6378         shCount -= 24;
6379         if(shCount)
6380             shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
6381         else
6382             movLeft2Result(left, MSB32, result, LSB, sign);
6383         addSign(result, MSB16, sign);
6384     }
6385     else if(shCount >= 16){
6386         shCount -= 16;
6387         if(shCount)
6388             shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
6389         else{
6390             movLeft2Result(left, MSB24, result, LSB, 0);
6391             movLeft2Result(left, MSB32, result, MSB16, sign);
6392         }
6393         addSign(result, MSB24, sign);
6394     }
6395     else if(shCount >= 8){
6396         shCount -= 8;
6397         if(shCount == 1)
6398             shiftRLong(left, MSB16, result, sign);
6399         else if(shCount == 0){
6400             movLeft2Result(left, MSB16, result, LSB, 0);
6401             movLeft2Result(left, MSB24, result, MSB16, 0);
6402             movLeft2Result(left, MSB32, result, MSB24, sign);
6403             addSign(result, MSB32, sign);
6404         }
6405         else{
6406             shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
6407             shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
6408             /* the last shift is signed */
6409             shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
6410             addSign(result, MSB32, sign);
6411         }
6412     }
6413     else{   /* 1 <= shCount <= 7 */
6414         if(shCount <= 2){
6415             shiftRLong(left, LSB, result, sign);
6416             if(shCount == 2)
6417                 shiftRLong(result, LSB, result, sign);
6418         }
6419         else{
6420             shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
6421             shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
6422             shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
6423         }
6424     }
6425 }
6426 #endif
6427
6428 #if 0
6429 //REMOVE ME!!!
6430 /*-----------------------------------------------------------------*/
6431 /* genRightShiftLiteral - right shifting by known count            */
6432 /*-----------------------------------------------------------------*/
6433 static void genRightShiftLiteral (operand *left,
6434                                   operand *right,
6435                                   operand *result,
6436                                   iCode *ic,
6437                                   int sign)
6438 {    
6439     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6440     int size;
6441
6442     D(emitcode(";", "genRightShiftLiteral"););
6443
6444     freeAsmop(right,NULL,ic,TRUE);
6445
6446     aopOp(left,ic,FALSE, FALSE);
6447     aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6448
6449 #if VIEW_SIZE
6450     emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
6451              AOP_SIZE(left));
6452 #endif
6453
6454     size = getDataSize(left);
6455     /* test the LEFT size !!! */
6456
6457     /* I suppose that the left size >= result size */
6458     if(shCount == 0){
6459         size = getDataSize(result);
6460         while(size--)
6461             movLeft2Result(left, size, result, size, 0);
6462     }
6463
6464     else if(shCount >= (size * 8)){
6465         if(sign)
6466             /* get sign in acc.7 */
6467             MOVA(aopGet(AOP(left),size-1,FALSE,FALSE,TRUE));
6468         addSign(result, LSB, sign);
6469     } else{
6470         switch (size) {
6471             case 1:
6472                 genrshOne (result,left,shCount,sign);
6473                 break;
6474
6475             case 2:
6476                 genrshTwo (result,left,shCount,sign);
6477                 break;
6478
6479             case 4:
6480                 genrshFour (result,left,shCount,sign);
6481                 break;
6482             default :
6483                 break;
6484         }
6485
6486         freeAsmop(left,NULL,ic,TRUE);
6487         freeAsmop(result,NULL,ic,TRUE);
6488     }
6489 }
6490 #endif
6491
6492 /*-----------------------------------------------------------------*/
6493 /* genSignedRightShift - right shift of signed number              */
6494 /*-----------------------------------------------------------------*/
6495 static void genSignedRightShift (iCode *ic)
6496 {
6497     operand *right, *left, *result;
6498     int size, offset;
6499     char *l;
6500     symbol *tlbl, *tlbl1 ;
6501
6502     D(emitcode(";", "genSignedRightShift "););
6503
6504     /* we do it the hard way put the shift count in b
6505     and loop thru preserving the sign */
6506
6507     right = IC_RIGHT(ic);
6508     left  = IC_LEFT(ic);
6509     result = IC_RESULT(ic);
6510
6511     aopOp(right,ic,FALSE, FALSE);
6512
6513 #if 0
6514     if ( AOP_TYPE(right) == AOP_LIT) {
6515         genRightShiftLiteral (left,right,result,ic,1);
6516         return ;
6517     }
6518 #endif
6519     /* shift count is unknown then we have to form 
6520        a loop get the loop count in B : Note: we take
6521        only the lower order byte since shifting
6522        more that 32 bits make no sense anyway, ( the
6523        largest size of an object can be only 32 bits ) */  
6524
6525     emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
6526     emitcode("inc","b");
6527     freeAsmop (right,NULL,ic,TRUE);
6528     aopOp(left,ic,FALSE, FALSE);
6529     aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6530
6531     /* now move the left to the result if they are not the
6532     same */
6533     if (!sameRegs(AOP(left),AOP(result)) && 
6534         AOP_SIZE(result) > 1) {
6535
6536         size = AOP_SIZE(result);
6537         offset=0;
6538         _startLazyDPSEvaluation();
6539         while (size--) {
6540             l = aopGet(AOP(left),offset,FALSE,TRUE,FALSE);
6541             if (*l == '@' && IS_AOP_PREG(result)) {
6542
6543                 emitcode("mov","a,%s",l);
6544                 aopPut(AOP(result),"a",offset);
6545             } else
6546                 aopPut(AOP(result),l,offset);
6547             offset++;
6548         }
6549         _endLazyDPSEvaluation();
6550     }
6551
6552     /* mov the highest order bit to OVR */    
6553     tlbl = newiTempLabel(NULL);
6554     tlbl1= newiTempLabel(NULL);
6555
6556     size = AOP_SIZE(result);
6557     offset = size - 1;
6558     emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
6559     emitcode("rlc","a");
6560     emitcode("mov","ov,c");
6561     /* if it is only one byte then */
6562     if (size == 1) {
6563         l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
6564         MOVA(l);
6565         emitcode("sjmp","%05d$",tlbl1->key+100);
6566         emitcode("","%05d$:",tlbl->key+100);
6567         emitcode("mov","c,ov");
6568         emitcode("rrc","a");
6569         emitcode("","%05d$:",tlbl1->key+100);
6570         emitcode("djnz","b,%05d$",tlbl->key+100);
6571         aopPut(AOP(result),"a",0);
6572         goto release ;
6573     }
6574
6575     reAdjustPreg(AOP(result));
6576     emitcode("sjmp","%05d$",tlbl1->key+100);
6577     emitcode("","%05d$:",tlbl->key+100);    
6578     emitcode("mov","c,ov");
6579     _startLazyDPSEvaluation();
6580     while (size--) {
6581         l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6582         MOVA(l);
6583         emitcode("rrc","a");         
6584         aopPut(AOP(result),"a",offset--);
6585     }
6586     _endLazyDPSEvaluation();
6587     reAdjustPreg(AOP(result));
6588     emitcode("","%05d$:",tlbl1->key+100);
6589     emitcode("djnz","b,%05d$",tlbl->key+100);
6590
6591 release:
6592     freeAsmop(left,NULL,ic,TRUE);
6593     freeAsmop(result,NULL,ic,TRUE);
6594 }
6595
6596 /*-----------------------------------------------------------------*/
6597 /* genRightShift - generate code for right shifting                */
6598 /*-----------------------------------------------------------------*/
6599 static void genRightShift (iCode *ic)
6600 {
6601     operand *right, *left, *result;
6602     sym_link *retype ;
6603     int size, offset;
6604     char *l;
6605     symbol *tlbl, *tlbl1 ;
6606
6607     D(emitcode(";", "genRightShift "););
6608
6609     /* if signed then we do it the hard way preserve the
6610     sign bit moving it inwards */
6611     retype = getSpec(operandType(IC_RESULT(ic)));
6612
6613     if (!SPEC_USIGN(retype)) {
6614         genSignedRightShift (ic);
6615         return ;
6616     }
6617
6618     /* signed & unsigned types are treated the same : i.e. the
6619     signed is NOT propagated inwards : quoting from the
6620     ANSI - standard : "for E1 >> E2, is equivalent to division
6621     by 2**E2 if unsigned or if it has a non-negative value,
6622     otherwise the result is implementation defined ", MY definition
6623     is that the sign does not get propagated */
6624
6625     right = IC_RIGHT(ic);
6626     left  = IC_LEFT(ic);
6627     result = IC_RESULT(ic);
6628
6629     aopOp(right,ic,FALSE, FALSE);
6630
6631 #if 0
6632     /* if the shift count is known then do it 
6633     as efficiently as possible */
6634     if (AOP_TYPE(right) == AOP_LIT) {
6635         genRightShiftLiteral (left,right,result,ic, 0);
6636         return ;
6637     }
6638 #endif
6639
6640     /* shift count is unknown then we have to form 
6641     a loop get the loop count in B : Note: we take
6642     only the lower order byte since shifting
6643     more that 32 bits make no sense anyway, ( the
6644     largest size of an object can be only 32 bits ) */  
6645
6646     emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
6647     emitcode("inc","b");
6648     freeAsmop (right,NULL,ic,TRUE);
6649     aopOp(left,ic,FALSE, FALSE);
6650     aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6651
6652     /* now move the left to the result if they are not the
6653     same */
6654     if (!sameRegs(AOP(left),AOP(result)) && 
6655         AOP_SIZE(result) > 1) {
6656
6657         size = AOP_SIZE(result);
6658         offset=0;
6659         _startLazyDPSEvaluation();
6660         while (size--) {
6661             l = aopGet(AOP(left),offset,FALSE,TRUE,FALSE);
6662             if (*l == '@' && IS_AOP_PREG(result)) {
6663
6664                 emitcode("mov","a,%s",l);
6665                 aopPut(AOP(result),"a",offset);
6666             } else
6667                 aopPut(AOP(result),l,offset);
6668             offset++;
6669         }
6670         _endLazyDPSEvaluation();
6671     }
6672
6673     tlbl = newiTempLabel(NULL);
6674     tlbl1= newiTempLabel(NULL);
6675     size = AOP_SIZE(result);
6676     offset = size - 1;
6677
6678     /* if it is only one byte then */
6679     if (size == 1) {
6680         l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
6681         MOVA(l);
6682         emitcode("sjmp","%05d$",tlbl1->key+100);
6683         emitcode("","%05d$:",tlbl->key+100);
6684         CLRC;
6685         emitcode("rrc","a");
6686         emitcode("","%05d$:",tlbl1->key+100);
6687         emitcode("djnz","b,%05d$",tlbl->key+100);
6688         aopPut(AOP(result),"a",0);
6689         goto release ;
6690     }
6691
6692     reAdjustPreg(AOP(result));
6693     emitcode("sjmp","%05d$",tlbl1->key+100);
6694     emitcode("","%05d$:",tlbl->key+100);    
6695     CLRC;
6696     _startLazyDPSEvaluation();
6697     while (size--) {
6698         l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6699         MOVA(l);
6700         emitcode("rrc","a");         
6701         aopPut(AOP(result),"a",offset--);
6702     }
6703     _endLazyDPSEvaluation();
6704     reAdjustPreg(AOP(result));
6705
6706     emitcode("","%05d$:",tlbl1->key+100);
6707     emitcode("djnz","b,%05d$",tlbl->key+100);
6708
6709 release:
6710     freeAsmop(left,NULL,ic,TRUE);
6711     freeAsmop(result,NULL,ic,TRUE);
6712 }
6713
6714 /*-----------------------------------------------------------------*/
6715 /* genUnpackBits - generates code for unpacking bits               */
6716 /*-----------------------------------------------------------------*/
6717 static void genUnpackBits (operand *result, char *rname, int ptype)
6718 {    
6719     int shCnt ;
6720     int rlen = 0 ;
6721     sym_link *etype;
6722     int offset = 0 ;
6723
6724     D(emitcode(";", "genUnpackBits "););
6725
6726     etype = getSpec(operandType(result));
6727
6728     /* read the first byte  */
6729     switch (ptype) {
6730
6731     case POINTER:
6732     case IPOINTER:
6733         emitcode("mov","a,@%s",rname);
6734         break;
6735         
6736     case PPOINTER:
6737         emitcode("movx","a,@%s",rname);
6738         break;
6739         
6740     case FPOINTER:
6741         emitcode("movx","a,@dptr");
6742         break;
6743
6744     case CPOINTER:
6745         emitcode("clr","a");
6746         emitcode("movc","a","@a+dptr");
6747         break;
6748
6749     case GPOINTER:
6750         emitcode("lcall","__gptrget");
6751         break;
6752     }
6753
6754     /* if we have bitdisplacement then it fits   */
6755     /* into this byte completely or if length is */
6756     /* less than a byte                          */
6757     if ((shCnt = SPEC_BSTR(etype)) || 
6758         (SPEC_BLEN(etype) <= 8))  {
6759
6760         /* shift right acc */
6761         AccRsh(shCnt);
6762
6763         emitcode("anl","a,#0x%02x",
6764                  ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
6765         aopPut(AOP(result),"a",offset);
6766         return ;
6767     }
6768
6769     /* bit field did not fit in a byte  */
6770     rlen = SPEC_BLEN(etype) - 8;
6771     aopPut(AOP(result),"a",offset++);
6772
6773     while (1)  {
6774
6775         switch (ptype) {
6776         case POINTER:
6777         case IPOINTER:
6778             emitcode("inc","%s",rname);
6779             emitcode("mov","a,@%s",rname);
6780             break;
6781             
6782         case PPOINTER:
6783             emitcode("inc","%s",rname);
6784             emitcode("movx","a,@%s",rname);
6785             break;
6786
6787         case FPOINTER:
6788             emitcode("inc","dptr");
6789             emitcode("movx","a,@dptr");
6790             break;
6791             
6792         case CPOINTER:
6793             emitcode("clr","a");
6794             emitcode("inc","dptr");
6795             emitcode("movc","a","@a+dptr");
6796             break;
6797             
6798         case GPOINTER:
6799             emitcode("inc","dptr");
6800             emitcode("lcall","__gptrget");
6801             break;
6802         }
6803
6804         rlen -= 8;            
6805         /* if we are done */
6806         if ( rlen < 8 )
6807             break ;
6808         
6809         aopPut(AOP(result),"a",offset++);
6810                               
6811     }
6812     
6813     if (rlen) {
6814         emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(rlen));
6815         aopPut(AOP(result),"a",offset);        
6816     }
6817     
6818     return ;
6819 }
6820
6821
6822 /*-----------------------------------------------------------------*/
6823 /* genDataPointerGet - generates code when ptr offset is known     */
6824 /*-----------------------------------------------------------------*/
6825 static void genDataPointerGet (operand *left, 
6826                                operand *result, 
6827                                iCode *ic)
6828 {
6829     char *l;
6830     char buffer[256];
6831     int size , offset = 0;
6832     aopOp(result,ic,TRUE, FALSE);
6833
6834     /* get the string representation of the name */
6835     l = aopGet(AOP(left),0,FALSE,TRUE,FALSE);
6836     size = AOP_SIZE(result);
6837     _startLazyDPSEvaluation();
6838     while (size--) {
6839         if (offset)
6840             sprintf(buffer,"(%s + %d)",l+1,offset);
6841         else
6842             sprintf(buffer,"%s",l+1);
6843         aopPut(AOP(result),buffer,offset++);
6844     }
6845     _endLazyDPSEvaluation();
6846
6847     freeAsmop(left,NULL,ic,TRUE);
6848     freeAsmop(result,NULL,ic,TRUE);
6849 }
6850
6851 /*-----------------------------------------------------------------*/
6852 /* genNearPointerGet - emitcode for near pointer fetch             */
6853 /*-----------------------------------------------------------------*/
6854 static void genNearPointerGet (operand *left, 
6855                                operand *result, 
6856                                iCode *ic)
6857 {
6858     asmop *aop = NULL;
6859     regs *preg = NULL ;
6860     char *rname ;
6861     sym_link *rtype, *retype, *letype;
6862     sym_link *ltype = operandType(left);    
6863     char buffer[80];
6864
6865     rtype = operandType(result);
6866     retype= getSpec(rtype);
6867     letype= getSpec(ltype);
6868
6869     aopOp(left,ic,FALSE, FALSE);
6870     
6871     /* if left is rematerialisable and
6872        result is not bit variable type and
6873        the left is pointer to data space i.e
6874        lower 128 bytes of space */
6875     if (AOP_TYPE(left) == AOP_IMMD &&
6876         !IS_BITVAR(retype)         &&
6877         !IS_BITVAR(letype)         &&
6878         DCL_TYPE(ltype) == POINTER) {
6879         genDataPointerGet (left,result,ic);
6880         return ;
6881     }
6882     
6883         /* if the value is already in a pointer register
6884        then don't need anything more */
6885     if (!AOP_INPREG(AOP(left))) {
6886         /* otherwise get a free pointer register */
6887         aop = newAsmop(0);
6888         preg = getFreePtr(ic,&aop,FALSE);
6889         emitcode("mov","%s,%s",
6890                 preg->name,
6891                 aopGet(AOP(left),0,FALSE,TRUE,FALSE));
6892         rname = preg->name ;
6893     } else
6894         rname = aopGet(AOP(left),0,FALSE,FALSE,FALSE);
6895     
6896     freeAsmop(left,NULL,ic,TRUE);
6897     aopOp (result,ic,FALSE, FALSE);
6898     
6899       /* if bitfield then unpack the bits */
6900     if (IS_BITVAR(retype) || IS_BITVAR(letype)) 
6901         genUnpackBits (result,rname,POINTER);
6902     else {
6903         /* we have can just get the values */
6904         int size = AOP_SIZE(result);
6905         int offset = 0 ;        
6906         
6907         while (size--) {
6908             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
6909
6910                 emitcode("mov","a,@%s",rname);
6911                 aopPut(AOP(result),"a",offset);
6912             } else {
6913                 sprintf(buffer,"@%s",rname);
6914                 aopPut(AOP(result),buffer,offset);
6915             }
6916             offset++ ;
6917             if (size)
6918                 emitcode("inc","%s",rname);
6919         }
6920     }
6921
6922     /* now some housekeeping stuff */
6923     if (aop) {
6924         /* we had to allocate for this iCode */
6925         freeAsmop(NULL,aop,ic,TRUE);
6926     } else { 
6927         /* we did not allocate which means left
6928            already in a pointer register, then
6929            if size > 0 && this could be used again
6930            we have to point it back to where it 
6931            belongs */
6932         if (AOP_SIZE(result) > 1 &&
6933             !OP_SYMBOL(left)->remat &&
6934             ( OP_SYMBOL(left)->liveTo > ic->seq ||
6935               ic->depth )) {
6936             int size = AOP_SIZE(result) - 1;
6937             while (size--)
6938                 emitcode("dec","%s",rname);
6939         }
6940     }
6941
6942     /* done */
6943     freeAsmop(result,NULL,ic,TRUE);
6944      
6945 }
6946
6947 /*-----------------------------------------------------------------*/
6948 /* genPagedPointerGet - emitcode for paged pointer fetch           */
6949 /*-----------------------------------------------------------------*/
6950 static void genPagedPointerGet (operand *left, 
6951                                operand *result, 
6952                                iCode *ic)
6953 {
6954     asmop *aop = NULL;
6955     regs *preg = NULL ;
6956     char *rname;
6957     sym_link *rtype, *retype, *letype;    
6958
6959     rtype = operandType(result);
6960     retype= getSpec(rtype);
6961     letype= getSpec(operandType(left));
6962     aopOp(left,ic,FALSE, FALSE);
6963
6964   /* if the value is already in a pointer register
6965        then don't need anything more */
6966     if (!AOP_INPREG(AOP(left))) {
6967         /* otherwise get a free pointer register */
6968         aop = newAsmop(0);
6969         preg = getFreePtr(ic,&aop,FALSE);
6970         emitcode("mov","%s,%s",
6971                 preg->name,
6972                 aopGet(AOP(left),0,FALSE,TRUE,FALSE));
6973         rname = preg->name ;
6974     } else
6975         rname = aopGet(AOP(left),0,FALSE,FALSE,FALSE);
6976     
6977     freeAsmop(left,NULL,ic,TRUE);
6978     aopOp (result,ic,FALSE, FALSE);
6979
6980     /* if bitfield then unpack the bits */
6981     if (IS_BITVAR(retype) || IS_BITVAR(letype)) 
6982         genUnpackBits (result,rname,PPOINTER);
6983     else {
6984         /* we have can just get the values */
6985         int size = AOP_SIZE(result);
6986         int offset = 0 ;        
6987         
6988         while (size--) {
6989             
6990             emitcode("movx","a,@%s",rname);
6991             aopPut(AOP(result),"a",offset);
6992             
6993             offset++ ;
6994             
6995             if (size)
6996                 emitcode("inc","%s",rname);
6997         }
6998     }
6999
7000     /* now some housekeeping stuff */
7001     if (aop) {
7002         /* we had to allocate for this iCode */
7003         freeAsmop(NULL,aop,ic,TRUE);
7004     } else { 
7005         /* we did not allocate which means left
7006            already in a pointer register, then
7007            if size > 0 && this could be used again
7008            we have to point it back to where it 
7009            belongs */
7010         if (AOP_SIZE(result) > 1 &&
7011             !OP_SYMBOL(left)->remat &&
7012             ( OP_SYMBOL(left)->liveTo > ic->seq ||
7013               ic->depth )) {
7014             int size = AOP_SIZE(result) - 1;
7015             while (size--)
7016                 emitcode("dec","%s",rname);
7017         }
7018     }
7019
7020     /* done */
7021     freeAsmop(result,NULL,ic,TRUE);
7022     
7023         
7024 }
7025
7026 /*-----------------------------------------------------------------*/
7027 /* genFarPointerGet - gget value from far space                    */
7028 /*-----------------------------------------------------------------*/
7029 static void genFarPointerGet (operand *left,
7030                               operand *result, iCode *ic)
7031 {
7032     int size, offset ;
7033     sym_link *retype = getSpec(operandType(result));
7034     sym_link *letype = getSpec(operandType(left));
7035     D(emitcode(";", "genFarPointerGet"););
7036
7037     aopOp(left,ic,FALSE, FALSE);
7038
7039     /* if the operand is already in dptr 
7040     then we do nothing else we move the value to dptr */
7041     if (AOP_TYPE(left) != AOP_STR) {
7042         /* if this is remateriazable */
7043         if (AOP_TYPE(left) == AOP_IMMD)
7044         {
7045             emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE,FALSE));
7046         }
7047         else 
7048         { 
7049             /* we need to get it byte by byte */
7050             _startLazyDPSEvaluation();
7051             if (AOP_TYPE(left) != AOP_DPTR)
7052             {
7053                 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
7054                 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
7055                 emitcode("mov","dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
7056             }
7057             else
7058             {
7059                  /* We need to generate a load to DPTR indirect through DPTR. */
7060                  D(emitcode(";", "genFarPointerGet -- indirection special case."););
7061                  emitcode("push", "%s", aopGet(AOP(left),0,FALSE,TRUE,TRUE));
7062                  emitcode("push", "%s", aopGet(AOP(left),1,FALSE,TRUE,TRUE));
7063                  emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
7064                  emitcode("pop", "dph");
7065                  emitcode("pop", "dpl");
7066             }
7067             _endLazyDPSEvaluation();
7068         }
7069     }
7070     /* so dptr know contains the address */
7071     freeAsmop(left,NULL,ic,TRUE);
7072     aopOp(result,ic,FALSE, TRUE);
7073
7074     /* if bit then unpack */
7075     if (IS_BITVAR(retype) || IS_BITVAR(letype)) 
7076         genUnpackBits(result,"dptr",FPOINTER);
7077     else {
7078         size = AOP_SIZE(result);
7079         offset = 0 ;
7080
7081         _startLazyDPSEvaluation();
7082         while (size--) {
7083             
7084             genSetDPTR(0);
7085             _flushLazyDPS();
7086             
7087             emitcode("movx","a,@dptr");
7088             if (size)
7089                 emitcode("inc","dptr");     
7090
7091             aopPut(AOP(result),"a",offset++);
7092         }
7093         _endLazyDPSEvaluation();
7094     }
7095
7096     freeAsmop(result,NULL,ic,TRUE);
7097 }
7098
7099 /*-----------------------------------------------------------------*/
7100 /* emitcodePointerGet - gget value from code space                  */
7101 /*-----------------------------------------------------------------*/
7102 static void emitcodePointerGet (operand *left,
7103                                 operand *result, iCode *ic)
7104 {
7105     int size, offset ;
7106     sym_link *retype = getSpec(operandType(result));
7107
7108     aopOp(left,ic,FALSE, FALSE);
7109
7110     /* if the operand is already in dptr 
7111     then we do nothing else we move the value to dptr */
7112     if (AOP_TYPE(left) != AOP_STR) {
7113         /* if this is remateriazable */
7114         if (AOP_TYPE(left) == AOP_IMMD)
7115         {
7116             emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE,FALSE));
7117         }
7118         else
7119         { /* we need to get it byte by byte */
7120             _startLazyDPSEvaluation();
7121             if (AOP_TYPE(left) != AOP_DPTR)
7122             {
7123                 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
7124                 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
7125                 emitcode("mov","dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
7126             }
7127             else
7128             {
7129                  /* We need to generate a load to DPTR indirect through DPTR. */
7130                  D(emitcode(";", "gencodePointerGet -- indirection special case."););
7131                  emitcode("push", "%s", aopGet(AOP(left),0,FALSE,TRUE,TRUE));
7132                  emitcode("push", "%s", aopGet(AOP(left),1,FALSE,TRUE,TRUE));
7133                  emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
7134                  emitcode("pop", "dph");
7135                  emitcode("pop", "dpl");
7136             }      
7137             _endLazyDPSEvaluation();        
7138         }
7139     }
7140     /* so dptr know contains the address */
7141     freeAsmop(left,NULL,ic,TRUE);
7142     aopOp(result,ic,FALSE, TRUE);
7143
7144     /* if bit then unpack */
7145     if (IS_BITVAR(retype)) 
7146         genUnpackBits(result,"dptr",CPOINTER);
7147     else {
7148         size = AOP_SIZE(result);
7149         offset = 0 ;
7150
7151         _startLazyDPSEvaluation();
7152         while (size--) 
7153         {
7154             genSetDPTR(0);
7155             _flushLazyDPS();
7156                               
7157             emitcode("clr","a");
7158             emitcode("movc","a,@a+dptr");
7159             if (size)
7160                 emitcode("inc","dptr");            
7161             aopPut(AOP(result),"a",offset++);
7162         }
7163         _endLazyDPSEvaluation();
7164     }
7165
7166     freeAsmop(result,NULL,ic,TRUE);
7167 }
7168
7169 /*-----------------------------------------------------------------*/
7170 /* genGenPointerGet - gget value from generic pointer space        */
7171 /*-----------------------------------------------------------------*/
7172 static void genGenPointerGet (operand *left,
7173                               operand *result, iCode *ic)
7174 {
7175     int size, offset ;
7176     sym_link *retype = getSpec(operandType(result));
7177     sym_link *letype = getSpec(operandType(left));
7178
7179     aopOp(left,ic,FALSE, TRUE);
7180
7181     /* if the operand is already in dptr 
7182     then we do nothing else we move the value to dptr */
7183     if (AOP_TYPE(left) != AOP_STR) {
7184         /* if this is remateriazable */
7185         if (AOP_TYPE(left) == AOP_IMMD) {
7186             emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE,FALSE));
7187             emitcode("mov","b,#%d",pointerCode(retype));
7188         }
7189         else { /* we need to get it byte by byte */
7190             _startLazyDPSEvaluation();
7191             emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
7192             emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
7193             emitcode("mov","dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
7194             emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE,TRUE));
7195             _endLazyDPSEvaluation();
7196         }
7197     }
7198     /* so dptr know contains the address */
7199     freeAsmop(left,NULL,ic,TRUE);
7200     aopOp(result,ic,FALSE, TRUE);
7201
7202     /* if bit then unpack */
7203     if (IS_BITVAR(retype) || IS_BITVAR(letype)) 
7204         genUnpackBits(result,"dptr",GPOINTER);
7205     else {
7206         size = AOP_SIZE(result);
7207         offset = 0 ;
7208
7209         while (size--) {
7210             emitcode("lcall","__gptrget");
7211             aopPut(AOP(result),"a",offset++);
7212             if (size)
7213                 emitcode("inc","dptr");
7214         }
7215     }
7216
7217     freeAsmop(result,NULL,ic,TRUE);
7218 }
7219
7220 /*-----------------------------------------------------------------*/
7221 /* genPointerGet - generate code for pointer get                   */
7222 /*-----------------------------------------------------------------*/
7223 static void genPointerGet (iCode *ic)
7224 {
7225     operand *left, *result ;
7226     sym_link *type, *etype;
7227     int p_type;
7228
7229     D(emitcode(";", "genPointerGet "););
7230
7231     left = IC_LEFT(ic);
7232     result = IC_RESULT(ic) ;
7233
7234     /* depending on the type of pointer we need to
7235     move it to the correct pointer register */
7236     type = operandType(left);
7237     etype = getSpec(type);
7238     /* if left is of type of pointer then it is simple */
7239     if (IS_PTR(type) && !IS_FUNC(type->next)) 
7240         p_type = DCL_TYPE(type);
7241     else {
7242         /* we have to go by the storage class */
7243         p_type = PTR_TYPE(SPEC_OCLS(etype));
7244     }
7245
7246     /* now that we have the pointer type we assign
7247     the pointer values */
7248     switch (p_type) {
7249
7250     case POINTER:       
7251     case IPOINTER:
7252         genNearPointerGet (left,result,ic);
7253         break;
7254
7255     case PPOINTER:
7256         genPagedPointerGet(left,result,ic);
7257         break;
7258
7259     case FPOINTER:
7260         genFarPointerGet (left,result,ic);
7261         break;
7262
7263     case CPOINTER:
7264         emitcodePointerGet (left,result,ic);
7265         break;
7266
7267     case GPOINTER:
7268         genGenPointerGet (left,result,ic);
7269         break;
7270     }
7271
7272 }
7273
7274 /*-----------------------------------------------------------------*/
7275 /* genPackBits - generates code for packed bit storage             */
7276 /*-----------------------------------------------------------------*/
7277 static void genPackBits (sym_link    *etype ,
7278                          operand *right ,
7279                          char *rname, int p_type)
7280 {
7281     int shCount = 0 ;
7282     int offset = 0  ;
7283     int rLen = 0 ;
7284     int blen, bstr ;   
7285     char *l ;
7286
7287     blen = SPEC_BLEN(etype);
7288     bstr = SPEC_BSTR(etype);
7289
7290     l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7291     MOVA(l);   
7292
7293     /* if the bit lenth is less than or    */
7294     /* it exactly fits a byte then         */
7295     if (SPEC_BLEN(etype) <= 8 )  {
7296         shCount = SPEC_BSTR(etype) ;
7297
7298         /* shift left acc */
7299         AccLsh(shCount);
7300
7301         if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
7302
7303
7304             switch (p_type) {
7305                 case POINTER:
7306                     emitcode ("mov","b,a");
7307                     emitcode("mov","a,@%s",rname);
7308                     break;
7309
7310                 case FPOINTER:
7311                     emitcode ("mov","b,a");
7312                     emitcode("movx","a,@dptr");
7313                     break;
7314
7315                 case GPOINTER:
7316                     emitcode ("push","b");
7317                     emitcode ("push","acc");
7318                     emitcode ("lcall","__gptrget");
7319                     emitcode ("pop","b");
7320                     break;
7321             }
7322
7323             emitcode ("anl","a,#0x%02x",(unsigned char)
7324                       ((unsigned char)(0xFF << (blen+bstr)) | 
7325                        (unsigned char)(0xFF >> (8-bstr)) ) );
7326             emitcode ("orl","a,b");
7327             if (p_type == GPOINTER)
7328                 emitcode("pop","b");
7329         }
7330     }
7331
7332     switch (p_type) {
7333         case POINTER:
7334             emitcode("mov","@%s,a",rname);
7335             break;
7336
7337         case FPOINTER:
7338             emitcode("movx","@dptr,a");
7339             break;
7340
7341         case GPOINTER:
7342             emitcode("lcall","__gptrput");
7343             break;
7344     }
7345
7346     /* if we r done */
7347     if ( SPEC_BLEN(etype) <= 8 )
7348         return ;
7349
7350     emitcode("inc","%s",rname);
7351     rLen = SPEC_BLEN(etype) ;     
7352
7353     /* now generate for lengths greater than one byte */
7354     while (1) {
7355
7356         l = aopGet(AOP(right),offset++,FALSE,TRUE,FALSE);
7357
7358         rLen -= 8 ;
7359         if (rLen < 8 )
7360             break ;
7361
7362         switch (p_type) {
7363             case POINTER:
7364                 if (*l == '@') {
7365                     MOVA(l);
7366                     emitcode("mov","@%s,a",rname);
7367                 } else
7368                     emitcode("mov","@%s,%s",rname,l);
7369                 break;
7370
7371             case FPOINTER:
7372                 MOVA(l);
7373                 emitcode("movx","@dptr,a");
7374                 break;
7375
7376             case GPOINTER:
7377                 MOVA(l);
7378                 emitcode("lcall","__gptrput");
7379                 break;  
7380         }   
7381         emitcode ("inc","%s",rname);
7382     }
7383
7384     MOVA(l);
7385
7386     /* last last was not complete */
7387     if (rLen)   {
7388         /* save the byte & read byte */
7389         switch (p_type) {
7390             case POINTER:
7391                 emitcode ("mov","b,a");
7392                 emitcode("mov","a,@%s",rname);
7393                 break;
7394
7395             case FPOINTER:
7396                 emitcode ("mov","b,a");
7397                 emitcode("movx","a,@dptr");
7398                 break;
7399
7400             case GPOINTER:
7401                 emitcode ("push","b");
7402                 emitcode ("push","acc");
7403                 emitcode ("lcall","__gptrget");
7404                 emitcode ("pop","b");
7405                 break;
7406         }
7407
7408         emitcode ("anl","a,#0x%02x",((unsigned char)-1 << rLen) );
7409         emitcode ("orl","a,b");
7410     }
7411
7412     if (p_type == GPOINTER)
7413         emitcode("pop","b");
7414
7415     switch (p_type) {
7416
7417     case POINTER:
7418         emitcode("mov","@%s,a",rname);
7419         break;
7420         
7421     case FPOINTER:
7422         emitcode("movx","@dptr,a");
7423         break;
7424         
7425     case GPOINTER:
7426         emitcode("lcall","__gptrput");
7427         break;                  
7428     }
7429 }
7430 /*-----------------------------------------------------------------*/
7431 /* genDataPointerSet - remat pointer to data space                 */
7432 /*-----------------------------------------------------------------*/
7433 static void genDataPointerSet(operand *right,
7434                               operand *result,
7435                               iCode *ic)
7436 {
7437     int size, offset = 0 ;
7438     char *l, buffer[256];
7439
7440     aopOp(right,ic,FALSE, FALSE);
7441     
7442     l = aopGet(AOP(result),0,FALSE,TRUE,FALSE);
7443     size = AOP_SIZE(right);
7444     while (size--) {
7445         if (offset)
7446             sprintf(buffer,"(%s + %d)",l+1,offset);
7447         else
7448             sprintf(buffer,"%s",l+1);
7449         emitcode("mov","%s,%s",buffer,
7450                  aopGet(AOP(right),offset++,FALSE,FALSE,FALSE));
7451     }
7452
7453     freeAsmop(right,NULL,ic,TRUE);
7454     freeAsmop(result,NULL,ic,TRUE);
7455 }
7456
7457 /*-----------------------------------------------------------------*/
7458 /* genNearPointerSet - emitcode for near pointer put                */
7459 /*-----------------------------------------------------------------*/
7460 static void genNearPointerSet (operand *right,
7461                                operand *result, 
7462                                iCode *ic)
7463 {
7464     asmop *aop = NULL;
7465     regs *preg = NULL ;
7466     char *rname , *l;
7467     sym_link *retype, *letype;
7468     sym_link *ptype = operandType(result);
7469     
7470     retype= getSpec(operandType(right));
7471     letype= getSpec(ptype);
7472
7473     aopOp(result,ic,FALSE, FALSE);
7474     
7475     /* if the result is rematerializable &
7476        in data space & not a bit variable */
7477     if (AOP_TYPE(result) == AOP_IMMD &&
7478         DCL_TYPE(ptype) == POINTER   &&
7479         !IS_BITVAR(retype) &&
7480         !IS_BITVAR(letype)) {
7481         genDataPointerSet (right,result,ic);
7482         return;
7483     }
7484
7485     /* if the value is already in a pointer register
7486     then don't need anything more */
7487     if (!AOP_INPREG(AOP(result))) {
7488         /* otherwise get a free pointer register */
7489         aop = newAsmop(0);
7490         preg = getFreePtr(ic,&aop,FALSE);
7491         emitcode("mov","%s,%s",
7492                  preg->name,
7493                  aopGet(AOP(result),0,FALSE,TRUE,FALSE));
7494         rname = preg->name ;
7495     } else
7496         rname = aopGet(AOP(result),0,FALSE,FALSE,FALSE);
7497
7498     freeAsmop(result,NULL,ic,TRUE);
7499     aopOp (right,ic,FALSE, FALSE);
7500
7501     /* if bitfield then unpack the bits */
7502     if (IS_BITVAR(retype) || IS_BITVAR(letype)) 
7503         genPackBits ((IS_BITVAR(retype) ? retype : letype),right,rname,POINTER);
7504     else {
7505         /* we have can just get the values */
7506         int size = AOP_SIZE(right);
7507         int offset = 0 ;    
7508
7509         while (size--) {
7510             l = aopGet(AOP(right),offset,FALSE,TRUE,FALSE);
7511             if (*l == '@' ) {
7512                 MOVA(l);
7513                 emitcode("mov","@%s,a",rname);
7514             } else
7515                 emitcode("mov","@%s,%s",rname,l);
7516             if (size)
7517                 emitcode("inc","%s",rname);
7518             offset++;
7519         }
7520     }
7521
7522     /* now some housekeeping stuff */
7523     if (aop) {
7524         /* we had to allocate for this iCode */
7525         freeAsmop(NULL,aop,ic,TRUE);
7526     } else { 
7527         /* we did not allocate which means left
7528         already in a pointer register, then
7529         if size > 0 && this could be used again
7530         we have to point it back to where it 
7531         belongs */
7532         if (AOP_SIZE(right) > 1 &&
7533             !OP_SYMBOL(result)->remat &&
7534             ( OP_SYMBOL(result)->liveTo > ic->seq ||
7535               ic->depth )) {
7536             int size = AOP_SIZE(right) - 1;
7537             while (size--)
7538                 emitcode("dec","%s",rname);
7539         }
7540     }
7541
7542     /* done */
7543     freeAsmop(right,NULL,ic,TRUE);
7544
7545
7546 }
7547
7548 /*-----------------------------------------------------------------*/
7549 /* genPagedPointerSet - emitcode for Paged pointer put             */
7550 /*-----------------------------------------------------------------*/
7551 static void genPagedPointerSet (operand *right,
7552                                operand *result, 
7553                                iCode *ic)
7554 {
7555     asmop *aop = NULL;
7556     regs *preg = NULL ;
7557     char *rname , *l;
7558     sym_link *retype, *letype;
7559        
7560     retype= getSpec(operandType(right));
7561     letype= getSpec(operandType(result));
7562     
7563     aopOp(result,ic,FALSE, FALSE);
7564     
7565     /* if the value is already in a pointer register
7566        then don't need anything more */
7567     if (!AOP_INPREG(AOP(result))) {
7568         /* otherwise get a free pointer register */
7569         aop = newAsmop(0);
7570         preg = getFreePtr(ic,&aop,FALSE);
7571         emitcode("mov","%s,%s",
7572                 preg->name,
7573                 aopGet(AOP(result),0,FALSE,TRUE,FALSE));
7574         rname = preg->name ;
7575     } else
7576         rname = aopGet(AOP(result),0,FALSE,FALSE,FALSE);
7577     
7578     freeAsmop(result,NULL,ic,TRUE);
7579     aopOp (right,ic,FALSE, FALSE);
7580
7581     /* if bitfield then unpack the bits */
7582     if (IS_BITVAR(retype) || IS_BITVAR(letype)) 
7583         genPackBits ((IS_BITVAR(retype) ? retype : letype) ,right,rname,PPOINTER);
7584     else {
7585         /* we have can just get the values */
7586         int size = AOP_SIZE(right);
7587         int offset = 0 ;        
7588         
7589         while (size--) {
7590             l = aopGet(AOP(right),offset,FALSE,TRUE,TRUE);
7591             
7592             MOVA(l);
7593             emitcode("movx","@%s,a",rname);
7594
7595             if (size)
7596                 emitcode("inc","%s",rname);
7597
7598             offset++;
7599         }
7600     }
7601     
7602     /* now some housekeeping stuff */
7603     if (aop) {
7604         /* we had to allocate for this iCode */
7605         freeAsmop(NULL,aop,ic,TRUE);
7606     } else { 
7607         /* we did not allocate which means left
7608            already in a pointer register, then
7609            if size > 0 && this could be used again
7610            we have to point it back to where it 
7611            belongs */
7612         if (AOP_SIZE(right) > 1 &&
7613             !OP_SYMBOL(result)->remat &&
7614             ( OP_SYMBOL(result)->liveTo > ic->seq ||
7615               ic->depth )) {
7616             int size = AOP_SIZE(right) - 1;
7617             while (size--)
7618                 emitcode("dec","%s",rname);
7619         }
7620     }
7621
7622     /* done */
7623     freeAsmop(right,NULL,ic,TRUE);
7624     
7625         
7626 }
7627
7628 /*-----------------------------------------------------------------*/
7629 /* genFarPointerSet - set value from far space                     */
7630 /*-----------------------------------------------------------------*/
7631 static void genFarPointerSet (operand *right,
7632                               operand *result, iCode *ic)
7633 {
7634     int size, offset ;
7635     sym_link *retype = getSpec(operandType(right));
7636     sym_link *letype = getSpec(operandType(result));
7637
7638     aopOp(result,ic,FALSE, FALSE);
7639
7640     /* if the operand is already in dptr 
7641     then we do nothing else we move the value to dptr */
7642     if (AOP_TYPE(result) != AOP_STR) {
7643         /* if this is remateriazable */
7644         if (AOP_TYPE(result) == AOP_IMMD)
7645             emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE,FALSE));
7646         else 
7647         {
7648             /* we need to get it byte by byte */
7649             _startLazyDPSEvaluation();
7650             if (AOP_TYPE(result) != AOP_DPTR)
7651             {
7652                 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE,TRUE));
7653                 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE,TRUE));
7654                 emitcode("mov","dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7655             }
7656             else
7657             {
7658                  /* We need to generate a load to DPTR indirect through DPTR. */
7659                  D(emitcode(";", "genFarPointerSet -- indirection special case."););
7660                  emitcode("push", "%s", aopGet(AOP(result),0,FALSE,TRUE,TRUE));
7661                  emitcode("push", "%s", aopGet(AOP(result),1,FALSE,TRUE,TRUE));
7662                  emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7663                  emitcode("pop", "dph");
7664                  emitcode("pop", "dpl");
7665             }
7666             _endLazyDPSEvaluation();
7667         }
7668     }
7669     /* so dptr know contains the address */
7670     freeAsmop(result,NULL,ic,TRUE);
7671     aopOp(right,ic,FALSE, TRUE);
7672
7673     /* if bit then unpack */
7674     if (IS_BITVAR(retype) || IS_BITVAR(letype)) 
7675         genPackBits((IS_BITVAR(retype)?retype:letype),right,"dptr",FPOINTER);
7676     else {
7677         size = AOP_SIZE(right);
7678         offset = 0 ;
7679
7680         _startLazyDPSEvaluation();
7681         while (size--) {
7682             char *l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7683             MOVA(l);
7684             
7685             genSetDPTR(0);
7686             _flushLazyDPS();
7687             
7688             emitcode("movx","@dptr,a");
7689             if (size)
7690                 emitcode("inc","dptr");
7691         }
7692         _endLazyDPSEvaluation();
7693     }
7694
7695     freeAsmop(right,NULL,ic,TRUE);
7696 }
7697
7698 /*-----------------------------------------------------------------*/
7699 /* genGenPointerSet - set value from generic pointer space         */
7700 /*-----------------------------------------------------------------*/
7701 static void genGenPointerSet (operand *right,
7702                               operand *result, iCode *ic)
7703 {
7704     int size, offset ;
7705     sym_link *retype = getSpec(operandType(right));
7706     sym_link *letype = getSpec(operandType(result));
7707
7708     aopOp(result,ic,FALSE, TRUE);
7709
7710     /* if the operand is already in dptr 
7711     then we do nothing else we move the value to dptr */
7712     if (AOP_TYPE(result) != AOP_STR) {
7713         _startLazyDPSEvaluation();
7714         /* if this is remateriazable */
7715         if (AOP_TYPE(result) == AOP_IMMD) {
7716             emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE,FALSE));
7717             emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE,FALSE));
7718         }
7719         else { /* we need to get it byte by byte */
7720             emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE,TRUE));
7721             emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE,TRUE));
7722             emitcode("mov","dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7723             emitcode("mov","b,%s",aopGet(AOP(result),3,FALSE,FALSE,TRUE));
7724         }
7725         _endLazyDPSEvaluation();
7726     }
7727     /* so dptr know contains the address */
7728     freeAsmop(result,NULL,ic,TRUE);
7729     aopOp(right,ic,FALSE, TRUE);
7730
7731     /* if bit then unpack */
7732     if (IS_BITVAR(retype) || IS_BITVAR(letype)) 
7733         genPackBits((IS_BITVAR(retype)?retype:letype),right,"dptr",GPOINTER);
7734     else {
7735         size = AOP_SIZE(right);
7736         offset = 0 ;
7737
7738         _startLazyDPSEvaluation();
7739         while (size--) {
7740             char *l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7741             MOVA(l);
7742             
7743             genSetDPTR(0);
7744             _flushLazyDPS();
7745             
7746             emitcode("lcall","__gptrput");
7747             if (size)
7748                 emitcode("inc","dptr");
7749         }
7750         _endLazyDPSEvaluation();
7751     }
7752
7753     freeAsmop(right,NULL,ic,TRUE);
7754 }
7755
7756 /*-----------------------------------------------------------------*/
7757 /* genPointerSet - stores the value into a pointer location        */
7758 /*-----------------------------------------------------------------*/
7759 static void genPointerSet (iCode *ic)
7760 {    
7761     operand *right, *result ;
7762     sym_link *type, *etype;
7763     int p_type;
7764
7765     D(emitcode(";", "genPointerSet "););
7766
7767     right = IC_RIGHT(ic);
7768     result = IC_RESULT(ic) ;
7769
7770     /* depending on the type of pointer we need to
7771     move it to the correct pointer register */
7772     type = operandType(result);
7773     etype = getSpec(type);
7774     /* if left is of type of pointer then it is simple */
7775     if (IS_PTR(type) && !IS_FUNC(type->next)) {
7776         p_type = DCL_TYPE(type);
7777     }
7778     else {
7779         /* we have to go by the storage class */
7780         p_type = PTR_TYPE(SPEC_OCLS(etype));
7781     }
7782
7783     /* now that we have the pointer type we assign
7784     the pointer values */
7785     switch (p_type) {
7786
7787     case POINTER:
7788     case IPOINTER:
7789         genNearPointerSet (right,result,ic);
7790         break;
7791
7792     case PPOINTER:
7793         genPagedPointerSet (right,result,ic);
7794         break;
7795
7796     case FPOINTER:
7797         genFarPointerSet (right,result,ic);
7798         break;
7799
7800     case GPOINTER:
7801         genGenPointerSet (right,result,ic);
7802         break;
7803     }
7804
7805 }
7806
7807 /*-----------------------------------------------------------------*/
7808 /* genIfx - generate code for Ifx statement                        */
7809 /*-----------------------------------------------------------------*/
7810 static void genIfx (iCode *ic, iCode *popIc)
7811 {
7812     operand *cond = IC_COND(ic);
7813     int isbit =0;
7814
7815     D(emitcode(";", "genIfx "););
7816
7817     aopOp(cond,ic,FALSE, FALSE);
7818
7819     /* get the value into acc */
7820     if (AOP_TYPE(cond) != AOP_CRY)
7821         toBoolean(cond);
7822     else
7823         isbit = 1;
7824     /* the result is now in the accumulator */
7825     freeAsmop(cond,NULL,ic,TRUE);
7826
7827     /* if there was something to be popped then do it */
7828     if (popIc)
7829         genIpop(popIc);
7830
7831     /* if the condition is  a bit variable */
7832     if (isbit && IS_ITEMP(cond) && 
7833         SPIL_LOC(cond))
7834         genIfxJump(ic,SPIL_LOC(cond)->rname);
7835     else
7836         if (isbit && !IS_ITEMP(cond))
7837             genIfxJump(ic,OP_SYMBOL(cond)->rname);
7838         else
7839             genIfxJump(ic,"a");
7840
7841     ic->generated = 1;
7842 }
7843
7844 /*-----------------------------------------------------------------*/
7845 /* genAddrOf - generates code for address of                       */
7846 /*-----------------------------------------------------------------*/
7847 static void genAddrOf (iCode *ic)
7848 {
7849     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
7850     int size, offset ;
7851
7852     D(emitcode(";", "genAddrOf "););
7853
7854     aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
7855
7856     /* if the operand is on the stack then we 
7857     need to get the stack offset of this
7858     variable */
7859     if (sym->onStack) {
7860         /* if it has an offset then we need to compute
7861         it */
7862         if (sym->stack) {
7863             emitcode("mov","a,_bp");
7864             emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
7865             aopPut(AOP(IC_RESULT(ic)),"a",0);       
7866         } else {
7867             /* we can just move _bp */
7868             aopPut(AOP(IC_RESULT(ic)),"_bp",0);
7869         }
7870         /* fill the result with zero */
7871         size = AOP_SIZE(IC_RESULT(ic)) - 1;
7872         
7873         
7874         if (options.stack10bit && size < (FPTRSIZE - 1))
7875         {
7876             fprintf(stderr, 
7877                     "*** warning: pointer to stack var truncated.\n");
7878         }
7879         
7880         offset = 1;
7881         while (size--)
7882         {
7883             /* Yuck! */
7884             if (options.stack10bit && offset == 2)
7885             {
7886                 aopPut(AOP(IC_RESULT(ic)),"#0x40", offset++);
7887             }
7888             else
7889             {
7890                 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
7891             }
7892         }
7893
7894         goto release;
7895     }
7896
7897     /* object not on stack then we need the name */
7898     size = AOP_SIZE(IC_RESULT(ic));
7899     offset = 0;
7900
7901     while (size--) {
7902         char s[SDCC_NAME_MAX];
7903         if (offset) 
7904             sprintf(s,"#(%s >> %d)",
7905                     sym->rname,
7906                     offset*8);
7907         else
7908             sprintf(s,"#%s",sym->rname);
7909         aopPut(AOP(IC_RESULT(ic)),s,offset++);
7910     }
7911
7912 release:
7913     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7914
7915 }
7916
7917 /*-----------------------------------------------------------------*/
7918 /* genFarFarAssign - assignment when both are in far space         */
7919 /*-----------------------------------------------------------------*/
7920 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
7921 {
7922     int size = AOP_SIZE(right);
7923     int offset = 0;
7924     char *l;
7925
7926 #ifdef LAZY_DPS_OPT
7927     if (size > 1)
7928     {
7929         /* This is a net loss for size == 1, but a big gain
7930          * otherwise.
7931          */
7932         D(emitcode(";", "genFarFarAssign (improved)"););
7933
7934         aopOp(result,ic,TRUE, TRUE);
7935
7936         _startLazyDPSEvaluation();
7937         while (size--) 
7938         {
7939             aopPut(AOP(result),
7940                    aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
7941                    offset);
7942             offset++;
7943         }
7944         _endLazyDPSEvaluation();    
7945         freeAsmop(result,NULL,ic,FALSE);
7946         freeAsmop(right,NULL,ic,FALSE);
7947     }
7948     else
7949 #endif
7950     {
7951     D(emitcode(";", "genFarFarAssign "););
7952
7953     /* first push the right side on to the stack */
7954     _startLazyDPSEvaluation();
7955     while (size--) {
7956         l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7957         MOVA(l);
7958         emitcode ("push","acc");
7959     }
7960
7961     freeAsmop(right,NULL,ic,FALSE);
7962     /* now assign DPTR to result */
7963     aopOp(result,ic,FALSE, FALSE);
7964     size = AOP_SIZE(result);
7965     while (size--) {
7966         emitcode ("pop","acc");
7967         aopPut(AOP(result),"a",--offset);
7968     }
7969     freeAsmop(result,NULL,ic,FALSE);
7970     _endLazyDPSEvaluation();
7971     }
7972 }
7973
7974 /*-----------------------------------------------------------------*/
7975 /* genAssign - generate code for assignment                        */
7976 /*-----------------------------------------------------------------*/
7977 static void genAssign (iCode *ic)
7978 {
7979     operand *result, *right;
7980     int size, offset ;
7981         unsigned long lit = 0L;
7982
7983     D(emitcode(";", "genAssign "););
7984
7985     result = IC_RESULT(ic);
7986     right  = IC_RIGHT(ic) ;
7987
7988     /* if they are the same */
7989     if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
7990         return ;
7991
7992     aopOp(right,ic,FALSE, FALSE);
7993     
7994     emitcode(";", "genAssign: resultIsFar = %s",
7995              isOperandInFarSpace(result) ?
7996              "TRUE" : "FALSE");
7997
7998     /* special case both in far space */
7999     if ((AOP_TYPE(right) == AOP_DPTR ||
8000          AOP_TYPE(right) == AOP_DPTR2) &&
8001     /* IS_TRUE_SYMOP(result)       && */
8002     isOperandInFarSpace(result)) {
8003         
8004         genFarFarAssign (result,right,ic);
8005         return ;
8006     }
8007
8008     aopOp(result,ic,TRUE, FALSE);
8009
8010     /* if they are the same registers */
8011     if (sameRegs(AOP(right),AOP(result)))
8012         goto release;
8013
8014     /* if the result is a bit */
8015     if (AOP_TYPE(result) == AOP_CRY) {
8016
8017         /* if the right size is a literal then
8018         we know what the value is */
8019         if (AOP_TYPE(right) == AOP_LIT) {
8020             if (((int) operandLitValue(right))) 
8021                 aopPut(AOP(result),one,0);
8022             else
8023                 aopPut(AOP(result),zero,0);
8024             goto release;
8025         }
8026
8027         /* the right is also a bit variable */
8028         if (AOP_TYPE(right) == AOP_CRY) {
8029             emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8030             aopPut(AOP(result),"c",0);
8031             goto release ;
8032         }
8033
8034         /* we need to or */
8035         toBoolean(right);
8036         aopPut(AOP(result),"a",0);
8037         goto release ;
8038     }
8039
8040     /* bit variables done */
8041     /* general case */
8042     size = AOP_SIZE(result);
8043     offset = 0 ;
8044     if(AOP_TYPE(right) == AOP_LIT)
8045         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
8046     
8047     if((size > 1) &&
8048        (AOP_TYPE(result) != AOP_REG) &&
8049        (AOP_TYPE(right) == AOP_LIT) &&
8050        !IS_FLOAT(operandType(right)) 
8051 #ifndef LAZY_DPS_OPT
8052        && (lit < 256L)
8053 #endif       
8054        )
8055     {
8056 #ifdef LAZY_DPS_OPT
8057         D(emitcode(";", "Kevin's better literal load code"););
8058         _startLazyDPSEvaluation();
8059     while (size && ((unsigned int)(lit >> (offset*8)) != 0))
8060         {
8061             aopPut(AOP(result),
8062                    aopGet(AOP(right),offset,FALSE,FALSE,TRUE),
8063                    offset);
8064             offset++;
8065             size--;
8066         }
8067         /* And now fill the rest with zeros. */
8068         if (size)
8069         {
8070             emitcode("clr","a");
8071         }
8072         while (size--)
8073         {
8074             aopPut(AOP(result), "a", offset++);
8075         }
8076         _endLazyDPSEvaluation();
8077 #else
8078         emitcode("clr","a");
8079         
8080         _startLazyDPSEvaluation();
8081         while (size--) 
8082         {
8083             if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
8084                 aopPut(AOP(result),"a",size);
8085             else
8086                 aopPut(AOP(result),
8087                        aopGet(AOP(right),size,FALSE,FALSE,FALSE),
8088                        size);
8089         }
8090         _endLazyDPSEvaluation();
8091 #endif  
8092     } 
8093     else 
8094     {
8095         _startLazyDPSEvaluation();
8096         while (size--) 
8097         {
8098             aopPut(AOP(result),
8099                    aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8100                    offset);
8101             offset++;
8102         }
8103         _endLazyDPSEvaluation();
8104     }
8105     
8106 release:
8107     freeAsmop (right,NULL,ic,FALSE);
8108     freeAsmop (result,NULL,ic,TRUE);
8109 }   
8110
8111 /*-----------------------------------------------------------------*/
8112 /* genJumpTab - generates code for jump table                      */
8113 /*-----------------------------------------------------------------*/
8114 static void genJumpTab (iCode *ic)
8115 {
8116     symbol *jtab;
8117     char *l;
8118
8119     D(emitcode(";", "genJumpTab "););
8120
8121     aopOp(IC_JTCOND(ic),ic,FALSE, FALSE);
8122     /* get the condition into accumulator */
8123     l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE,TRUE);
8124     MOVA(l);
8125     /* multiply by four! */
8126     emitcode("add","a,acc");
8127     emitcode("add","a,acc");
8128     freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
8129
8130     jtab = newiTempLabel(NULL);
8131     emitcode("mov","dptr,#%05d$",jtab->key+100);
8132     emitcode("jmp","@a+dptr");
8133     emitcode("","%05d$:",jtab->key+100);
8134     /* now generate the jump labels */
8135     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
8136          jtab = setNextItem(IC_JTLABELS(ic)))
8137         emitcode("ljmp","%05d$",jtab->key+100);
8138
8139 }
8140
8141 /*-----------------------------------------------------------------*/
8142 /* genCast - gen code for casting                                  */
8143 /*-----------------------------------------------------------------*/
8144 static void genCast (iCode *ic)
8145 {
8146     operand *result = IC_RESULT(ic);
8147     sym_link *ctype = operandType(IC_LEFT(ic));
8148     sym_link *rtype = operandType(IC_RIGHT(ic));
8149     operand *right = IC_RIGHT(ic);
8150     int size, offset ;
8151
8152     D(emitcode(";", "genCast "););
8153
8154     /* if they are equivalent then do nothing */
8155     if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
8156         return ;
8157
8158     aopOp(right,ic,FALSE, FALSE) ;
8159     aopOp(result,ic,FALSE, AOP_TYPE(right) == AOP_DPTR);
8160
8161     /* if the result is a bit */
8162     if (AOP_TYPE(result) == AOP_CRY) {
8163         /* if the right size is a literal then
8164         we know what the value is */
8165         if (AOP_TYPE(right) == AOP_LIT) {
8166             if (((int) operandLitValue(right))) 
8167                 aopPut(AOP(result),one,0);
8168             else
8169                 aopPut(AOP(result),zero,0);
8170
8171             goto release;
8172         }
8173
8174         /* the right is also a bit variable */
8175         if (AOP_TYPE(right) == AOP_CRY) {
8176             emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8177             aopPut(AOP(result),"c",0);
8178             goto release ;
8179         }
8180
8181         /* we need to or */
8182         toBoolean(right);
8183         aopPut(AOP(result),"a",0);
8184         goto release ;
8185     }
8186
8187     /* if they are the same size : or less */
8188     if (AOP_SIZE(result) <= AOP_SIZE(right)) {
8189
8190         /* if they are in the same place */
8191         if (sameRegs(AOP(right),AOP(result)))
8192             goto release;
8193
8194         /* if they in different places then copy */
8195         size = AOP_SIZE(result);
8196         offset = 0 ;
8197         _startLazyDPSEvaluation();
8198         while (size--) {
8199             aopPut(AOP(result),
8200                    aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8201                    offset);
8202             offset++;
8203         }
8204         _endLazyDPSEvaluation();
8205         goto release;
8206     }
8207
8208
8209     /* if the result is of type pointer */
8210     if (IS_PTR(ctype)) {
8211
8212         int p_type;
8213         sym_link *type = operandType(right);
8214
8215         /* pointer to generic pointer */
8216         if (IS_GENPTR(ctype)) {
8217             char *l = zero;
8218             
8219             if (IS_PTR(type)) 
8220             {
8221                 p_type = DCL_TYPE(type);
8222             }
8223             else 
8224             {
8225 #if OLD_CAST_BEHAVIOR
8226                 /* KV: we are converting a non-pointer type to
8227                  * a generic pointer. This (ifdef'd out) code
8228                  * says that the resulting generic pointer 
8229                  * should have the same class as the storage
8230                  * location of the non-pointer variable.
8231                  * 
8232                  * For example, converting an int (which happens
8233                  * to be stored in DATA space) to a pointer results
8234                  * in a DATA generic pointer; if the original int
8235                  * in XDATA space, so will be the resulting pointer.
8236                  *
8237                  * I don't like that behavior, and thus this change:
8238                  * all such conversions will be forced to XDATA and
8239                  * throw a warning. If you want some non-XDATA
8240                  * type, or you want to suppress the warning, you
8241                  * must go through an intermediate cast, like so:
8242                  *
8243                  * char _generic *gp = (char _xdata *)(intVar);
8244                  */
8245                 sym_link *etype = getSpec(type);                 
8246
8247                 /* we have to go by the storage class */
8248                 if (SPEC_OCLS(etype) != generic)
8249                 {
8250                     p_type = PTR_TYPE(SPEC_OCLS(etype));
8251                 }
8252                 else
8253 #endif          
8254                 {
8255                     /* Converting unknown class (i.e. register variable)
8256                      * to generic pointer. This is not good, but
8257                      * we'll make a guess (and throw a warning).
8258                      */
8259                     p_type = FPOINTER;
8260                     werror(W_INT_TO_GEN_PTR_CAST);           
8261                 }
8262             }
8263                 
8264             /* the first two bytes are known */
8265             size = GPTRSIZE - 1; 
8266             offset = 0 ;
8267             _startLazyDPSEvaluation();
8268             while (size--) {
8269                 aopPut(AOP(result),
8270                        aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8271                        offset);
8272                 offset++;
8273             }
8274             _endLazyDPSEvaluation();
8275             
8276             /* the last byte depending on type */
8277             switch (p_type) {
8278             case IPOINTER:
8279             case POINTER:
8280                 l = zero;
8281                 break;
8282             case FPOINTER:
8283                 l = one;
8284                 break;
8285             case CPOINTER:
8286                 l = "#0x02";
8287                 break;                          
8288             case PPOINTER:
8289                 l = "#0x03";
8290                 break;
8291                 
8292             default:
8293                 /* this should never happen */
8294                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8295                        "got unknown pointer type");
8296                 exit(1);
8297             }
8298             aopPut(AOP(result),l, GPTRSIZE - 1);            
8299             goto release ;
8300         }
8301         
8302         /* just copy the pointers */
8303         size = AOP_SIZE(result);
8304         offset = 0 ;
8305         _startLazyDPSEvaluation();
8306         while (size--) {
8307             aopPut(AOP(result),
8308                    aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8309                    offset);
8310             offset++;
8311         }
8312         _endLazyDPSEvaluation();
8313         goto release ;
8314     }
8315     
8316     /* so we now know that the size of destination is greater
8317     than the size of the source */
8318     /* we move to result for the size of source */
8319     size = AOP_SIZE(right);
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
8330     /* now depending on the sign of the source && destination */
8331     size = AOP_SIZE(result) - AOP_SIZE(right);
8332     /* if unsigned or not an integral type */
8333     /* also, if the source is a bit, we don't need to sign extend, because
8334      * it can't possibly have set the sign bit.
8335      */
8336     if (SPEC_USIGN(rtype) || !IS_SPEC(rtype) || AOP_TYPE(right) == AOP_CRY) 
8337     {
8338         while (size--)
8339         {
8340             aopPut(AOP(result),zero,offset++);
8341         }
8342     } 
8343     else 
8344     {
8345         /* we need to extend the sign :{ */
8346         char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
8347                          FALSE,FALSE,TRUE);
8348         MOVA(l);
8349         emitcode("rlc","a");
8350         emitcode("subb","a,acc");
8351         while (size--)
8352             aopPut(AOP(result),"a",offset++);   
8353     }
8354
8355     /* we are done hurray !!!! */
8356
8357 release:
8358     freeAsmop(right,NULL,ic,TRUE);
8359     freeAsmop(result,NULL,ic,TRUE);
8360
8361 }
8362
8363 /*-----------------------------------------------------------------*/
8364 /* genDjnz - generate decrement & jump if not zero instrucion      */
8365 /*-----------------------------------------------------------------*/
8366 static int genDjnz (iCode *ic, iCode *ifx)
8367 {
8368     symbol *lbl, *lbl1;
8369     if (!ifx)
8370         return 0;
8371     
8372     /* if the if condition has a false label
8373        then we cannot save */
8374     if (IC_FALSE(ifx))
8375         return 0;
8376
8377     /* if the minus is not of the form 
8378        a = a - 1 */
8379     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
8380         !IS_OP_LITERAL(IC_RIGHT(ic)))
8381         return 0;
8382
8383     if (operandLitValue(IC_RIGHT(ic)) != 1)
8384         return 0;
8385
8386     /* if the size of this greater than one then no
8387        saving */
8388     if (getSize(operandType(IC_RESULT(ic))) > 1)
8389         return 0;
8390
8391     /* otherwise we can save BIG */
8392     lbl = newiTempLabel(NULL);
8393     lbl1= newiTempLabel(NULL);
8394
8395     aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
8396     
8397     if (IS_AOP_PREG(IC_RESULT(ic))) {
8398         emitcode("dec","%s",
8399                  aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
8400         emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
8401         emitcode("jnz","%05d$",lbl->key+100);
8402     } else {    
8403         emitcode ("djnz","%s,%05d$",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE),
8404                   lbl->key+100);
8405     }
8406     emitcode ("sjmp","%05d$",lbl1->key+100);
8407     emitcode ("","%05d$:",lbl->key+100);
8408     emitcode ("ljmp","%05d$",IC_TRUE(ifx)->key+100);
8409     emitcode ("","%05d$:",lbl1->key+100);
8410     
8411     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8412     ifx->generated = 1;
8413     return 1;
8414 }
8415
8416 /*-----------------------------------------------------------------*/
8417 /* genReceive - generate code for a receive iCode                  */
8418 /*-----------------------------------------------------------------*/
8419 static void genReceive (iCode *ic)
8420 {    
8421
8422     D(emitcode(";", "genReceive "););
8423
8424     if (isOperandInFarSpace(IC_RESULT(ic)) && 
8425         ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
8426           IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
8427         int size = getSize(operandType(IC_RESULT(ic)));
8428         int offset =  fReturnSize_390 - size;
8429         while (size--) {
8430             emitcode ("push","%s", (strcmp(fReturn[fReturnSize_390 - offset - 1],"a") ?
8431                                     fReturn[fReturnSize_390 - offset - 1] : "acc"));
8432             offset++;
8433         }
8434         aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
8435         size = AOP_SIZE(IC_RESULT(ic));
8436         offset = 0;
8437         while (size--) {
8438             emitcode ("pop","acc");
8439             aopPut (AOP(IC_RESULT(ic)),"a",offset++);
8440         }
8441         
8442     } else {
8443         _G.accInUse++;
8444         aopOp(IC_RESULT(ic),ic,FALSE, FALSE);  
8445         _G.accInUse--;
8446         assignResultValue(IC_RESULT(ic));       
8447     }
8448
8449     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8450 }
8451
8452 /*-----------------------------------------------------------------*/
8453 /* gen390Code - generate code for Dallas 390 based controllers     */
8454 /*-----------------------------------------------------------------*/
8455 void gen390Code (iCode *lic)
8456 {
8457     iCode *ic;
8458     int cln = 0;
8459
8460     lineHead = lineCurr = NULL;
8461
8462 #if 0
8463     //REMOVE ME!!!
8464     /* print the allocation information */
8465     if (allocInfo)
8466         printAllocInfo( currFunc, codeOutFile);
8467 #endif
8468     /* if debug information required */
8469     if (options.debug && currFunc) {
8470     //jwk if (currFunc) {
8471         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
8472         _G.debugLine = 1;
8473         if (IS_STATIC(currFunc->etype))
8474             emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name); 
8475         else
8476             emitcode("","G$%s$0$0 ==.",currFunc->name);
8477         _G.debugLine = 0;
8478     }
8479     /* stack pointer name */
8480     if (options.useXstack)
8481         spname = "_spx";
8482     else
8483         spname = "sp";
8484     
8485  
8486     for (ic = lic ; ic ; ic = ic->next ) {
8487         
8488         if ( cln != ic->lineno ) {
8489             if ( options.debug ) {
8490                 _G.debugLine = 1;
8491                 emitcode("","C$%s$%d$%d$%d ==.",
8492                          ic->filename,ic->lineno,
8493                          ic->level,ic->block);
8494                 _G.debugLine = 0;
8495             }
8496             emitcode(";","%s %d",ic->filename,ic->lineno);
8497             cln = ic->lineno ;
8498         }
8499         /* if the result is marked as
8500            spilt and rematerializable or code for
8501            this has already been generated then
8502            do nothing */
8503         if (resultRemat(ic) || ic->generated ) 
8504             continue ;
8505         
8506         /* depending on the operation */
8507         switch (ic->op) {
8508         case '!' :
8509             genNot(ic);
8510             break;
8511             
8512         case '~' :
8513             genCpl(ic);
8514             break;
8515             
8516         case UNARYMINUS:
8517             genUminus (ic);
8518             break;
8519             
8520         case IPUSH:
8521             genIpush (ic);
8522             break;
8523             
8524         case IPOP:
8525             /* IPOP happens only when trying to restore a 
8526                spilt live range, if there is an ifx statement
8527                following this pop then the if statement might
8528                be using some of the registers being popped which
8529                would destory the contents of the register so
8530                we need to check for this condition and handle it */
8531             if (ic->next            && 
8532                 ic->next->op == IFX &&
8533                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
8534                 genIfx (ic->next,ic);
8535             else
8536                 genIpop (ic);
8537             break; 
8538             
8539         case CALL:
8540             genCall (ic);
8541             break;
8542             
8543         case PCALL:
8544             genPcall (ic);
8545             break;
8546             
8547         case FUNCTION:
8548             genFunction (ic);
8549             break;
8550             
8551         case ENDFUNCTION:
8552             genEndFunction (ic);
8553             break;
8554             
8555         case RETURN:
8556             genRet (ic);
8557             break;
8558             
8559         case LABEL:
8560             genLabel (ic);
8561             break;
8562             
8563         case GOTO:
8564             genGoto (ic);
8565             break;
8566             
8567         case '+' :
8568             genPlus (ic) ;
8569             break;
8570             
8571         case '-' :
8572             if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
8573                 genMinus (ic);
8574             break;
8575             
8576         case '*' :
8577             genMult (ic);
8578             break;
8579             
8580         case '/' :
8581             genDiv (ic) ;
8582             break;
8583             
8584         case '%' :
8585             genMod (ic);
8586             break;
8587             
8588         case '>' :
8589             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
8590             break;
8591             
8592         case '<' :
8593             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
8594             break;
8595             
8596         case LE_OP:
8597         case GE_OP:
8598         case NE_OP:
8599             
8600             /* note these two are xlated by algebraic equivalence
8601                during parsing SDCC.y */
8602             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8603                    "got '>=' or '<=' shouldn't have come here");
8604             break;      
8605             
8606         case EQ_OP:
8607             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
8608             break;          
8609             
8610         case AND_OP:
8611             genAndOp (ic);
8612             break;
8613             
8614         case OR_OP:
8615             genOrOp (ic);
8616             break;
8617             
8618         case '^' :
8619             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
8620             break;
8621             
8622         case '|' :
8623                 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
8624             break;
8625             
8626         case BITWISEAND:
8627             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
8628             break;
8629             
8630         case INLINEASM:
8631             genInline (ic);
8632             break;
8633             
8634         case RRC:
8635             genRRC (ic);
8636             break;
8637             
8638         case RLC:
8639             genRLC (ic);
8640             break;
8641             
8642         case GETHBIT:
8643             genGetHbit (ic);
8644             break;
8645             
8646         case LEFT_OP:
8647             genLeftShift (ic);
8648             break;
8649             
8650         case RIGHT_OP:
8651             genRightShift (ic);
8652             break;
8653             
8654         case GET_VALUE_AT_ADDRESS:
8655             genPointerGet(ic);
8656             break;
8657             
8658         case '=' :
8659             if (POINTER_SET(ic))
8660                 genPointerSet(ic);
8661             else
8662                 genAssign(ic);
8663             break;
8664             
8665         case IFX:
8666             genIfx (ic,NULL);
8667             break;
8668             
8669         case ADDRESS_OF:
8670             genAddrOf (ic);
8671             break;
8672             
8673         case JUMPTABLE:
8674             genJumpTab (ic);
8675             break;
8676             
8677         case CAST:
8678             genCast (ic);
8679             break;
8680             
8681         case RECEIVE:
8682             genReceive(ic);
8683             break;
8684             
8685         case SEND:
8686             addSet(&_G.sendSet,ic);
8687             break;
8688
8689         default :
8690             ic = ic;
8691             /*      piCode(ic,stdout); */
8692             
8693         }
8694     }
8695     
8696
8697     /* now we are ready to call the 
8698        peep hole optimizer */
8699     if (!options.nopeep)
8700         peepHole (&lineHead);
8701
8702     /* now do the actual printing */
8703     printLine (lineHead,codeOutFile);    
8704     return;
8705 }