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