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