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