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