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