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