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