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