bug #435214 "(long)>>9"
[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)
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       if (currFunc)
2948         {
2949           _G.debugLine = 1;
2950           emitcode ("", "C$%s$%d$%d$%d ==.",
2951                     FileBaseName (ic->filename), currFunc->lastLine,
2952                     ic->level, ic->block);
2953           if (IS_STATIC (currFunc->etype))
2954             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2955           else
2956             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2957           _G.debugLine = 0;
2958         }
2959
2960       emitcode ("reti", "");
2961     }
2962   else
2963     {
2964       if (SPEC_CRTCL (sym->etype))
2965         emitcode ("setb", "ea");
2966
2967       if (sym->calleeSave)
2968         {
2969           int i;
2970
2971           /* if any registers used */
2972           if (sym->regsUsed)
2973             {
2974               /* save the registers used */
2975               for (i = sym->regsUsed->size; i >= 0; i--)
2976                 {
2977                   if (bitVectBitValue (sym->regsUsed, i) ||
2978                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2979                     emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2980                 }
2981             }
2982
2983         }
2984
2985       /* if debug then send end of function */
2986       if (currFunc)
2987         {
2988           _G.debugLine = 1;
2989           emitcode ("", "C$%s$%d$%d$%d ==.",
2990                     FileBaseName (ic->filename), currFunc->lastLine,
2991                     ic->level, ic->block);
2992           if (IS_STATIC (currFunc->etype))
2993             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2994           else
2995             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2996           _G.debugLine = 0;
2997         }
2998
2999       emitcode ("ret", "");
3000     }
3001
3002 }
3003
3004 /*-----------------------------------------------------------------*/
3005 /* genRet - generate code for return statement                     */
3006 /*-----------------------------------------------------------------*/
3007 static void
3008 genRet (iCode * ic)
3009 {
3010   int size, offset = 0, pushed = 0;
3011
3012   D (emitcode (";", "genRet ");
3013     );
3014
3015   /* if we have no return value then
3016      just generate the "ret" */
3017   if (!IC_LEFT (ic))
3018     goto jumpret;
3019
3020   /* we have something to return then
3021      move the return value into place */
3022   aopOp (IC_LEFT (ic), ic, FALSE, TRUE);
3023   size = AOP_SIZE (IC_LEFT (ic));
3024
3025   _startLazyDPSEvaluation ();
3026   while (size--)
3027     {
3028       char *l;
3029       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3030         {
3031           l = aopGet (AOP (IC_LEFT (ic)), offset++,
3032                       FALSE, TRUE, FALSE);
3033           emitcode ("push", "%s", l);
3034           pushed++;
3035         }
3036       else
3037         {
3038           /* Since A is the last element of fReturn,
3039            * is is OK to clobber it in the aopGet.
3040            */
3041           l = aopGet (AOP (IC_LEFT (ic)), offset,
3042                       FALSE, FALSE, TRUE);
3043           if (strcmp (fReturn[offset], l))
3044             emitcode ("mov", "%s,%s", fReturn[offset++], l);
3045         }
3046     }
3047   _endLazyDPSEvaluation ();
3048
3049   if (pushed)
3050     {
3051       while (pushed)
3052         {
3053           pushed--;
3054           if (strcmp (fReturn[pushed], "a"))
3055             emitcode ("pop", fReturn[pushed]);
3056           else
3057             emitcode ("pop", "acc");
3058         }
3059     }
3060   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3061
3062 jumpret:
3063   /* generate a jump to the return label
3064      if the next is not the return statement */
3065   if (!(ic->next && ic->next->op == LABEL &&
3066         IC_LABEL (ic->next) == returnLabel))
3067
3068     emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3069
3070 }
3071
3072 /*-----------------------------------------------------------------*/
3073 /* genLabel - generates a label                                    */
3074 /*-----------------------------------------------------------------*/
3075 static void
3076 genLabel (iCode * ic)
3077 {
3078   /* special case never generate */
3079   if (IC_LABEL (ic) == entryLabel)
3080     return;
3081
3082   D (emitcode (";", "genLabel ");
3083     );
3084
3085   emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3086 }
3087
3088 /*-----------------------------------------------------------------*/
3089 /* genGoto - generates a ljmp                                      */
3090 /*-----------------------------------------------------------------*/
3091 static void
3092 genGoto (iCode * ic)
3093 {
3094   D (emitcode (";", "genGoto ");
3095     );
3096   emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
3097 }
3098
3099 /*-----------------------------------------------------------------*/
3100 /* findLabelBackwards: walks back through the iCode chain looking  */
3101 /* for the given label. Returns number of iCode instructions     */
3102 /* between that label and given ic.          */
3103 /* Returns zero if label not found.          */
3104 /*-----------------------------------------------------------------*/
3105 static int
3106 findLabelBackwards (iCode * ic, int key)
3107 {
3108   int count = 0;
3109
3110   while (ic->prev)
3111     {
3112       ic = ic->prev;
3113       count++;
3114
3115       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3116         {
3117           /* printf("findLabelBackwards = %d\n", count); */
3118           return count;
3119         }
3120     }
3121
3122   return 0;
3123 }
3124
3125 /*-----------------------------------------------------------------*/
3126 /* genPlusIncr :- does addition with increment if possible         */
3127 /*-----------------------------------------------------------------*/
3128 static bool
3129 genPlusIncr (iCode * ic)
3130 {
3131   unsigned int icount;
3132   unsigned int size = getDataSize (IC_RESULT (ic));
3133
3134   /* will try to generate an increment */
3135   /* if the right side is not a literal
3136      we cannot */
3137   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3138     return FALSE;
3139
3140   /* if the literal value of the right hand side
3141      is greater than 4 then it is not worth it */
3142   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3143     return FALSE;
3144
3145   /* if increment 16 bits in register */
3146   if (
3147        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3148        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3149        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3150        (size > 1) &&
3151        (icount == 1))
3152     {
3153       symbol *tlbl;
3154       int emitTlbl;
3155       int labelRange;
3156
3157       /* If the next instruction is a goto and the goto target
3158        * is <= 5 instructions previous to this, we can generate
3159        * jumps straight to that target.
3160        */
3161       if (ic->next && ic->next->op == GOTO
3162           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3163           && labelRange <= 5)
3164         {
3165           emitcode (";", "tail increment optimized (range %d)", labelRange);
3166           tlbl = IC_LABEL (ic->next);
3167           emitTlbl = 0;
3168         }
3169       else
3170         {
3171           tlbl = newiTempLabel (NULL);
3172           emitTlbl = 1;
3173         }
3174       emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3175       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3176           IS_AOP_PREG (IC_RESULT (ic)))
3177         emitcode ("cjne", "%s,#0x00,%05d$"
3178                   ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3179                   ,tlbl->key + 100);
3180       else
3181         {
3182           emitcode ("clr", "a");
3183           emitcode ("cjne", "a,%s,%05d$"
3184                     ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3185                     ,tlbl->key + 100);
3186         }
3187
3188       emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3189       if (size > 2)
3190         {
3191           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3192               IS_AOP_PREG (IC_RESULT (ic)))
3193             emitcode ("cjne", "%s,#0x00,%05d$"
3194                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3195                       ,tlbl->key + 100);
3196           else
3197             emitcode ("cjne", "a,%s,%05d$"
3198                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3199                       ,tlbl->key + 100);
3200
3201           emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3202         }
3203       if (size > 3)
3204         {
3205           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3206               IS_AOP_PREG (IC_RESULT (ic)))
3207             emitcode ("cjne", "%s,#0x00,%05d$"
3208                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3209                       ,tlbl->key + 100);
3210           else
3211             {
3212               emitcode ("cjne", "a,%s,%05d$"
3213                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3214                         ,tlbl->key + 100);
3215             }
3216           emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3217         }
3218
3219       if (emitTlbl)
3220         {
3221           emitcode ("", "%05d$:", tlbl->key + 100);
3222         }
3223       return TRUE;
3224     }
3225
3226   /* if the sizes are greater than 1 then we cannot */
3227   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3228       AOP_SIZE (IC_LEFT (ic)) > 1)
3229     return FALSE;
3230
3231   /* we can if the aops of the left & result match or
3232      if they are in registers and the registers are the
3233      same */
3234   if (
3235        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3236        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3237        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3238     {
3239
3240       if (icount > 3)
3241         {
3242           MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3243           emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3244           aopPut (AOP (IC_RESULT (ic)), "a", 0);
3245         }
3246       else
3247         {
3248
3249           _startLazyDPSEvaluation ();
3250           while (icount--)
3251             {
3252               emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3253             }
3254           _endLazyDPSEvaluation ();
3255         }
3256
3257       return TRUE;
3258     }
3259
3260   return FALSE;
3261 }
3262
3263 /*-----------------------------------------------------------------*/
3264 /* outBitAcc - output a bit in acc                                 */
3265 /*-----------------------------------------------------------------*/
3266 static void
3267 outBitAcc (operand * result)
3268 {
3269   symbol *tlbl = newiTempLabel (NULL);
3270   /* if the result is a bit */
3271   if (AOP_TYPE (result) == AOP_CRY)
3272     {
3273       aopPut (AOP (result), "a", 0);
3274     }
3275   else
3276     {
3277       emitcode ("jz", "%05d$", tlbl->key + 100);
3278       emitcode ("mov", "a,%s", one);
3279       emitcode ("", "%05d$:", tlbl->key + 100);
3280       outAcc (result);
3281     }
3282 }
3283
3284 /*-----------------------------------------------------------------*/
3285 /* genPlusBits - generates code for addition of two bits           */
3286 /*-----------------------------------------------------------------*/
3287 static void
3288 genPlusBits (iCode * ic)
3289 {
3290   D (emitcode (";", "genPlusBits ");
3291     );
3292   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3293     {
3294       symbol *lbl = newiTempLabel (NULL);
3295       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3296       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3297       emitcode ("cpl", "c");
3298       emitcode ("", "%05d$:", (lbl->key + 100));
3299       outBitC (IC_RESULT (ic));
3300     }
3301   else
3302     {
3303       emitcode ("clr", "a");
3304       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3305       emitcode ("rlc", "a");
3306       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3307       emitcode ("addc", "a,#0x00");
3308       outAcc (IC_RESULT (ic));
3309     }
3310 }
3311
3312 static void
3313 adjustArithmeticResult (iCode * ic)
3314 {
3315   if (opIsGptr (IC_RESULT (ic)) &&
3316       opIsGptr (IC_LEFT (ic)) &&
3317       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3318     {
3319       aopPut (AOP (IC_RESULT (ic)),
3320               aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3321               GPTRSIZE - 1);
3322     }
3323
3324   if (opIsGptr (IC_RESULT (ic)) &&
3325       opIsGptr (IC_RIGHT (ic)) &&
3326       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3327     {
3328       aopPut (AOP (IC_RESULT (ic)),
3329             aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3330               GPTRSIZE - 1);
3331     }
3332
3333   if (opIsGptr (IC_RESULT (ic)) &&
3334       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3335       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3336       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3337       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3338     {
3339       char buffer[5];
3340       sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3341       aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3342     }
3343 }
3344
3345 // Macro to aopOp all three operands of an ic. Will fatal if this cannot be done
3346 // (because all three operands are in far space).
3347 #define AOP_OP_3(ic) \
3348     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3349     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3350     aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3351               (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3352     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3353         AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3354     { \
3355         /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3356         fprintf(stderr,                                  \
3357                "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno);   \
3358     }
3359
3360 // Macro to aopOp all three operands of an ic. If this cannot be done, 
3361 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3362 // will be set TRUE. The caller must then handle the case specially, noting
3363 // that the IC_RESULT operand is not aopOp'd.
3364 #define AOP_OP_3_NOFATAL(ic, rc) \
3365     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3366     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3367     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3368         isOperandInFarSpace(IC_RESULT(ic))) \
3369     { \
3370        /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3371        rc = TRUE; \
3372     }  \
3373     else \
3374     { \
3375        aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3376                                      (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3377        rc = FALSE; \
3378        if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3379            AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3380        { \
3381             /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3382             fprintf(stderr,                                  \
3383                     "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno);   \
3384        } \
3385     }
3386
3387 // aopOp the left & right operands of an ic.
3388 #define AOP_OP_2(ic) \
3389     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3390     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3391
3392 // convienience macro.
3393 #define AOP_SET_LOCALS(ic) \
3394     left = IC_LEFT(ic); \
3395     right = IC_RIGHT(ic); \
3396     result = IC_RESULT(ic);
3397
3398
3399 // Given an integer value of pushedSize bytes on the stack,
3400 // adjust it to be resultSize bytes, either by discarding
3401 // the most significant bytes or by zero-padding.
3402 //
3403 // On exit from this macro, pushedSize will have been adjusted to
3404 // equal resultSize, and ACC may be trashed.
3405 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize)            \
3406       /* If the pushed data is bigger than the result,          \
3407        * simply discard unused bytes. Icky, but works.          \
3408        */                                                       \
3409       while (pushedSize > resultSize)                           \
3410       {                                                         \
3411           D (emitcode (";", "discarding unused result byte."););\
3412           emitcode ("pop", "acc");                              \
3413           pushedSize--;                                         \
3414       }                                                         \
3415       if (pushedSize < resultSize)                              \
3416       {                                                         \
3417           emitcode ("clr", "a");                                \
3418           /* Conversly, we haven't pushed enough here.          \
3419            * just zero-pad, and all is well.                    \
3420            */                                                   \
3421           while (pushedSize < resultSize)                       \
3422           {                                                     \
3423               emitcode("push", "acc");                          \
3424               pushedSize++;                                     \
3425           }                                                     \
3426       }                                                         \
3427       assert(pushedSize == resultSize);
3428
3429 /*-----------------------------------------------------------------*/
3430 /* genPlus - generates code for addition                           */
3431 /*-----------------------------------------------------------------*/
3432 static void
3433 genPlus (iCode * ic)
3434 {
3435   int size, offset = 0;
3436   bool pushResult = FALSE;
3437   int rSize;
3438
3439   D (emitcode (";", "genPlus "););
3440
3441   /* special cases :- */
3442
3443   AOP_OP_3_NOFATAL (ic, pushResult);
3444   if (pushResult)
3445     {
3446       D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3447     }
3448
3449   if (!pushResult)
3450     {
3451       /* if literal, literal on the right or
3452          if left requires ACC or right is already
3453          in ACC */
3454       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3455        || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3456           || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3457         {
3458           operand *t = IC_RIGHT (ic);
3459           IC_RIGHT (ic) = IC_LEFT (ic);
3460           IC_LEFT (ic) = t;
3461           emitcode (";", "Swapped plus args.");
3462         }
3463
3464       /* if both left & right are in bit
3465          space */
3466       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3467           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3468         {
3469           genPlusBits (ic);
3470           goto release;
3471         }
3472
3473       /* if left in bit space & right literal */
3474       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3475           AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3476         {
3477           emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3478           /* if result in bit space */
3479           if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3480             {
3481               if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3482                 emitcode ("cpl", "c");
3483               outBitC (IC_RESULT (ic));
3484             }
3485           else
3486             {
3487               size = getDataSize (IC_RESULT (ic));
3488               _startLazyDPSEvaluation ();
3489               while (size--)
3490                 {
3491                   MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3492                   emitcode ("addc", "a,#00");
3493                   aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3494                 }
3495               _endLazyDPSEvaluation ();
3496             }
3497           goto release;
3498         }
3499
3500       /* if I can do an increment instead
3501          of add then GOOD for ME */
3502       if (genPlusIncr (ic) == TRUE)
3503         {
3504           emitcode (";", "did genPlusIncr");
3505           goto release;
3506         }
3507
3508     }
3509   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3510
3511   _startLazyDPSEvaluation ();
3512   while (size--)
3513     {
3514       if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
3515         {
3516           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3517           if (offset == 0)
3518             emitcode ("add", "a,%s",
3519                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3520           else
3521             emitcode ("addc", "a,%s",
3522                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3523         }
3524       else
3525         {
3526           if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
3527           {
3528               /* right is going to use ACC or we would have taken the
3529                * above branch.
3530                */
3531               assert(AOP_NEEDSACC(IC_RIGHT(ic)));
3532               D(emitcode(";", "+ AOP_ACC special case."););
3533               emitcode("xch", "a, %s", DP2_RESULT_REG);
3534           }
3535           MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3536           if (offset == 0)
3537           {
3538             if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
3539             {
3540                 emitcode("add", "a, %s", DP2_RESULT_REG); 
3541             }
3542             else
3543             {
3544                 emitcode ("add", "a,%s",
3545                         aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE, FALSE));
3546             }
3547           }
3548           else
3549           {
3550             emitcode ("addc", "a,%s",
3551                   aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3552           }
3553         }
3554       if (!pushResult)
3555         {
3556           aopPut (AOP (IC_RESULT (ic)), "a", offset);
3557         }
3558       else
3559         {
3560           emitcode ("push", "acc");
3561         }
3562       offset++;
3563     }
3564   _endLazyDPSEvaluation ();
3565
3566   if (pushResult)
3567     {
3568       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3569
3570       size = getDataSize (IC_LEFT (ic));
3571       rSize = getDataSize (IC_RESULT (ic));
3572
3573       ADJUST_PUSHED_RESULT(size, rSize);
3574
3575       _startLazyDPSEvaluation ();
3576       while (size--)
3577         {
3578           emitcode ("pop", "acc");
3579           aopPut (AOP (IC_RESULT (ic)), "a", size);
3580         }
3581       _endLazyDPSEvaluation ();
3582     }
3583
3584   adjustArithmeticResult (ic);
3585
3586 release:
3587   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3588   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3589   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3590 }
3591
3592 /*-----------------------------------------------------------------*/
3593 /* genMinusDec :- does subtraction with deccrement if possible     */
3594 /*-----------------------------------------------------------------*/
3595 static bool
3596 genMinusDec (iCode * ic)
3597 {
3598   unsigned int icount;
3599   unsigned int size = getDataSize (IC_RESULT (ic));
3600
3601   /* will try to generate an increment */
3602   /* if the right side is not a literal
3603      we cannot */
3604   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3605     return FALSE;
3606
3607   /* if the literal value of the right hand side
3608      is greater than 4 then it is not worth it */
3609   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3610     return FALSE;
3611
3612   /* if decrement 16 bits in register */
3613   if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3614       AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3615       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3616       (size > 1) &&
3617       (icount == 1))
3618     {
3619       symbol *tlbl;
3620       int emitTlbl;
3621       int labelRange;
3622
3623       /* If the next instruction is a goto and the goto target
3624          * is <= 5 instructions previous to this, we can generate
3625          * jumps straight to that target.
3626        */
3627       if (ic->next && ic->next->op == GOTO
3628           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3629           && labelRange <= 5)
3630         {
3631           emitcode (";", "tail decrement optimized (range %d)", labelRange);
3632           tlbl = IC_LABEL (ic->next);
3633           emitTlbl = 0;
3634         }
3635       else
3636         {
3637           tlbl = newiTempLabel (NULL);
3638           emitTlbl = 1;
3639         }
3640
3641       emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3642       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3643           AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3644           IS_AOP_PREG (IC_RESULT (ic)))
3645         emitcode ("cjne", "%s,#0xff,%05d$"
3646                   ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3647                   ,tlbl->key + 100);
3648       else
3649         {
3650           emitcode ("mov", "a,#0xff");
3651           emitcode ("cjne", "a,%s,%05d$"
3652                     ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3653                     ,tlbl->key + 100);
3654         }
3655       emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3656       if (size > 2)
3657         {
3658           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3659               AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3660               IS_AOP_PREG (IC_RESULT (ic)))
3661             emitcode ("cjne", "%s,#0xff,%05d$"
3662                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3663                       ,tlbl->key + 100);
3664           else
3665             {
3666               emitcode ("cjne", "a,%s,%05d$"
3667                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3668                         ,tlbl->key + 100);
3669             }
3670           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3671         }
3672       if (size > 3)
3673         {
3674           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3675               AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3676               IS_AOP_PREG (IC_RESULT (ic)))
3677             emitcode ("cjne", "%s,#0xff,%05d$"
3678                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3679                       ,tlbl->key + 100);
3680           else
3681             {
3682               emitcode ("cjne", "a,%s,%05d$"
3683                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3684                         ,tlbl->key + 100);
3685             }
3686           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3687         }
3688       if (emitTlbl)
3689         {
3690           emitcode ("", "%05d$:", tlbl->key + 100);
3691         }
3692       return TRUE;
3693     }
3694
3695   /* if the sizes are greater than 1 then we cannot */
3696   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3697       AOP_SIZE (IC_LEFT (ic)) > 1)
3698     return FALSE;
3699
3700   /* we can if the aops of the left & result match or
3701      if they are in registers and the registers are the
3702      same */
3703   if (
3704        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3705        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3706        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3707     {
3708
3709       _startLazyDPSEvaluation ();
3710       while (icount--)
3711         {
3712           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
3713         }
3714       _endLazyDPSEvaluation ();
3715
3716       return TRUE;
3717     }
3718
3719   return FALSE;
3720 }
3721
3722 /*-----------------------------------------------------------------*/
3723 /* addSign - complete with sign                                    */
3724 /*-----------------------------------------------------------------*/
3725 static void
3726 addSign (operand * result, int offset, int sign)
3727 {
3728   int size = (getDataSize (result) - offset);
3729   if (size > 0)
3730     {
3731       _startLazyDPSEvaluation();
3732       if (sign)
3733         {
3734           emitcode ("rlc", "a");
3735           emitcode ("subb", "a,acc");
3736           while (size--)
3737           {
3738             aopPut (AOP (result), "a", offset++);
3739           }
3740         }
3741       else
3742       {
3743         while (size--)
3744         {
3745           aopPut (AOP (result), zero, offset++);
3746         }
3747       }
3748       _endLazyDPSEvaluation();
3749     }
3750 }
3751
3752 /*-----------------------------------------------------------------*/
3753 /* genMinusBits - generates code for subtraction  of two bits      */
3754 /*-----------------------------------------------------------------*/
3755 static void
3756 genMinusBits (iCode * ic)
3757 {
3758   symbol *lbl = newiTempLabel (NULL);
3759
3760   D (emitcode (";", "genMinusBits "););
3761
3762   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3763     {
3764       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3765       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3766       emitcode ("cpl", "c");
3767       emitcode ("", "%05d$:", (lbl->key + 100));
3768       outBitC (IC_RESULT (ic));
3769     }
3770   else
3771     {
3772       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3773       emitcode ("subb", "a,acc");
3774       emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3775       emitcode ("inc", "a");
3776       emitcode ("", "%05d$:", (lbl->key + 100));
3777       aopPut (AOP (IC_RESULT (ic)), "a", 0);
3778       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3779     }
3780 }
3781
3782 /*-----------------------------------------------------------------*/
3783 /* genMinus - generates code for subtraction                       */
3784 /*-----------------------------------------------------------------*/
3785 static void
3786 genMinus (iCode * ic)
3787 {
3788   int size, offset = 0;
3789   int rSize;
3790   unsigned long lit = 0L;
3791   bool pushResult = FALSE;
3792
3793   D (emitcode (";", "genMinus "););
3794
3795   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3796   aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
3797   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
3798       (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
3799     {
3800       pushResult = TRUE;
3801     }
3802   else
3803     {
3804       aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
3805
3806       /* special cases :- */
3807       /* if both left & right are in bit space */
3808       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3809           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3810         {
3811           genMinusBits (ic);
3812           goto release;
3813         }
3814
3815       /* if I can do an decrement instead
3816          of subtract then GOOD for ME */
3817       if (genMinusDec (ic) == TRUE)
3818         goto release;
3819
3820     }
3821
3822   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3823
3824   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3825     {
3826       CLRC;
3827     }
3828   else
3829     {
3830       lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3831       lit = -(long) lit;
3832     }
3833
3834
3835   /* if literal, add a,#-lit, else normal subb */
3836   _startLazyDPSEvaluation ();
3837   while (size--)
3838     {
3839       MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3840       if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3841         emitcode ("subb", "a,%s",
3842                   aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3843       else
3844         {
3845           /* first add without previous c */
3846           if (!offset)
3847             emitcode ("add", "a,#0x%02x",
3848                       (unsigned int) (lit & 0x0FFL));
3849           else
3850             emitcode ("addc", "a,#0x%02x",
3851                       (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3852         }
3853
3854       if (pushResult)
3855         {
3856           emitcode ("push", "acc");
3857         }
3858       else
3859         {
3860           aopPut (AOP (IC_RESULT (ic)), "a", offset);
3861         }
3862       offset++;
3863     }
3864   _endLazyDPSEvaluation ();
3865
3866   if (pushResult)
3867     {
3868       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3869
3870       size = getDataSize (IC_LEFT (ic));
3871       rSize = getDataSize (IC_RESULT (ic));
3872
3873       ADJUST_PUSHED_RESULT(size, rSize);
3874
3875       _startLazyDPSEvaluation ();
3876       while (size--)
3877         {
3878           emitcode ("pop", "acc");
3879           aopPut (AOP (IC_RESULT (ic)), "a", size);
3880         }
3881       _endLazyDPSEvaluation ();
3882     }
3883
3884   adjustArithmeticResult (ic);
3885
3886 release:
3887   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3888   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3889   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3890 }
3891
3892
3893 /*-----------------------------------------------------------------*/
3894 /* genMultbits :- multiplication of bits                           */
3895 /*-----------------------------------------------------------------*/
3896 static void
3897 genMultbits (operand * left,
3898              operand * right,
3899              operand * result)
3900 {
3901   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3902   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3903   outBitC (result);
3904 }
3905
3906
3907 /*-----------------------------------------------------------------*/
3908 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
3909 /*-----------------------------------------------------------------*/
3910 static void
3911 genMultOneByte (operand * left,
3912                 operand * right,
3913                 operand * result)
3914 {
3915   sym_link *opetype = operandType (result);
3916   symbol *lbl;
3917   int size=AOP_SIZE(result);
3918
3919   if (size<1 || size>2) {
3920     // this should never happen
3921       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
3922                AOP_SIZE(result), __FILE__, lineno);
3923       exit (1);
3924   }
3925
3926   /* (if two literals: the value is computed before) */
3927   /* if one literal, literal on the right */
3928   if (AOP_TYPE (left) == AOP_LIT)
3929     {
3930       operand *t = right;
3931       right = left;
3932       left = t;
3933       emitcode (";", "swapped left and right");
3934     }
3935
3936   if (SPEC_USIGN(opetype)
3937       // ignore the sign of left and right, what else can we do?
3938       || (SPEC_USIGN(operandType(left)) && 
3939           SPEC_USIGN(operandType(right)))) {
3940     // just an unsigned 8*8=8/16 multiply
3941     //emitcode (";","unsigned");
3942     emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3943     MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3944     emitcode ("mul", "ab");
3945     aopPut (AOP (result), "a", 0);
3946     if (size==2) {
3947       aopPut (AOP (result), "b", 1);
3948     }
3949     return;
3950   }
3951
3952   // we have to do a signed multiply
3953
3954   emitcode (";", "signed");
3955   emitcode ("clr", "F0"); // reset sign flag
3956   emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3957   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3958
3959   lbl=newiTempLabel(NULL);
3960   emitcode ("jnb", "acc.7,%05d$",  lbl->key+100);
3961   // left side is negative, 8-bit two's complement, this fails for -128
3962   emitcode ("setb", "F0"); // set sign flag
3963   emitcode ("cpl", "a");
3964   emitcode ("inc", "a");
3965
3966   emitcode ("", "%05d$:", lbl->key+100);
3967   emitcode ("xch", "a,b");
3968
3969   /* if literal */
3970   if (AOP_TYPE(right)==AOP_LIT) {
3971     /* AND literal negative */
3972     if ((int) floatFromVal (AOP (right)->aopu.aop_lit) < 0) {
3973       // two's complement for literal<0
3974       emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
3975       emitcode ("cpl", "a");
3976       emitcode ("inc", "a");
3977     }
3978   } else {
3979     lbl=newiTempLabel(NULL);
3980     emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3981     // right side is negative, 8-bit two's complement
3982     emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
3983     emitcode ("cpl", "a");
3984     emitcode ("inc", "a");
3985     emitcode ("", "%05d$:", lbl->key+100);
3986   }
3987   emitcode ("mul", "ab");
3988     
3989   lbl=newiTempLabel(NULL);
3990   emitcode ("jnb", "F0,%05d$", lbl->key+100);
3991   // only ONE op was negative, we have to do a 8/16-bit two's complement
3992   emitcode ("cpl", "a"); // lsb
3993   if (size==1) {
3994     emitcode ("inc", "a");
3995   } else {
3996     emitcode ("add", "a,#1");
3997     emitcode ("xch", "a,b");
3998     emitcode ("cpl", "a"); // msb
3999     emitcode ("addc", "a,#0");
4000     emitcode ("xch", "a,b");
4001   }
4002
4003   emitcode ("", "%05d$:", lbl->key+100);
4004   aopPut (AOP (result), "a", 0);
4005   if (size==2) {
4006     aopPut (AOP (result), "b", 1);
4007   }
4008 }
4009
4010 /*-----------------------------------------------------------------*/
4011 /* genMult - generates code for multiplication                     */
4012 /*-----------------------------------------------------------------*/
4013 static void
4014 genMult (iCode * ic)
4015 {
4016   operand *left = IC_LEFT (ic);
4017   operand *right = IC_RIGHT (ic);
4018   operand *result = IC_RESULT (ic);
4019
4020   D (emitcode (";", "genMult "););
4021
4022   /* assign the amsops */
4023   AOP_OP_3 (ic);
4024
4025   /* special cases first */
4026   /* both are bits */
4027   if (AOP_TYPE (left) == AOP_CRY &&
4028       AOP_TYPE (right) == AOP_CRY)
4029     {
4030       genMultbits (left, right, result);
4031       goto release;
4032     }
4033
4034   /* if both are of size == 1 */
4035   if (AOP_SIZE (left) == 1 &&
4036       AOP_SIZE (right) == 1)
4037     {
4038       genMultOneByte (left, right, result);
4039       goto release;
4040     }
4041
4042   /* should have been converted to function call */
4043   assert (1);
4044
4045 release:
4046   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4047   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4048   freeAsmop (result, NULL, ic, TRUE);
4049 }
4050
4051 /*-----------------------------------------------------------------*/
4052 /* genDivbits :- division of bits                                  */
4053 /*-----------------------------------------------------------------*/
4054 static void
4055 genDivbits (operand * left,
4056             operand * right,
4057             operand * result)
4058 {
4059
4060   char *l;
4061
4062   /* the result must be bit */
4063   LOAD_AB_FOR_DIV (left, right, l);
4064   emitcode ("div", "ab");
4065   emitcode ("rrc", "a");
4066   aopPut (AOP (result), "c", 0);
4067 }
4068
4069 /*-----------------------------------------------------------------*/
4070 /* genDivOneByte : 8 bit division                                  */
4071 /*-----------------------------------------------------------------*/
4072 static void
4073 genDivOneByte (operand * left,
4074                operand * right,
4075                operand * result)
4076 {
4077   sym_link *opetype = operandType (result);
4078   char *l;
4079   symbol *lbl;
4080   int size, offset;
4081
4082   size = AOP_SIZE (result) - 1;
4083   offset = 1;
4084   /* signed or unsigned */
4085   if (SPEC_USIGN (opetype))
4086     {
4087       /* unsigned is easy */
4088       LOAD_AB_FOR_DIV (left, right, l);
4089       emitcode ("div", "ab");
4090       aopPut (AOP (result), "a", 0);
4091       while (size--)
4092         aopPut (AOP (result), zero, offset++);
4093       return;
4094     }
4095
4096   /* signed is a little bit more difficult */
4097
4098   /* save the signs of the operands */
4099   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4100   MOVA (l);
4101   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4102   emitcode ("push", "acc");     /* save it on the stack */
4103
4104   /* now sign adjust for both left & right */
4105   l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4106   MOVA (l);
4107   lbl = newiTempLabel (NULL);
4108   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4109   emitcode ("cpl", "a");
4110   emitcode ("inc", "a");
4111   emitcode ("", "%05d$:", (lbl->key + 100));
4112   emitcode ("mov", "b,a");
4113
4114   /* sign adjust left side */
4115   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4116   MOVA (l);
4117
4118   lbl = newiTempLabel (NULL);
4119   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4120   emitcode ("cpl", "a");
4121   emitcode ("inc", "a");
4122   emitcode ("", "%05d$:", (lbl->key + 100));
4123
4124   /* now the division */
4125   emitcode ("nop", "; workaround for DS80C390 div bug.");
4126   emitcode ("div", "ab");
4127   /* we are interested in the lower order
4128      only */
4129   emitcode ("mov", "b,a");
4130   lbl = newiTempLabel (NULL);
4131   emitcode ("pop", "acc");
4132   /* if there was an over flow we don't
4133      adjust the sign of the result */
4134   emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4135   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4136   CLRC;
4137   emitcode ("clr", "a");
4138   emitcode ("subb", "a,b");
4139   emitcode ("mov", "b,a");
4140   emitcode ("", "%05d$:", (lbl->key + 100));
4141
4142   /* now we are done */
4143   aopPut (AOP (result), "b", 0);
4144   if (size > 0)
4145     {
4146       emitcode ("mov", "c,b.7");
4147       emitcode ("subb", "a,acc");
4148     }
4149   while (size--)
4150     aopPut (AOP (result), "a", offset++);
4151
4152 }
4153
4154 /*-----------------------------------------------------------------*/
4155 /* genDiv - generates code for division                            */
4156 /*-----------------------------------------------------------------*/
4157 static void
4158 genDiv (iCode * ic)
4159 {
4160   operand *left = IC_LEFT (ic);
4161   operand *right = IC_RIGHT (ic);
4162   operand *result = IC_RESULT (ic);
4163
4164   D (emitcode (";", "genDiv ");
4165     );
4166
4167   /* assign the amsops */
4168   AOP_OP_3 (ic);
4169
4170   /* special cases first */
4171   /* both are bits */
4172   if (AOP_TYPE (left) == AOP_CRY &&
4173       AOP_TYPE (right) == AOP_CRY)
4174     {
4175       genDivbits (left, right, result);
4176       goto release;
4177     }
4178
4179   /* if both are of size == 1 */
4180   if (AOP_SIZE (left) == 1 &&
4181       AOP_SIZE (right) == 1)
4182     {
4183       genDivOneByte (left, right, result);
4184       goto release;
4185     }
4186
4187   /* should have been converted to function call */
4188   assert (1);
4189 release:
4190   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4191   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4192   freeAsmop (result, NULL, ic, TRUE);
4193 }
4194
4195 /*-----------------------------------------------------------------*/
4196 /* genModbits :- modulus of bits                                   */
4197 /*-----------------------------------------------------------------*/
4198 static void
4199 genModbits (operand * left,
4200             operand * right,
4201             operand * result)
4202 {
4203
4204   char *l;
4205
4206   /* the result must be bit */
4207   LOAD_AB_FOR_DIV (left, right, l);
4208   emitcode ("div", "ab");
4209   emitcode ("mov", "a,b");
4210   emitcode ("rrc", "a");
4211   aopPut (AOP (result), "c", 0);
4212 }
4213
4214 /*-----------------------------------------------------------------*/
4215 /* genModOneByte : 8 bit modulus                                   */
4216 /*-----------------------------------------------------------------*/
4217 static void
4218 genModOneByte (operand * left,
4219                operand * right,
4220                operand * result)
4221 {
4222   sym_link *opetype = operandType (result);
4223   char *l;
4224   symbol *lbl;
4225
4226   /* signed or unsigned */
4227   if (SPEC_USIGN (opetype))
4228     {
4229       /* unsigned is easy */
4230       LOAD_AB_FOR_DIV (left, right, l);
4231       emitcode ("div", "ab");
4232       aopPut (AOP (result), "b", 0);
4233       return;
4234     }
4235
4236   /* signed is a little bit more difficult */
4237
4238   /* save the signs of the operands */
4239   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4240   MOVA (l);
4241
4242   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4243   emitcode ("push", "acc");     /* save it on the stack */
4244
4245   /* now sign adjust for both left & right */
4246   l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4247   MOVA (l);
4248
4249   lbl = newiTempLabel (NULL);
4250   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4251   emitcode ("cpl", "a");
4252   emitcode ("inc", "a");
4253   emitcode ("", "%05d$:", (lbl->key + 100));
4254   emitcode ("mov", "b,a");
4255
4256   /* sign adjust left side */
4257   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4258   MOVA (l);
4259
4260   lbl = newiTempLabel (NULL);
4261   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4262   emitcode ("cpl", "a");
4263   emitcode ("inc", "a");
4264   emitcode ("", "%05d$:", (lbl->key + 100));
4265
4266   /* now the multiplication */
4267   emitcode ("nop", "; workaround for DS80C390 div bug.");
4268   emitcode ("div", "ab");
4269   /* we are interested in the lower order
4270      only */
4271   lbl = newiTempLabel (NULL);
4272   emitcode ("pop", "acc");
4273   /* if there was an over flow we don't
4274      adjust the sign of the result */
4275   emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4276   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4277   CLRC;
4278   emitcode ("clr", "a");
4279   emitcode ("subb", "a,b");
4280   emitcode ("mov", "b,a");
4281   emitcode ("", "%05d$:", (lbl->key + 100));
4282
4283   /* now we are done */
4284   aopPut (AOP (result), "b", 0);
4285
4286 }
4287
4288 /*-----------------------------------------------------------------*/
4289 /* genMod - generates code for division                            */
4290 /*-----------------------------------------------------------------*/
4291 static void
4292 genMod (iCode * ic)
4293 {
4294   operand *left = IC_LEFT (ic);
4295   operand *right = IC_RIGHT (ic);
4296   operand *result = IC_RESULT (ic);
4297
4298   D (emitcode (";", "genMod ");
4299     );
4300
4301   /* assign the amsops */
4302   AOP_OP_3 (ic);
4303
4304   /* special cases first */
4305   /* both are bits */
4306   if (AOP_TYPE (left) == AOP_CRY &&
4307       AOP_TYPE (right) == AOP_CRY)
4308     {
4309       genModbits (left, right, result);
4310       goto release;
4311     }
4312
4313   /* if both are of size == 1 */
4314   if (AOP_SIZE (left) == 1 &&
4315       AOP_SIZE (right) == 1)
4316     {
4317       genModOneByte (left, right, result);
4318       goto release;
4319     }
4320
4321   /* should have been converted to function call */
4322   assert (1);
4323
4324 release:
4325   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4326   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4327   freeAsmop (result, NULL, ic, TRUE);
4328 }
4329
4330 /*-----------------------------------------------------------------*/
4331 /* genIfxJump :- will create a jump depending on the ifx           */
4332 /*-----------------------------------------------------------------*/
4333 static void
4334 genIfxJump (iCode * ic, char *jval)
4335 {
4336   symbol *jlbl;
4337   symbol *tlbl = newiTempLabel (NULL);
4338   char *inst;
4339
4340   D (emitcode (";", "genIfxJump ");
4341     );
4342
4343   /* if true label then we jump if condition
4344      supplied is true */
4345   if (IC_TRUE (ic))
4346     {
4347       jlbl = IC_TRUE (ic);
4348       inst = ((strcmp (jval, "a") == 0 ? "jz" :
4349                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4350     }
4351   else
4352     {
4353       /* false label is present */
4354       jlbl = IC_FALSE (ic);
4355       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4356                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4357     }
4358   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4359     emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4360   else
4361     emitcode (inst, "%05d$", tlbl->key + 100);
4362   emitcode ("ljmp", "%05d$", jlbl->key + 100);
4363   emitcode ("", "%05d$:", tlbl->key + 100);
4364
4365   /* mark the icode as generated */
4366   ic->generated = 1;
4367 }
4368
4369 /*-----------------------------------------------------------------*/
4370 /* genCmp :- greater or less than comparison                       */
4371 /*-----------------------------------------------------------------*/
4372 static void
4373 genCmp (operand * left, operand * right,
4374         iCode * ic, iCode * ifx, int sign)
4375 {
4376   int size, offset = 0;
4377   unsigned long lit = 0L;
4378   operand *result;
4379
4380   D (emitcode (";", "genCmp");
4381     );
4382
4383   result = IC_RESULT (ic);
4384
4385   /* if left & right are bit variables */
4386   if (AOP_TYPE (left) == AOP_CRY &&
4387       AOP_TYPE (right) == AOP_CRY)
4388     {
4389       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4390       emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
4391     }
4392   else
4393     {
4394       /* subtract right from left if at the
4395          end the carry flag is set then we know that
4396          left is greater than right */
4397       size = max (AOP_SIZE (left), AOP_SIZE (right));
4398
4399       /* if unsigned char cmp with lit, do cjne left,#right,zz */
4400       if ((size == 1) && !sign &&
4401           (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4402         {
4403           symbol *lbl = newiTempLabel (NULL);
4404           emitcode ("cjne", "%s,%s,%05d$",
4405                     aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
4406                     aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4407                     lbl->key + 100);
4408           emitcode ("", "%05d$:", lbl->key + 100);
4409         }
4410       else
4411         {
4412           if (AOP_TYPE (right) == AOP_LIT)
4413             {
4414               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4415               /* optimize if(x < 0) or if(x >= 0) */
4416               if (lit == 0L)
4417                 {
4418                   if (!sign)
4419                     {
4420                       CLRC;
4421                     }
4422                   else
4423                     {
4424                       MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
4425
4426                       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4427                       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4428
4429                       aopOp (result, ic, FALSE, FALSE);
4430
4431                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4432                         {
4433                           freeAsmop (result, NULL, ic, TRUE);
4434                           genIfxJump (ifx, "acc.7");
4435                           return;
4436                         }
4437                       else
4438                         {
4439                           emitcode ("rlc", "a");
4440                         }
4441                       goto release_freedLR;
4442                     }
4443                   goto release;
4444                 }
4445             }
4446           CLRC;
4447           while (size--)
4448             {
4449               emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
4450               MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4451               emitcode (";", "genCmp #2");
4452               if (sign && (size == 0))
4453                 {
4454                   emitcode (";", "genCmp #3");
4455                   emitcode ("xrl", "a,#0x80");
4456                   if (AOP_TYPE (right) == AOP_LIT)
4457                     {
4458                       unsigned long lit = (unsigned long)
4459                       floatFromVal (AOP (right)->aopu.aop_lit);
4460                       emitcode (";", "genCmp #3.1");
4461                       emitcode ("subb", "a,#0x%02x",
4462                                 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4463                     }
4464                   else
4465                     {
4466                       emitcode (";", "genCmp #3.2");
4467                       if (AOP_NEEDSACC (right))
4468                         {
4469                           emitcode ("push", "acc");
4470                         }
4471                       emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
4472                                                        FALSE, FALSE, FALSE));
4473                       emitcode ("xrl", "b,#0x80");
4474                       if (AOP_NEEDSACC (right))
4475                         {
4476                           emitcode ("pop", "acc");
4477                         }
4478                       emitcode ("subb", "a,b");
4479                     }
4480                 }
4481               else
4482                 {
4483                   const char *s;
4484
4485                   emitcode (";", "genCmp #4");
4486                   if (AOP_NEEDSACC (right))
4487                     {
4488                       /* Yuck!! */
4489                       emitcode (";", "genCmp #4.1");
4490                       emitcode ("xch", "a, b");
4491                       MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
4492                       emitcode ("xch", "a, b");
4493                       s = "b";
4494                     }
4495                   else
4496                     {
4497                       emitcode (";", "genCmp #4.2");
4498                       s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
4499                     }
4500
4501                   emitcode ("subb", "a,%s", s);
4502                 }
4503             }
4504         }
4505     }
4506
4507 release:
4508 /* Don't need the left & right operands any more; do need the result. */
4509   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4510   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4511
4512   aopOp (result, ic, FALSE, FALSE);
4513
4514 release_freedLR:
4515
4516   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4517     {
4518       outBitC (result);
4519     }
4520   else
4521     {
4522       /* if the result is used in the next
4523          ifx conditional branch then generate
4524          code a little differently */
4525       if (ifx)
4526         {
4527           genIfxJump (ifx, "c");
4528         }
4529       else
4530         {
4531           outBitC (result);
4532         }
4533       /* leave the result in acc */
4534     }
4535   freeAsmop (result, NULL, ic, TRUE);
4536 }
4537
4538 /*-----------------------------------------------------------------*/
4539 /* genCmpGt :- greater than comparison                             */
4540 /*-----------------------------------------------------------------*/
4541 static void
4542 genCmpGt (iCode * ic, iCode * ifx)
4543 {
4544   operand *left, *right;
4545   sym_link *letype, *retype;
4546   int sign;
4547
4548   D (emitcode (";", "genCmpGt ");
4549     );
4550
4551   left = IC_LEFT (ic);
4552   right = IC_RIGHT (ic);
4553
4554   letype = getSpec (operandType (left));
4555   retype = getSpec (operandType (right));
4556   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4557
4558   /* assign the left & right amsops */
4559   AOP_OP_2 (ic);
4560
4561   genCmp (right, left, ic, ifx, sign);
4562 }
4563
4564 /*-----------------------------------------------------------------*/
4565 /* genCmpLt - less than comparisons                                */
4566 /*-----------------------------------------------------------------*/
4567 static void
4568 genCmpLt (iCode * ic, iCode * ifx)
4569 {
4570   operand *left, *right;
4571   sym_link *letype, *retype;
4572   int sign;
4573
4574   D (emitcode (";", "genCmpLt "););
4575
4576   left = IC_LEFT (ic);
4577   right = IC_RIGHT (ic);
4578
4579   letype = getSpec (operandType (left));
4580   retype = getSpec (operandType (right));
4581   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4582
4583   /* assign the left & right amsops */
4584   AOP_OP_2 (ic);
4585
4586   genCmp (left, right, ic, ifx, sign);
4587 }
4588
4589 /*-----------------------------------------------------------------*/
4590 /* gencjneshort - compare and jump if not equal                    */
4591 /*-----------------------------------------------------------------*/
4592 static void
4593 gencjneshort (operand * left, operand * right, symbol * lbl)
4594 {
4595   int size = max (AOP_SIZE (left), AOP_SIZE (right));
4596   int offset = 0;
4597   unsigned long lit = 0L;
4598
4599   D (emitcode (";", "gencjneshort");
4600     );
4601
4602   /* if the left side is a literal or
4603      if the right is in a pointer register and left
4604      is not */
4605   if ((AOP_TYPE (left) == AOP_LIT) ||
4606       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4607     {
4608       operand *t = right;
4609       right = left;
4610       left = t;
4611     }
4612
4613   if (AOP_TYPE (right) == AOP_LIT)
4614     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4615
4616   if (opIsGptr (left) || opIsGptr (right))
4617     {
4618       /* We are comparing a generic pointer to something.
4619        * Exclude the generic type byte from the comparison.
4620        */
4621       size--;
4622       D (emitcode (";", "cjneshort: generic ptr special case.");
4623         )
4624     }
4625
4626
4627   /* if the right side is a literal then anything goes */
4628   if (AOP_TYPE (right) == AOP_LIT &&
4629       AOP_TYPE (left) != AOP_DIR)
4630     {
4631       while (size--)
4632         {
4633           char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4634           MOVA (l);
4635           emitcode ("cjne", "a,%s,%05d$",
4636                     aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4637                     lbl->key + 100);
4638           offset++;
4639         }
4640     }
4641
4642   /* if the right side is in a register or in direct space or
4643      if the left is a pointer register & right is not */
4644   else if (AOP_TYPE (right) == AOP_REG ||
4645            AOP_TYPE (right) == AOP_DIR ||
4646            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4647            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4648     {
4649       while (size--)
4650         {
4651           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4652           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4653               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4654             emitcode ("jnz", "%05d$", lbl->key + 100);
4655           else
4656             emitcode ("cjne", "a,%s,%05d$",
4657                       aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
4658                       lbl->key + 100);
4659           offset++;
4660         }
4661     }
4662   else
4663     {
4664       /* right is a pointer reg need both a & b */
4665       while (size--)
4666         {
4667           char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4668           if (strcmp (l, "b"))
4669             emitcode ("mov", "b,%s", l);
4670           MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
4671           emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4672           offset++;
4673         }
4674     }
4675 }
4676
4677 /*-----------------------------------------------------------------*/
4678 /* gencjne - compare and jump if not equal                         */
4679 /*-----------------------------------------------------------------*/
4680 static void
4681 gencjne (operand * left, operand * right, symbol * lbl)
4682 {
4683   symbol *tlbl = newiTempLabel (NULL);
4684
4685   D (emitcode (";", "gencjne");
4686     );
4687
4688   gencjneshort (left, right, lbl);
4689
4690   emitcode ("mov", "a,%s", one);
4691   emitcode ("sjmp", "%05d$", tlbl->key + 100);
4692   emitcode ("", "%05d$:", lbl->key + 100);
4693   emitcode ("clr", "a");
4694   emitcode ("", "%05d$:", tlbl->key + 100);
4695 }
4696
4697 /*-----------------------------------------------------------------*/
4698 /* genCmpEq - generates code for equal to                          */
4699 /*-----------------------------------------------------------------*/
4700 static void
4701 genCmpEq (iCode * ic, iCode * ifx)
4702 {
4703   operand *left, *right, *result;
4704
4705   D (emitcode (";", "genCmpEq ");
4706     );
4707
4708   AOP_OP_2 (ic);
4709   AOP_SET_LOCALS (ic);
4710
4711   /* if literal, literal on the right or
4712      if the right is in a pointer register and left
4713      is not */
4714   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4715       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4716     {
4717       operand *t = IC_RIGHT (ic);
4718       IC_RIGHT (ic) = IC_LEFT (ic);
4719       IC_LEFT (ic) = t;
4720     }
4721
4722   if (ifx &&                    /* !AOP_SIZE(result) */
4723       OP_SYMBOL (result) &&
4724       OP_SYMBOL (result)->regType == REG_CND)
4725     {
4726       symbol *tlbl;
4727       /* if they are both bit variables */
4728       if (AOP_TYPE (left) == AOP_CRY &&
4729           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4730         {
4731           if (AOP_TYPE (right) == AOP_LIT)
4732             {
4733               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4734               if (lit == 0L)
4735                 {
4736                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4737                   emitcode ("cpl", "c");
4738                 }
4739               else if (lit == 1L)
4740                 {
4741                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4742                 }
4743               else
4744                 {
4745                   emitcode ("clr", "c");
4746                 }
4747               /* AOP_TYPE(right) == AOP_CRY */
4748             }
4749           else
4750             {
4751               symbol *lbl = newiTempLabel (NULL);
4752               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4753               emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4754               emitcode ("cpl", "c");
4755               emitcode ("", "%05d$:", (lbl->key + 100));
4756             }
4757           /* if true label then we jump if condition
4758              supplied is true */
4759           tlbl = newiTempLabel (NULL);
4760           if (IC_TRUE (ifx))
4761             {
4762               emitcode ("jnc", "%05d$", tlbl->key + 100);
4763               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4764             }
4765           else
4766             {
4767               emitcode ("jc", "%05d$", tlbl->key + 100);
4768               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4769             }
4770           emitcode ("", "%05d$:", tlbl->key + 100);
4771         }
4772       else
4773         {
4774           tlbl = newiTempLabel (NULL);
4775           gencjneshort (left, right, tlbl);
4776           if (IC_TRUE (ifx))
4777             {
4778               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4779               emitcode ("", "%05d$:", tlbl->key + 100);
4780             }
4781           else
4782             {
4783               symbol *lbl = newiTempLabel (NULL);
4784               emitcode ("sjmp", "%05d$", lbl->key + 100);
4785               emitcode ("", "%05d$:", tlbl->key + 100);
4786               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4787               emitcode ("", "%05d$:", lbl->key + 100);
4788             }
4789         }
4790       /* mark the icode as generated */
4791       ifx->generated = 1;
4792
4793       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4794       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4795       return;
4796     }
4797
4798   /* if they are both bit variables */
4799   if (AOP_TYPE (left) == AOP_CRY &&
4800       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4801     {
4802       if (AOP_TYPE (right) == AOP_LIT)
4803         {
4804           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4805           if (lit == 0L)
4806             {
4807               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4808               emitcode ("cpl", "c");
4809             }
4810           else if (lit == 1L)
4811             {
4812               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4813             }
4814           else
4815             {
4816               emitcode ("clr", "c");
4817             }
4818           /* AOP_TYPE(right) == AOP_CRY */
4819         }
4820       else
4821         {
4822           symbol *lbl = newiTempLabel (NULL);
4823           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4824           emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4825           emitcode ("cpl", "c");
4826           emitcode ("", "%05d$:", (lbl->key + 100));
4827         }
4828
4829       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4830       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4831
4832       aopOp (result, ic, TRUE, FALSE);
4833
4834       /* c = 1 if egal */
4835       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4836         {
4837           outBitC (result);
4838           goto release;
4839         }
4840       if (ifx)
4841         {
4842           genIfxJump (ifx, "c");
4843           goto release;
4844         }
4845       /* if the result is used in an arithmetic operation
4846          then put the result in place */
4847       outBitC (result);
4848     }
4849   else
4850     {
4851       gencjne (left, right, newiTempLabel (NULL));
4852
4853       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4854       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4855
4856       aopOp (result, ic, TRUE, FALSE);
4857
4858       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4859         {
4860           aopPut (AOP (result), "a", 0);
4861           goto release;
4862         }
4863       if (ifx)
4864         {
4865           genIfxJump (ifx, "a");
4866           goto release;
4867         }
4868       /* if the result is used in an arithmetic operation
4869          then put the result in place */
4870       if (AOP_TYPE (result) != AOP_CRY)
4871         outAcc (result);
4872       /* leave the result in acc */
4873     }
4874
4875 release:
4876   freeAsmop (result, NULL, ic, TRUE);
4877 }
4878
4879 /*-----------------------------------------------------------------*/
4880 /* ifxForOp - returns the icode containing the ifx for operand     */
4881 /*-----------------------------------------------------------------*/
4882 static iCode *
4883 ifxForOp (operand * op, iCode * ic)
4884 {
4885   /* if true symbol then needs to be assigned */
4886   if (IS_TRUE_SYMOP (op))
4887     return NULL;
4888
4889   /* if this has register type condition and
4890      the next instruction is ifx with the same operand
4891      and live to of the operand is upto the ifx only then */
4892   if (ic->next &&
4893       ic->next->op == IFX &&
4894       IC_COND (ic->next)->key == op->key &&
4895       OP_SYMBOL (op)->liveTo <= ic->next->seq)
4896     return ic->next;
4897
4898   return NULL;
4899 }
4900 /*-----------------------------------------------------------------*/
4901 /* genAndOp - for && operation                                     */
4902 /*-----------------------------------------------------------------*/
4903 static void
4904 genAndOp (iCode * ic)
4905 {
4906   operand *left, *right, *result;
4907   symbol *tlbl;
4908
4909   D (emitcode (";", "genAndOp "););
4910
4911   /* note here that && operations that are in an
4912      if statement are taken away by backPatchLabels
4913      only those used in arthmetic operations remain */
4914   AOP_OP_2 (ic);
4915   AOP_SET_LOCALS (ic);
4916
4917   /* if both are bit variables */
4918   if (AOP_TYPE (left) == AOP_CRY &&
4919       AOP_TYPE (right) == AOP_CRY)
4920     {
4921       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4922       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4923       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4924       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4925   
4926       aopOp (result,ic,FALSE, FALSE);
4927       outBitC (result);
4928     }
4929   else
4930     {
4931       tlbl = newiTempLabel (NULL);
4932       toBoolean (left);
4933       emitcode ("jz", "%05d$", tlbl->key + 100);
4934       toBoolean (right);
4935       emitcode ("", "%05d$:", tlbl->key + 100);
4936       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4937       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4938   
4939       aopOp (result,ic,FALSE, FALSE);
4940       outBitAcc (result);
4941     }
4942     freeAsmop (result, NULL, ic, TRUE);
4943 }
4944
4945
4946 /*-----------------------------------------------------------------*/
4947 /* genOrOp - for || operation                                      */
4948 /*-----------------------------------------------------------------*/
4949 static void
4950 genOrOp (iCode * ic)
4951 {
4952   operand *left, *right, *result;
4953   symbol *tlbl;
4954
4955   D (emitcode (";", "genOrOp "););
4956
4957   /* note here that || operations that are in an
4958      if statement are taken away by backPatchLabels
4959      only those used in arthmetic operations remain */
4960   AOP_OP_2 (ic);
4961   AOP_SET_LOCALS (ic);
4962
4963   /* if both are bit variables */
4964   if (AOP_TYPE (left) == AOP_CRY &&
4965       AOP_TYPE (right) == AOP_CRY)
4966     {
4967       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4968       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4969       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4970       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4971   
4972       aopOp (result,ic,FALSE, FALSE);
4973       
4974       outBitC (result);
4975     }
4976   else
4977     {
4978       tlbl = newiTempLabel (NULL);
4979       toBoolean (left);
4980       emitcode ("jnz", "%05d$", tlbl->key + 100);
4981       toBoolean (right);
4982       emitcode ("", "%05d$:", tlbl->key + 100);
4983       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4984       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4985   
4986       aopOp (result,ic,FALSE, FALSE);
4987       
4988       outBitAcc (result);
4989     }
4990
4991   freeAsmop (result, NULL, ic, TRUE);
4992 }
4993
4994 /*-----------------------------------------------------------------*/
4995 /* isLiteralBit - test if lit == 2^n                               */
4996 /*-----------------------------------------------------------------*/
4997 static int
4998 isLiteralBit (unsigned long lit)
4999 {
5000   unsigned long pw[32] =
5001   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5002    0x100L, 0x200L, 0x400L, 0x800L,
5003    0x1000L, 0x2000L, 0x4000L, 0x8000L,
5004    0x10000L, 0x20000L, 0x40000L, 0x80000L,
5005    0x100000L, 0x200000L, 0x400000L, 0x800000L,
5006    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5007    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5008   int idx;
5009
5010   for (idx = 0; idx < 32; idx++)
5011     if (lit == pw[idx])
5012       return idx + 1;
5013   return 0;
5014 }
5015
5016 /*-----------------------------------------------------------------*/
5017 /* continueIfTrue -                                                */
5018 /*-----------------------------------------------------------------*/
5019 static void
5020 continueIfTrue (iCode * ic)
5021 {
5022   if (IC_TRUE (ic))
5023     emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5024   ic->generated = 1;
5025 }
5026
5027 /*-----------------------------------------------------------------*/
5028 /* jmpIfTrue -                                                     */
5029 /*-----------------------------------------------------------------*/
5030 static void
5031 jumpIfTrue (iCode * ic)
5032 {
5033   if (!IC_TRUE (ic))
5034     emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5035   ic->generated = 1;
5036 }
5037
5038 /*-----------------------------------------------------------------*/
5039 /* jmpTrueOrFalse -                                                */
5040 /*-----------------------------------------------------------------*/
5041 static void
5042 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
5043 {
5044   // ugly but optimized by peephole
5045   if (IC_TRUE (ic))
5046     {
5047       symbol *nlbl = newiTempLabel (NULL);
5048       emitcode ("sjmp", "%05d$", nlbl->key + 100);
5049       emitcode ("", "%05d$:", tlbl->key + 100);
5050       emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5051       emitcode ("", "%05d$:", nlbl->key + 100);
5052     }
5053   else
5054     {
5055       emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5056       emitcode ("", "%05d$:", tlbl->key + 100);
5057     }
5058   ic->generated = 1;
5059 }
5060
5061 // Generate code to perform a bit-wise logic operation
5062 // on two operands in far space (assumed to already have been 
5063 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
5064 // in far space. This requires pushing the result on the stack
5065 // then popping it into the result.
5066 static void
5067 genFarFarLogicOp(iCode *ic, char *logicOp)
5068 {
5069       int size, resultSize, compSize;
5070       int offset = 0;
5071       
5072       D(emitcode(";", "%s special case for 3 far operands.", logicOp););
5073       compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ? 
5074                   AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
5075       
5076       _startLazyDPSEvaluation();
5077       for (size = compSize; (size--); offset++)
5078       {
5079           MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
5080           emitcode ("mov", "%s, acc", DP2_RESULT_REG);
5081           MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
5082           
5083           emitcode (logicOp, "a,%s", DP2_RESULT_REG);
5084           emitcode ("push", "acc");
5085       }
5086       _endLazyDPSEvaluation();
5087      
5088       freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5089       freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5090       aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
5091      
5092       resultSize = AOP_SIZE(IC_RESULT(ic));
5093
5094       ADJUST_PUSHED_RESULT(compSize, resultSize);
5095
5096       _startLazyDPSEvaluation();
5097       while (compSize--)
5098       {
5099           emitcode ("pop", "acc");
5100           aopPut (AOP (IC_RESULT (ic)), "a", compSize);
5101       }
5102       _endLazyDPSEvaluation();
5103       freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
5104 }
5105
5106
5107 /*-----------------------------------------------------------------*/
5108 /* genAnd  - code for and                                          */
5109 /*-----------------------------------------------------------------*/
5110 static void
5111 genAnd (iCode * ic, iCode * ifx)
5112 {
5113   operand *left, *right, *result;
5114   int size, offset = 0;
5115   unsigned long lit = 0L;
5116   int bytelit = 0;
5117   char buffer[10];
5118   bool pushResult;
5119
5120   D (emitcode (";", "genAnd "););
5121
5122   AOP_OP_3_NOFATAL (ic, pushResult);
5123   AOP_SET_LOCALS (ic);
5124
5125   if (pushResult)
5126   {
5127       genFarFarLogicOp(ic, "anl");
5128       return;
5129   }  
5130
5131 #ifdef DEBUG_TYPE
5132   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5133             AOP_TYPE (result),
5134             AOP_TYPE (left), AOP_TYPE (right));
5135   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5136             AOP_SIZE (result),
5137             AOP_SIZE (left), AOP_SIZE (right));
5138 #endif
5139
5140   /* if left is a literal & right is not then exchange them */
5141   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5142       AOP_NEEDSACC (left))
5143     {
5144       operand *tmp = right;
5145       right = left;
5146       left = tmp;
5147     }
5148
5149   /* if result = right then exchange them */
5150   if (sameRegs (AOP (result), AOP (right)))
5151     {
5152       operand *tmp = right;
5153       right = left;
5154       left = tmp;
5155     }
5156
5157   /* if right is bit then exchange them */
5158   if (AOP_TYPE (right) == AOP_CRY &&
5159       AOP_TYPE (left) != AOP_CRY)
5160     {
5161       operand *tmp = right;
5162       right = left;
5163       left = tmp;
5164     }
5165   if (AOP_TYPE (right) == AOP_LIT)
5166     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5167
5168   size = AOP_SIZE (result);
5169
5170   // if(bit & yy)
5171   // result = bit & yy;
5172   if (AOP_TYPE (left) == AOP_CRY)
5173     {
5174       // c = bit & literal;
5175       if (AOP_TYPE (right) == AOP_LIT)
5176         {
5177           if (lit & 1)
5178             {
5179               if (size && sameRegs (AOP (result), AOP (left)))
5180                 // no change
5181                 goto release;
5182               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5183             }
5184           else
5185             {
5186               // bit(result) = 0;
5187               if (size && (AOP_TYPE (result) == AOP_CRY))
5188                 {
5189                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5190                   goto release;
5191                 }
5192               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5193                 {
5194                   jumpIfTrue (ifx);
5195                   goto release;
5196                 }
5197               emitcode ("clr", "c");
5198             }
5199         }
5200       else
5201         {
5202           if (AOP_TYPE (right) == AOP_CRY)
5203             {
5204               // c = bit & bit;
5205               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5206               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5207             }
5208           else
5209             {
5210               // c = bit & val;
5211               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
5212               // c = lsb
5213               emitcode ("rrc", "a");
5214               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5215             }
5216         }
5217       // bit = c
5218       // val = c
5219       if (size)
5220         outBitC (result);
5221       // if(bit & ...)
5222       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5223         genIfxJump (ifx, "c");
5224       goto release;
5225     }
5226
5227   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5228   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5229   if ((AOP_TYPE (right) == AOP_LIT) &&
5230       (AOP_TYPE (result) == AOP_CRY) &&
5231       (AOP_TYPE (left) != AOP_CRY))
5232     {
5233       int posbit = isLiteralBit (lit);
5234       /* left &  2^n */
5235       if (posbit)
5236         {
5237           posbit--;
5238           MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
5239           // bit = left & 2^n
5240           if (size)
5241             emitcode ("mov", "c,acc.%d", posbit & 0x07);
5242           // if(left &  2^n)
5243           else
5244             {
5245               if (ifx)
5246                 {
5247                   sprintf (buffer, "acc.%d", posbit & 0x07);
5248                   genIfxJump (ifx, buffer);
5249                 }
5250               goto release;
5251             }
5252         }
5253       else
5254         {
5255           symbol *tlbl = newiTempLabel (NULL);
5256           int sizel = AOP_SIZE (left);
5257           if (size)
5258             emitcode ("setb", "c");
5259           while (sizel--)
5260             {
5261               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5262                 {
5263                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5264                   // byte ==  2^n ?
5265                   if ((posbit = isLiteralBit (bytelit)) != 0)
5266                     emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5267                   else
5268                     {
5269                       if (bytelit != 0x0FFL)
5270                         emitcode ("anl", "a,%s",
5271                           aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
5272                       emitcode ("jnz", "%05d$", tlbl->key + 100);
5273                     }
5274                 }
5275               offset++;
5276             }
5277           // bit = left & literal
5278           if (size)
5279             {
5280               emitcode ("clr", "c");
5281               emitcode ("", "%05d$:", tlbl->key + 100);
5282             }
5283           // if(left & literal)
5284           else
5285             {
5286               if (ifx)
5287                 jmpTrueOrFalse (ifx, tlbl);
5288               goto release;
5289             }
5290         }
5291       outBitC (result);
5292       goto release;
5293     }
5294
5295   /* if left is same as result */
5296   if (sameRegs (AOP (result), AOP (left)))
5297     {
5298       for (; size--; offset++)
5299         {
5300           if (AOP_TYPE (right) == AOP_LIT)
5301             {
5302               if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5303                 continue;
5304               else if (bytelit == 0)
5305                 aopPut (AOP (result), zero, offset);
5306               else if (IS_AOP_PREG (result))
5307                 {
5308                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5309                   emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5310                   aopPut (AOP (result), "a", offset);
5311                 }
5312               else
5313                 emitcode ("anl", "%s,%s",
5314                           aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5315                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5316             }
5317           else
5318             {
5319               if (AOP_TYPE (left) == AOP_ACC)
5320                 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5321               else
5322                 {
5323                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5324                   if (IS_AOP_PREG (result))
5325                     {
5326                       emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5327                       aopPut (AOP (result), "a", offset);
5328
5329                     }
5330                   else
5331                     emitcode ("anl", "%s,a",
5332                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5333                 }
5334             }
5335         }
5336     }
5337   else
5338     {
5339       // left & result in different registers
5340       if (AOP_TYPE (result) == AOP_CRY)
5341         {
5342           // result = bit
5343           // if(size), result in bit
5344           // if(!size && ifx), conditional oper: if(left & right)
5345           symbol *tlbl = newiTempLabel (NULL);
5346           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5347           if (size)
5348             emitcode ("setb", "c");
5349           while (sizer--)
5350             {
5351               MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5352               emitcode ("anl", "a,%s",
5353                         aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5354               emitcode ("jnz", "%05d$", tlbl->key + 100);
5355               offset++;
5356             }
5357           if (size)
5358             {
5359               CLRC;
5360               emitcode ("", "%05d$:", tlbl->key + 100);
5361               outBitC (result);
5362             }
5363           else if (ifx)
5364             jmpTrueOrFalse (ifx, tlbl);
5365         }
5366       else
5367         {
5368           for (; (size--); offset++)
5369             {
5370               // normal case
5371               // result = left & right
5372               if (AOP_TYPE (right) == AOP_LIT)
5373                 {
5374                   if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5375                     {
5376                       aopPut (AOP (result),
5377                            aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5378                               offset);
5379                       continue;
5380                     }
5381                   else if (bytelit == 0)
5382                     {
5383                       aopPut (AOP (result), zero, offset);
5384                       continue;
5385                     }
5386                   D (emitcode (";", "better literal AND.");
5387                     );
5388                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5389                   emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
5390                                                     FALSE, FALSE, FALSE));
5391
5392                 }
5393               else
5394                 {
5395                   // faster than result <- left, anl result,right
5396                   // and better if result is SFR
5397                   if (AOP_TYPE (left) == AOP_ACC)
5398                     {
5399                       emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
5400                                                        FALSE, FALSE, FALSE));
5401                     }
5402                   else
5403                     {
5404                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5405                       emitcode ("anl", "a,%s",
5406                           aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5407                     }
5408                 }
5409               aopPut (AOP (result), "a", offset);
5410             }
5411         }
5412     }
5413
5414 release:
5415   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5416   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5417   freeAsmop (result, NULL, ic, TRUE);
5418 }
5419
5420
5421 /*-----------------------------------------------------------------*/
5422 /* genOr  - code for or                                            */
5423 /*-----------------------------------------------------------------*/
5424 static void
5425 genOr (iCode * ic, iCode * ifx)
5426 {
5427   operand *left, *right, *result;
5428   int size, offset = 0;
5429   unsigned long lit = 0L;
5430   bool     pushResult;
5431
5432   D (emitcode (";", "genOr "););
5433
5434   AOP_OP_3_NOFATAL (ic, pushResult);
5435   AOP_SET_LOCALS (ic);
5436
5437   if (pushResult)
5438   {
5439       genFarFarLogicOp(ic, "orl");
5440       return;
5441   }
5442
5443
5444 #ifdef DEBUG_TYPE
5445   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5446             AOP_TYPE (result),
5447             AOP_TYPE (left), AOP_TYPE (right));
5448   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5449             AOP_SIZE (result),
5450             AOP_SIZE (left), AOP_SIZE (right));
5451 #endif
5452
5453   /* if left is a literal & right is not then exchange them */
5454   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5455       AOP_NEEDSACC (left))
5456     {
5457       operand *tmp = right;
5458       right = left;
5459       left = tmp;
5460     }
5461
5462   /* if result = right then exchange them */
5463   if (sameRegs (AOP (result), AOP (right)))
5464     {
5465       operand *tmp = right;
5466       right = left;
5467       left = tmp;
5468     }
5469
5470   /* if right is bit then exchange them */
5471   if (AOP_TYPE (right) == AOP_CRY &&
5472       AOP_TYPE (left) != AOP_CRY)
5473     {
5474       operand *tmp = right;
5475       right = left;
5476       left = tmp;
5477     }
5478   if (AOP_TYPE (right) == AOP_LIT)
5479     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5480
5481   size = AOP_SIZE (result);
5482
5483   // if(bit | yy)
5484   // xx = bit | yy;
5485   if (AOP_TYPE (left) == AOP_CRY)
5486     {
5487       if (AOP_TYPE (right) == AOP_LIT)
5488         {
5489           // c = bit & literal;
5490           if (lit)
5491             {
5492               // lit != 0 => result = 1
5493               if (AOP_TYPE (result) == AOP_CRY)
5494                 {
5495                   if (size)
5496                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5497                   else if (ifx)
5498                     continueIfTrue (ifx);
5499                   goto release;
5500                 }
5501               emitcode ("setb", "c");
5502             }
5503           else
5504             {
5505               // lit == 0 => result = left
5506               if (size && sameRegs (AOP (result), AOP (left)))
5507                 goto release;
5508               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5509             }
5510         }
5511       else
5512         {
5513           if (AOP_TYPE (right) == AOP_CRY)
5514             {
5515               // c = bit | bit;
5516               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5517               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5518             }
5519           else
5520             {
5521               // c = bit | val;
5522               symbol *tlbl = newiTempLabel (NULL);
5523               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5524                 emitcode ("setb", "c");
5525               emitcode ("jb", "%s,%05d$",
5526                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
5527               toBoolean (right);
5528               emitcode ("jnz", "%05d$", tlbl->key + 100);
5529               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5530                 {
5531                   jmpTrueOrFalse (ifx, tlbl);
5532                   goto release;
5533                 }
5534               else
5535                 {
5536                   CLRC;
5537                   emitcode ("", "%05d$:", tlbl->key + 100);
5538                 }
5539             }
5540         }
5541       // bit = c
5542       // val = c
5543       if (size)
5544         outBitC (result);
5545       // if(bit | ...)
5546       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5547         genIfxJump (ifx, "c");
5548       goto release;
5549     }
5550
5551   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5552   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5553   if ((AOP_TYPE (right) == AOP_LIT) &&
5554       (AOP_TYPE (result) == AOP_CRY) &&
5555       (AOP_TYPE (left) != AOP_CRY))
5556     {
5557       if (lit)
5558         {
5559           // result = 1
5560           if (size)
5561             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5562           else
5563             continueIfTrue (ifx);
5564           goto release;
5565         }
5566       else
5567         {
5568           // lit = 0, result = boolean(left)
5569           if (size)
5570             emitcode ("setb", "c");
5571           toBoolean (right);
5572           if (size)
5573             {
5574               symbol *tlbl = newiTempLabel (NULL);
5575               emitcode ("jnz", "%05d$", tlbl->key + 100);
5576               CLRC;
5577               emitcode ("", "%05d$:", tlbl->key + 100);
5578             }
5579           else
5580             {
5581               genIfxJump (ifx, "a");
5582               goto release;
5583             }
5584         }
5585       outBitC (result);
5586       goto release;
5587     }
5588
5589   /* if left is same as result */
5590   if (sameRegs (AOP (result), AOP (left)))
5591     {
5592       for (; size--; offset++)
5593         {
5594           if (AOP_TYPE (right) == AOP_LIT)
5595             {
5596               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5597                 {
5598                   continue;
5599                 }
5600               else
5601                 {
5602                   if (IS_AOP_PREG (left))
5603                     {
5604                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5605                       emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5606                       aopPut (AOP (result), "a", offset);
5607                     }
5608                   else
5609                     {
5610                       emitcode ("orl", "%s,%s",
5611                             aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5612                          aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5613                     }
5614                 }
5615             }
5616           else
5617             {
5618               if (AOP_TYPE (left) == AOP_ACC)
5619                 {
5620                   emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5621                 }
5622               else
5623                 {
5624                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5625                   if (IS_AOP_PREG (left))
5626                     {
5627                       emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5628                       aopPut (AOP (result), "a", offset);
5629                     }
5630                   else
5631                     {
5632                       emitcode ("orl", "%s,a",
5633                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5634                     }
5635                 }
5636             }
5637         }
5638     }
5639   else
5640     {
5641       // left & result in different registers
5642       if (AOP_TYPE (result) == AOP_CRY)
5643         {
5644           // result = bit
5645           // if(size), result in bit
5646           // if(!size && ifx), conditional oper: if(left | right)
5647           symbol *tlbl = newiTempLabel (NULL);
5648           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5649           if (size)
5650             emitcode ("setb", "c");
5651           while (sizer--)
5652             {
5653               MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5654               emitcode ("orl", "a,%s",
5655                         aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5656               emitcode ("jnz", "%05d$", tlbl->key + 100);
5657               offset++;
5658             }
5659           if (size)
5660             {
5661               CLRC;
5662               emitcode ("", "%05d$:", tlbl->key + 100);
5663               outBitC (result);
5664             }
5665           else if (ifx)
5666             jmpTrueOrFalse (ifx, tlbl);
5667         }
5668       else
5669         {
5670           for (; (size--); offset++)
5671             {
5672               // normal case
5673               // result = left & right
5674               if (AOP_TYPE (right) == AOP_LIT)
5675                 {
5676                   if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5677                     {
5678                       aopPut (AOP (result),
5679                            aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5680                               offset);
5681                       continue;
5682                     }
5683                   D (emitcode (";", "better literal OR.");
5684                     );
5685                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5686                   emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
5687                                                     FALSE, FALSE, FALSE));
5688
5689                 }
5690               else
5691                 {
5692                   // faster than result <- left, anl result,right
5693                   // and better if result is SFR
5694                   if (AOP_TYPE (left) == AOP_ACC)
5695                     {
5696                       emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
5697                                                        FALSE, FALSE, FALSE));
5698                     }
5699                   else
5700                     {
5701                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5702                       emitcode ("orl", "a,%s",
5703                           aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5704                     }
5705                 }
5706               aopPut (AOP (result), "a", offset);
5707             }
5708         }
5709     }
5710
5711 release:
5712   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5713   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5714   freeAsmop (result, NULL, ic, TRUE);
5715 }
5716
5717 /*-----------------------------------------------------------------*/
5718 /* genXor - code for xclusive or                                   */
5719 /*-----------------------------------------------------------------*/
5720 static void
5721 genXor (iCode * ic, iCode * ifx)
5722 {
5723   operand *left, *right, *result;
5724   int size, offset = 0;
5725   unsigned long lit = 0L;
5726   bool pushResult;
5727
5728   D (emitcode (";", "genXor "););
5729
5730   AOP_OP_3_NOFATAL (ic, pushResult);
5731   AOP_SET_LOCALS (ic);
5732
5733   if (pushResult)
5734   {
5735       genFarFarLogicOp(ic, "xrl");
5736       return;
5737   }  
5738
5739 #ifdef DEBUG_TYPE
5740   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5741             AOP_TYPE (result),
5742             AOP_TYPE (left), AOP_TYPE (right));
5743   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5744             AOP_SIZE (result),
5745             AOP_SIZE (left), AOP_SIZE (right));
5746 #endif
5747
5748   /* if left is a literal & right is not ||
5749      if left needs acc & right does not */
5750   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5751       (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5752     {
5753       operand *tmp = right;
5754       right = left;
5755       left = tmp;
5756     }
5757
5758   /* if result = right then exchange them */
5759   if (sameRegs (AOP (result), AOP (right)))
5760     {
5761       operand *tmp = right;
5762       right = left;
5763       left = tmp;
5764     }
5765
5766   /* if right is bit then exchange them */
5767   if (AOP_TYPE (right) == AOP_CRY &&
5768       AOP_TYPE (left) != AOP_CRY)
5769     {
5770       operand *tmp = right;
5771       right = left;
5772       left = tmp;
5773     }
5774   if (AOP_TYPE (right) == AOP_LIT)
5775     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5776
5777   size = AOP_SIZE (result);
5778
5779   // if(bit ^ yy)
5780   // xx = bit ^ yy;
5781   if (AOP_TYPE (left) == AOP_CRY)
5782     {
5783       if (AOP_TYPE (right) == AOP_LIT)
5784         {
5785           // c = bit & literal;
5786           if (lit >> 1)
5787             {
5788               // lit>>1  != 0 => result = 1
5789               if (AOP_TYPE (result) == AOP_CRY)
5790                 {
5791                   if (size)
5792                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5793                   else if (ifx)
5794                     continueIfTrue (ifx);
5795                   goto release;
5796                 }
5797               emitcode ("setb", "c");
5798             }
5799           else
5800             {
5801               // lit == (0 or 1)
5802               if (lit == 0)
5803                 {
5804                   // lit == 0, result = left
5805                   if (size && sameRegs (AOP (result), AOP (left)))
5806                     goto release;
5807                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5808                 }
5809               else
5810                 {
5811                   // lit == 1, result = not(left)
5812                   if (size && sameRegs (AOP (result), AOP (left)))
5813                     {
5814                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5815                       goto release;
5816                     }
5817                   else
5818                     {
5819                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5820                       emitcode ("cpl", "c");
5821                     }
5822                 }
5823             }
5824
5825         }
5826       else
5827         {
5828           // right != literal
5829           symbol *tlbl = newiTempLabel (NULL);
5830           if (AOP_TYPE (right) == AOP_CRY)
5831             {
5832               // c = bit ^ bit;
5833               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5834             }
5835           else
5836             {
5837               int sizer = AOP_SIZE (right);
5838               // c = bit ^ val
5839               // if val>>1 != 0, result = 1
5840               emitcode ("setb", "c");
5841               while (sizer)
5842                 {
5843                   MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
5844                   if (sizer == 1)
5845                     // test the msb of the lsb
5846                     emitcode ("anl", "a,#0xfe");
5847                   emitcode ("jnz", "%05d$", tlbl->key + 100);
5848                   sizer--;
5849                 }
5850               // val = (0,1)
5851               emitcode ("rrc", "a");
5852             }
5853           emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5854           emitcode ("cpl", "c");
5855           emitcode ("", "%05d$:", (tlbl->key + 100));
5856         }
5857       // bit = c
5858       // val = c
5859       if (size)
5860         outBitC (result);
5861       // if(bit | ...)
5862       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5863         genIfxJump (ifx, "c");
5864       goto release;
5865     }
5866
5867   if (sameRegs (AOP (result), AOP (left)))
5868     {
5869       /* if left is same as result */
5870       for (; size--; offset++)
5871         {
5872           if (AOP_TYPE (right) == AOP_LIT)
5873             {
5874               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5875                 continue;
5876               else if (IS_AOP_PREG (left))
5877                 {
5878                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5879                   emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5880                   aopPut (AOP (result), "a", offset);
5881                 }
5882               else
5883                 emitcode ("xrl", "%s,%s",
5884                           aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5885                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5886             }
5887           else
5888             {
5889               if (AOP_TYPE (left) == AOP_ACC)
5890                 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5891               else
5892                 {
5893                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5894                   if (IS_AOP_PREG (left))
5895                     {
5896                       emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5897                       aopPut (AOP (result), "a", offset);
5898                     }
5899                   else
5900                     emitcode ("xrl", "%s,a",
5901                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5902                 }
5903             }
5904         }
5905     }
5906   else
5907     {
5908       // left & result in different registers
5909       if (AOP_TYPE (result) == AOP_CRY)
5910         {
5911           // result = bit
5912           // if(size), result in bit
5913           // if(!size && ifx), conditional oper: if(left ^ right)
5914           symbol *tlbl = newiTempLabel (NULL);
5915           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5916           if (size)
5917             emitcode ("setb", "c");
5918           while (sizer--)
5919             {
5920               if ((AOP_TYPE (right) == AOP_LIT) &&
5921                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5922                 {
5923                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5924                 }
5925               else
5926                 {
5927                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5928                   emitcode ("xrl", "a,%s",
5929                           aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5930                 }
5931               emitcode ("jnz", "%05d$", tlbl->key + 100);
5932               offset++;
5933             }
5934           if (size)
5935             {
5936               CLRC;
5937               emitcode ("", "%05d$:", tlbl->key + 100);
5938               outBitC (result);
5939             }
5940           else if (ifx)
5941             jmpTrueOrFalse (ifx, tlbl);
5942         }
5943       else
5944         for (; (size--); offset++)
5945           {
5946             // normal case
5947             // result = left & right
5948             if (AOP_TYPE (right) == AOP_LIT)
5949               {
5950                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5951                   {
5952                     aopPut (AOP (result),
5953                             aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5954                             offset);
5955                     continue;
5956                   }
5957                 D (emitcode (";", "better literal XOR.");
5958                   );
5959                 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5960                 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
5961                                                   FALSE, FALSE, FALSE));
5962               }
5963             else
5964               {
5965                 // faster than result <- left, anl result,right
5966                 // and better if result is SFR
5967                 if (AOP_TYPE (left) == AOP_ACC)
5968                   {
5969                     emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
5970                                                      FALSE, FALSE, FALSE));
5971                   }
5972                 else
5973                   {
5974                     MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5975                     emitcode ("xrl", "a,%s",
5976                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5977                   }
5978               }
5979             aopPut (AOP (result), "a", offset);
5980           }
5981     }
5982
5983 release:
5984   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5985   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5986   freeAsmop (result, NULL, ic, TRUE);
5987 }
5988
5989 /*-----------------------------------------------------------------*/
5990 /* genInline - write the inline code out                           */
5991 /*-----------------------------------------------------------------*/
5992 static void
5993 genInline (iCode * ic)
5994 {
5995   char *buffer, *bp, *bp1;
5996
5997   D (emitcode (";", "genInline ");
5998     );
5999
6000   _G.inLine += (!options.asmpeep);
6001
6002   buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6003   strcpy (buffer, IC_INLINE (ic));
6004
6005   /* emit each line as a code */
6006   while (*bp)
6007     {
6008       if (*bp == '\n')
6009         {
6010           *bp++ = '\0';
6011           emitcode (bp1, "");
6012           bp1 = bp;
6013         }
6014       else
6015         {
6016           if (*bp == ':')
6017             {
6018               bp++;
6019               *bp = '\0';
6020               bp++;
6021               emitcode (bp1, "");
6022               bp1 = bp;
6023             }
6024           else
6025             bp++;
6026         }
6027     }
6028   if (bp1 != bp)
6029     emitcode (bp1, "");
6030   /*     emitcode("",buffer); */
6031   _G.inLine -= (!options.asmpeep);
6032 }
6033
6034 /*-----------------------------------------------------------------*/
6035 /* genRRC - rotate right with carry                                */
6036 /*-----------------------------------------------------------------*/
6037 static void
6038 genRRC (iCode * ic)
6039 {
6040   operand *left, *result;
6041   int size, offset = 0;
6042   char *l;
6043
6044   D (emitcode (";", "genRRC ");
6045     );
6046
6047   /* rotate right with carry */
6048   left = IC_LEFT (ic);
6049   result = IC_RESULT (ic);
6050   aopOp (left, ic, FALSE, FALSE);
6051   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6052
6053   /* move it to the result */
6054   size = AOP_SIZE (result);
6055   offset = size - 1;
6056   CLRC;
6057
6058   _startLazyDPSEvaluation ();
6059   while (size--)
6060     {
6061       l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6062       MOVA (l);
6063       emitcode ("rrc", "a");
6064       if (AOP_SIZE (result) > 1)
6065         aopPut (AOP (result), "a", offset--);
6066     }
6067   _endLazyDPSEvaluation ();
6068
6069   /* now we need to put the carry into the
6070      highest order byte of the result */
6071   if (AOP_SIZE (result) > 1)
6072     {
6073       l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
6074       MOVA (l);
6075     }
6076   emitcode ("mov", "acc.7,c");
6077   aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
6078   freeAsmop (left, NULL, ic, TRUE);
6079   freeAsmop (result, NULL, ic, TRUE);
6080 }
6081
6082 /*-----------------------------------------------------------------*/
6083 /* genRLC - generate code for rotate left with carry               */
6084 /*-----------------------------------------------------------------*/
6085 static void
6086 genRLC (iCode * ic)
6087 {
6088   operand *left, *result;
6089   int size, offset = 0;
6090   char *l;
6091
6092   D (emitcode (";", "genRLC ");
6093     );
6094
6095   /* rotate right with carry */
6096   left = IC_LEFT (ic);
6097   result = IC_RESULT (ic);
6098   aopOp (left, ic, FALSE, FALSE);
6099   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6100
6101   /* move it to the result */
6102   size = AOP_SIZE (result);
6103   offset = 0;
6104   if (size--)
6105     {
6106       l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6107       MOVA (l);
6108       emitcode ("add", "a,acc");
6109       if (AOP_SIZE (result) > 1)
6110         {
6111           aopPut (AOP (result), "a", offset++);
6112         }
6113
6114       _startLazyDPSEvaluation ();
6115       while (size--)
6116         {
6117           l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6118           MOVA (l);
6119           emitcode ("rlc", "a");
6120           if (AOP_SIZE (result) > 1)
6121             aopPut (AOP (result), "a", offset++);
6122         }
6123       _endLazyDPSEvaluation ();
6124     }
6125   /* now we need to put the carry into the
6126      highest order byte of the result */
6127   if (AOP_SIZE (result) > 1)
6128     {
6129       l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
6130       MOVA (l);
6131     }
6132   emitcode ("mov", "acc.0,c");
6133   aopPut (AOP (result), "a", 0);
6134   freeAsmop (left, NULL, ic, TRUE);
6135   freeAsmop (result, NULL, ic, TRUE);
6136 }
6137
6138 /*-----------------------------------------------------------------*/
6139 /* genGetHbit - generates code get highest order bit               */
6140 /*-----------------------------------------------------------------*/
6141 static void
6142 genGetHbit (iCode * ic)
6143 {
6144   operand *left, *result;
6145   left = IC_LEFT (ic);
6146   result = IC_RESULT (ic);
6147   aopOp (left, ic, FALSE, FALSE);
6148   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6149
6150   D (emitcode (";", "genGetHbit ");
6151     );
6152
6153   /* get the highest order byte into a */
6154   MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
6155   if (AOP_TYPE (result) == AOP_CRY)
6156     {
6157       emitcode ("rlc", "a");
6158       outBitC (result);
6159     }
6160   else
6161     {
6162       emitcode ("rl", "a");
6163       emitcode ("anl", "a,#0x01");
6164       outAcc (result);
6165     }
6166
6167
6168   freeAsmop (left, NULL, ic, TRUE);
6169   freeAsmop (result, NULL, ic, TRUE);
6170 }
6171
6172 /*-----------------------------------------------------------------*/
6173 /* AccRol - rotate left accumulator by known count                 */
6174 /*-----------------------------------------------------------------*/
6175 static void
6176 AccRol (int shCount)
6177 {
6178   shCount &= 0x0007;            // shCount : 0..7
6179
6180   switch (shCount)
6181     {
6182     case 0:
6183       break;
6184     case 1:
6185       emitcode ("rl", "a");
6186       break;
6187     case 2:
6188       emitcode ("rl", "a");
6189       emitcode ("rl", "a");
6190       break;
6191     case 3:
6192       emitcode ("swap", "a");
6193       emitcode ("rr", "a");
6194       break;
6195     case 4:
6196       emitcode ("swap", "a");
6197       break;
6198     case 5:
6199       emitcode ("swap", "a");
6200       emitcode ("rl", "a");
6201       break;
6202     case 6:
6203       emitcode ("rr", "a");
6204       emitcode ("rr", "a");
6205       break;
6206     case 7:
6207       emitcode ("rr", "a");
6208       break;
6209     }
6210 }
6211
6212 /*-----------------------------------------------------------------*/
6213 /* AccLsh - left shift accumulator by known count                  */
6214 /*-----------------------------------------------------------------*/
6215 static void
6216 AccLsh (int shCount)
6217 {
6218   if (shCount != 0)
6219     {
6220       if (shCount == 1)
6221         emitcode ("add", "a,acc");
6222       else if (shCount == 2)
6223         {
6224           emitcode ("add", "a,acc");
6225           emitcode ("add", "a,acc");
6226         }
6227       else
6228         {
6229           /* rotate left accumulator */
6230           AccRol (shCount);
6231           /* and kill the lower order bits */
6232           emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6233         }
6234     }
6235 }
6236
6237 /*-----------------------------------------------------------------*/
6238 /* AccRsh - right shift accumulator by known count                 */
6239 /*-----------------------------------------------------------------*/
6240 static void
6241 AccRsh (int shCount)
6242 {
6243   if (shCount != 0)
6244     {
6245       if (shCount == 1)
6246         {
6247           CLRC;
6248           emitcode ("rrc", "a");
6249         }
6250       else
6251         {
6252           /* rotate right accumulator */
6253           AccRol (8 - shCount);
6254           /* and kill the higher order bits */
6255           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6256         }
6257     }
6258 }
6259
6260 #ifdef BETTER_LITERAL_SHIFT
6261 /*-----------------------------------------------------------------*/
6262 /* AccSRsh - signed right shift accumulator by known count                 */
6263 /*-----------------------------------------------------------------*/
6264 static void
6265 AccSRsh (int shCount)
6266 {
6267   symbol *tlbl;
6268   if (shCount != 0)
6269     {
6270       if (shCount == 1)
6271         {
6272           emitcode ("mov", "c,acc.7");
6273           emitcode ("rrc", "a");
6274         }
6275       else if (shCount == 2)
6276         {
6277           emitcode ("mov", "c,acc.7");
6278           emitcode ("rrc", "a");
6279           emitcode ("mov", "c,acc.7");
6280           emitcode ("rrc", "a");
6281         }
6282       else
6283         {
6284           tlbl = newiTempLabel (NULL);
6285           /* rotate right accumulator */
6286           AccRol (8 - shCount);
6287           /* and kill the higher order bits */
6288           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6289           emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6290           emitcode ("orl", "a,#0x%02x",
6291                     (unsigned char) ~SRMask[shCount]);
6292           emitcode ("", "%05d$:", tlbl->key + 100);
6293         }
6294     }
6295 }
6296 #endif
6297
6298 #ifdef BETTER_LITERAL_SHIFT
6299 /*-----------------------------------------------------------------*/
6300 /* shiftR1Left2Result - shift right one byte from left to result   */
6301 /*-----------------------------------------------------------------*/
6302 static void
6303 shiftR1Left2Result (operand * left, int offl,
6304                     operand * result, int offr,
6305                     int shCount, int sign)
6306 {
6307   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6308   /* shift right accumulator */
6309   if (sign)
6310     AccSRsh (shCount);
6311   else
6312     AccRsh (shCount);
6313   aopPut (AOP (result), "a", offr);
6314 }
6315 #endif
6316
6317 #ifdef BETTER_LITERAL_SHIFT
6318 /*-----------------------------------------------------------------*/
6319 /* shiftL1Left2Result - shift left one byte from left to result    */
6320 /*-----------------------------------------------------------------*/
6321 static void
6322 shiftL1Left2Result (operand * left, int offl,
6323                     operand * result, int offr, int shCount)
6324 {
6325   MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6326   /* shift left accumulator */
6327   AccLsh (shCount);
6328   aopPut (AOP (result), "a", offr);
6329 }
6330 #endif
6331
6332 #ifdef BETTER_LITERAL_SHIFT
6333 /*-----------------------------------------------------------------*/
6334 /* movLeft2Result - move byte from left to result                  */
6335 /*-----------------------------------------------------------------*/
6336 static void
6337 movLeft2Result (operand * left, int offl,
6338                 operand * result, int offr, int sign)
6339 {
6340   char *l;
6341   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6342   {
6343       l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
6344
6345       if (*l == '@' && (IS_AOP_PREG (result)))
6346       {
6347           emitcode ("mov", "a,%s", l);
6348           aopPut (AOP (result), "a", offr);
6349       }
6350       else
6351       {
6352           if (!sign)
6353           {
6354             aopPut (AOP (result), l, offr);
6355           }
6356           else
6357             {
6358               /* MSB sign in acc.7 ! */
6359               if (getDataSize (left) == offl + 1)
6360                 {
6361                   emitcode ("mov", "a,%s", l);
6362                   aopPut (AOP (result), "a", offr);
6363                 }
6364             }
6365       }
6366   }
6367 }
6368 #endif
6369
6370 #ifdef BETTER_LITERAL_SHIFT
6371 /*-----------------------------------------------------------------*/
6372 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
6373 /*-----------------------------------------------------------------*/
6374 static void
6375 AccAXRrl1 (char *x)
6376 {
6377   emitcode ("rrc", "a");
6378   emitcode ("xch", "a,%s", x);
6379   emitcode ("rrc", "a");
6380   emitcode ("xch", "a,%s", x);
6381 }
6382 #endif
6383
6384 #ifdef BETTER_LITERAL_SHIFT
6385 //REMOVE ME!!!
6386 /*-----------------------------------------------------------------*/
6387 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
6388 /*-----------------------------------------------------------------*/
6389 static void
6390 AccAXLrl1 (char *x)
6391 {
6392   emitcode ("xch", "a,%s", x);
6393   emitcode ("rlc", "a");
6394   emitcode ("xch", "a,%s", x);
6395   emitcode ("rlc", "a");
6396 }
6397 #endif
6398
6399 #ifdef BETTER_LITERAL_SHIFT
6400 /*-----------------------------------------------------------------*/
6401 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
6402 /*-----------------------------------------------------------------*/
6403 static void
6404 AccAXLsh1 (char *x)
6405 {
6406   emitcode ("xch", "a,%s", x);
6407   emitcode ("add", "a,acc");
6408   emitcode ("xch", "a,%s", x);
6409   emitcode ("rlc", "a");
6410 }
6411 #endif
6412
6413 #ifdef BETTER_LITERAL_SHIFT
6414 /*-----------------------------------------------------------------*/
6415 /* AccAXLsh - left shift a:x by known count (0..7)                 */
6416 /*-----------------------------------------------------------------*/
6417 static void
6418 AccAXLsh (char *x, int shCount)
6419 {
6420   switch (shCount)
6421     {
6422     case 0:
6423       break;
6424     case 1:
6425       AccAXLsh1 (x);
6426       break;
6427     case 2:
6428       AccAXLsh1 (x);
6429       AccAXLsh1 (x);
6430       break;
6431     case 3:
6432     case 4:
6433     case 5:                     // AAAAABBB:CCCCCDDD
6434
6435       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
6436
6437       emitcode ("anl", "a,#0x%02x",
6438                 SLMask[shCount]);       // BBB00000:CCCCCDDD
6439
6440       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
6441
6442       AccRol (shCount);         // DDDCCCCC:BBB00000
6443
6444       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
6445
6446       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
6447
6448       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
6449
6450       emitcode ("anl", "a,#0x%02x",
6451                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
6452
6453       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
6454
6455       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
6456
6457       break;
6458     case 6:                     // AAAAAABB:CCCCCCDD
6459       emitcode ("anl", "a,#0x%02x",
6460                 SRMask[shCount]);       // 000000BB:CCCCCCDD
6461       emitcode ("mov", "c,acc.0");      // c = B
6462       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
6463 #if 0
6464       AccAXRrl1 (x);            // BCCCCCCD:D000000B
6465       AccAXRrl1 (x);            // BBCCCCCC:DD000000
6466 #else
6467       emitcode("rrc","a"); 
6468       emitcode("xch","a,%s", x); 
6469       emitcode("rrc","a"); 
6470       emitcode("mov","c,acc.0"); //<< get correct bit 
6471       emitcode("xch","a,%s", x); 
6472
6473       emitcode("rrc","a"); 
6474       emitcode("xch","a,%s", x); 
6475       emitcode("rrc","a"); 
6476       emitcode("xch","a,%s", x); 
6477 #endif
6478       break;
6479     case 7:                     // a:x <<= 7
6480
6481       emitcode ("anl", "a,#0x%02x",
6482                 SRMask[shCount]);       // 0000000B:CCCCCCCD
6483
6484       emitcode ("mov", "c,acc.0");      // c = B
6485
6486       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
6487
6488       AccAXRrl1 (x);            // BCCCCCCC:D0000000
6489
6490       break;
6491     default:
6492       break;
6493     }
6494 }
6495 #endif
6496
6497 #ifdef BETTER_LITERAL_SHIFT
6498 //REMOVE ME!!!
6499 /*-----------------------------------------------------------------*/
6500 /* AccAXRsh - right shift a:x known count (0..7)                   */
6501 /*-----------------------------------------------------------------*/
6502 static void
6503 AccAXRsh (char *x, int shCount)
6504 {
6505   switch (shCount)
6506     {
6507     case 0:
6508       break;
6509     case 1:
6510       CLRC;
6511       AccAXRrl1 (x);            // 0->a:x
6512
6513       break;
6514     case 2:
6515       CLRC;
6516       AccAXRrl1 (x);            // 0->a:x
6517
6518       CLRC;
6519       AccAXRrl1 (x);            // 0->a:x
6520
6521       break;
6522     case 3:
6523     case 4:
6524     case 5:                     // AAAAABBB:CCCCCDDD = a:x
6525
6526       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
6527
6528       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
6529
6530       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
6531
6532       emitcode ("anl", "a,#0x%02x",
6533                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
6534
6535       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
6536
6537       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
6538
6539       emitcode ("anl", "a,#0x%02x",
6540                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
6541
6542       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
6543
6544       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
6545
6546       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
6547
6548       break;
6549     case 6:                     // AABBBBBB:CCDDDDDD
6550
6551       emitcode ("mov", "c,acc.7");
6552       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
6553
6554       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
6555
6556       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
6557
6558       emitcode ("anl", "a,#0x%02x",
6559                 SRMask[shCount]);       // 000000AA:BBBBBBCC
6560
6561       break;
6562     case 7:                     // ABBBBBBB:CDDDDDDD
6563
6564       emitcode ("mov", "c,acc.7");      // c = A
6565
6566       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
6567
6568       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
6569
6570       emitcode ("anl", "a,#0x%02x",
6571                 SRMask[shCount]);       // 0000000A:BBBBBBBC
6572
6573       break;
6574     default:
6575       break;
6576     }
6577 }
6578 #endif
6579
6580 #ifdef BETTER_LITERAL_SHIFT
6581 //REMOVE ME!!!
6582 /*-----------------------------------------------------------------*/
6583 /* AccAXRshS - right shift signed a:x known count (0..7)           */
6584 /*-----------------------------------------------------------------*/
6585 static void
6586 AccAXRshS (char *x, int shCount)
6587 {
6588   symbol *tlbl;
6589   switch (shCount)
6590     {
6591     case 0:
6592       break;
6593     case 1:
6594       emitcode ("mov", "c,acc.7");
6595       AccAXRrl1 (x);            // s->a:x
6596
6597       break;
6598     case 2:
6599       emitcode ("mov", "c,acc.7");
6600       AccAXRrl1 (x);            // s->a:x
6601
6602       emitcode ("mov", "c,acc.7");
6603       AccAXRrl1 (x);            // s->a:x
6604
6605       break;
6606     case 3:
6607     case 4:
6608     case 5:                     // AAAAABBB:CCCCCDDD = a:x
6609
6610       tlbl = newiTempLabel (NULL);
6611       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
6612
6613       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
6614
6615       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
6616
6617       emitcode ("anl", "a,#0x%02x",
6618                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
6619
6620       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
6621
6622       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
6623
6624       emitcode ("anl", "a,#0x%02x",
6625                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
6626
6627       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
6628
6629       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
6630
6631       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
6632
6633       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6634       emitcode ("orl", "a,#0x%02x",
6635                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
6636
6637       emitcode ("", "%05d$:", tlbl->key + 100);
6638       break;                    // SSSSAAAA:BBBCCCCC
6639
6640     case 6:                     // AABBBBBB:CCDDDDDD
6641
6642       tlbl = newiTempLabel (NULL);
6643       emitcode ("mov", "c,acc.7");
6644       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
6645
6646       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
6647
6648       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
6649
6650       emitcode ("anl", "a,#0x%02x",
6651                 SRMask[shCount]);       // 000000AA:BBBBBBCC
6652
6653       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6654       emitcode ("orl", "a,#0x%02x",
6655                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
6656
6657       emitcode ("", "%05d$:", tlbl->key + 100);
6658       break;
6659     case 7:                     // ABBBBBBB:CDDDDDDD
6660
6661       tlbl = newiTempLabel (NULL);
6662       emitcode ("mov", "c,acc.7");      // c = A
6663
6664       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
6665
6666       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
6667
6668       emitcode ("anl", "a,#0x%02x",
6669                 SRMask[shCount]);       // 0000000A:BBBBBBBC
6670
6671       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6672       emitcode ("orl", "a,#0x%02x",
6673                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
6674
6675       emitcode ("", "%05d$:", tlbl->key + 100);
6676       break;
6677     default:
6678       break;
6679     }
6680 }
6681 #endif
6682
6683 #ifdef BETTER_LITERAL_SHIFT
6684 static void
6685 _loadLeftIntoAx(char    **lsb, 
6686                 operand *left, 
6687                 operand *result,
6688                 int     offl,
6689                 int     offr)
6690 {
6691   // Get the initial value from left into a pair of registers.
6692   // MSB must be in A, LSB can be any register.
6693   //
6694   // If the result is held in registers, it is an optimization
6695   // if the LSB can be held in the register which will hold the,
6696   // result LSB since this saves us from having to copy it into
6697   // the result following AccAXLsh.
6698   //
6699   // If the result is addressed indirectly, this is not a gain.
6700   if (AOP_NEEDSACC(result))
6701   {
6702        char *leftByte;
6703        
6704        _startLazyDPSEvaluation();
6705        if (AOP_TYPE(left) == AOP_DPTR2)
6706        {
6707            // Get MSB in A.
6708            MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
6709            // get LSB in DP2_RESULT_REG.
6710            leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
6711            assert(!strcmp(leftByte, DP2_RESULT_REG));
6712        }
6713        else
6714        {
6715            // get LSB into DP2_RESULT_REG
6716            leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
6717            if (strcmp(leftByte, DP2_RESULT_REG))
6718            {
6719                emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
6720            }
6721            // And MSB in A.
6722            leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
6723            assert(strcmp(leftByte, DP2_RESULT_REG));
6724            MOVA(leftByte);
6725        }
6726        _endLazyDPSEvaluation();
6727        *lsb = DP2_RESULT_REG;
6728   }
6729   else
6730   {
6731       if (sameRegs (AOP (result), AOP (left)) &&
6732         ((offl + MSB16) == offr))
6733       {
6734           /* don't crash result[offr] */
6735           MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
6736           emitcode ("xch", "a,%s", 
6737                     aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
6738       }
6739       else
6740       {
6741           movLeft2Result (left, offl, result, offr, 0);
6742           MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
6743       }
6744       *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
6745       assert(strcmp(*lsb,"a"));      
6746   }
6747 }
6748
6749 static void
6750 _storeAxResults(char    *lsb,
6751                 operand *result,
6752                 int     offr)
6753 {
6754   _startLazyDPSEvaluation();
6755   if (AOP_NEEDSACC(result))
6756   {
6757       /* We have to explicitly update the result LSB.
6758        */
6759       emitcode("xch","a,%s", lsb);
6760       aopPut(AOP(result), "a", offr);
6761       emitcode("mov","a,%s", lsb);
6762   }
6763   if (getDataSize (result) > 1)
6764   {
6765       aopPut (AOP (result), "a", offr + MSB16);
6766   }
6767   _endLazyDPSEvaluation();
6768 }
6769
6770 /*-----------------------------------------------------------------*/
6771 /* shiftL2Left2Result - shift left two bytes from left to result   */
6772 /*-----------------------------------------------------------------*/
6773 static void
6774 shiftL2Left2Result (operand * left, int offl,
6775                     operand * result, int offr, int shCount)
6776 {
6777   char *lsb;
6778
6779   _loadLeftIntoAx(&lsb, left, result, offl, offr);
6780   
6781   AccAXLsh (lsb, shCount);
6782   
6783   _storeAxResults(lsb, result, offr);
6784 }
6785 #endif
6786
6787 #ifdef BETTER_LITERAL_SHIFT
6788 /*-----------------------------------------------------------------*/
6789 /* shiftR2Left2Result - shift right two bytes from left to result  */
6790 /*-----------------------------------------------------------------*/
6791 static void
6792 shiftR2Left2Result (operand * left, int offl,
6793                     operand * result, int offr,
6794                     int shCount, int sign)
6795 {
6796   char *lsb;
6797   
6798   _loadLeftIntoAx(&lsb, left, result, offl, offr);
6799   
6800   /* a:x >> shCount (x = lsb(result)) */
6801   if (sign)
6802   {
6803     AccAXRshS(aopGet(AOP(result), offr, FALSE, FALSE, FALSE), shCount);
6804   }
6805   else
6806   {
6807     AccAXRsh(aopGet(AOP(result), offr, FALSE, FALSE, FALSE), shCount);
6808   }
6809   
6810   _storeAxResults(lsb, result, offr);
6811 }
6812 #endif
6813
6814 #if 0
6815 //REMOVE ME!!!
6816 /*-----------------------------------------------------------------*/
6817 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6818 /*-----------------------------------------------------------------*/
6819 static void
6820 shiftLLeftOrResult (operand * left, int offl,
6821                     operand * result, int offr, int shCount)
6822 {
6823   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6824   /* shift left accumulator */
6825   AccLsh (shCount);
6826   /* or with result */
6827   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6828   /* back to result */
6829   aopPut (AOP (result), "a", offr);
6830 }
6831 #endif
6832
6833 #if 0
6834 //REMOVE ME!!!
6835 /*-----------------------------------------------------------------*/
6836 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6837 /*-----------------------------------------------------------------*/
6838 static void
6839 shiftRLeftOrResult (operand * left, int offl,
6840                     operand * result, int offr, int shCount)
6841 {
6842   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6843   /* shift right accumulator */
6844   AccRsh (shCount);
6845   /* or with result */
6846   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6847   /* back to result */
6848   aopPut (AOP (result), "a", offr);
6849 }
6850 #endif
6851
6852 #ifdef BETTER_LITERAL_SHIFT
6853 /*-----------------------------------------------------------------*/
6854 /* genlshOne - left shift a one byte quantity by known count       */
6855 /*-----------------------------------------------------------------*/
6856 static void
6857 genlshOne (operand * result, operand * left, int shCount)
6858 {
6859   D (emitcode (";", "genlshOne "););
6860   shiftL1Left2Result (left, LSB, result, LSB, shCount);
6861 }
6862 #endif
6863
6864 #ifdef BETTER_LITERAL_SHIFT
6865 /*-----------------------------------------------------------------*/
6866 /* genlshTwo - left shift two bytes by known amount != 0           */
6867 /*-----------------------------------------------------------------*/
6868 static void
6869 genlshTwo (operand * result, operand * left, int shCount)
6870 {
6871   int size;
6872
6873   D (emitcode (";", "genlshTwo "););
6874
6875   size = getDataSize (result);
6876
6877   /* if shCount >= 8 */
6878   if (shCount >= 8)
6879   {
6880       shCount -= 8;
6881
6882       _startLazyDPSEvaluation();
6883
6884       if (size > 1)
6885         {
6886           if (shCount)
6887           {
6888             _endLazyDPSEvaluation();
6889             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6890             aopPut (AOP (result), zero, LSB);       
6891           }
6892           else
6893           {
6894             movLeft2Result (left, LSB, result, MSB16, 0);
6895             aopPut (AOP (result), zero, LSB);
6896             _endLazyDPSEvaluation();
6897           }
6898         }
6899         else
6900         {
6901           aopPut (AOP (result), zero, LSB);
6902           _endLazyDPSEvaluation();
6903         }
6904   }
6905
6906   /*  1 <= shCount <= 7 */
6907   else
6908     {
6909       if (size == 1)
6910       {
6911         shiftL1Left2Result (left, LSB, result, LSB, shCount);
6912       }
6913       else
6914       {
6915         shiftL2Left2Result (left, LSB, result, LSB, shCount);
6916       }
6917     }
6918 }
6919 #endif
6920
6921 #if 0
6922 //REMOVE ME!!!
6923 /*-----------------------------------------------------------------*/
6924 /* shiftLLong - shift left one long from left to result            */
6925 /* offl = LSB or MSB16                                             */
6926 /*-----------------------------------------------------------------*/
6927 static void
6928 shiftLLong (operand * left, operand * result, int offr)
6929 {
6930   char *l;
6931   int size = AOP_SIZE (result);
6932
6933   if (size >= LSB + offr)
6934     {
6935       l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
6936       MOVA (l);
6937       emitcode ("add", "a,acc");
6938       if (sameRegs (AOP (left), AOP (result)) &&
6939           size >= MSB16 + offr && offr != LSB)
6940         emitcode ("xch", "a,%s",
6941                   aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
6942       else
6943         aopPut (AOP (result), "a", LSB + offr);
6944     }
6945
6946   if (size >= MSB16 + offr)
6947     {
6948       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6949         {
6950           l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
6951           MOVA (l);
6952         }
6953       emitcode ("rlc", "a");
6954       if (sameRegs (AOP (left), AOP (result)) &&
6955           size >= MSB24 + offr && offr != LSB)
6956         emitcode ("xch", "a,%s",
6957                   aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
6958       else
6959         aopPut (AOP (result), "a", MSB16 + offr);
6960     }
6961
6962   if (size >= MSB24 + offr)
6963     {
6964       if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6965         {
6966           l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
6967           MOVA (l);
6968         }
6969       emitcode ("rlc", "a");
6970       if (sameRegs (AOP (left), AOP (result)) &&
6971           size >= MSB32 + offr && offr != LSB)
6972         emitcode ("xch", "a,%s",
6973                   aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
6974       else
6975         aopPut (AOP (result), "a", MSB24 + offr);
6976     }
6977
6978   if (size > MSB32 + offr)
6979     {
6980       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6981         {
6982           l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
6983           MOVA (l);
6984         }
6985       emitcode ("rlc", "a");
6986       aopPut (AOP (result), "a", MSB32 + offr);
6987     }
6988   if (offr != LSB)
6989     aopPut (AOP (result), zero, LSB);
6990 }
6991 #endif
6992
6993 #if 0
6994 //REMOVE ME!!!
6995 /*-----------------------------------------------------------------*/
6996 /* genlshFour - shift four byte by a known amount != 0             */
6997 /*-----------------------------------------------------------------*/
6998 static void
6999 genlshFour (operand * result, operand * left, int shCount)
7000 {
7001   int size;
7002
7003   D (emitcode (";", "genlshFour ");
7004     );
7005
7006   size = AOP_SIZE (result);
7007
7008   /* if shifting more that 3 bytes */
7009   if (shCount >= 24)
7010     {
7011       shCount -= 24;
7012       if (shCount)
7013         /* lowest order of left goes to the highest
7014            order of the destination */
7015         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7016       else
7017         movLeft2Result (left, LSB, result, MSB32, 0);
7018       aopPut (AOP (result), zero, LSB);
7019       aopPut (AOP (result), zero, MSB16);
7020       aopPut (AOP (result), zero, MSB24);
7021       return;
7022     }
7023
7024   /* more than two bytes */
7025   else if (shCount >= 16)
7026     {
7027       /* lower order two bytes goes to higher order two bytes */
7028       shCount -= 16;
7029       /* if some more remaining */
7030       if (shCount)
7031         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7032       else
7033         {
7034           movLeft2Result (left, MSB16, result, MSB32, 0);
7035           movLeft2Result (left, LSB, result, MSB24, 0);
7036         }
7037       aopPut (AOP (result), zero, MSB16);
7038       aopPut (AOP (result), zero, LSB);
7039       return;
7040     }
7041
7042   /* if more than 1 byte */
7043   else if (shCount >= 8)
7044     {
7045       /* lower order three bytes goes to higher order  three bytes */
7046       shCount -= 8;
7047       if (size == 2)
7048         {
7049           if (shCount)
7050             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7051           else
7052             movLeft2Result (left, LSB, result, MSB16, 0);
7053         }
7054       else
7055         {                       /* size = 4 */
7056           if (shCount == 0)
7057             {
7058               movLeft2Result (left, MSB24, result, MSB32, 0);
7059               movLeft2Result (left, MSB16, result, MSB24, 0);
7060               movLeft2Result (left, LSB, result, MSB16, 0);
7061               aopPut (AOP (result), zero, LSB);
7062             }
7063           else if (shCount == 1)
7064             shiftLLong (left, result, MSB16);
7065           else
7066             {
7067               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7068               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7069               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7070               aopPut (AOP (result), zero, LSB);
7071             }
7072         }
7073     }
7074
7075   /* 1 <= shCount <= 7 */
7076   else if (shCount <= 2)
7077     {
7078       shiftLLong (left, result, LSB);
7079       if (shCount == 2)
7080         shiftLLong (result, result, LSB);
7081     }
7082   /* 3 <= shCount <= 7, optimize */
7083   else
7084     {
7085       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7086       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7087       shiftL2Left2Result (left, LSB, result, LSB, shCount);
7088     }
7089 }
7090 #endif
7091
7092 #ifdef BETTER_LITERAL_SHIFT
7093 /*-----------------------------------------------------------------*/
7094 /* genLeftShiftLiteral - left shifting by known count              */
7095 /*-----------------------------------------------------------------*/
7096 static bool
7097 genLeftShiftLiteral (operand * left,
7098                      operand * right,
7099                      operand * result,
7100                      iCode * ic)
7101 {
7102   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7103   int size;
7104
7105   size = getSize (operandType (result));
7106
7107   D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
7108
7109   /* We only handle certain easy cases so far. */
7110   if ((shCount != 0)
7111    && (shCount < (size * 8))
7112    && (size != 1)
7113    && (size != 2))
7114   {
7115       D(emitcode (";", "genLeftShiftLiteral wimping out"););    
7116       return FALSE;
7117   }
7118
7119   freeAsmop (right, NULL, ic, TRUE);
7120
7121   aopOp(left, ic, FALSE, FALSE);
7122   aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
7123
7124 #if 1 // debug spew
7125   if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
7126   {
7127         emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
7128         if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
7129         {
7130            emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
7131         }
7132   }
7133   if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
7134   {
7135         emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
7136         if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
7137         {
7138            emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
7139         }       
7140   }  
7141 #endif
7142   
7143 #if VIEW_SIZE
7144   emitcode ("; shift left ", "result %d, left %d", size,
7145             AOP_SIZE (left));
7146 #endif
7147
7148   /* I suppose that the left size >= result size */
7149   if (shCount == 0)
7150   {
7151         _startLazyDPSEvaluation();
7152         while (size--)
7153         {
7154           movLeft2Result (left, size, result, size, 0);
7155         }
7156         _endLazyDPSEvaluation();
7157   }
7158   else if (shCount >= (size * 8))
7159   {
7160     _startLazyDPSEvaluation();
7161     while (size--)
7162     {
7163       aopPut (AOP (result), zero, size);
7164     }
7165     _endLazyDPSEvaluation();
7166   }
7167   else
7168   {
7169       switch (size)
7170         {
7171         case 1:
7172           genlshOne (result, left, shCount);
7173           break;
7174
7175         case 2:
7176           genlshTwo (result, left, shCount);
7177           break;
7178 #if 0
7179         case 4:
7180           genlshFour (result, left, shCount);
7181           break;
7182 #endif
7183         default:
7184           fprintf(stderr, "*** ack! mystery literal shift!\n");   
7185           break;
7186         }
7187     }
7188   freeAsmop (left, NULL, ic, TRUE);
7189   freeAsmop (result, NULL, ic, TRUE);
7190   return TRUE;
7191 }
7192 #endif
7193
7194 /*-----------------------------------------------------------------*/
7195 /* genLeftShift - generates code for left shifting                 */
7196 /*-----------------------------------------------------------------*/
7197 static void
7198 genLeftShift (iCode * ic)
7199 {
7200   operand *left, *right, *result;
7201   int size, offset;
7202   char *l;
7203   symbol *tlbl, *tlbl1;
7204
7205   D (emitcode (";", "genLeftShift "););
7206
7207   right = IC_RIGHT (ic);
7208   left = IC_LEFT (ic);
7209   result = IC_RESULT (ic);
7210
7211   aopOp (right, ic, FALSE, FALSE);
7212
7213
7214 #ifdef BETTER_LITERAL_SHIFT
7215   /* if the shift count is known then do it
7216      as efficiently as possible */
7217   if (AOP_TYPE (right) == AOP_LIT)
7218     {
7219       if (genLeftShiftLiteral (left, right, result, ic))
7220       {
7221         return;
7222       }
7223     }
7224 #endif
7225
7226   /* shift count is unknown then we have to form
7227      a loop get the loop count in B : Note: we take
7228      only the lower order byte since shifting
7229      more that 32 bits make no sense anyway, ( the
7230      largest size of an object can be only 32 bits ) */
7231
7232   if (AOP_TYPE (right) == AOP_LIT)
7233   {
7234       /* Really should be handled by genLeftShiftLiteral,
7235        * but since I'm too lazy to fix that today, at least we can make
7236        * some small improvement.
7237        */
7238        emitcode("mov", "b,#0x%02x",
7239                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7240   }
7241   else
7242   {
7243         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7244         emitcode ("inc", "b");
7245   }
7246   freeAsmop (right, NULL, ic, TRUE);
7247   aopOp (left, ic, FALSE, FALSE);
7248   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7249
7250   /* now move the left to the result if they are not the
7251      same */
7252   if (!sameRegs (AOP (left), AOP (result)) &&
7253       AOP_SIZE (result) > 1)
7254     {
7255
7256       size = AOP_SIZE (result);
7257       offset = 0;
7258       _startLazyDPSEvaluation ();
7259       while (size--)
7260         {
7261           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7262           if (*l == '@' && (IS_AOP_PREG (result)))
7263             {
7264
7265               emitcode ("mov", "a,%s", l);
7266               aopPut (AOP (result), "a", offset);
7267             }
7268           else
7269             aopPut (AOP (result), l, offset);
7270           offset++;
7271         }
7272       _endLazyDPSEvaluation ();
7273     }
7274
7275   tlbl = newiTempLabel (NULL);
7276   size = AOP_SIZE (result);
7277   offset = 0;
7278   tlbl1 = newiTempLabel (NULL);
7279
7280   /* if it is only one byte then */
7281   if (size == 1)
7282     {
7283       symbol *tlbl1 = newiTempLabel (NULL);
7284
7285       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7286       MOVA (l);
7287       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7288       emitcode ("", "%05d$:", tlbl->key + 100);
7289       emitcode ("add", "a,acc");
7290       emitcode ("", "%05d$:", tlbl1->key + 100);
7291       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7292       aopPut (AOP (result), "a", 0);
7293       goto release;
7294     }
7295
7296   reAdjustPreg (AOP (result));
7297
7298   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7299   emitcode ("", "%05d$:", tlbl->key + 100);
7300   l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7301   MOVA (l);
7302   emitcode ("add", "a,acc");
7303   aopPut (AOP (result), "a", offset++);
7304   _startLazyDPSEvaluation ();
7305   while (--size)
7306     {
7307       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7308       MOVA (l);
7309       emitcode ("rlc", "a");
7310       aopPut (AOP (result), "a", offset++);
7311     }
7312   _endLazyDPSEvaluation ();
7313   reAdjustPreg (AOP (result));
7314
7315   emitcode ("", "%05d$:", tlbl1->key + 100);
7316   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7317 release:
7318   freeAsmop (left, NULL, ic, TRUE);
7319   freeAsmop (result, NULL, ic, TRUE);
7320 }
7321
7322 #ifdef BETTER_LITERAL_SHIFT
7323 /*-----------------------------------------------------------------*/
7324 /* genrshOne - right shift a one byte quantity by known count      */
7325 /*-----------------------------------------------------------------*/
7326 static void
7327 genrshOne (operand * result, operand * left,
7328            int shCount, int sign)
7329 {
7330   D (emitcode (";", "genrshOne"););
7331   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7332 }
7333 #endif
7334
7335 #ifdef BETTER_LITERAL_SHIFT
7336 /*-----------------------------------------------------------------*/
7337 /* genrshTwo - right shift two bytes by known amount != 0          */
7338 /*-----------------------------------------------------------------*/
7339 static void
7340 genrshTwo (operand * result, operand * left,
7341            int shCount, int sign)
7342 {
7343   D (emitcode (";", "genrshTwo"););
7344
7345   /* if shCount >= 8 */
7346   if (shCount >= 8)
7347     {
7348       shCount -= 8;
7349       _startLazyDPSEvaluation();
7350       if (shCount)
7351       {
7352         shiftR1Left2Result (left, MSB16, result, LSB,
7353                             shCount, sign);
7354       }                     
7355       else
7356       {
7357         movLeft2Result (left, MSB16, result, LSB, sign);
7358       }
7359       addSign (result, MSB16, sign);
7360       _endLazyDPSEvaluation();
7361     }
7362
7363   /*  1 <= shCount <= 7 */
7364   else
7365   {
7366     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7367   }
7368 }
7369 #endif
7370
7371 #if 0
7372 //REMOVE ME!!!
7373 /*-----------------------------------------------------------------*/
7374 /* shiftRLong - shift right one long from left to result           */
7375 /* offl = LSB or MSB16                                             */
7376 /*-----------------------------------------------------------------*/
7377 static void
7378 shiftRLong (operand * left, int offl,
7379             operand * result, int sign)
7380 {
7381   int isSameRegs=sameRegs(AOP(left),AOP(result));
7382
7383   if (isSameRegs && offl>1) {
7384     // we are in big trouble, but this shouldn't happen
7385     werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
7386   }
7387
7388   MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7389   
7390   if (offl==MSB16) {
7391     // shift is > 8
7392     if (sign) {
7393       emitcode ("rlc", "a");
7394       emitcode ("subb", "a,acc");
7395       emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
7396     } else {
7397       aopPut (AOP(result), zero, MSB32);
7398     }
7399   }
7400
7401   if (!sign) {
7402     emitcode ("clr", "c");
7403   } else {
7404     emitcode ("mov", "c,acc.7");
7405   }
7406
7407   emitcode ("rrc", "a");
7408
7409   if (isSameRegs && offl==MSB16) {
7410     emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
7411   } else {
7412     aopPut (AOP (result), "a", MSB32);
7413     MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
7414   }
7415
7416   emitcode ("rrc", "a");
7417   if (isSameRegs && offl==1) {
7418     emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
7419   } else {
7420     aopPut (AOP (result), "a", MSB24);
7421     MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
7422   }
7423   emitcode ("rrc", "a");
7424   aopPut (AOP (result), "a", MSB16 - offl);
7425
7426   if (offl == LSB)
7427     {
7428       MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
7429       emitcode ("rrc", "a");
7430       aopPut (AOP (result), "a", LSB);
7431     }
7432 }
7433 #endif
7434
7435 #if 0
7436 //REMOVE ME!!!
7437 /*-----------------------------------------------------------------*/
7438 /* genrshFour - shift four byte by a known amount != 0             */
7439 /*-----------------------------------------------------------------*/
7440 static void
7441 genrshFour (operand * result, operand * left,
7442             int shCount, int sign)
7443 {
7444   D (emitcode (";", "genrshFour");
7445     );
7446
7447   /* if shifting more that 3 bytes */
7448   if (shCount >= 24)
7449     {
7450       shCount -= 24;
7451       if (shCount)
7452         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7453       else
7454         movLeft2Result (left, MSB32, result, LSB, sign);
7455       addSign (result, MSB16, sign);
7456     }
7457   else if (shCount >= 16)
7458     {
7459       shCount -= 16;
7460       if (shCount)
7461         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7462       else
7463         {
7464           movLeft2Result (left, MSB24, result, LSB, 0);
7465           movLeft2Result (left, MSB32, result, MSB16, sign);
7466         }
7467       addSign (result, MSB24, sign);
7468     }
7469   else if (shCount >= 8)
7470     {
7471       shCount -= 8;
7472       if (shCount == 1)
7473         shiftRLong (left, MSB16, result, sign);
7474       else if (shCount == 0)
7475         {
7476           movLeft2Result (left, MSB16, result, LSB, 0);
7477           movLeft2Result (left, MSB24, result, MSB16, 0);
7478           movLeft2Result (left, MSB32, result, MSB24, sign);
7479           addSign (result, MSB32, sign);
7480         }
7481       else
7482         {
7483           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7484           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7485           /* the last shift is signed */
7486           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7487           addSign (result, MSB32, sign);
7488         }
7489     }
7490   else
7491     {                           /* 1 <= shCount <= 7 */
7492       if (shCount <= 2)
7493         {
7494           shiftRLong (left, LSB, result, sign);
7495           if (shCount == 2)
7496             shiftRLong (result, LSB, result, sign);
7497         }
7498       else
7499         {
7500           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7501           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7502           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7503         }
7504     }
7505 }
7506 #endif
7507
7508 #ifdef BETTER_LITERAL_SHIFT
7509 /*-----------------------------------------------------------------*/
7510 /* genRightShiftLiteral - right shifting by known count            */
7511 /*-----------------------------------------------------------------*/
7512 static bool
7513 genRightShiftLiteral (operand * left,
7514                       operand * right,
7515                       operand * result,
7516                       iCode * ic,
7517                       int sign)
7518 {
7519   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7520   int size;
7521
7522   size = getSize (operandType (result));
7523
7524   D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
7525
7526   /* We only handle certain easy cases so far. */
7527   if ((shCount != 0)
7528    && (shCount < (size * 8))
7529    && (size != 1)
7530    && (size != 2))
7531   {
7532       D(emitcode (";", "genRightShiftLiteral wimping out"););   
7533       return FALSE;
7534   }
7535
7536   freeAsmop (right, NULL, ic, TRUE);
7537
7538   aopOp (left, ic, FALSE, FALSE);
7539   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7540
7541 #if VIEW_SIZE
7542   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7543             AOP_SIZE (left));
7544 #endif
7545
7546   /* test the LEFT size !!! */
7547
7548   /* I suppose that the left size >= result size */
7549   if (shCount == 0)
7550   {
7551       size = getDataSize (result);
7552       _startLazyDPSEvaluation();
7553       while (size--)
7554       {
7555         movLeft2Result (left, size, result, size, 0);
7556       }
7557       _endLazyDPSEvaluation();
7558   }
7559   else if (shCount >= (size * 8))
7560     {
7561       if (sign)
7562       {
7563         /* get sign in acc.7 */
7564         MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
7565       }
7566       addSign (result, LSB, sign);
7567     }
7568   else
7569     {
7570       switch (size)
7571         {
7572         case 1:
7573           genrshOne (result, left, shCount, sign);
7574           break;
7575
7576         case 2:
7577           genrshTwo (result, left, shCount, sign);
7578           break;
7579 #if 0
7580         case 4:
7581           genrshFour (result, left, shCount, sign);
7582           break;
7583 #endif    
7584         default:
7585           break;
7586         }
7587
7588       freeAsmop (left, NULL, ic, TRUE);
7589       freeAsmop (result, NULL, ic, TRUE);
7590     }
7591     return TRUE;
7592 }
7593 #endif
7594
7595 /*-----------------------------------------------------------------*/
7596 /* genSignedRightShift - right shift of signed number              */
7597 /*-----------------------------------------------------------------*/
7598 static void
7599 genSignedRightShift (iCode * ic)
7600 {
7601   operand *right, *left, *result;
7602   int size, offset;
7603   char *l;
7604   symbol *tlbl, *tlbl1;
7605
7606   D (emitcode (";", "genSignedRightShift "););
7607
7608   /* we do it the hard way put the shift count in b
7609      and loop thru preserving the sign */
7610
7611   right = IC_RIGHT (ic);
7612   left = IC_LEFT (ic);
7613   result = IC_RESULT (ic);
7614
7615   aopOp (right, ic, FALSE, FALSE);
7616
7617 #ifdef BETTER_LITERAL_SHIFT
7618   if (AOP_TYPE (right) == AOP_LIT)
7619     {
7620       if (genRightShiftLiteral (left, right, result, ic, 1))
7621       {
7622         return;
7623       }
7624     }
7625 #endif
7626   /* shift count is unknown then we have to form
7627      a loop get the loop count in B : Note: we take
7628      only the lower order byte since shifting
7629      more that 32 bits make no sense anyway, ( the
7630      largest size of an object can be only 32 bits ) */
7631
7632   if (AOP_TYPE (right) == AOP_LIT)
7633   {
7634       /* Really should be handled by genRightShiftLiteral,
7635        * but since I'm too lazy to fix that today, at least we can make
7636        * some small improvement.
7637        */
7638        emitcode("mov", "b,#0x%02x",
7639                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7640   }
7641   else
7642   {
7643         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7644         emitcode ("inc", "b");
7645   }
7646   freeAsmop (right, NULL, ic, TRUE);
7647   aopOp (left, ic, FALSE, FALSE);
7648   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7649
7650   /* now move the left to the result if they are not the
7651      same */
7652   if (!sameRegs (AOP (left), AOP (result)) &&
7653       AOP_SIZE (result) > 1)
7654     {
7655
7656       size = AOP_SIZE (result);
7657       offset = 0;
7658       _startLazyDPSEvaluation ();
7659       while (size--)
7660         {
7661           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7662           if (*l == '@' && IS_AOP_PREG (result))
7663             {
7664
7665               emitcode ("mov", "a,%s", l);
7666               aopPut (AOP (result), "a", offset);
7667             }
7668           else
7669             aopPut (AOP (result), l, offset);
7670           offset++;
7671         }
7672       _endLazyDPSEvaluation ();
7673     }
7674
7675   /* mov the highest order bit to OVR */
7676   tlbl = newiTempLabel (NULL);
7677   tlbl1 = newiTempLabel (NULL);
7678
7679   size = AOP_SIZE (result);
7680   offset = size - 1;
7681   emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
7682   emitcode ("rlc", "a");
7683   emitcode ("mov", "ov,c");
7684   /* if it is only one byte then */
7685   if (size == 1)
7686     {
7687       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7688       MOVA (l);
7689       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7690       emitcode ("", "%05d$:", tlbl->key + 100);
7691       emitcode ("mov", "c,ov");
7692       emitcode ("rrc", "a");
7693       emitcode ("", "%05d$:", tlbl1->key + 100);
7694       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7695       aopPut (AOP (result), "a", 0);
7696       goto release;
7697     }
7698
7699   reAdjustPreg (AOP (result));
7700   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7701   emitcode ("", "%05d$:", tlbl->key + 100);
7702   emitcode ("mov", "c,ov");
7703   _startLazyDPSEvaluation ();
7704   while (size--)
7705     {
7706       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7707       MOVA (l);
7708       emitcode ("rrc", "a");
7709       aopPut (AOP (result), "a", offset--);
7710     }
7711   _endLazyDPSEvaluation ();
7712   reAdjustPreg (AOP (result));
7713   emitcode ("", "%05d$:", tlbl1->key + 100);
7714   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7715
7716 release:
7717   freeAsmop (left, NULL, ic, TRUE);
7718   freeAsmop (result, NULL, ic, TRUE);
7719 }
7720
7721 /*-----------------------------------------------------------------*/
7722 /* genRightShift - generate code for right shifting                */
7723 /*-----------------------------------------------------------------*/
7724 static void
7725 genRightShift (iCode * ic)
7726 {
7727   operand *right, *left, *result;
7728   sym_link *retype;
7729   int size, offset;
7730   char *l;
7731   symbol *tlbl, *tlbl1;
7732
7733   D (emitcode (";", "genRightShift "););
7734
7735   /* if signed then we do it the hard way preserve the
7736      sign bit moving it inwards */
7737   retype = getSpec (operandType (IC_RESULT (ic)));
7738
7739   if (!SPEC_USIGN (retype))
7740     {
7741       genSignedRightShift (ic);
7742       return;
7743     }
7744
7745   /* signed & unsigned types are treated the same : i.e. the
7746      signed is NOT propagated inwards : quoting from the
7747      ANSI - standard : "for E1 >> E2, is equivalent to division
7748      by 2**E2 if unsigned or if it has a non-negative value,
7749      otherwise the result is implementation defined ", MY definition
7750      is that the sign does not get propagated */
7751
7752   right = IC_RIGHT (ic);
7753   left = IC_LEFT (ic);
7754   result = IC_RESULT (ic);
7755
7756   aopOp (right, ic, FALSE, FALSE);
7757
7758 #ifdef BETTER_LITERAL_SHIFT
7759   /* if the shift count is known then do it
7760      as efficiently as possible */
7761   if (AOP_TYPE (right) == AOP_LIT)
7762     {
7763       if (genRightShiftLiteral (left, right, result, ic, 0))
7764       {
7765         return;
7766       }
7767     }
7768 #endif
7769
7770   /* shift count is unknown then we have to form
7771      a loop get the loop count in B : Note: we take
7772      only the lower order byte since shifting
7773      more that 32 bits make no sense anyway, ( the
7774      largest size of an object can be only 32 bits ) */
7775   
7776   if (AOP_TYPE (right) == AOP_LIT)
7777   {
7778       /* Really should be handled by genRightShiftLiteral,
7779        * but since I'm too lazy to fix that today, at least we can make
7780        * some small improvement.
7781        */
7782        emitcode("mov", "b,#0x%02x",
7783                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7784   }
7785   else
7786   {
7787         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7788         emitcode ("inc", "b");
7789   }
7790   freeAsmop (right, NULL, ic, TRUE);
7791   aopOp (left, ic, FALSE, FALSE);
7792   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7793
7794   /* now move the left to the result if they are not the
7795      same */
7796   if (!sameRegs (AOP (left), AOP (result)) &&
7797       AOP_SIZE (result) > 1)
7798     {
7799
7800       size = AOP_SIZE (result);
7801       offset = 0;
7802       _startLazyDPSEvaluation ();
7803       while (size--)
7804         {
7805           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7806           if (*l == '@' && IS_AOP_PREG (result))
7807             {
7808
7809               emitcode ("mov", "a,%s", l);
7810               aopPut (AOP (result), "a", offset);
7811             }
7812           else
7813             aopPut (AOP (result), l, offset);
7814           offset++;
7815         }
7816       _endLazyDPSEvaluation ();
7817     }
7818
7819   tlbl = newiTempLabel (NULL);
7820   tlbl1 = newiTempLabel (NULL);
7821   size = AOP_SIZE (result);
7822   offset = size - 1;
7823
7824   /* if it is only one byte then */
7825   if (size == 1)
7826     {
7827       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7828       MOVA (l);
7829       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7830       emitcode ("", "%05d$:", tlbl->key + 100);
7831       CLRC;
7832       emitcode ("rrc", "a");
7833       emitcode ("", "%05d$:", tlbl1->key + 100);
7834       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7835       aopPut (AOP (result), "a", 0);
7836       goto release;
7837     }
7838
7839   reAdjustPreg (AOP (result));
7840   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7841   emitcode ("", "%05d$:", tlbl->key + 100);
7842   CLRC;
7843   _startLazyDPSEvaluation ();
7844   while (size--)
7845     {
7846       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7847       MOVA (l);
7848       emitcode ("rrc", "a");
7849       aopPut (AOP (result), "a", offset--);
7850     }
7851   _endLazyDPSEvaluation ();
7852   reAdjustPreg (AOP (result));
7853
7854   emitcode ("", "%05d$:", tlbl1->key + 100);
7855   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7856
7857 release:
7858   freeAsmop (left, NULL, ic, TRUE);
7859   freeAsmop (result, NULL, ic, TRUE);
7860 }
7861
7862 /*-----------------------------------------------------------------*/
7863 /* genUnpackBits - generates code for unpacking bits               */
7864 /*-----------------------------------------------------------------*/
7865 static void
7866 genUnpackBits (operand * result, char *rname, int ptype)
7867 {
7868   int shCnt;
7869   int rlen = 0;
7870   sym_link *etype;
7871   int offset = 0;
7872
7873   D (emitcode (";", "genUnpackBits ");
7874     );
7875
7876   etype = getSpec (operandType (result));
7877
7878   /* read the first byte  */
7879   switch (ptype)
7880     {
7881
7882     case POINTER:
7883     case IPOINTER:
7884       emitcode ("mov", "a,@%s", rname);
7885       break;
7886
7887     case PPOINTER:
7888       emitcode ("movx", "a,@%s", rname);
7889       break;
7890
7891     case FPOINTER:
7892       emitcode ("movx", "a,@dptr");
7893       break;
7894
7895     case CPOINTER:
7896       emitcode ("clr", "a");
7897       emitcode ("movc", "a", "@a+dptr");
7898       break;
7899
7900     case GPOINTER:
7901       emitcode ("lcall", "__gptrget");
7902       break;
7903     }
7904
7905   /* if we have bitdisplacement then it fits   */
7906   /* into this byte completely or if length is */
7907   /* less than a byte                          */
7908   if ((shCnt = SPEC_BSTR (etype)) ||
7909       (SPEC_BLEN (etype) <= 8))
7910     {
7911
7912       /* shift right acc */
7913       AccRsh (shCnt);
7914
7915       emitcode ("anl", "a,#0x%02x",
7916                 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
7917       aopPut (AOP (result), "a", offset);
7918       return;
7919     }
7920
7921   /* bit field did not fit in a byte  */
7922   rlen = SPEC_BLEN (etype) - 8;
7923   aopPut (AOP (result), "a", offset++);
7924
7925   while (1)
7926     {
7927
7928       switch (ptype)
7929         {
7930         case POINTER:
7931         case IPOINTER:
7932           emitcode ("inc", "%s", rname);
7933           emitcode ("mov", "a,@%s", rname);
7934           break;
7935
7936         case PPOINTER:
7937           emitcode ("inc", "%s", rname);
7938           emitcode ("movx", "a,@%s", rname);
7939           break;
7940
7941         case FPOINTER:
7942           emitcode ("inc", "dptr");
7943           emitcode ("movx", "a,@dptr");
7944           break;
7945
7946         case CPOINTER:
7947           emitcode ("clr", "a");
7948           emitcode ("inc", "dptr");
7949           emitcode ("movc", "a", "@a+dptr");
7950           break;
7951
7952         case GPOINTER:
7953           emitcode ("inc", "dptr");
7954           emitcode ("lcall", "__gptrget");
7955           break;
7956         }
7957
7958       rlen -= 8;
7959       /* if we are done */
7960       if (rlen < 8)
7961         break;
7962
7963       aopPut (AOP (result), "a", offset++);
7964
7965     }
7966
7967   if (rlen)
7968     {
7969       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
7970       aopPut (AOP (result), "a", offset);
7971     }
7972
7973   return;
7974 }
7975
7976
7977 /*-----------------------------------------------------------------*/
7978 /* genDataPointerGet - generates code when ptr offset is known     */
7979 /*-----------------------------------------------------------------*/
7980 static void
7981 genDataPointerGet (operand * left,
7982                    operand * result,
7983                    iCode * ic)
7984 {
7985   char *l;
7986   char buffer[256];
7987   int size, offset = 0;
7988   aopOp (result, ic, TRUE, FALSE);
7989
7990   /* get the string representation of the name */
7991   l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
7992   size = AOP_SIZE (result);
7993   _startLazyDPSEvaluation ();
7994   while (size--)
7995     {
7996       if (offset)
7997         sprintf (buffer, "(%s + %d)", l + 1, offset);
7998       else
7999         sprintf (buffer, "%s", l + 1);
8000       aopPut (AOP (result), buffer, offset++);
8001     }
8002   _endLazyDPSEvaluation ();
8003
8004   freeAsmop (left, NULL, ic, TRUE);
8005   freeAsmop (result, NULL, ic, TRUE);
8006 }
8007
8008 /*-----------------------------------------------------------------*/
8009 /* genNearPointerGet - emitcode for near pointer fetch             */
8010 /*-----------------------------------------------------------------*/
8011 static void
8012 genNearPointerGet (operand * left,
8013                    operand * result,
8014                    iCode * ic)
8015 {
8016   asmop *aop = NULL;
8017   regs *preg = NULL;
8018   char *rname;
8019   sym_link *rtype, *retype, *letype;
8020   sym_link *ltype = operandType (left);
8021   char buffer[80];
8022
8023   rtype = operandType (result);
8024   retype = getSpec (rtype);
8025   letype = getSpec (ltype);
8026
8027   aopOp (left, ic, FALSE, FALSE);
8028
8029   /* if left is rematerialisable and
8030      result is not bit variable type and
8031      the left is pointer to data space i.e
8032      lower 128 bytes of space */
8033   if (AOP_TYPE (left) == AOP_IMMD &&
8034       !IS_BITVAR (retype) &&
8035       !IS_BITVAR (letype) &&
8036       DCL_TYPE (ltype) == POINTER)
8037     {
8038       genDataPointerGet (left, result, ic);
8039       return;
8040     }
8041
8042   /* if the value is already in a pointer register
8043      then don't need anything more */
8044   if (!AOP_INPREG (AOP (left)))
8045     {
8046       /* otherwise get a free pointer register */
8047       aop = newAsmop (0);
8048       preg = getFreePtr (ic, &aop, FALSE);
8049       emitcode ("mov", "%s,%s",
8050                 preg->name,
8051                 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8052       rname = preg->name;
8053     }
8054   else
8055     rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8056
8057   freeAsmop (left, NULL, ic, TRUE);
8058   aopOp (result, ic, FALSE, FALSE);
8059
8060   /* if bitfield then unpack the bits */
8061   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8062     genUnpackBits (result, rname, POINTER);
8063   else
8064     {
8065       /* we have can just get the values */
8066       int size = AOP_SIZE (result);
8067       int offset = 0;
8068
8069       while (size--)
8070         {
8071           if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8072             {
8073
8074               emitcode ("mov", "a,@%s", rname);
8075               aopPut (AOP (result), "a", offset);
8076             }
8077           else
8078             {
8079               sprintf (buffer, "@%s", rname);
8080               aopPut (AOP (result), buffer, offset);
8081             }
8082           offset++;
8083           if (size)
8084             emitcode ("inc", "%s", rname);
8085         }
8086     }
8087
8088   /* now some housekeeping stuff */
8089   if (aop)
8090     {
8091       /* we had to allocate for this iCode */
8092       freeAsmop (NULL, aop, ic, TRUE);
8093     }
8094   else
8095     {
8096       /* we did not allocate which means left
8097          already in a pointer register, then
8098          if size > 0 && this could be used again
8099          we have to point it back to where it
8100          belongs */
8101       if (AOP_SIZE (result) > 1 &&
8102           !OP_SYMBOL (left)->remat &&
8103           (OP_SYMBOL (left)->liveTo > ic->seq ||
8104            ic->depth))
8105         {
8106           int size = AOP_SIZE (result) - 1;
8107           while (size--)
8108             emitcode ("dec", "%s", rname);
8109         }
8110     }
8111
8112   /* done */
8113   freeAsmop (result, NULL, ic, TRUE);
8114
8115 }
8116
8117 /*-----------------------------------------------------------------*/
8118 /* genPagedPointerGet - emitcode for paged pointer fetch           */
8119 /*-----------------------------------------------------------------*/
8120 static void
8121 genPagedPointerGet (operand * left,
8122                     operand * result,
8123                     iCode * ic)
8124 {
8125   asmop *aop = NULL;
8126   regs *preg = NULL;
8127   char *rname;
8128   sym_link *rtype, *retype, *letype;
8129
8130   rtype = operandType (result);
8131   retype = getSpec (rtype);
8132   letype = getSpec (operandType (left));
8133   aopOp (left, ic, FALSE, FALSE);
8134
8135   /* if the value is already in a pointer register
8136      then don't need anything more */
8137   if (!AOP_INPREG (AOP (left)))
8138     {
8139       /* otherwise get a free pointer register */
8140       aop = newAsmop (0);
8141       preg = getFreePtr (ic, &aop, FALSE);
8142       emitcode ("mov", "%s,%s",
8143                 preg->name,
8144                 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8145       rname = preg->name;
8146     }
8147   else
8148     rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8149
8150   freeAsmop (left, NULL, ic, TRUE);
8151   aopOp (result, ic, FALSE, FALSE);
8152
8153   /* if bitfield then unpack the bits */
8154   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8155     genUnpackBits (result, rname, PPOINTER);
8156   else
8157     {
8158       /* we have can just get the values */
8159       int size = AOP_SIZE (result);
8160       int offset = 0;
8161
8162       while (size--)
8163         {
8164
8165           emitcode ("movx", "a,@%s", rname);
8166           aopPut (AOP (result), "a", offset);
8167
8168           offset++;
8169
8170           if (size)
8171             emitcode ("inc", "%s", rname);
8172         }
8173     }
8174
8175   /* now some housekeeping stuff */
8176   if (aop)
8177     {
8178       /* we had to allocate for this iCode */
8179       freeAsmop (NULL, aop, ic, TRUE);
8180     }
8181   else
8182     {
8183       /* we did not allocate which means left
8184          already in a pointer register, then
8185          if size > 0 && this could be used again
8186          we have to point it back to where it
8187          belongs */
8188       if (AOP_SIZE (result) > 1 &&
8189           !OP_SYMBOL (left)->remat &&
8190           (OP_SYMBOL (left)->liveTo > ic->seq ||
8191            ic->depth))
8192         {
8193           int size = AOP_SIZE (result) - 1;
8194           while (size--)
8195             emitcode ("dec", "%s", rname);
8196         }
8197     }
8198
8199   /* done */
8200   freeAsmop (result, NULL, ic, TRUE);
8201
8202
8203 }
8204
8205 /*-----------------------------------------------------------------*/
8206 /* genFarPointerGet - gget value from far space                    */
8207 /*-----------------------------------------------------------------*/
8208 static void
8209 genFarPointerGet (operand * left,
8210                   operand * result, iCode * ic)
8211 {
8212   int size, offset;
8213   sym_link *retype = getSpec (operandType (result));
8214   sym_link *letype = getSpec (operandType (left));
8215   D (emitcode (";", "genFarPointerGet");
8216     );
8217
8218   aopOp (left, ic, FALSE, FALSE);
8219
8220   /* if the operand is already in dptr
8221      then we do nothing else we move the value to dptr */
8222   if (AOP_TYPE (left) != AOP_STR)
8223     {
8224       /* if this is remateriazable */
8225       if (AOP_TYPE (left) == AOP_IMMD)
8226         {
8227           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8228         }
8229       else
8230         {
8231           /* we need to get it byte by byte */
8232           _startLazyDPSEvaluation ();
8233           if (AOP_TYPE (left) != AOP_DPTR)
8234             {
8235               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8236               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8237               emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8238             }
8239           else
8240             {
8241               /* We need to generate a load to DPTR indirect through DPTR. */
8242               D (emitcode (";", "genFarPointerGet -- indirection special case.");
8243                 );
8244               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8245               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8246               emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8247               emitcode ("pop", "dph");
8248               emitcode ("pop", "dpl");
8249             }
8250           _endLazyDPSEvaluation ();
8251         }
8252     }
8253   /* so dptr know contains the address */
8254   freeAsmop (left, NULL, ic, TRUE);
8255   aopOp (result, ic, FALSE, TRUE);
8256
8257   /* if bit then unpack */
8258   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8259     genUnpackBits (result, "dptr", FPOINTER);
8260   else
8261     {
8262       size = AOP_SIZE (result);
8263       offset = 0;
8264
8265       _startLazyDPSEvaluation ();
8266       while (size--)
8267         {
8268
8269           genSetDPTR (0);
8270           _flushLazyDPS ();
8271
8272           emitcode ("movx", "a,@dptr");
8273           if (size)
8274             emitcode ("inc", "dptr");
8275
8276           aopPut (AOP (result), "a", offset++);
8277         }
8278       _endLazyDPSEvaluation ();
8279     }
8280
8281   freeAsmop (result, NULL, ic, TRUE);
8282 }
8283
8284 /*-----------------------------------------------------------------*/
8285 /* emitcodePointerGet - gget value from code space                  */
8286 /*-----------------------------------------------------------------*/
8287 static void
8288 emitcodePointerGet (operand * left,
8289                     operand * result, iCode * ic)
8290 {
8291   int size, offset;
8292   sym_link *retype = getSpec (operandType (result));
8293
8294   aopOp (left, ic, FALSE, FALSE);
8295
8296   /* if the operand is already in dptr
8297      then we do nothing else we move the value to dptr */
8298   if (AOP_TYPE (left) != AOP_STR)
8299     {
8300       /* if this is remateriazable */
8301       if (AOP_TYPE (left) == AOP_IMMD)
8302         {
8303           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8304         }
8305       else
8306         {                       /* we need to get it byte by byte */
8307           _startLazyDPSEvaluation ();
8308           if (AOP_TYPE (left) != AOP_DPTR)
8309             {
8310               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8311               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8312               emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8313             }
8314           else
8315             {
8316               /* We need to generate a load to DPTR indirect through DPTR. */
8317               D (emitcode (";", "gencodePointerGet -- indirection special case.");
8318                 );
8319               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8320               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8321               emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8322               emitcode ("pop", "dph");
8323               emitcode ("pop", "dpl");
8324             }
8325           _endLazyDPSEvaluation ();
8326         }
8327     }
8328   /* so dptr know contains the address */
8329   freeAsmop (left, NULL, ic, TRUE);
8330   aopOp (result, ic, FALSE, TRUE);
8331
8332   /* if bit then unpack */
8333   if (IS_BITVAR (retype))
8334     genUnpackBits (result, "dptr", CPOINTER);
8335   else
8336     {
8337       size = AOP_SIZE (result);
8338       offset = 0;
8339
8340       _startLazyDPSEvaluation ();
8341       while (size--)
8342         {
8343           genSetDPTR (0);
8344           _flushLazyDPS ();
8345
8346           emitcode ("clr", "a");
8347           emitcode ("movc", "a,@a+dptr");
8348           if (size)
8349             emitcode ("inc", "dptr");
8350           aopPut (AOP (result), "a", offset++);
8351         }
8352       _endLazyDPSEvaluation ();
8353     }
8354
8355   freeAsmop (result, NULL, ic, TRUE);
8356 }
8357
8358 /*-----------------------------------------------------------------*/
8359 /* genGenPointerGet - gget value from generic pointer space        */
8360 /*-----------------------------------------------------------------*/
8361 static void
8362 genGenPointerGet (operand * left,
8363                   operand * result, iCode * ic)
8364 {
8365   int size, offset;
8366   sym_link *retype = getSpec (operandType (result));
8367   sym_link *letype = getSpec (operandType (left));
8368
8369   D (emitcode (";", "genGenPointerGet "); );
8370
8371   aopOp (left, ic, FALSE, TRUE);
8372
8373   /* if the operand is already in dptr
8374      then we do nothing else we move the value to dptr */
8375   if (AOP_TYPE (left) != AOP_STR)
8376     {
8377       /* if this is remateriazable */
8378       if (AOP_TYPE (left) == AOP_IMMD)
8379         {
8380           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8381           emitcode ("mov", "b,#%d", pointerCode (retype));
8382         }
8383       else
8384         {                       /* we need to get it byte by byte */
8385           _startLazyDPSEvaluation ();
8386           if (AOP(left)->type==AOP_DPTR2) {
8387             char *l;
8388             l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
8389             genSetDPTR(0);
8390             _flushLazyDPS();
8391             emitcode ("mov", "dpl,%s", l);
8392             l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
8393             genSetDPTR(0);
8394             _flushLazyDPS();
8395             emitcode ("mov", "dph,%s", l);
8396             l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
8397             genSetDPTR(0);
8398             _flushLazyDPS();
8399             emitcode ("mov", "dpx,%s", l);
8400             emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8401           } else {
8402             emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
8403             emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
8404             emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8405             emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8406           }
8407           _endLazyDPSEvaluation ();
8408         }
8409     }
8410   /* so dptr know contains the address */
8411   freeAsmop (left, NULL, ic, TRUE);
8412   aopOp (result, ic, FALSE, TRUE);
8413
8414   /* if bit then unpack */
8415   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8416     genUnpackBits (result, "dptr", GPOINTER);
8417   else
8418     {
8419       size = AOP_SIZE (result);
8420       offset = 0;
8421
8422       while (size--)
8423         {
8424           emitcode ("lcall", "__gptrget");
8425           aopPut (AOP (result), "a", offset++);
8426           if (size)
8427             emitcode ("inc", "dptr");
8428         }
8429     }
8430
8431   freeAsmop (result, NULL, ic, TRUE);
8432 }
8433
8434 /*-----------------------------------------------------------------*/
8435 /* genPointerGet - generate code for pointer get                   */
8436 /*-----------------------------------------------------------------*/
8437 static void
8438 genPointerGet (iCode * ic)
8439 {
8440   operand *left, *result;
8441   sym_link *type, *etype;
8442   int p_type;
8443
8444   D (emitcode (";", "genPointerGet ");
8445     );
8446
8447   left = IC_LEFT (ic);
8448   result = IC_RESULT (ic);
8449
8450   /* depending on the type of pointer we need to
8451      move it to the correct pointer register */
8452   type = operandType (left);
8453   etype = getSpec (type);
8454   /* if left is of type of pointer then it is simple */
8455   if (IS_PTR (type) && !IS_FUNC (type->next))
8456     p_type = DCL_TYPE (type);
8457   else
8458     {
8459       /* we have to go by the storage class */
8460       p_type = PTR_TYPE (SPEC_OCLS (etype));
8461     }
8462
8463   /* now that we have the pointer type we assign
8464      the pointer values */
8465   switch (p_type)
8466     {
8467
8468     case POINTER:
8469     case IPOINTER:
8470       genNearPointerGet (left, result, ic);
8471       break;
8472
8473     case PPOINTER:
8474       genPagedPointerGet (left, result, ic);
8475       break;
8476
8477     case FPOINTER:
8478       genFarPointerGet (left, result, ic);
8479       break;
8480
8481     case CPOINTER:
8482       emitcodePointerGet (left, result, ic);
8483       break;
8484
8485     case GPOINTER:
8486       genGenPointerGet (left, result, ic);
8487       break;
8488     }
8489
8490 }
8491
8492 /*-----------------------------------------------------------------*/
8493 /* genPackBits - generates code for packed bit storage             */
8494 /*-----------------------------------------------------------------*/
8495 static void
8496 genPackBits (sym_link * etype,
8497              operand * right,
8498              char *rname, int p_type)
8499 {
8500   int shCount = 0;
8501   int offset = 0;
8502   int rLen = 0;
8503   int blen, bstr;
8504   char *l;
8505
8506   blen = SPEC_BLEN (etype);
8507   bstr = SPEC_BSTR (etype);
8508
8509   l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8510   MOVA (l);
8511
8512   /* if the bit lenth is less than or    */
8513   /* it exactly fits a byte then         */
8514   if (SPEC_BLEN (etype) <= 8)
8515     {
8516       shCount = SPEC_BSTR (etype);
8517
8518       /* shift left acc */
8519       AccLsh (shCount);
8520
8521       if (SPEC_BLEN (etype) < 8)
8522         {                       /* if smaller than a byte */
8523
8524
8525           switch (p_type)
8526             {
8527             case POINTER:
8528               emitcode ("mov", "b,a");
8529               emitcode ("mov", "a,@%s", rname);
8530               break;
8531
8532             case FPOINTER:
8533               emitcode ("mov", "b,a");
8534               emitcode ("movx", "a,@dptr");
8535               break;
8536
8537             case GPOINTER:
8538               emitcode ("push", "b");
8539               emitcode ("push", "acc");
8540               emitcode ("lcall", "__gptrget");
8541               emitcode ("pop", "b");
8542               break;
8543             }
8544
8545           emitcode ("anl", "a,#0x%02x", (unsigned char)
8546                     ((unsigned char) (0xFF << (blen + bstr)) |
8547                      (unsigned char) (0xFF >> (8 - bstr))));
8548           emitcode ("orl", "a,b");
8549           if (p_type == GPOINTER)
8550             emitcode ("pop", "b");
8551         }
8552     }
8553
8554   switch (p_type)
8555     {
8556     case POINTER:
8557       emitcode ("mov", "@%s,a", rname);
8558       break;
8559
8560     case FPOINTER:
8561       emitcode ("movx", "@dptr,a");
8562       break;
8563
8564     case GPOINTER:
8565       emitcode ("lcall", "__gptrput");
8566       break;
8567     }
8568
8569   /* if we r done */
8570   if (SPEC_BLEN (etype) <= 8)
8571     return;
8572
8573   emitcode ("inc", "%s", rname);
8574   rLen = SPEC_BLEN (etype);
8575
8576   /* now generate for lengths greater than one byte */
8577   while (1)
8578     {
8579
8580       l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
8581
8582       rLen -= 8;
8583       if (rLen < 8)
8584         break;
8585
8586       switch (p_type)
8587         {
8588         case POINTER:
8589           if (*l == '@')
8590             {
8591               MOVA (l);
8592               emitcode ("mov", "@%s,a", rname);
8593             }
8594           else
8595             emitcode ("mov", "@%s,%s", rname, l);
8596           break;
8597
8598         case FPOINTER:
8599           MOVA (l);
8600           emitcode ("movx", "@dptr,a");
8601           break;
8602
8603         case GPOINTER:
8604           MOVA (l);
8605           emitcode ("lcall", "__gptrput");
8606           break;
8607         }
8608       emitcode ("inc", "%s", rname);
8609     }
8610
8611   MOVA (l);
8612
8613   /* last last was not complete */
8614   if (rLen)
8615     {
8616       /* save the byte & read byte */
8617       switch (p_type)
8618         {
8619         case POINTER:
8620           emitcode ("mov", "b,a");
8621           emitcode ("mov", "a,@%s", rname);
8622           break;
8623
8624         case FPOINTER:
8625           emitcode ("mov", "b,a");
8626           emitcode ("movx", "a,@dptr");
8627           break;
8628
8629         case GPOINTER:
8630           emitcode ("push", "b");
8631           emitcode ("push", "acc");
8632           emitcode ("lcall", "__gptrget");
8633           emitcode ("pop", "b");
8634           break;
8635         }
8636
8637       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
8638       emitcode ("orl", "a,b");
8639     }
8640
8641   if (p_type == GPOINTER)
8642     emitcode ("pop", "b");
8643
8644   switch (p_type)
8645     {
8646
8647     case POINTER:
8648       emitcode ("mov", "@%s,a", rname);
8649       break;
8650
8651     case FPOINTER:
8652       emitcode ("movx", "@dptr,a");
8653       break;
8654
8655     case GPOINTER:
8656       emitcode ("lcall", "__gptrput");
8657       break;
8658     }
8659 }
8660 /*-----------------------------------------------------------------*/
8661 /* genDataPointerSet - remat pointer to data space                 */
8662 /*-----------------------------------------------------------------*/
8663 static void
8664 genDataPointerSet (operand * right,
8665                    operand * result,
8666                    iCode * ic)
8667 {
8668   int size, offset = 0;
8669   char *l, buffer[256];
8670
8671   aopOp (right, ic, FALSE, FALSE);
8672
8673   l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
8674   size = AOP_SIZE (right);
8675   while (size--)
8676     {
8677       if (offset)
8678         sprintf (buffer, "(%s + %d)", l + 1, offset);
8679       else
8680         sprintf (buffer, "%s", l + 1);
8681       emitcode ("mov", "%s,%s", buffer,
8682                 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
8683     }
8684
8685   freeAsmop (right, NULL, ic, TRUE);
8686   freeAsmop (result, NULL, ic, TRUE);
8687 }
8688
8689 /*-----------------------------------------------------------------*/
8690 /* genNearPointerSet - emitcode for near pointer put                */
8691 /*-----------------------------------------------------------------*/
8692 static void
8693 genNearPointerSet (operand * right,
8694                    operand * result,
8695                    iCode * ic)
8696 {
8697   asmop *aop = NULL;
8698   regs *preg = NULL;
8699   char *rname, *l;
8700   sym_link *retype, *letype;
8701   sym_link *ptype = operandType (result);
8702
8703   retype = getSpec (operandType (right));
8704   letype = getSpec (ptype);
8705
8706   aopOp (result, ic, FALSE, FALSE);
8707
8708   /* if the result is rematerializable &
8709      in data space & not a bit variable */
8710   if (AOP_TYPE (result) == AOP_IMMD &&
8711       DCL_TYPE (ptype) == POINTER &&
8712       !IS_BITVAR (retype) &&
8713       !IS_BITVAR (letype))
8714     {
8715       genDataPointerSet (right, result, ic);
8716       return;
8717     }
8718
8719   /* if the value is already in a pointer register
8720      then don't need anything more */
8721   if (!AOP_INPREG (AOP (result)))
8722     {
8723       /* otherwise get a free pointer register */
8724       aop = newAsmop (0);
8725       preg = getFreePtr (ic, &aop, FALSE);
8726       emitcode ("mov", "%s,%s",
8727                 preg->name,
8728                 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8729       rname = preg->name;
8730     }
8731   else
8732     rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8733
8734   freeAsmop (result, NULL, ic, TRUE);
8735   aopOp (right, ic, FALSE, FALSE);
8736
8737   /* if bitfield then unpack the bits */
8738   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8739     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
8740   else
8741     {
8742       /* we have can just get the values */
8743       int size = AOP_SIZE (right);
8744       int offset = 0;
8745
8746       while (size--)
8747         {
8748           l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
8749           if (*l == '@')
8750             {
8751               MOVA (l);
8752               emitcode ("mov", "@%s,a", rname);
8753             }
8754           else
8755             emitcode ("mov", "@%s,%s", rname, l);
8756           if (size)
8757             emitcode ("inc", "%s", rname);
8758           offset++;
8759         }
8760     }
8761
8762   /* now some housekeeping stuff */
8763   if (aop)
8764     {
8765       /* we had to allocate for this iCode */
8766       freeAsmop (NULL, aop, ic, TRUE);
8767     }
8768   else
8769     {
8770       /* we did not allocate which means left
8771          already in a pointer register, then
8772          if size > 0 && this could be used again
8773          we have to point it back to where it
8774          belongs */
8775       if (AOP_SIZE (right) > 1 &&
8776           !OP_SYMBOL (result)->remat &&
8777           (OP_SYMBOL (result)->liveTo > ic->seq ||
8778            ic->depth))
8779         {
8780           int size = AOP_SIZE (right) - 1;
8781           while (size--)
8782             emitcode ("dec", "%s", rname);
8783         }
8784     }
8785
8786   /* done */
8787   freeAsmop (right, NULL, ic, TRUE);
8788
8789
8790 }
8791
8792 /*-----------------------------------------------------------------*/
8793 /* genPagedPointerSet - emitcode for Paged pointer put             */
8794 /*-----------------------------------------------------------------*/
8795 static void
8796 genPagedPointerSet (operand * right,
8797                     operand * result,
8798                     iCode * ic)
8799 {
8800   asmop *aop = NULL;
8801   regs *preg = NULL;
8802   char *rname, *l;
8803   sym_link *retype, *letype;
8804
8805   retype = getSpec (operandType (right));
8806   letype = getSpec (operandType (result));
8807
8808   aopOp (result, ic, FALSE, FALSE);
8809
8810   /* if the value is already in a pointer register
8811      then don't need anything more */
8812   if (!AOP_INPREG (AOP (result)))
8813     {
8814       /* otherwise get a free pointer register */
8815       aop = newAsmop (0);
8816       preg = getFreePtr (ic, &aop, FALSE);
8817       emitcode ("mov", "%s,%s",
8818                 preg->name,
8819                 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8820       rname = preg->name;
8821     }
8822   else
8823     rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8824
8825   freeAsmop (result, NULL, ic, TRUE);
8826   aopOp (right, ic, FALSE, FALSE);
8827
8828   /* if bitfield then unpack the bits */
8829   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8830     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8831   else
8832     {
8833       /* we have can just get the values */
8834       int size = AOP_SIZE (right);
8835       int offset = 0;
8836
8837       while (size--)
8838         {
8839           l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
8840
8841           MOVA (l);
8842           emitcode ("movx", "@%s,a", rname);
8843
8844           if (size)
8845             emitcode ("inc", "%s", rname);
8846
8847           offset++;
8848         }
8849     }
8850
8851   /* now some housekeeping stuff */
8852   if (aop)
8853     {
8854       /* we had to allocate for this iCode */
8855       freeAsmop (NULL, aop, ic, TRUE);
8856     }
8857   else
8858     {
8859       /* we did not allocate which means left
8860          already in a pointer register, then
8861          if size > 0 && this could be used again
8862          we have to point it back to where it
8863          belongs */
8864       if (AOP_SIZE (right) > 1 &&
8865           !OP_SYMBOL (result)->remat &&
8866           (OP_SYMBOL (result)->liveTo > ic->seq ||
8867            ic->depth))
8868         {
8869           int size = AOP_SIZE (right) - 1;
8870           while (size--)
8871             emitcode ("dec", "%s", rname);
8872         }
8873     }
8874
8875   /* done */
8876   freeAsmop (right, NULL, ic, TRUE);
8877
8878
8879 }
8880
8881 /*-----------------------------------------------------------------*/
8882 /* genFarPointerSet - set value from far space                     */
8883 /*-----------------------------------------------------------------*/
8884 static void
8885 genFarPointerSet (operand * right,
8886                   operand * result, iCode * ic)
8887 {
8888   int size, offset;
8889   sym_link *retype = getSpec (operandType (right));
8890   sym_link *letype = getSpec (operandType (result));
8891
8892   aopOp (result, ic, FALSE, FALSE);
8893
8894   /* if the operand is already in dptr
8895      then we do nothing else we move the value to dptr */
8896   if (AOP_TYPE (result) != AOP_STR)
8897     {
8898       /* if this is remateriazable */
8899       if (AOP_TYPE (result) == AOP_IMMD)
8900         emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8901       else
8902         {
8903           /* we need to get it byte by byte */
8904           _startLazyDPSEvaluation ();
8905           if (AOP_TYPE (result) != AOP_DPTR)
8906             {
8907               emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8908               emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8909               emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8910             }
8911           else
8912             {
8913               /* We need to generate a load to DPTR indirect through DPTR. */
8914               D (emitcode (";", "genFarPointerSet -- indirection special case.");
8915                 );
8916               emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
8917               emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
8918               emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8919               emitcode ("pop", "dph");
8920               emitcode ("pop", "dpl");
8921             }
8922           _endLazyDPSEvaluation ();
8923         }
8924     }
8925   /* so dptr know contains the address */
8926   freeAsmop (result, NULL, ic, TRUE);
8927   aopOp (right, ic, FALSE, TRUE);
8928
8929   /* if bit then unpack */
8930   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8931     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8932   else
8933     {
8934       size = AOP_SIZE (right);
8935       offset = 0;
8936
8937       _startLazyDPSEvaluation ();
8938       while (size--)
8939         {
8940           char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8941           MOVA (l);
8942
8943           genSetDPTR (0);
8944           _flushLazyDPS ();
8945
8946           emitcode ("movx", "@dptr,a");
8947           if (size)
8948             emitcode ("inc", "dptr");
8949         }
8950       _endLazyDPSEvaluation ();
8951     }
8952
8953   freeAsmop (right, NULL, ic, TRUE);
8954 }
8955
8956 /*-----------------------------------------------------------------*/
8957 /* genGenPointerSet - set value from generic pointer space         */
8958 /*-----------------------------------------------------------------*/
8959 static void
8960 genGenPointerSet (operand * right,
8961                   operand * result, iCode * ic)
8962 {
8963   int size, offset;
8964   sym_link *retype = getSpec (operandType (right));
8965   sym_link *letype = getSpec (operandType (result));
8966
8967   aopOp (result, ic, FALSE, TRUE);
8968
8969   /* if the operand is already in dptr
8970      then we do nothing else we move the value to dptr */
8971   if (AOP_TYPE (result) != AOP_STR)
8972     {
8973       _startLazyDPSEvaluation ();
8974       /* if this is remateriazable */
8975       if (AOP_TYPE (result) == AOP_IMMD)
8976         {
8977           emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8978           emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8979         }
8980       else
8981         {                       /* we need to get it byte by byte */
8982           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8983           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8984           emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8985           emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
8986         }
8987       _endLazyDPSEvaluation ();
8988     }
8989   /* so dptr know contains the address */
8990   freeAsmop (result, NULL, ic, TRUE);
8991   aopOp (right, ic, FALSE, TRUE);
8992
8993   /* if bit then unpack */
8994   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8995     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8996   else
8997     {
8998       size = AOP_SIZE (right);
8999       offset = 0;
9000
9001       _startLazyDPSEvaluation ();
9002       while (size--)
9003         {
9004           char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9005           MOVA (l);
9006
9007           genSetDPTR (0);
9008           _flushLazyDPS ();
9009
9010           emitcode ("lcall", "__gptrput");
9011           if (size)
9012             emitcode ("inc", "dptr");
9013         }
9014       _endLazyDPSEvaluation ();
9015     }
9016
9017   freeAsmop (right, NULL, ic, TRUE);
9018 }
9019
9020 /*-----------------------------------------------------------------*/
9021 /* genPointerSet - stores the value into a pointer location        */
9022 /*-----------------------------------------------------------------*/
9023 static void
9024 genPointerSet (iCode * ic)
9025 {
9026   operand *right, *result;
9027   sym_link *type, *etype;
9028   int p_type;
9029
9030   D (emitcode (";", "genPointerSet ");
9031     );
9032
9033   right = IC_RIGHT (ic);
9034   result = IC_RESULT (ic);
9035
9036   /* depending on the type of pointer we need to
9037      move it to the correct pointer register */
9038   type = operandType (result);
9039   etype = getSpec (type);
9040   /* if left is of type of pointer then it is simple */
9041   if (IS_PTR (type) && !IS_FUNC (type->next))
9042     {
9043       p_type = DCL_TYPE (type);
9044     }
9045   else
9046     {
9047       /* we have to go by the storage class */
9048       p_type = PTR_TYPE (SPEC_OCLS (etype));
9049     }
9050
9051   /* now that we have the pointer type we assign
9052      the pointer values */
9053   switch (p_type)
9054     {
9055
9056     case POINTER:
9057     case IPOINTER:
9058       genNearPointerSet (right, result, ic);
9059       break;
9060
9061     case PPOINTER:
9062       genPagedPointerSet (right, result, ic);
9063       break;
9064
9065     case FPOINTER:
9066       genFarPointerSet (right, result, ic);
9067       break;
9068
9069     case GPOINTER:
9070       genGenPointerSet (right, result, ic);
9071       break;
9072     }
9073
9074 }
9075
9076 /*-----------------------------------------------------------------*/
9077 /* genIfx - generate code for Ifx statement                        */
9078 /*-----------------------------------------------------------------*/
9079 static void
9080 genIfx (iCode * ic, iCode * popIc)
9081 {
9082   operand *cond = IC_COND (ic);
9083   int isbit = 0;
9084
9085   D (emitcode (";", "genIfx "););
9086
9087   aopOp (cond, ic, FALSE, FALSE);
9088
9089   /* get the value into acc */
9090   if (AOP_TYPE (cond) != AOP_CRY)
9091     toBoolean (cond);
9092   else
9093     isbit = 1;
9094   /* the result is now in the accumulator */
9095   freeAsmop (cond, NULL, ic, TRUE);
9096
9097   /* if there was something to be popped then do it */
9098   if (popIc)
9099     genIpop (popIc);
9100
9101   /* if the condition is  a bit variable */
9102   if (isbit && IS_ITEMP (cond) &&
9103       SPIL_LOC (cond))
9104     genIfxJump (ic, SPIL_LOC (cond)->rname);
9105   else if (isbit && !IS_ITEMP (cond))
9106     genIfxJump (ic, OP_SYMBOL (cond)->rname);
9107   else
9108     genIfxJump (ic, "a");
9109
9110   ic->generated = 1;
9111 }
9112
9113 /*-----------------------------------------------------------------*/
9114 /* genAddrOf - generates code for address of                       */
9115 /*-----------------------------------------------------------------*/
9116 static void
9117 genAddrOf (iCode * ic)
9118 {
9119   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
9120   int size, offset;
9121
9122   D (emitcode (";", "genAddrOf ");
9123     );
9124
9125   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9126
9127   /* if the operand is on the stack then we
9128      need to get the stack offset of this
9129      variable */
9130   if (sym->onStack)
9131     {
9132       /* if it has an offset then we need to compute
9133          it */
9134       if (sym->stack)
9135         {
9136           emitcode ("mov", "a,_bp");
9137           emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
9138           aopPut (AOP (IC_RESULT (ic)), "a", 0);
9139         }
9140       else
9141         {
9142           /* we can just move _bp */
9143           aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
9144         }
9145       /* fill the result with zero */
9146       size = AOP_SIZE (IC_RESULT (ic)) - 1;
9147
9148
9149       if (options.stack10bit && size < (FPTRSIZE - 1))
9150         {
9151           fprintf (stderr,
9152                    "*** warning: pointer to stack var truncated.\n");
9153         }
9154
9155       offset = 1;
9156       while (size--)
9157         {
9158           /* Yuck! */
9159           if (options.stack10bit && offset == 2)
9160             {
9161               aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
9162             }
9163           else
9164             {
9165               aopPut (AOP (IC_RESULT (ic)), zero, offset++);
9166             }
9167         }
9168
9169       goto release;
9170     }
9171
9172   /* object not on stack then we need the name */
9173   size = AOP_SIZE (IC_RESULT (ic));
9174   offset = 0;
9175
9176   while (size--)
9177     {
9178       char s[SDCC_NAME_MAX];
9179       if (offset)
9180         sprintf (s, "#(%s >> %d)",
9181                  sym->rname,
9182                  offset * 8);
9183       else
9184         sprintf (s, "#%s", sym->rname);
9185       aopPut (AOP (IC_RESULT (ic)), s, offset++);
9186     }
9187
9188 release:
9189   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9190
9191 }
9192
9193 /*-----------------------------------------------------------------*/
9194 /* genFarFarAssign - assignment when both are in far space         */
9195 /*-----------------------------------------------------------------*/
9196 static void
9197 genFarFarAssign (operand * result, operand * right, iCode * ic)
9198 {
9199   int size = AOP_SIZE (right);
9200   int offset = 0;
9201   symbol *rSym = NULL;
9202
9203   if (size == 1)
9204   {
9205       /* quick & easy case. */
9206       D(emitcode(";","genFarFarAssign (1 byte case)"););      
9207       MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
9208       freeAsmop (right, NULL, ic, FALSE);
9209       /* now assign DPTR to result */
9210       _G.accInUse++;
9211       aopOp(result, ic, FALSE, FALSE);
9212       _G.accInUse--;
9213       aopPut(AOP(result), "a", 0);
9214       freeAsmop(result, NULL, ic, FALSE);
9215       return;
9216   }
9217   
9218   /* See if we've got an underlying symbol to abuse. */
9219   if (IS_SYMOP(result) && OP_SYMBOL(result))
9220   {
9221       if (IS_TRUE_SYMOP(result))
9222       {
9223           rSym = OP_SYMBOL(result);
9224       }
9225       else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
9226       {
9227           rSym = OP_SYMBOL(result)->usl.spillLoc;
9228       }
9229   }
9230              
9231   if (size > 1 && rSym && rSym->rname && !rSym->onStack)
9232   {
9233       /* We can use the '390 auto-toggle feature to good effect here. */
9234       
9235       D(emitcode(";","genFarFarAssign ('390 auto-toggle fun)"););
9236       emitcode("mov", "dps, #0x21");    /* Select DPTR2 & auto-toggle. */
9237       emitcode ("mov", "dptr,#%s", rSym->rname); 
9238       /* DP2 = result, DP1 = right, DP1 is current. */
9239       while (size)
9240       {
9241           emitcode("movx", "a,@dptr");
9242           emitcode("movx", "@dptr,a");
9243           if (--size)
9244           {
9245                emitcode("inc", "dptr");
9246                emitcode("inc", "dptr");
9247           }
9248       }
9249       emitcode("mov", "dps, #0");
9250       freeAsmop (right, NULL, ic, FALSE);
9251   }
9252   else
9253   {
9254       D (emitcode (";", "genFarFarAssign"););
9255       aopOp (result, ic, TRUE, TRUE);
9256
9257       _startLazyDPSEvaluation ();
9258       
9259       while (size--)
9260         {
9261           aopPut (AOP (result),
9262                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
9263           offset++;
9264         }
9265       _endLazyDPSEvaluation ();
9266       freeAsmop (result, NULL, ic, FALSE);
9267       freeAsmop (right, NULL, ic, FALSE);
9268   }
9269 }
9270
9271 /*-----------------------------------------------------------------*/
9272 /* genAssign - generate code for assignment                        */
9273 /*-----------------------------------------------------------------*/
9274 static void
9275 genAssign (iCode * ic)
9276 {
9277   operand *result, *right;
9278   int size, offset;
9279   unsigned long lit = 0L;
9280
9281   D (emitcode (";", "genAssign ");
9282     );
9283
9284   result = IC_RESULT (ic);
9285   right = IC_RIGHT (ic);
9286
9287   /* if they are the same */
9288   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9289     return;
9290
9291   aopOp (right, ic, FALSE, FALSE);
9292
9293   emitcode (";", "genAssign: resultIsFar = %s",
9294             isOperandInFarSpace (result) ?
9295             "TRUE" : "FALSE");
9296
9297   /* special case both in far space */
9298   if ((AOP_TYPE (right) == AOP_DPTR ||
9299        AOP_TYPE (right) == AOP_DPTR2) &&
9300   /* IS_TRUE_SYMOP(result)       && */
9301       isOperandInFarSpace (result))
9302     {
9303       genFarFarAssign (result, right, ic);
9304       return;
9305     }
9306
9307   aopOp (result, ic, TRUE, FALSE);
9308
9309   /* if they are the same registers */
9310   if (sameRegs (AOP (right), AOP (result)))
9311     goto release;
9312
9313   /* if the result is a bit */
9314   if (AOP_TYPE (result) == AOP_CRY)
9315     {
9316
9317       /* if the right size is a literal then
9318          we know what the value is */
9319       if (AOP_TYPE (right) == AOP_LIT)
9320         {
9321           if (((int) operandLitValue (right)))
9322             aopPut (AOP (result), one, 0);
9323           else
9324             aopPut (AOP (result), zero, 0);
9325           goto release;
9326         }
9327
9328       /* the right is also a bit variable */
9329       if (AOP_TYPE (right) == AOP_CRY)
9330         {
9331           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9332           aopPut (AOP (result), "c", 0);
9333           goto release;
9334         }
9335
9336       /* we need to or */
9337       toBoolean (right);
9338       aopPut (AOP (result), "a", 0);
9339       goto release;
9340     }
9341
9342   /* bit variables done */
9343   /* general case */
9344   size = AOP_SIZE (result);
9345   offset = 0;
9346   if (AOP_TYPE (right) == AOP_LIT)
9347     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
9348
9349   if ((size > 1) &&
9350       (AOP_TYPE (result) != AOP_REG) &&
9351       (AOP_TYPE (right) == AOP_LIT) &&
9352       !IS_FLOAT (operandType (right)))
9353     {
9354       _startLazyDPSEvaluation ();
9355       while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
9356         {
9357           aopPut (AOP (result),
9358                   aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
9359                   offset);
9360           offset++;
9361           size--;
9362         }
9363       /* And now fill the rest with zeros. */
9364       if (size)
9365         {
9366           emitcode ("clr", "a");
9367         }
9368       while (size--)
9369         {
9370           aopPut (AOP (result), "a", offset++);
9371         }
9372       _endLazyDPSEvaluation ();
9373     }
9374   else
9375     {
9376       _startLazyDPSEvaluation ();
9377       while (size--)
9378         {
9379           aopPut (AOP (result),
9380                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9381                   offset);
9382           offset++;
9383         }
9384       _endLazyDPSEvaluation ();
9385     }
9386
9387 release:
9388   freeAsmop (right, NULL, ic, FALSE);
9389   freeAsmop (result, NULL, ic, TRUE);
9390 }
9391
9392 /*-----------------------------------------------------------------*/
9393 /* genJumpTab - generates code for jump table                      */
9394 /*-----------------------------------------------------------------*/
9395 static void
9396 genJumpTab (iCode * ic)
9397 {
9398   symbol *jtab;
9399   char *l;
9400
9401   D (emitcode (";", "genJumpTab ");
9402     );
9403
9404   aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
9405   /* get the condition into accumulator */
9406   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
9407   MOVA (l);
9408   /* multiply by four! */
9409   emitcode ("add", "a,acc");
9410   emitcode ("add", "a,acc");
9411   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9412
9413   jtab = newiTempLabel (NULL);
9414   emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
9415   emitcode ("jmp", "@a+dptr");
9416   emitcode ("", "%05d$:", jtab->key + 100);
9417   /* now generate the jump labels */
9418   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9419        jtab = setNextItem (IC_JTLABELS (ic)))
9420     emitcode ("ljmp", "%05d$", jtab->key + 100);
9421
9422 }
9423
9424 /*-----------------------------------------------------------------*/
9425 /* genCast - gen code for casting                                  */
9426 /*-----------------------------------------------------------------*/
9427 static void
9428 genCast (iCode * ic)
9429 {
9430   operand *result = IC_RESULT (ic);
9431   sym_link *ctype = operandType (IC_LEFT (ic));
9432   sym_link *rtype = operandType (IC_RIGHT (ic));
9433   operand *right = IC_RIGHT (ic);
9434   int size, offset;
9435
9436   D (emitcode (";", "genCast ");
9437     );
9438
9439   /* if they are equivalent then do nothing */
9440   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9441     return;
9442
9443   aopOp (right, ic, FALSE, FALSE);
9444   aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
9445
9446   /* if the result is a bit */
9447   if (AOP_TYPE (result) == AOP_CRY)
9448     {
9449       /* if the right size is a literal then
9450          we know what the value is */
9451       if (AOP_TYPE (right) == AOP_LIT)
9452         {
9453           if (((int) operandLitValue (right)))
9454             aopPut (AOP (result), one, 0);
9455           else
9456             aopPut (AOP (result), zero, 0);
9457
9458           goto release;
9459         }
9460
9461       /* the right is also a bit variable */
9462       if (AOP_TYPE (right) == AOP_CRY)
9463         {
9464           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9465           aopPut (AOP (result), "c", 0);
9466           goto release;
9467         }
9468
9469       /* we need to or */
9470       toBoolean (right);
9471       aopPut (AOP (result), "a", 0);
9472       goto release;
9473     }
9474
9475   /* if they are the same size : or less */
9476   if (AOP_SIZE (result) <= AOP_SIZE (right))
9477     {
9478
9479       /* if they are in the same place */
9480       if (sameRegs (AOP (right), AOP (result)))
9481         goto release;
9482
9483       /* if they in different places then copy */
9484       size = AOP_SIZE (result);
9485       offset = 0;
9486       _startLazyDPSEvaluation ();
9487       while (size--)
9488         {
9489           aopPut (AOP (result),
9490                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9491                   offset);
9492           offset++;
9493         }
9494       _endLazyDPSEvaluation ();
9495       goto release;
9496     }
9497
9498
9499   /* if the result is of type pointer */
9500   if (IS_PTR (ctype))
9501     {
9502
9503       int p_type;
9504       sym_link *type = operandType (right);
9505
9506       /* pointer to generic pointer */
9507       if (IS_GENPTR (ctype))
9508         {
9509           char *l = zero;
9510
9511           if (IS_PTR (type))
9512             {
9513               p_type = DCL_TYPE (type);
9514             }
9515           else
9516             {
9517 #if OLD_CAST_BEHAVIOR
9518               /* KV: we are converting a non-pointer type to
9519                * a generic pointer. This (ifdef'd out) code
9520                * says that the resulting generic pointer
9521                * should have the same class as the storage
9522                * location of the non-pointer variable.
9523                *
9524                * For example, converting an int (which happens
9525                * to be stored in DATA space) to a pointer results
9526                * in a DATA generic pointer; if the original int
9527                * in XDATA space, so will be the resulting pointer.
9528                *
9529                * I don't like that behavior, and thus this change:
9530                * all such conversions will be forced to XDATA and
9531                * throw a warning. If you want some non-XDATA
9532                * type, or you want to suppress the warning, you
9533                * must go through an intermediate cast, like so:
9534                *
9535                * char _generic *gp = (char _xdata *)(intVar);
9536                */
9537               sym_link *etype = getSpec (type);
9538
9539               /* we have to go by the storage class */
9540               if (SPEC_OCLS (etype) != generic)
9541                 {
9542                   p_type = PTR_TYPE (SPEC_OCLS (etype));
9543                 }
9544               else
9545 #endif
9546                 {
9547                   /* Converting unknown class (i.e. register variable)
9548                    * to generic pointer. This is not good, but
9549                    * we'll make a guess (and throw a warning).
9550                    */
9551                   p_type = FPOINTER;
9552                   werror (W_INT_TO_GEN_PTR_CAST);
9553                 }
9554             }
9555
9556           /* the first two bytes are known */
9557           size = GPTRSIZE - 1;
9558           offset = 0;
9559           _startLazyDPSEvaluation ();
9560           while (size--)
9561             {
9562               aopPut (AOP (result),
9563                       aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9564                       offset);
9565               offset++;
9566             }
9567           _endLazyDPSEvaluation ();
9568
9569           /* the last byte depending on type */
9570           switch (p_type)
9571             {
9572             case IPOINTER:
9573             case POINTER:
9574               l = zero;
9575               break;
9576             case FPOINTER:
9577               l = one;
9578               break;
9579             case CPOINTER:
9580               l = "#0x02";
9581               break;
9582             case PPOINTER:
9583               l = "#0x03";
9584               break;
9585
9586             default:
9587               /* this should never happen */
9588               werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9589                       "got unknown pointer type");
9590               exit (1);
9591             }
9592           aopPut (AOP (result), l, GPTRSIZE - 1);
9593           goto release;
9594         }
9595
9596       /* just copy the pointers */
9597       size = AOP_SIZE (result);
9598       offset = 0;
9599       _startLazyDPSEvaluation ();
9600       while (size--)
9601         {
9602           aopPut (AOP (result),
9603                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9604                   offset);
9605           offset++;
9606         }
9607       _endLazyDPSEvaluation ();
9608       goto release;
9609     }
9610
9611   /* so we now know that the size of destination is greater
9612      than the size of the source */
9613   /* we move to result for the size of source */
9614   size = AOP_SIZE (right);
9615   offset = 0;
9616   _startLazyDPSEvaluation ();
9617   while (size--)
9618     {
9619       aopPut (AOP (result),
9620               aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9621               offset);
9622       offset++;
9623     }
9624   _endLazyDPSEvaluation ();
9625
9626   /* now depending on the sign of the source && destination */
9627   size = AOP_SIZE (result) - AOP_SIZE (right);
9628   /* if unsigned or not an integral type */
9629   /* also, if the source is a bit, we don't need to sign extend, because
9630    * it can't possibly have set the sign bit.
9631    */
9632   if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
9633     {
9634       while (size--)
9635         {
9636           aopPut (AOP (result), zero, offset++);
9637         }
9638     }
9639   else
9640     {
9641       /* we need to extend the sign :{ */
9642       char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
9643                         FALSE, FALSE, TRUE);
9644       MOVA (l);
9645       emitcode ("rlc", "a");
9646       emitcode ("subb", "a,acc");
9647       while (size--)
9648         aopPut (AOP (result), "a", offset++);
9649     }
9650
9651   /* we are done hurray !!!! */
9652
9653 release:
9654   freeAsmop (right, NULL, ic, TRUE);
9655   freeAsmop (result, NULL, ic, TRUE);
9656
9657 }
9658
9659 /*-----------------------------------------------------------------*/
9660 /* genDjnz - generate decrement & jump if not zero instrucion      */
9661 /*-----------------------------------------------------------------*/
9662 static int
9663 genDjnz (iCode * ic, iCode * ifx)
9664 {
9665   symbol *lbl, *lbl1;
9666   if (!ifx)
9667     return 0;
9668
9669   /* if the if condition has a false label
9670      then we cannot save */
9671   if (IC_FALSE (ifx))
9672     return 0;
9673
9674   /* if the minus is not of the form
9675      a = a - 1 */
9676   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
9677       !IS_OP_LITERAL (IC_RIGHT (ic)))
9678     return 0;
9679
9680   if (operandLitValue (IC_RIGHT (ic)) != 1)
9681     return 0;
9682
9683   /* if the size of this greater than one then no
9684      saving */
9685   if (getSize (operandType (IC_RESULT (ic))) > 1)
9686     return 0;
9687
9688   /* otherwise we can save BIG */
9689   D(emitcode(";", "genDjnz"););
9690
9691   lbl = newiTempLabel (NULL);
9692   lbl1 = newiTempLabel (NULL);
9693
9694   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9695
9696   if (AOP_NEEDSACC(IC_RESULT(ic)))
9697   {
9698       /* If the result is accessed indirectly via
9699        * the accumulator, we must explicitly write
9700        * it back after the decrement.
9701        */
9702       char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
9703       
9704       if (strcmp(rByte, "a"))
9705       {
9706            /* Something is hopelessly wrong */
9707            fprintf(stderr, "*** warning: internal error at %s:%d\n",
9708                    __FILE__, __LINE__);
9709            /* We can just give up; the generated code will be inefficient,
9710             * but what the hey.
9711             */
9712            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9713            return 0;
9714       }
9715       emitcode ("dec", "%s", rByte);
9716       aopPut(AOP(IC_RESULT(ic)), rByte, 0);
9717       emitcode ("jnz", "%05d$", lbl->key + 100);
9718   }
9719   else if (IS_AOP_PREG (IC_RESULT (ic)))
9720     {
9721       emitcode ("dec", "%s",
9722                 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9723       emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9724       emitcode ("jnz", "%05d$", lbl->key + 100);
9725     }
9726   else
9727     {
9728       emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
9729                 lbl->key + 100);
9730     }
9731   emitcode ("sjmp", "%05d$", lbl1->key + 100);
9732   emitcode ("", "%05d$:", lbl->key + 100);
9733   emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
9734   emitcode ("", "%05d$:", lbl1->key + 100);
9735
9736   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9737   ifx->generated = 1;
9738   return 1;
9739 }
9740
9741 /*-----------------------------------------------------------------*/
9742 /* genReceive - generate code for a receive iCode                  */
9743 /*-----------------------------------------------------------------*/
9744 static void
9745 genReceive (iCode * ic)
9746 {
9747
9748   D (emitcode (";", "genReceive ");
9749     );
9750
9751   if (isOperandInFarSpace (IC_RESULT (ic)) &&
9752       (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
9753        IS_TRUE_SYMOP (IC_RESULT (ic))))
9754     {
9755       int size = getSize (operandType (IC_RESULT (ic)));
9756       int offset = fReturnSizeDS390 - size;
9757       while (size--)
9758         {
9759           emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
9760                             fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
9761           offset++;
9762         }
9763       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9764       size = AOP_SIZE (IC_RESULT (ic));
9765       offset = 0;
9766       while (size--)
9767         {
9768           emitcode ("pop", "acc");
9769           aopPut (AOP (IC_RESULT (ic)), "a", offset++);
9770         }
9771
9772     }
9773   else
9774     {
9775       _G.accInUse++;
9776       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9777       _G.accInUse--;
9778       assignResultValue (IC_RESULT (ic));
9779     }
9780
9781   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9782 }
9783
9784 /*-----------------------------------------------------------------*/
9785 /* gen390Code - generate code for Dallas 390 based controllers     */
9786 /*-----------------------------------------------------------------*/
9787 void
9788 gen390Code (iCode * lic)
9789 {
9790   iCode *ic;
9791   int cln = 0;
9792
9793   lineHead = lineCurr = NULL;
9794
9795 #if 0
9796   //REMOVE ME!!!
9797   /* print the allocation information */
9798   if (allocInfo)
9799     printAllocInfo (currFunc, codeOutFile);
9800 #endif
9801   /* if debug information required */
9802   if (options.debug && currFunc)
9803     {
9804       cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
9805       _G.debugLine = 1;
9806       if (IS_STATIC (currFunc->etype))
9807         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
9808       else
9809         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
9810       _G.debugLine = 0;
9811     }
9812   /* stack pointer name */
9813   if (options.useXstack)
9814     spname = "_spx";
9815   else
9816     spname = "sp";
9817
9818
9819   for (ic = lic; ic; ic = ic->next)
9820     {
9821
9822       if (cln != ic->lineno)
9823         {
9824           if (options.debug)
9825             {
9826               _G.debugLine = 1;
9827               emitcode ("", "C$%s$%d$%d$%d ==.",
9828                         FileBaseName (ic->filename), ic->lineno,
9829                         ic->level, ic->block);
9830               _G.debugLine = 0;
9831             }
9832           emitcode (";", "%s %d", ic->filename, ic->lineno);
9833           cln = ic->lineno;
9834         }
9835       /* if the result is marked as
9836          spilt and rematerializable or code for
9837          this has already been generated then
9838          do nothing */
9839       if (resultRemat (ic) || ic->generated)
9840         continue;
9841
9842       /* depending on the operation */
9843       switch (ic->op)
9844         {
9845         case '!':
9846           genNot (ic);
9847           break;
9848
9849         case '~':
9850           genCpl (ic);
9851           break;
9852
9853         case UNARYMINUS:
9854           genUminus (ic);
9855           break;
9856
9857         case IPUSH:
9858           genIpush (ic);
9859           break;
9860
9861         case IPOP:
9862           /* IPOP happens only when trying to restore a
9863              spilt live range, if there is an ifx statement
9864              following this pop then the if statement might
9865              be using some of the registers being popped which
9866              would destory the contents of the register so
9867              we need to check for this condition and handle it */
9868           if (ic->next &&
9869               ic->next->op == IFX &&
9870               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
9871             genIfx (ic->next, ic);
9872           else
9873             genIpop (ic);
9874           break;
9875
9876         case CALL:
9877           genCall (ic);
9878           break;
9879
9880         case PCALL:
9881           genPcall (ic);
9882           break;
9883
9884         case FUNCTION:
9885           genFunction (ic);
9886           break;
9887
9888         case ENDFUNCTION:
9889           genEndFunction (ic);
9890           break;
9891
9892         case RETURN:
9893           genRet (ic);
9894           break;
9895
9896         case LABEL:
9897           genLabel (ic);
9898           break;
9899
9900         case GOTO:
9901           genGoto (ic);
9902           break;
9903
9904         case '+':
9905           genPlus (ic);
9906           break;
9907
9908         case '-':
9909           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9910             genMinus (ic);
9911           break;
9912
9913         case '*':
9914           genMult (ic);
9915           break;
9916
9917         case '/':
9918           genDiv (ic);
9919           break;
9920
9921         case '%':
9922           genMod (ic);
9923           break;
9924
9925         case '>':
9926           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9927           break;
9928
9929         case '<':
9930           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9931           break;
9932
9933         case LE_OP:
9934         case GE_OP:
9935         case NE_OP:
9936
9937           /* note these two are xlated by algebraic equivalence
9938              during parsing SDCC.y */
9939           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9940                   "got '>=' or '<=' shouldn't have come here");
9941           break;
9942
9943         case EQ_OP:
9944           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9945           break;
9946
9947         case AND_OP:
9948           genAndOp (ic);
9949           break;
9950
9951         case OR_OP:
9952           genOrOp (ic);
9953           break;
9954
9955         case '^':
9956           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9957           break;
9958
9959         case '|':
9960           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9961           break;
9962
9963         case BITWISEAND:
9964           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9965           break;
9966
9967         case INLINEASM:
9968           genInline (ic);
9969           break;
9970
9971         case RRC:
9972           genRRC (ic);
9973           break;
9974
9975         case RLC:
9976           genRLC (ic);
9977           break;
9978
9979         case GETHBIT:
9980           genGetHbit (ic);
9981           break;
9982
9983         case LEFT_OP:
9984           genLeftShift (ic);
9985           break;
9986
9987         case RIGHT_OP:
9988           genRightShift (ic);
9989           break;
9990
9991         case GET_VALUE_AT_ADDRESS:
9992           genPointerGet (ic);
9993           break;
9994
9995         case '=':
9996           if (POINTER_SET (ic))
9997             genPointerSet (ic);
9998           else
9999             genAssign (ic);
10000           break;
10001
10002         case IFX:
10003           genIfx (ic, NULL);
10004           break;
10005
10006         case ADDRESS_OF:
10007           genAddrOf (ic);
10008           break;
10009
10010         case JUMPTABLE:
10011           genJumpTab (ic);
10012           break;
10013
10014         case CAST:
10015           genCast (ic);
10016           break;
10017
10018         case RECEIVE:
10019           genReceive (ic);
10020           break;
10021
10022         case SEND:
10023           addSet (&_G.sendSet, ic);
10024           break;
10025
10026         default:
10027           ic = ic;
10028         }
10029     }
10030
10031
10032   /* now we are ready to call the
10033      peep hole optimizer */
10034   if (!options.nopeep)
10035     peepHole (&lineHead);
10036
10037   /* now do the actual printing */
10038   printLine (lineHead, codeOutFile);
10039   return;
10040 }