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