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