final 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                 if (AOP_TYPE(left)==AOP_ACC) {
5357                   emitcode("mov", "b,a");
5358                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5359                   emitcode("anl", "a,b");
5360                 }else {
5361                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5362                   emitcode ("anl", "a,%s",
5363                             aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5364                 }
5365               }
5366               emitcode ("jnz", "%05d$", tlbl->key + 100);
5367               offset++;
5368             }
5369           if (size)
5370             {
5371               CLRC;
5372               emitcode ("", "%05d$:", tlbl->key + 100);
5373               outBitC (result);
5374             }
5375           else if (ifx)
5376             jmpTrueOrFalse (ifx, tlbl);
5377         }
5378       else
5379         {
5380           for (; (size--); offset++)
5381             {
5382               // normal case
5383               // result = left & right
5384               if (AOP_TYPE (right) == AOP_LIT)
5385                 {
5386                   if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5387                     {
5388                       aopPut (AOP (result),
5389                            aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5390                               offset);
5391                       continue;
5392                     }
5393                   else if (bytelit == 0)
5394                     {
5395                       aopPut (AOP (result), zero, offset);
5396                       continue;
5397                     }
5398                   D (emitcode (";", "better literal AND.");
5399                     );
5400                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5401                   emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
5402                                                     FALSE, FALSE, FALSE));
5403
5404                 }
5405               else
5406                 {
5407                   // faster than result <- left, anl result,right
5408                   // and better if result is SFR
5409                   if (AOP_TYPE (left) == AOP_ACC)
5410                     {
5411                       emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
5412                                                        FALSE, FALSE, FALSE));
5413                     }
5414                   else
5415                     {
5416                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5417                       emitcode ("anl", "a,%s",
5418                           aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5419                     }
5420                 }
5421               aopPut (AOP (result), "a", offset);
5422             }
5423         }
5424     }
5425
5426 release:
5427   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5428   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5429   freeAsmop (result, NULL, ic, TRUE);
5430 }
5431
5432
5433 /*-----------------------------------------------------------------*/
5434 /* genOr  - code for or                                            */
5435 /*-----------------------------------------------------------------*/
5436 static void
5437 genOr (iCode * ic, iCode * ifx)
5438 {
5439   operand *left, *right, *result;
5440   int size, offset = 0;
5441   unsigned long lit = 0L;
5442   bool     pushResult;
5443
5444   D (emitcode (";", "genOr "););
5445
5446   AOP_OP_3_NOFATAL (ic, pushResult);
5447   AOP_SET_LOCALS (ic);
5448
5449   if (pushResult)
5450   {
5451       genFarFarLogicOp(ic, "orl");
5452       return;
5453   }
5454
5455
5456 #ifdef DEBUG_TYPE
5457   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5458             AOP_TYPE (result),
5459             AOP_TYPE (left), AOP_TYPE (right));
5460   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5461             AOP_SIZE (result),
5462             AOP_SIZE (left), AOP_SIZE (right));
5463 #endif
5464
5465   /* if left is a literal & right is not then exchange them */
5466   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5467       AOP_NEEDSACC (left))
5468     {
5469       operand *tmp = right;
5470       right = left;
5471       left = tmp;
5472     }
5473
5474   /* if result = right then exchange them */
5475   if (sameRegs (AOP (result), AOP (right)))
5476     {
5477       operand *tmp = right;
5478       right = left;
5479       left = tmp;
5480     }
5481
5482   /* if right is bit then exchange them */
5483   if (AOP_TYPE (right) == AOP_CRY &&
5484       AOP_TYPE (left) != AOP_CRY)
5485     {
5486       operand *tmp = right;
5487       right = left;
5488       left = tmp;
5489     }
5490   if (AOP_TYPE (right) == AOP_LIT)
5491     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5492
5493   size = AOP_SIZE (result);
5494
5495   // if(bit | yy)
5496   // xx = bit | yy;
5497   if (AOP_TYPE (left) == AOP_CRY)
5498     {
5499       if (AOP_TYPE (right) == AOP_LIT)
5500         {
5501           // c = bit & literal;
5502           if (lit)
5503             {
5504               // lit != 0 => result = 1
5505               if (AOP_TYPE (result) == AOP_CRY)
5506                 {
5507                   if (size)
5508                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5509                   else if (ifx)
5510                     continueIfTrue (ifx);
5511                   goto release;
5512                 }
5513               emitcode ("setb", "c");
5514             }
5515           else
5516             {
5517               // lit == 0 => result = left
5518               if (size && sameRegs (AOP (result), AOP (left)))
5519                 goto release;
5520               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5521             }
5522         }
5523       else
5524         {
5525           if (AOP_TYPE (right) == AOP_CRY)
5526             {
5527               // c = bit | bit;
5528               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5529               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5530             }
5531           else
5532             {
5533               // c = bit | val;
5534               symbol *tlbl = newiTempLabel (NULL);
5535               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5536                 emitcode ("setb", "c");
5537               emitcode ("jb", "%s,%05d$",
5538                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
5539               toBoolean (right);
5540               emitcode ("jnz", "%05d$", tlbl->key + 100);
5541               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5542                 {
5543                   jmpTrueOrFalse (ifx, tlbl);
5544                   goto release;
5545                 }
5546               else
5547                 {
5548                   CLRC;
5549                   emitcode ("", "%05d$:", tlbl->key + 100);
5550                 }
5551             }
5552         }
5553       // bit = c
5554       // val = c
5555       if (size)
5556         outBitC (result);
5557       // if(bit | ...)
5558       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5559         genIfxJump (ifx, "c");
5560       goto release;
5561     }
5562
5563   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5564   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5565   if ((AOP_TYPE (right) == AOP_LIT) &&
5566       (AOP_TYPE (result) == AOP_CRY) &&
5567       (AOP_TYPE (left) != AOP_CRY))
5568     {
5569       if (lit)
5570         {
5571           // result = 1
5572           if (size)
5573             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5574           else
5575             continueIfTrue (ifx);
5576           goto release;
5577         }
5578       else
5579         {
5580           // lit = 0, result = boolean(left)
5581           if (size)
5582             emitcode ("setb", "c");
5583           toBoolean (right);
5584           if (size)
5585             {
5586               symbol *tlbl = newiTempLabel (NULL);
5587               emitcode ("jnz", "%05d$", tlbl->key + 100);
5588               CLRC;
5589               emitcode ("", "%05d$:", tlbl->key + 100);
5590             }
5591           else
5592             {
5593               genIfxJump (ifx, "a");
5594               goto release;
5595             }
5596         }
5597       outBitC (result);
5598       goto release;
5599     }
5600
5601   /* if left is same as result */
5602   if (sameRegs (AOP (result), AOP (left)))
5603     {
5604       for (; size--; offset++)
5605         {
5606           if (AOP_TYPE (right) == AOP_LIT)
5607             {
5608               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5609                 {
5610                   continue;
5611                 }
5612               else
5613                 {
5614                   if (IS_AOP_PREG (left))
5615                     {
5616                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5617                       emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5618                       aopPut (AOP (result), "a", offset);
5619                     }
5620                   else
5621                     {
5622                       emitcode ("orl", "%s,%s",
5623                             aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5624                          aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5625                     }
5626                 }
5627             }
5628           else
5629             {
5630               if (AOP_TYPE (left) == AOP_ACC)
5631                 {
5632                   emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5633                 }
5634               else
5635                 {
5636                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5637                   if (IS_AOP_PREG (left))
5638                     {
5639                       emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5640                       aopPut (AOP (result), "a", offset);
5641                     }
5642                   else
5643                     {
5644                       emitcode ("orl", "%s,a",
5645                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5646                     }
5647                 }
5648             }
5649         }
5650     }
5651   else
5652     {
5653       // left & result in different registers
5654       if (AOP_TYPE (result) == AOP_CRY)
5655         {
5656           // result = bit
5657           // if(size), result in bit
5658           // if(!size && ifx), conditional oper: if(left | right)
5659           symbol *tlbl = newiTempLabel (NULL);
5660           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5661           if (size)
5662             emitcode ("setb", "c");
5663           while (sizer--)
5664             {
5665               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5666                 emitcode ("orl", "a,%s",
5667                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5668               } else {
5669                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5670                 emitcode ("orl", "a,%s",
5671                           aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5672               }
5673               emitcode ("jnz", "%05d$", tlbl->key + 100);
5674               offset++;
5675             }
5676           if (size)
5677             {
5678               CLRC;
5679               emitcode ("", "%05d$:", tlbl->key + 100);
5680               outBitC (result);
5681             }
5682           else if (ifx)
5683             jmpTrueOrFalse (ifx, tlbl);
5684         }
5685       else
5686         {
5687           for (; (size--); offset++)
5688             {
5689               // normal case
5690               // result = left & right
5691               if (AOP_TYPE (right) == AOP_LIT)
5692                 {
5693                   if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5694                     {
5695                       aopPut (AOP (result),
5696                            aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5697                               offset);
5698                       continue;
5699                     }
5700                   D (emitcode (";", "better literal OR.");
5701                     );
5702                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5703                   emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
5704                                                     FALSE, FALSE, FALSE));
5705
5706                 }
5707               else
5708                 {
5709                   // faster than result <- left, anl result,right
5710                   // and better if result is SFR
5711                   if (AOP_TYPE (left) == AOP_ACC)
5712                     {
5713                       emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
5714                                                        FALSE, FALSE, FALSE));
5715                     }
5716                   else
5717                     {
5718                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5719                       emitcode ("orl", "a,%s",
5720                           aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5721                     }
5722                 }
5723               aopPut (AOP (result), "a", offset);
5724             }
5725         }
5726     }
5727
5728 release:
5729   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5730   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5731   freeAsmop (result, NULL, ic, TRUE);
5732 }
5733
5734 /*-----------------------------------------------------------------*/
5735 /* genXor - code for xclusive or                                   */
5736 /*-----------------------------------------------------------------*/
5737 static void
5738 genXor (iCode * ic, iCode * ifx)
5739 {
5740   operand *left, *right, *result;
5741   int size, offset = 0;
5742   unsigned long lit = 0L;
5743   bool pushResult;
5744
5745   D (emitcode (";", "genXor "););
5746
5747   AOP_OP_3_NOFATAL (ic, pushResult);
5748   AOP_SET_LOCALS (ic);
5749
5750   if (pushResult)
5751   {
5752       genFarFarLogicOp(ic, "xrl");
5753       return;
5754   }  
5755
5756 #ifdef DEBUG_TYPE
5757   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5758             AOP_TYPE (result),
5759             AOP_TYPE (left), AOP_TYPE (right));
5760   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5761             AOP_SIZE (result),
5762             AOP_SIZE (left), AOP_SIZE (right));
5763 #endif
5764
5765   /* if left is a literal & right is not ||
5766      if left needs acc & right does not */
5767   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5768       (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5769     {
5770       operand *tmp = right;
5771       right = left;
5772       left = tmp;
5773     }
5774
5775   /* if result = right then exchange them */
5776   if (sameRegs (AOP (result), AOP (right)))
5777     {
5778       operand *tmp = right;
5779       right = left;
5780       left = tmp;
5781     }
5782
5783   /* if right is bit then exchange them */
5784   if (AOP_TYPE (right) == AOP_CRY &&
5785       AOP_TYPE (left) != AOP_CRY)
5786     {
5787       operand *tmp = right;
5788       right = left;
5789       left = tmp;
5790     }
5791   if (AOP_TYPE (right) == AOP_LIT)
5792     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5793
5794   size = AOP_SIZE (result);
5795
5796   // if(bit ^ yy)
5797   // xx = bit ^ yy;
5798   if (AOP_TYPE (left) == AOP_CRY)
5799     {
5800       if (AOP_TYPE (right) == AOP_LIT)
5801         {
5802           // c = bit & literal;
5803           if (lit >> 1)
5804             {
5805               // lit>>1  != 0 => result = 1
5806               if (AOP_TYPE (result) == AOP_CRY)
5807                 {
5808                   if (size)
5809                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5810                   else if (ifx)
5811                     continueIfTrue (ifx);
5812                   goto release;
5813                 }
5814               emitcode ("setb", "c");
5815             }
5816           else
5817             {
5818               // lit == (0 or 1)
5819               if (lit == 0)
5820                 {
5821                   // lit == 0, result = left
5822                   if (size && sameRegs (AOP (result), AOP (left)))
5823                     goto release;
5824                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5825                 }
5826               else
5827                 {
5828                   // lit == 1, result = not(left)
5829                   if (size && sameRegs (AOP (result), AOP (left)))
5830                     {
5831                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5832                       goto release;
5833                     }
5834                   else
5835                     {
5836                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5837                       emitcode ("cpl", "c");
5838                     }
5839                 }
5840             }
5841
5842         }
5843       else
5844         {
5845           // right != literal
5846           symbol *tlbl = newiTempLabel (NULL);
5847           if (AOP_TYPE (right) == AOP_CRY)
5848             {
5849               // c = bit ^ bit;
5850               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5851             }
5852           else
5853             {
5854               int sizer = AOP_SIZE (right);
5855               // c = bit ^ val
5856               // if val>>1 != 0, result = 1
5857               emitcode ("setb", "c");
5858               while (sizer)
5859                 {
5860                   MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
5861                   if (sizer == 1)
5862                     // test the msb of the lsb
5863                     emitcode ("anl", "a,#0xfe");
5864                   emitcode ("jnz", "%05d$", tlbl->key + 100);
5865                   sizer--;
5866                 }
5867               // val = (0,1)
5868               emitcode ("rrc", "a");
5869             }
5870           emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5871           emitcode ("cpl", "c");
5872           emitcode ("", "%05d$:", (tlbl->key + 100));
5873         }
5874       // bit = c
5875       // val = c
5876       if (size)
5877         outBitC (result);
5878       // if(bit | ...)
5879       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5880         genIfxJump (ifx, "c");
5881       goto release;
5882     }
5883
5884   if (sameRegs (AOP (result), AOP (left)))
5885     {
5886       /* if left is same as result */
5887       for (; size--; offset++)
5888         {
5889           if (AOP_TYPE (right) == AOP_LIT)
5890             {
5891               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5892                 continue;
5893               else if (IS_AOP_PREG (left))
5894                 {
5895                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5896                   emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5897                   aopPut (AOP (result), "a", offset);
5898                 }
5899               else
5900                 emitcode ("xrl", "%s,%s",
5901                           aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5902                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5903             }
5904           else
5905             {
5906               if (AOP_TYPE (left) == AOP_ACC)
5907                 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5908               else
5909                 {
5910                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5911                   if (IS_AOP_PREG (left))
5912                     {
5913                       emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5914                       aopPut (AOP (result), "a", offset);
5915                     }
5916                   else
5917                     emitcode ("xrl", "%s,a",
5918                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5919                 }
5920             }
5921         }
5922     }
5923   else
5924     {
5925       // left & result in different registers
5926       if (AOP_TYPE (result) == AOP_CRY)
5927         {
5928           // result = bit
5929           // if(size), result in bit
5930           // if(!size && ifx), conditional oper: if(left ^ right)
5931           symbol *tlbl = newiTempLabel (NULL);
5932           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5933           if (size)
5934             emitcode ("setb", "c");
5935           while (sizer--)
5936             {
5937               if ((AOP_TYPE (right) == AOP_LIT) &&
5938                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5939                 {
5940                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5941                 }
5942               else
5943                 {
5944                   if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5945                     emitcode ("xrl", "a,%s",
5946                               aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5947                   } else {
5948                     MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5949                     emitcode ("xrl", "a,%s",
5950                               aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5951                   }
5952                 }
5953               emitcode ("jnz", "%05d$", tlbl->key + 100);
5954               offset++;
5955             }
5956           if (size)
5957             {
5958               CLRC;
5959               emitcode ("", "%05d$:", tlbl->key + 100);
5960               outBitC (result);
5961             }
5962           else if (ifx)
5963             jmpTrueOrFalse (ifx, tlbl);
5964         }
5965       else
5966         for (; (size--); offset++)
5967           {
5968             // normal case
5969             // result = left & right
5970             if (AOP_TYPE (right) == AOP_LIT)
5971               {
5972                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5973                   {
5974                     aopPut (AOP (result),
5975                             aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5976                             offset);
5977                     continue;
5978                   }
5979                 D (emitcode (";", "better literal XOR.");
5980                   );
5981                 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5982                 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
5983                                                   FALSE, FALSE, FALSE));
5984               }
5985             else
5986               {
5987                 // faster than result <- left, anl result,right
5988                 // and better if result is SFR
5989                 if (AOP_TYPE (left) == AOP_ACC)
5990                   {
5991                     emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
5992                                                      FALSE, FALSE, FALSE));
5993                   }
5994                 else
5995                   {
5996                     MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5997                     emitcode ("xrl", "a,%s",
5998                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5999                   }
6000               }
6001             aopPut (AOP (result), "a", offset);
6002           }
6003     }
6004
6005 release:
6006   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6007   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6008   freeAsmop (result, NULL, ic, TRUE);
6009 }
6010
6011 /*-----------------------------------------------------------------*/
6012 /* genInline - write the inline code out                           */
6013 /*-----------------------------------------------------------------*/
6014 static void
6015 genInline (iCode * ic)
6016 {
6017   char *buffer, *bp, *bp1;
6018
6019   D (emitcode (";", "genInline ");
6020     );
6021
6022   _G.inLine += (!options.asmpeep);
6023
6024   buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6025   strcpy (buffer, IC_INLINE (ic));
6026
6027   /* emit each line as a code */
6028   while (*bp)
6029     {
6030       if (*bp == '\n')
6031         {
6032           *bp++ = '\0';
6033           emitcode (bp1, "");
6034           bp1 = bp;
6035         }
6036       else
6037         {
6038           if (*bp == ':')
6039             {
6040               bp++;
6041               *bp = '\0';
6042               bp++;
6043               emitcode (bp1, "");
6044               bp1 = bp;
6045             }
6046           else
6047             bp++;
6048         }
6049     }
6050   if (bp1 != bp)
6051     emitcode (bp1, "");
6052   /*     emitcode("",buffer); */
6053   _G.inLine -= (!options.asmpeep);
6054 }
6055
6056 /*-----------------------------------------------------------------*/
6057 /* genRRC - rotate right with carry                                */
6058 /*-----------------------------------------------------------------*/
6059 static void
6060 genRRC (iCode * ic)
6061 {
6062   operand *left, *result;
6063   int size, offset = 0;
6064   char *l;
6065
6066   D (emitcode (";", "genRRC ");
6067     );
6068
6069   /* rotate right with carry */
6070   left = IC_LEFT (ic);
6071   result = IC_RESULT (ic);
6072   aopOp (left, ic, FALSE, FALSE);
6073   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6074
6075   /* move it to the result */
6076   size = AOP_SIZE (result);
6077   offset = size - 1;
6078   CLRC;
6079
6080   _startLazyDPSEvaluation ();
6081   while (size--)
6082     {
6083       l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6084       MOVA (l);
6085       emitcode ("rrc", "a");
6086       if (AOP_SIZE (result) > 1)
6087         aopPut (AOP (result), "a", offset--);
6088     }
6089   _endLazyDPSEvaluation ();
6090
6091   /* now we need to put the carry into the
6092      highest order byte of the result */
6093   if (AOP_SIZE (result) > 1)
6094     {
6095       l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
6096       MOVA (l);
6097     }
6098   emitcode ("mov", "acc.7,c");
6099   aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
6100   freeAsmop (left, NULL, ic, TRUE);
6101   freeAsmop (result, NULL, ic, TRUE);
6102 }
6103
6104 /*-----------------------------------------------------------------*/
6105 /* genRLC - generate code for rotate left with carry               */
6106 /*-----------------------------------------------------------------*/
6107 static void
6108 genRLC (iCode * ic)
6109 {
6110   operand *left, *result;
6111   int size, offset = 0;
6112   char *l;
6113
6114   D (emitcode (";", "genRLC ");
6115     );
6116
6117   /* rotate right with carry */
6118   left = IC_LEFT (ic);
6119   result = IC_RESULT (ic);
6120   aopOp (left, ic, FALSE, FALSE);
6121   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6122
6123   /* move it to the result */
6124   size = AOP_SIZE (result);
6125   offset = 0;
6126   if (size--)
6127     {
6128       l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6129       MOVA (l);
6130       emitcode ("add", "a,acc");
6131       if (AOP_SIZE (result) > 1)
6132         {
6133           aopPut (AOP (result), "a", offset++);
6134         }
6135
6136       _startLazyDPSEvaluation ();
6137       while (size--)
6138         {
6139           l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6140           MOVA (l);
6141           emitcode ("rlc", "a");
6142           if (AOP_SIZE (result) > 1)
6143             aopPut (AOP (result), "a", offset++);
6144         }
6145       _endLazyDPSEvaluation ();
6146     }
6147   /* now we need to put the carry into the
6148      highest order byte of the result */
6149   if (AOP_SIZE (result) > 1)
6150     {
6151       l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
6152       MOVA (l);
6153     }
6154   emitcode ("mov", "acc.0,c");
6155   aopPut (AOP (result), "a", 0);
6156   freeAsmop (left, NULL, ic, TRUE);
6157   freeAsmop (result, NULL, ic, TRUE);
6158 }
6159
6160 /*-----------------------------------------------------------------*/
6161 /* genGetHbit - generates code get highest order bit               */
6162 /*-----------------------------------------------------------------*/
6163 static void
6164 genGetHbit (iCode * ic)
6165 {
6166   operand *left, *result;
6167   left = IC_LEFT (ic);
6168   result = IC_RESULT (ic);
6169   aopOp (left, ic, FALSE, FALSE);
6170   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6171
6172   D (emitcode (";", "genGetHbit ");
6173     );
6174
6175   /* get the highest order byte into a */
6176   MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
6177   if (AOP_TYPE (result) == AOP_CRY)
6178     {
6179       emitcode ("rlc", "a");
6180       outBitC (result);
6181     }
6182   else
6183     {
6184       emitcode ("rl", "a");
6185       emitcode ("anl", "a,#0x01");
6186       outAcc (result);
6187     }
6188
6189
6190   freeAsmop (left, NULL, ic, TRUE);
6191   freeAsmop (result, NULL, ic, TRUE);
6192 }
6193
6194 /*-----------------------------------------------------------------*/
6195 /* AccRol - rotate left accumulator by known count                 */
6196 /*-----------------------------------------------------------------*/
6197 static void
6198 AccRol (int shCount)
6199 {
6200   shCount &= 0x0007;            // shCount : 0..7
6201
6202   switch (shCount)
6203     {
6204     case 0:
6205       break;
6206     case 1:
6207       emitcode ("rl", "a");
6208       break;
6209     case 2:
6210       emitcode ("rl", "a");
6211       emitcode ("rl", "a");
6212       break;
6213     case 3:
6214       emitcode ("swap", "a");
6215       emitcode ("rr", "a");
6216       break;
6217     case 4:
6218       emitcode ("swap", "a");
6219       break;
6220     case 5:
6221       emitcode ("swap", "a");
6222       emitcode ("rl", "a");
6223       break;
6224     case 6:
6225       emitcode ("rr", "a");
6226       emitcode ("rr", "a");
6227       break;
6228     case 7:
6229       emitcode ("rr", "a");
6230       break;
6231     }
6232 }
6233
6234 /*-----------------------------------------------------------------*/
6235 /* AccLsh - left shift accumulator by known count                  */
6236 /*-----------------------------------------------------------------*/
6237 static void
6238 AccLsh (int shCount)
6239 {
6240   if (shCount != 0)
6241     {
6242       if (shCount == 1)
6243         emitcode ("add", "a,acc");
6244       else if (shCount == 2)
6245         {
6246           emitcode ("add", "a,acc");
6247           emitcode ("add", "a,acc");
6248         }
6249       else
6250         {
6251           /* rotate left accumulator */
6252           AccRol (shCount);
6253           /* and kill the lower order bits */
6254           emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6255         }
6256     }
6257 }
6258
6259 /*-----------------------------------------------------------------*/
6260 /* AccRsh - right shift accumulator by known count                 */
6261 /*-----------------------------------------------------------------*/
6262 static void
6263 AccRsh (int shCount)
6264 {
6265   if (shCount != 0)
6266     {
6267       if (shCount == 1)
6268         {
6269           CLRC;
6270           emitcode ("rrc", "a");
6271         }
6272       else
6273         {
6274           /* rotate right accumulator */
6275           AccRol (8 - shCount);
6276           /* and kill the higher order bits */
6277           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6278         }
6279     }
6280 }
6281
6282 #ifdef BETTER_LITERAL_SHIFT
6283 /*-----------------------------------------------------------------*/
6284 /* AccSRsh - signed right shift accumulator by known count                 */
6285 /*-----------------------------------------------------------------*/
6286 static void
6287 AccSRsh (int shCount)
6288 {
6289   symbol *tlbl;
6290   if (shCount != 0)
6291     {
6292       if (shCount == 1)
6293         {
6294           emitcode ("mov", "c,acc.7");
6295           emitcode ("rrc", "a");
6296         }
6297       else if (shCount == 2)
6298         {
6299           emitcode ("mov", "c,acc.7");
6300           emitcode ("rrc", "a");
6301           emitcode ("mov", "c,acc.7");
6302           emitcode ("rrc", "a");
6303         }
6304       else
6305         {
6306           tlbl = newiTempLabel (NULL);
6307           /* rotate right accumulator */
6308           AccRol (8 - shCount);
6309           /* and kill the higher order bits */
6310           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6311           emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6312           emitcode ("orl", "a,#0x%02x",
6313                     (unsigned char) ~SRMask[shCount]);
6314           emitcode ("", "%05d$:", tlbl->key + 100);
6315         }
6316     }
6317 }
6318 #endif
6319
6320 #ifdef BETTER_LITERAL_SHIFT
6321 /*-----------------------------------------------------------------*/
6322 /* shiftR1Left2Result - shift right one byte from left to result   */
6323 /*-----------------------------------------------------------------*/
6324 static void
6325 shiftR1Left2Result (operand * left, int offl,
6326                     operand * result, int offr,
6327                     int shCount, int sign)
6328 {
6329   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6330   /* shift right accumulator */
6331   if (sign)
6332     AccSRsh (shCount);
6333   else
6334     AccRsh (shCount);
6335   aopPut (AOP (result), "a", offr);
6336 }
6337 #endif
6338
6339 #ifdef BETTER_LITERAL_SHIFT
6340 /*-----------------------------------------------------------------*/
6341 /* shiftL1Left2Result - shift left one byte from left to result    */
6342 /*-----------------------------------------------------------------*/
6343 static void
6344 shiftL1Left2Result (operand * left, int offl,
6345                     operand * result, int offr, int shCount)
6346 {
6347   MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6348   /* shift left accumulator */
6349   AccLsh (shCount);
6350   aopPut (AOP (result), "a", offr);
6351 }
6352 #endif
6353
6354 #ifdef BETTER_LITERAL_SHIFT
6355 /*-----------------------------------------------------------------*/
6356 /* movLeft2Result - move byte from left to result                  */
6357 /*-----------------------------------------------------------------*/
6358 static void
6359 movLeft2Result (operand * left, int offl,
6360                 operand * result, int offr, int sign)
6361 {
6362   char *l;
6363   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6364   {
6365       l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
6366
6367       if (*l == '@' && (IS_AOP_PREG (result)))
6368       {
6369           emitcode ("mov", "a,%s", l);
6370           aopPut (AOP (result), "a", offr);
6371       }
6372       else
6373       {
6374           if (!sign)
6375           {
6376             aopPut (AOP (result), l, offr);
6377           }
6378           else
6379             {
6380               /* MSB sign in acc.7 ! */
6381               if (getDataSize (left) == offl + 1)
6382                 {
6383                   emitcode ("mov", "a,%s", l);
6384                   aopPut (AOP (result), "a", offr);
6385                 }
6386             }
6387       }
6388   }
6389 }
6390 #endif
6391
6392 #ifdef BETTER_LITERAL_SHIFT
6393 /*-----------------------------------------------------------------*/
6394 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
6395 /*-----------------------------------------------------------------*/
6396 static void
6397 AccAXRrl1 (char *x)
6398 {
6399   emitcode ("rrc", "a");
6400   emitcode ("xch", "a,%s", x);
6401   emitcode ("rrc", "a");
6402   emitcode ("xch", "a,%s", x);
6403 }
6404 #endif
6405
6406 #ifdef BETTER_LITERAL_SHIFT
6407 //REMOVE ME!!!
6408 /*-----------------------------------------------------------------*/
6409 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
6410 /*-----------------------------------------------------------------*/
6411 static void
6412 AccAXLrl1 (char *x)
6413 {
6414   emitcode ("xch", "a,%s", x);
6415   emitcode ("rlc", "a");
6416   emitcode ("xch", "a,%s", x);
6417   emitcode ("rlc", "a");
6418 }
6419 #endif
6420
6421 #ifdef BETTER_LITERAL_SHIFT
6422 /*-----------------------------------------------------------------*/
6423 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
6424 /*-----------------------------------------------------------------*/
6425 static void
6426 AccAXLsh1 (char *x)
6427 {
6428   emitcode ("xch", "a,%s", x);
6429   emitcode ("add", "a,acc");
6430   emitcode ("xch", "a,%s", x);
6431   emitcode ("rlc", "a");
6432 }
6433 #endif
6434
6435 #ifdef BETTER_LITERAL_SHIFT
6436 /*-----------------------------------------------------------------*/
6437 /* AccAXLsh - left shift a:x by known count (0..7)                 */
6438 /*-----------------------------------------------------------------*/
6439 static void
6440 AccAXLsh (char *x, int shCount)
6441 {
6442   switch (shCount)
6443     {
6444     case 0:
6445       break;
6446     case 1:
6447       AccAXLsh1 (x);
6448       break;
6449     case 2:
6450       AccAXLsh1 (x);
6451       AccAXLsh1 (x);
6452       break;
6453     case 3:
6454     case 4:
6455     case 5:                     // AAAAABBB:CCCCCDDD
6456
6457       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
6458
6459       emitcode ("anl", "a,#0x%02x",
6460                 SLMask[shCount]);       // BBB00000:CCCCCDDD
6461
6462       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
6463
6464       AccRol (shCount);         // DDDCCCCC:BBB00000
6465
6466       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
6467
6468       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
6469
6470       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
6471
6472       emitcode ("anl", "a,#0x%02x",
6473                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
6474
6475       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
6476
6477       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
6478
6479       break;
6480     case 6:                     // AAAAAABB:CCCCCCDD
6481       emitcode ("anl", "a,#0x%02x",
6482                 SRMask[shCount]);       // 000000BB:CCCCCCDD
6483       emitcode ("mov", "c,acc.0");      // c = B
6484       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
6485 #if 0
6486       AccAXRrl1 (x);            // BCCCCCCD:D000000B
6487       AccAXRrl1 (x);            // BBCCCCCC:DD000000
6488 #else
6489       emitcode("rrc","a"); 
6490       emitcode("xch","a,%s", x); 
6491       emitcode("rrc","a"); 
6492       emitcode("mov","c,acc.0"); //<< get correct bit 
6493       emitcode("xch","a,%s", x); 
6494
6495       emitcode("rrc","a"); 
6496       emitcode("xch","a,%s", x); 
6497       emitcode("rrc","a"); 
6498       emitcode("xch","a,%s", x); 
6499 #endif
6500       break;
6501     case 7:                     // a:x <<= 7
6502
6503       emitcode ("anl", "a,#0x%02x",
6504                 SRMask[shCount]);       // 0000000B:CCCCCCCD
6505
6506       emitcode ("mov", "c,acc.0");      // c = B
6507
6508       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
6509
6510       AccAXRrl1 (x);            // BCCCCCCC:D0000000
6511
6512       break;
6513     default:
6514       break;
6515     }
6516 }
6517 #endif
6518
6519 #ifdef BETTER_LITERAL_SHIFT
6520 //REMOVE ME!!!
6521 /*-----------------------------------------------------------------*/
6522 /* AccAXRsh - right shift a:x known count (0..7)                   */
6523 /*-----------------------------------------------------------------*/
6524 static void
6525 AccAXRsh (char *x, int shCount)
6526 {
6527   switch (shCount)
6528     {
6529     case 0:
6530       break;
6531     case 1:
6532       CLRC;
6533       AccAXRrl1 (x);            // 0->a:x
6534
6535       break;
6536     case 2:
6537       CLRC;
6538       AccAXRrl1 (x);            // 0->a:x
6539
6540       CLRC;
6541       AccAXRrl1 (x);            // 0->a:x
6542
6543       break;
6544     case 3:
6545     case 4:
6546     case 5:                     // AAAAABBB:CCCCCDDD = a:x
6547
6548       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
6549
6550       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
6551
6552       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
6553
6554       emitcode ("anl", "a,#0x%02x",
6555                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
6556
6557       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
6558
6559       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
6560
6561       emitcode ("anl", "a,#0x%02x",
6562                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
6563
6564       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
6565
6566       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
6567
6568       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
6569
6570       break;
6571     case 6:                     // AABBBBBB:CCDDDDDD
6572
6573       emitcode ("mov", "c,acc.7");
6574       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
6575
6576       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
6577
6578       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
6579
6580       emitcode ("anl", "a,#0x%02x",
6581                 SRMask[shCount]);       // 000000AA:BBBBBBCC
6582
6583       break;
6584     case 7:                     // ABBBBBBB:CDDDDDDD
6585
6586       emitcode ("mov", "c,acc.7");      // c = A
6587
6588       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
6589
6590       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
6591
6592       emitcode ("anl", "a,#0x%02x",
6593                 SRMask[shCount]);       // 0000000A:BBBBBBBC
6594
6595       break;
6596     default:
6597       break;
6598     }
6599 }
6600 #endif
6601
6602 #ifdef BETTER_LITERAL_SHIFT
6603 //REMOVE ME!!!
6604 /*-----------------------------------------------------------------*/
6605 /* AccAXRshS - right shift signed a:x known count (0..7)           */
6606 /*-----------------------------------------------------------------*/
6607 static void
6608 AccAXRshS (char *x, int shCount)
6609 {
6610   symbol *tlbl;
6611   switch (shCount)
6612     {
6613     case 0:
6614       break;
6615     case 1:
6616       emitcode ("mov", "c,acc.7");
6617       AccAXRrl1 (x);            // s->a:x
6618
6619       break;
6620     case 2:
6621       emitcode ("mov", "c,acc.7");
6622       AccAXRrl1 (x);            // s->a:x
6623
6624       emitcode ("mov", "c,acc.7");
6625       AccAXRrl1 (x);            // s->a:x
6626
6627       break;
6628     case 3:
6629     case 4:
6630     case 5:                     // AAAAABBB:CCCCCDDD = a:x
6631
6632       tlbl = newiTempLabel (NULL);
6633       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
6634
6635       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
6636
6637       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
6638
6639       emitcode ("anl", "a,#0x%02x",
6640                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
6641
6642       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
6643
6644       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
6645
6646       emitcode ("anl", "a,#0x%02x",
6647                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
6648
6649       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
6650
6651       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
6652
6653       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
6654
6655       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6656       emitcode ("orl", "a,#0x%02x",
6657                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
6658
6659       emitcode ("", "%05d$:", tlbl->key + 100);
6660       break;                    // SSSSAAAA:BBBCCCCC
6661
6662     case 6:                     // AABBBBBB:CCDDDDDD
6663
6664       tlbl = newiTempLabel (NULL);
6665       emitcode ("mov", "c,acc.7");
6666       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
6667
6668       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
6669
6670       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
6671
6672       emitcode ("anl", "a,#0x%02x",
6673                 SRMask[shCount]);       // 000000AA:BBBBBBCC
6674
6675       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6676       emitcode ("orl", "a,#0x%02x",
6677                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
6678
6679       emitcode ("", "%05d$:", tlbl->key + 100);
6680       break;
6681     case 7:                     // ABBBBBBB:CDDDDDDD
6682
6683       tlbl = newiTempLabel (NULL);
6684       emitcode ("mov", "c,acc.7");      // c = A
6685
6686       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
6687
6688       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
6689
6690       emitcode ("anl", "a,#0x%02x",
6691                 SRMask[shCount]);       // 0000000A:BBBBBBBC
6692
6693       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6694       emitcode ("orl", "a,#0x%02x",
6695                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
6696
6697       emitcode ("", "%05d$:", tlbl->key + 100);
6698       break;
6699     default:
6700       break;
6701     }
6702 }
6703 #endif
6704
6705 #ifdef BETTER_LITERAL_SHIFT
6706 static void
6707 _loadLeftIntoAx(char    **lsb, 
6708                 operand *left, 
6709                 operand *result,
6710                 int     offl,
6711                 int     offr)
6712 {
6713   // Get the initial value from left into a pair of registers.
6714   // MSB must be in A, LSB can be any register.
6715   //
6716   // If the result is held in registers, it is an optimization
6717   // if the LSB can be held in the register which will hold the,
6718   // result LSB since this saves us from having to copy it into
6719   // the result following AccAXLsh.
6720   //
6721   // If the result is addressed indirectly, this is not a gain.
6722   if (AOP_NEEDSACC(result))
6723   {
6724        char *leftByte;
6725        
6726        _startLazyDPSEvaluation();
6727        if (AOP_TYPE(left) == AOP_DPTR2)
6728        {
6729            // Get MSB in A.
6730            MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
6731            // get LSB in DP2_RESULT_REG.
6732            leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
6733            assert(!strcmp(leftByte, DP2_RESULT_REG));
6734        }
6735        else
6736        {
6737            // get LSB into DP2_RESULT_REG
6738            leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
6739            if (strcmp(leftByte, DP2_RESULT_REG))
6740            {
6741                emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
6742            }
6743            // And MSB in A.
6744            leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
6745            assert(strcmp(leftByte, DP2_RESULT_REG));
6746            MOVA(leftByte);
6747        }
6748        _endLazyDPSEvaluation();
6749        *lsb = DP2_RESULT_REG;
6750   }
6751   else
6752   {
6753       if (sameRegs (AOP (result), AOP (left)) &&
6754         ((offl + MSB16) == offr))
6755       {
6756           /* don't crash result[offr] */
6757           MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
6758           emitcode ("xch", "a,%s", 
6759                     aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
6760       }
6761       else
6762       {
6763           movLeft2Result (left, offl, result, offr, 0);
6764           MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
6765       }
6766       *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
6767       assert(strcmp(*lsb,"a"));      
6768   }
6769 }
6770
6771 static void
6772 _storeAxResults(char    *lsb,
6773                 operand *result,
6774                 int     offr)
6775 {
6776   _startLazyDPSEvaluation();
6777   if (AOP_NEEDSACC(result))
6778   {
6779       /* We have to explicitly update the result LSB.
6780        */
6781       emitcode("xch","a,%s", lsb);
6782       aopPut(AOP(result), "a", offr);
6783       emitcode("mov","a,%s", lsb);
6784   }
6785   if (getDataSize (result) > 1)
6786   {
6787       aopPut (AOP (result), "a", offr + MSB16);
6788   }
6789   _endLazyDPSEvaluation();
6790 }
6791
6792 /*-----------------------------------------------------------------*/
6793 /* shiftL2Left2Result - shift left two bytes from left to result   */
6794 /*-----------------------------------------------------------------*/
6795 static void
6796 shiftL2Left2Result (operand * left, int offl,
6797                     operand * result, int offr, int shCount)
6798 {
6799   char *lsb;
6800
6801   _loadLeftIntoAx(&lsb, left, result, offl, offr);
6802   
6803   AccAXLsh (lsb, shCount);
6804   
6805   _storeAxResults(lsb, result, offr);
6806 }
6807 #endif
6808
6809 #ifdef BETTER_LITERAL_SHIFT
6810 /*-----------------------------------------------------------------*/
6811 /* shiftR2Left2Result - shift right two bytes from left to result  */
6812 /*-----------------------------------------------------------------*/
6813 static void
6814 shiftR2Left2Result (operand * left, int offl,
6815                     operand * result, int offr,
6816                     int shCount, int sign)
6817 {
6818   char *lsb;
6819   
6820   _loadLeftIntoAx(&lsb, left, result, offl, offr);
6821   
6822   /* a:x >> shCount (x = lsb(result)) */
6823   if (sign)
6824   {
6825     AccAXRshS(aopGet(AOP(result), offr, FALSE, FALSE, FALSE), shCount);
6826   }
6827   else
6828   {
6829     AccAXRsh(aopGet(AOP(result), offr, FALSE, FALSE, FALSE), shCount);
6830   }
6831   
6832   _storeAxResults(lsb, result, offr);
6833 }
6834 #endif
6835
6836 #if 0
6837 //REMOVE ME!!!
6838 /*-----------------------------------------------------------------*/
6839 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6840 /*-----------------------------------------------------------------*/
6841 static void
6842 shiftLLeftOrResult (operand * left, int offl,
6843                     operand * result, int offr, int shCount)
6844 {
6845   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6846   /* shift left accumulator */
6847   AccLsh (shCount);
6848   /* or with result */
6849   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6850   /* back to result */
6851   aopPut (AOP (result), "a", offr);
6852 }
6853 #endif
6854
6855 #if 0
6856 //REMOVE ME!!!
6857 /*-----------------------------------------------------------------*/
6858 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6859 /*-----------------------------------------------------------------*/
6860 static void
6861 shiftRLeftOrResult (operand * left, int offl,
6862                     operand * result, int offr, int shCount)
6863 {
6864   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6865   /* shift right accumulator */
6866   AccRsh (shCount);
6867   /* or with result */
6868   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6869   /* back to result */
6870   aopPut (AOP (result), "a", offr);
6871 }
6872 #endif
6873
6874 #ifdef BETTER_LITERAL_SHIFT
6875 /*-----------------------------------------------------------------*/
6876 /* genlshOne - left shift a one byte quantity by known count       */
6877 /*-----------------------------------------------------------------*/
6878 static void
6879 genlshOne (operand * result, operand * left, int shCount)
6880 {
6881   D (emitcode (";", "genlshOne "););
6882   shiftL1Left2Result (left, LSB, result, LSB, shCount);
6883 }
6884 #endif
6885
6886 #ifdef BETTER_LITERAL_SHIFT
6887 /*-----------------------------------------------------------------*/
6888 /* genlshTwo - left shift two bytes by known amount != 0           */
6889 /*-----------------------------------------------------------------*/
6890 static void
6891 genlshTwo (operand * result, operand * left, int shCount)
6892 {
6893   int size;
6894
6895   D (emitcode (";", "genlshTwo "););
6896
6897   size = getDataSize (result);
6898
6899   /* if shCount >= 8 */
6900   if (shCount >= 8)
6901   {
6902       shCount -= 8;
6903
6904       _startLazyDPSEvaluation();
6905
6906       if (size > 1)
6907         {
6908           if (shCount)
6909           {
6910             _endLazyDPSEvaluation();
6911             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6912             aopPut (AOP (result), zero, LSB);       
6913           }
6914           else
6915           {
6916             movLeft2Result (left, LSB, result, MSB16, 0);
6917             aopPut (AOP (result), zero, LSB);
6918             _endLazyDPSEvaluation();
6919           }
6920         }
6921         else
6922         {
6923           aopPut (AOP (result), zero, LSB);
6924           _endLazyDPSEvaluation();
6925         }
6926   }
6927
6928   /*  1 <= shCount <= 7 */
6929   else
6930     {
6931       if (size == 1)
6932       {
6933         shiftL1Left2Result (left, LSB, result, LSB, shCount);
6934       }
6935       else
6936       {
6937         shiftL2Left2Result (left, LSB, result, LSB, shCount);
6938       }
6939     }
6940 }
6941 #endif
6942
6943 #if 0
6944 //REMOVE ME!!!
6945 /*-----------------------------------------------------------------*/
6946 /* shiftLLong - shift left one long from left to result            */
6947 /* offl = LSB or MSB16                                             */
6948 /*-----------------------------------------------------------------*/
6949 static void
6950 shiftLLong (operand * left, operand * result, int offr)
6951 {
6952   char *l;
6953   int size = AOP_SIZE (result);
6954
6955   if (size >= LSB + offr)
6956     {
6957       l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
6958       MOVA (l);
6959       emitcode ("add", "a,acc");
6960       if (sameRegs (AOP (left), AOP (result)) &&
6961           size >= MSB16 + offr && offr != LSB)
6962         emitcode ("xch", "a,%s",
6963                   aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
6964       else
6965         aopPut (AOP (result), "a", LSB + offr);
6966     }
6967
6968   if (size >= MSB16 + offr)
6969     {
6970       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6971         {
6972           l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
6973           MOVA (l);
6974         }
6975       emitcode ("rlc", "a");
6976       if (sameRegs (AOP (left), AOP (result)) &&
6977           size >= MSB24 + offr && offr != LSB)
6978         emitcode ("xch", "a,%s",
6979                   aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
6980       else
6981         aopPut (AOP (result), "a", MSB16 + offr);
6982     }
6983
6984   if (size >= MSB24 + offr)
6985     {
6986       if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6987         {
6988           l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
6989           MOVA (l);
6990         }
6991       emitcode ("rlc", "a");
6992       if (sameRegs (AOP (left), AOP (result)) &&
6993           size >= MSB32 + offr && offr != LSB)
6994         emitcode ("xch", "a,%s",
6995                   aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
6996       else
6997         aopPut (AOP (result), "a", MSB24 + offr);
6998     }
6999
7000   if (size > MSB32 + offr)
7001     {
7002       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7003         {
7004           l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
7005           MOVA (l);
7006         }
7007       emitcode ("rlc", "a");
7008       aopPut (AOP (result), "a", MSB32 + offr);
7009     }
7010   if (offr != LSB)
7011     aopPut (AOP (result), zero, LSB);
7012 }
7013 #endif
7014
7015 #if 0
7016 //REMOVE ME!!!
7017 /*-----------------------------------------------------------------*/
7018 /* genlshFour - shift four byte by a known amount != 0             */
7019 /*-----------------------------------------------------------------*/
7020 static void
7021 genlshFour (operand * result, operand * left, int shCount)
7022 {
7023   int size;
7024
7025   D (emitcode (";", "genlshFour ");
7026     );
7027
7028   size = AOP_SIZE (result);
7029
7030   /* if shifting more that 3 bytes */
7031   if (shCount >= 24)
7032     {
7033       shCount -= 24;
7034       if (shCount)
7035         /* lowest order of left goes to the highest
7036            order of the destination */
7037         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7038       else
7039         movLeft2Result (left, LSB, result, MSB32, 0);
7040       aopPut (AOP (result), zero, LSB);
7041       aopPut (AOP (result), zero, MSB16);
7042       aopPut (AOP (result), zero, MSB24);
7043       return;
7044     }
7045
7046   /* more than two bytes */
7047   else if (shCount >= 16)
7048     {
7049       /* lower order two bytes goes to higher order two bytes */
7050       shCount -= 16;
7051       /* if some more remaining */
7052       if (shCount)
7053         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7054       else
7055         {
7056           movLeft2Result (left, MSB16, result, MSB32, 0);
7057           movLeft2Result (left, LSB, result, MSB24, 0);
7058         }
7059       aopPut (AOP (result), zero, MSB16);
7060       aopPut (AOP (result), zero, LSB);
7061       return;
7062     }
7063
7064   /* if more than 1 byte */
7065   else if (shCount >= 8)
7066     {
7067       /* lower order three bytes goes to higher order  three bytes */
7068       shCount -= 8;
7069       if (size == 2)
7070         {
7071           if (shCount)
7072             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7073           else
7074             movLeft2Result (left, LSB, result, MSB16, 0);
7075         }
7076       else
7077         {                       /* size = 4 */
7078           if (shCount == 0)
7079             {
7080               movLeft2Result (left, MSB24, result, MSB32, 0);
7081               movLeft2Result (left, MSB16, result, MSB24, 0);
7082               movLeft2Result (left, LSB, result, MSB16, 0);
7083               aopPut (AOP (result), zero, LSB);
7084             }
7085           else if (shCount == 1)
7086             shiftLLong (left, result, MSB16);
7087           else
7088             {
7089               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7090               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7091               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7092               aopPut (AOP (result), zero, LSB);
7093             }
7094         }
7095     }
7096
7097   /* 1 <= shCount <= 7 */
7098   else if (shCount <= 2)
7099     {
7100       shiftLLong (left, result, LSB);
7101       if (shCount == 2)
7102         shiftLLong (result, result, LSB);
7103     }
7104   /* 3 <= shCount <= 7, optimize */
7105   else
7106     {
7107       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7108       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7109       shiftL2Left2Result (left, LSB, result, LSB, shCount);
7110     }
7111 }
7112 #endif
7113
7114 #ifdef BETTER_LITERAL_SHIFT
7115 /*-----------------------------------------------------------------*/
7116 /* genLeftShiftLiteral - left shifting by known count              */
7117 /*-----------------------------------------------------------------*/
7118 static bool
7119 genLeftShiftLiteral (operand * left,
7120                      operand * right,
7121                      operand * result,
7122                      iCode * ic)
7123 {
7124   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7125   int size;
7126
7127   size = getSize (operandType (result));
7128
7129   D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
7130
7131   /* We only handle certain easy cases so far. */
7132   if ((shCount != 0)
7133    && (shCount < (size * 8))
7134    && (size != 1)
7135    && (size != 2))
7136   {
7137       D(emitcode (";", "genLeftShiftLiteral wimping out"););    
7138       return FALSE;
7139   }
7140
7141   freeAsmop (right, NULL, ic, TRUE);
7142
7143   aopOp(left, ic, FALSE, FALSE);
7144   aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
7145
7146 #if 1 // debug spew
7147   if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
7148   {
7149         emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
7150         if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
7151         {
7152            emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
7153         }
7154   }
7155   if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
7156   {
7157         emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
7158         if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
7159         {
7160            emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
7161         }       
7162   }  
7163 #endif
7164   
7165 #if VIEW_SIZE
7166   emitcode ("; shift left ", "result %d, left %d", size,
7167             AOP_SIZE (left));
7168 #endif
7169
7170   /* I suppose that the left size >= result size */
7171   if (shCount == 0)
7172   {
7173         _startLazyDPSEvaluation();
7174         while (size--)
7175         {
7176           movLeft2Result (left, size, result, size, 0);
7177         }
7178         _endLazyDPSEvaluation();
7179   }
7180   else if (shCount >= (size * 8))
7181   {
7182     _startLazyDPSEvaluation();
7183     while (size--)
7184     {
7185       aopPut (AOP (result), zero, size);
7186     }
7187     _endLazyDPSEvaluation();
7188   }
7189   else
7190   {
7191       switch (size)
7192         {
7193         case 1:
7194           genlshOne (result, left, shCount);
7195           break;
7196
7197         case 2:
7198           genlshTwo (result, left, shCount);
7199           break;
7200 #if 0
7201         case 4:
7202           genlshFour (result, left, shCount);
7203           break;
7204 #endif
7205         default:
7206           fprintf(stderr, "*** ack! mystery literal shift!\n");   
7207           break;
7208         }
7209     }
7210   freeAsmop (left, NULL, ic, TRUE);
7211   freeAsmop (result, NULL, ic, TRUE);
7212   return TRUE;
7213 }
7214 #endif
7215
7216 /*-----------------------------------------------------------------*/
7217 /* genLeftShift - generates code for left shifting                 */
7218 /*-----------------------------------------------------------------*/
7219 static void
7220 genLeftShift (iCode * ic)
7221 {
7222   operand *left, *right, *result;
7223   int size, offset;
7224   char *l;
7225   symbol *tlbl, *tlbl1;
7226
7227   D (emitcode (";", "genLeftShift "););
7228
7229   right = IC_RIGHT (ic);
7230   left = IC_LEFT (ic);
7231   result = IC_RESULT (ic);
7232
7233   aopOp (right, ic, FALSE, FALSE);
7234
7235
7236 #ifdef BETTER_LITERAL_SHIFT
7237   /* if the shift count is known then do it
7238      as efficiently as possible */
7239   if (AOP_TYPE (right) == AOP_LIT)
7240     {
7241       if (genLeftShiftLiteral (left, right, result, ic))
7242       {
7243         return;
7244       }
7245     }
7246 #endif
7247
7248   /* shift count is unknown then we have to form
7249      a loop get the loop count in B : Note: we take
7250      only the lower order byte since shifting
7251      more that 32 bits make no sense anyway, ( the
7252      largest size of an object can be only 32 bits ) */
7253
7254   if (AOP_TYPE (right) == AOP_LIT)
7255   {
7256       /* Really should be handled by genLeftShiftLiteral,
7257        * but since I'm too lazy to fix that today, at least we can make
7258        * some small improvement.
7259        */
7260        emitcode("mov", "b,#0x%02x",
7261                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7262   }
7263   else
7264   {
7265         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7266         emitcode ("inc", "b");
7267   }
7268   freeAsmop (right, NULL, ic, TRUE);
7269   aopOp (left, ic, FALSE, FALSE);
7270   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7271
7272   /* now move the left to the result if they are not the
7273      same */
7274   if (!sameRegs (AOP (left), AOP (result)) &&
7275       AOP_SIZE (result) > 1)
7276     {
7277
7278       size = AOP_SIZE (result);
7279       offset = 0;
7280       _startLazyDPSEvaluation ();
7281       while (size--)
7282         {
7283           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7284           if (*l == '@' && (IS_AOP_PREG (result)))
7285             {
7286
7287               emitcode ("mov", "a,%s", l);
7288               aopPut (AOP (result), "a", offset);
7289             }
7290           else
7291             aopPut (AOP (result), l, offset);
7292           offset++;
7293         }
7294       _endLazyDPSEvaluation ();
7295     }
7296
7297   tlbl = newiTempLabel (NULL);
7298   size = AOP_SIZE (result);
7299   offset = 0;
7300   tlbl1 = newiTempLabel (NULL);
7301
7302   /* if it is only one byte then */
7303   if (size == 1)
7304     {
7305       symbol *tlbl1 = newiTempLabel (NULL);
7306
7307       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7308       MOVA (l);
7309       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7310       emitcode ("", "%05d$:", tlbl->key + 100);
7311       emitcode ("add", "a,acc");
7312       emitcode ("", "%05d$:", tlbl1->key + 100);
7313       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7314       aopPut (AOP (result), "a", 0);
7315       goto release;
7316     }
7317
7318   reAdjustPreg (AOP (result));
7319
7320   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7321   emitcode ("", "%05d$:", tlbl->key + 100);
7322   l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7323   MOVA (l);
7324   emitcode ("add", "a,acc");
7325   aopPut (AOP (result), "a", offset++);
7326   _startLazyDPSEvaluation ();
7327   while (--size)
7328     {
7329       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7330       MOVA (l);
7331       emitcode ("rlc", "a");
7332       aopPut (AOP (result), "a", offset++);
7333     }
7334   _endLazyDPSEvaluation ();
7335   reAdjustPreg (AOP (result));
7336
7337   emitcode ("", "%05d$:", tlbl1->key + 100);
7338   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7339 release:
7340   freeAsmop (left, NULL, ic, TRUE);
7341   freeAsmop (result, NULL, ic, TRUE);
7342 }
7343
7344 #ifdef BETTER_LITERAL_SHIFT
7345 /*-----------------------------------------------------------------*/
7346 /* genrshOne - right shift a one byte quantity by known count      */
7347 /*-----------------------------------------------------------------*/
7348 static void
7349 genrshOne (operand * result, operand * left,
7350            int shCount, int sign)
7351 {
7352   D (emitcode (";", "genrshOne"););
7353   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7354 }
7355 #endif
7356
7357 #ifdef BETTER_LITERAL_SHIFT
7358 /*-----------------------------------------------------------------*/
7359 /* genrshTwo - right shift two bytes by known amount != 0          */
7360 /*-----------------------------------------------------------------*/
7361 static void
7362 genrshTwo (operand * result, operand * left,
7363            int shCount, int sign)
7364 {
7365   D (emitcode (";", "genrshTwo"););
7366
7367   /* if shCount >= 8 */
7368   if (shCount >= 8)
7369     {
7370       shCount -= 8;
7371       _startLazyDPSEvaluation();
7372       if (shCount)
7373       {
7374         shiftR1Left2Result (left, MSB16, result, LSB,
7375                             shCount, sign);
7376       }                     
7377       else
7378       {
7379         movLeft2Result (left, MSB16, result, LSB, sign);
7380       }
7381       addSign (result, MSB16, sign);
7382       _endLazyDPSEvaluation();
7383     }
7384
7385   /*  1 <= shCount <= 7 */
7386   else
7387   {
7388     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7389   }
7390 }
7391 #endif
7392
7393 #if 0
7394 //REMOVE ME!!!
7395 /*-----------------------------------------------------------------*/
7396 /* shiftRLong - shift right one long from left to result           */
7397 /* offl = LSB or MSB16                                             */
7398 /*-----------------------------------------------------------------*/
7399 static void
7400 shiftRLong (operand * left, int offl,
7401             operand * result, int sign)
7402 {
7403   int isSameRegs=sameRegs(AOP(left),AOP(result));
7404
7405   if (isSameRegs && offl>1) {
7406     // we are in big trouble, but this shouldn't happen
7407     werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
7408   }
7409
7410   MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7411   
7412   if (offl==MSB16) {
7413     // shift is > 8
7414     if (sign) {
7415       emitcode ("rlc", "a");
7416       emitcode ("subb", "a,acc");
7417       emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
7418     } else {
7419       aopPut (AOP(result), zero, MSB32);
7420     }
7421   }
7422
7423   if (!sign) {
7424     emitcode ("clr", "c");
7425   } else {
7426     emitcode ("mov", "c,acc.7");
7427   }
7428
7429   emitcode ("rrc", "a");
7430
7431   if (isSameRegs && offl==MSB16) {
7432     emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
7433   } else {
7434     aopPut (AOP (result), "a", MSB32);
7435     MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
7436   }
7437
7438   emitcode ("rrc", "a");
7439   if (isSameRegs && offl==1) {
7440     emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
7441   } else {
7442     aopPut (AOP (result), "a", MSB24);
7443     MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
7444   }
7445   emitcode ("rrc", "a");
7446   aopPut (AOP (result), "a", MSB16 - offl);
7447
7448   if (offl == LSB)
7449     {
7450       MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
7451       emitcode ("rrc", "a");
7452       aopPut (AOP (result), "a", LSB);
7453     }
7454 }
7455 #endif
7456
7457 #if 0
7458 //REMOVE ME!!!
7459 /*-----------------------------------------------------------------*/
7460 /* genrshFour - shift four byte by a known amount != 0             */
7461 /*-----------------------------------------------------------------*/
7462 static void
7463 genrshFour (operand * result, operand * left,
7464             int shCount, int sign)
7465 {
7466   D (emitcode (";", "genrshFour");
7467     );
7468
7469   /* if shifting more that 3 bytes */
7470   if (shCount >= 24)
7471     {
7472       shCount -= 24;
7473       if (shCount)
7474         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7475       else
7476         movLeft2Result (left, MSB32, result, LSB, sign);
7477       addSign (result, MSB16, sign);
7478     }
7479   else if (shCount >= 16)
7480     {
7481       shCount -= 16;
7482       if (shCount)
7483         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7484       else
7485         {
7486           movLeft2Result (left, MSB24, result, LSB, 0);
7487           movLeft2Result (left, MSB32, result, MSB16, sign);
7488         }
7489       addSign (result, MSB24, sign);
7490     }
7491   else if (shCount >= 8)
7492     {
7493       shCount -= 8;
7494       if (shCount == 1)
7495         shiftRLong (left, MSB16, result, sign);
7496       else if (shCount == 0)
7497         {
7498           movLeft2Result (left, MSB16, result, LSB, 0);
7499           movLeft2Result (left, MSB24, result, MSB16, 0);
7500           movLeft2Result (left, MSB32, result, MSB24, sign);
7501           addSign (result, MSB32, sign);
7502         }
7503       else
7504         {
7505           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7506           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7507           /* the last shift is signed */
7508           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7509           addSign (result, MSB32, sign);
7510         }
7511     }
7512   else
7513     {                           /* 1 <= shCount <= 7 */
7514       if (shCount <= 2)
7515         {
7516           shiftRLong (left, LSB, result, sign);
7517           if (shCount == 2)
7518             shiftRLong (result, LSB, result, sign);
7519         }
7520       else
7521         {
7522           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7523           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7524           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7525         }
7526     }
7527 }
7528 #endif
7529
7530 #ifdef BETTER_LITERAL_SHIFT
7531 /*-----------------------------------------------------------------*/
7532 /* genRightShiftLiteral - right shifting by known count            */
7533 /*-----------------------------------------------------------------*/
7534 static bool
7535 genRightShiftLiteral (operand * left,
7536                       operand * right,
7537                       operand * result,
7538                       iCode * ic,
7539                       int sign)
7540 {
7541   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7542   int size;
7543
7544   size = getSize (operandType (result));
7545
7546   D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
7547
7548   /* We only handle certain easy cases so far. */
7549   if ((shCount != 0)
7550    && (shCount < (size * 8))
7551    && (size != 1)
7552    && (size != 2))
7553   {
7554       D(emitcode (";", "genRightShiftLiteral wimping out"););   
7555       return FALSE;
7556   }
7557
7558   freeAsmop (right, NULL, ic, TRUE);
7559
7560   aopOp (left, ic, FALSE, FALSE);
7561   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7562
7563 #if VIEW_SIZE
7564   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7565             AOP_SIZE (left));
7566 #endif
7567
7568   /* test the LEFT size !!! */
7569
7570   /* I suppose that the left size >= result size */
7571   if (shCount == 0)
7572   {
7573       size = getDataSize (result);
7574       _startLazyDPSEvaluation();
7575       while (size--)
7576       {
7577         movLeft2Result (left, size, result, size, 0);
7578       }
7579       _endLazyDPSEvaluation();
7580   }
7581   else if (shCount >= (size * 8))
7582     {
7583       if (sign)
7584       {
7585         /* get sign in acc.7 */
7586         MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
7587       }
7588       addSign (result, LSB, sign);
7589     }
7590   else
7591     {
7592       switch (size)
7593         {
7594         case 1:
7595           genrshOne (result, left, shCount, sign);
7596           break;
7597
7598         case 2:
7599           genrshTwo (result, left, shCount, sign);
7600           break;
7601 #if 0
7602         case 4:
7603           genrshFour (result, left, shCount, sign);
7604           break;
7605 #endif    
7606         default:
7607           break;
7608         }
7609
7610       freeAsmop (left, NULL, ic, TRUE);
7611       freeAsmop (result, NULL, ic, TRUE);
7612     }
7613     return TRUE;
7614 }
7615 #endif
7616
7617 /*-----------------------------------------------------------------*/
7618 /* genSignedRightShift - right shift of signed number              */
7619 /*-----------------------------------------------------------------*/
7620 static void
7621 genSignedRightShift (iCode * ic)
7622 {
7623   operand *right, *left, *result;
7624   int size, offset;
7625   char *l;
7626   symbol *tlbl, *tlbl1;
7627
7628   D (emitcode (";", "genSignedRightShift "););
7629
7630   /* we do it the hard way put the shift count in b
7631      and loop thru preserving the sign */
7632
7633   right = IC_RIGHT (ic);
7634   left = IC_LEFT (ic);
7635   result = IC_RESULT (ic);
7636
7637   aopOp (right, ic, FALSE, FALSE);
7638
7639 #ifdef BETTER_LITERAL_SHIFT
7640   if (AOP_TYPE (right) == AOP_LIT)
7641     {
7642       if (genRightShiftLiteral (left, right, result, ic, 1))
7643       {
7644         return;
7645       }
7646     }
7647 #endif
7648   /* shift count is unknown then we have to form
7649      a loop get the loop count in B : Note: we take
7650      only the lower order byte since shifting
7651      more that 32 bits make no sense anyway, ( the
7652      largest size of an object can be only 32 bits ) */
7653
7654   if (AOP_TYPE (right) == AOP_LIT)
7655   {
7656       /* Really should be handled by genRightShiftLiteral,
7657        * but since I'm too lazy to fix that today, at least we can make
7658        * some small improvement.
7659        */
7660        emitcode("mov", "b,#0x%02x",
7661                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7662   }
7663   else
7664   {
7665         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7666         emitcode ("inc", "b");
7667   }
7668   freeAsmop (right, NULL, ic, TRUE);
7669   aopOp (left, ic, FALSE, FALSE);
7670   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7671
7672   /* now move the left to the result if they are not the
7673      same */
7674   if (!sameRegs (AOP (left), AOP (result)) &&
7675       AOP_SIZE (result) > 1)
7676     {
7677
7678       size = AOP_SIZE (result);
7679       offset = 0;
7680       _startLazyDPSEvaluation ();
7681       while (size--)
7682         {
7683           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7684           if (*l == '@' && IS_AOP_PREG (result))
7685             {
7686
7687               emitcode ("mov", "a,%s", l);
7688               aopPut (AOP (result), "a", offset);
7689             }
7690           else
7691             aopPut (AOP (result), l, offset);
7692           offset++;
7693         }
7694       _endLazyDPSEvaluation ();
7695     }
7696
7697   /* mov the highest order bit to OVR */
7698   tlbl = newiTempLabel (NULL);
7699   tlbl1 = newiTempLabel (NULL);
7700
7701   size = AOP_SIZE (result);
7702   offset = size - 1;
7703   emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
7704   emitcode ("rlc", "a");
7705   emitcode ("mov", "ov,c");
7706   /* if it is only one byte then */
7707   if (size == 1)
7708     {
7709       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7710       MOVA (l);
7711       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7712       emitcode ("", "%05d$:", tlbl->key + 100);
7713       emitcode ("mov", "c,ov");
7714       emitcode ("rrc", "a");
7715       emitcode ("", "%05d$:", tlbl1->key + 100);
7716       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7717       aopPut (AOP (result), "a", 0);
7718       goto release;
7719     }
7720
7721   reAdjustPreg (AOP (result));
7722   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7723   emitcode ("", "%05d$:", tlbl->key + 100);
7724   emitcode ("mov", "c,ov");
7725   _startLazyDPSEvaluation ();
7726   while (size--)
7727     {
7728       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7729       MOVA (l);
7730       emitcode ("rrc", "a");
7731       aopPut (AOP (result), "a", offset--);
7732     }
7733   _endLazyDPSEvaluation ();
7734   reAdjustPreg (AOP (result));
7735   emitcode ("", "%05d$:", tlbl1->key + 100);
7736   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7737
7738 release:
7739   freeAsmop (left, NULL, ic, TRUE);
7740   freeAsmop (result, NULL, ic, TRUE);
7741 }
7742
7743 /*-----------------------------------------------------------------*/
7744 /* genRightShift - generate code for right shifting                */
7745 /*-----------------------------------------------------------------*/
7746 static void
7747 genRightShift (iCode * ic)
7748 {
7749   operand *right, *left, *result;
7750   sym_link *retype;
7751   int size, offset;
7752   char *l;
7753   symbol *tlbl, *tlbl1;
7754
7755   D (emitcode (";", "genRightShift "););
7756
7757   /* if signed then we do it the hard way preserve the
7758      sign bit moving it inwards */
7759   retype = getSpec (operandType (IC_RESULT (ic)));
7760
7761   if (!SPEC_USIGN (retype))
7762     {
7763       genSignedRightShift (ic);
7764       return;
7765     }
7766
7767   /* signed & unsigned types are treated the same : i.e. the
7768      signed is NOT propagated inwards : quoting from the
7769      ANSI - standard : "for E1 >> E2, is equivalent to division
7770      by 2**E2 if unsigned or if it has a non-negative value,
7771      otherwise the result is implementation defined ", MY definition
7772      is that the sign does not get propagated */
7773
7774   right = IC_RIGHT (ic);
7775   left = IC_LEFT (ic);
7776   result = IC_RESULT (ic);
7777
7778   aopOp (right, ic, FALSE, FALSE);
7779
7780 #ifdef BETTER_LITERAL_SHIFT
7781   /* if the shift count is known then do it
7782      as efficiently as possible */
7783   if (AOP_TYPE (right) == AOP_LIT)
7784     {
7785       if (genRightShiftLiteral (left, right, result, ic, 0))
7786       {
7787         return;
7788       }
7789     }
7790 #endif
7791
7792   /* shift count is unknown then we have to form
7793      a loop get the loop count in B : Note: we take
7794      only the lower order byte since shifting
7795      more that 32 bits make no sense anyway, ( the
7796      largest size of an object can be only 32 bits ) */
7797   
7798   if (AOP_TYPE (right) == AOP_LIT)
7799   {
7800       /* Really should be handled by genRightShiftLiteral,
7801        * but since I'm too lazy to fix that today, at least we can make
7802        * some small improvement.
7803        */
7804        emitcode("mov", "b,#0x%02x",
7805                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7806   }
7807   else
7808   {
7809         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7810         emitcode ("inc", "b");
7811   }
7812   freeAsmop (right, NULL, ic, TRUE);
7813   aopOp (left, ic, FALSE, FALSE);
7814   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7815
7816   /* now move the left to the result if they are not the
7817      same */
7818   if (!sameRegs (AOP (left), AOP (result)) &&
7819       AOP_SIZE (result) > 1)
7820     {
7821
7822       size = AOP_SIZE (result);
7823       offset = 0;
7824       _startLazyDPSEvaluation ();
7825       while (size--)
7826         {
7827           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7828           if (*l == '@' && IS_AOP_PREG (result))
7829             {
7830
7831               emitcode ("mov", "a,%s", l);
7832               aopPut (AOP (result), "a", offset);
7833             }
7834           else
7835             aopPut (AOP (result), l, offset);
7836           offset++;
7837         }
7838       _endLazyDPSEvaluation ();
7839     }
7840
7841   tlbl = newiTempLabel (NULL);
7842   tlbl1 = newiTempLabel (NULL);
7843   size = AOP_SIZE (result);
7844   offset = size - 1;
7845
7846   /* if it is only one byte then */
7847   if (size == 1)
7848     {
7849       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7850       MOVA (l);
7851       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7852       emitcode ("", "%05d$:", tlbl->key + 100);
7853       CLRC;
7854       emitcode ("rrc", "a");
7855       emitcode ("", "%05d$:", tlbl1->key + 100);
7856       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7857       aopPut (AOP (result), "a", 0);
7858       goto release;
7859     }
7860
7861   reAdjustPreg (AOP (result));
7862   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7863   emitcode ("", "%05d$:", tlbl->key + 100);
7864   CLRC;
7865   _startLazyDPSEvaluation ();
7866   while (size--)
7867     {
7868       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7869       MOVA (l);
7870       emitcode ("rrc", "a");
7871       aopPut (AOP (result), "a", offset--);
7872     }
7873   _endLazyDPSEvaluation ();
7874   reAdjustPreg (AOP (result));
7875
7876   emitcode ("", "%05d$:", tlbl1->key + 100);
7877   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7878
7879 release:
7880   freeAsmop (left, NULL, ic, TRUE);
7881   freeAsmop (result, NULL, ic, TRUE);
7882 }
7883
7884 /*-----------------------------------------------------------------*/
7885 /* genUnpackBits - generates code for unpacking bits               */
7886 /*-----------------------------------------------------------------*/
7887 static void
7888 genUnpackBits (operand * result, char *rname, int ptype)
7889 {
7890   int shCnt;
7891   int rlen = 0;
7892   sym_link *etype;
7893   int offset = 0;
7894
7895   D (emitcode (";", "genUnpackBits ");
7896     );
7897
7898   etype = getSpec (operandType (result));
7899
7900   /* read the first byte  */
7901   switch (ptype)
7902     {
7903
7904     case POINTER:
7905     case IPOINTER:
7906       emitcode ("mov", "a,@%s", rname);
7907       break;
7908
7909     case PPOINTER:
7910       emitcode ("movx", "a,@%s", rname);
7911       break;
7912
7913     case FPOINTER:
7914       emitcode ("movx", "a,@dptr");
7915       break;
7916
7917     case CPOINTER:
7918       emitcode ("clr", "a");
7919       emitcode ("movc", "a", "@a+dptr");
7920       break;
7921
7922     case GPOINTER:
7923       emitcode ("lcall", "__gptrget");
7924       break;
7925     }
7926
7927   /* if we have bitdisplacement then it fits   */
7928   /* into this byte completely or if length is */
7929   /* less than a byte                          */
7930   if ((shCnt = SPEC_BSTR (etype)) ||
7931       (SPEC_BLEN (etype) <= 8))
7932     {
7933
7934       /* shift right acc */
7935       AccRsh (shCnt);
7936
7937       emitcode ("anl", "a,#0x%02x",
7938                 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
7939       aopPut (AOP (result), "a", offset);
7940       return;
7941     }
7942
7943   /* bit field did not fit in a byte  */
7944   rlen = SPEC_BLEN (etype) - 8;
7945   aopPut (AOP (result), "a", offset++);
7946
7947   while (1)
7948     {
7949
7950       switch (ptype)
7951         {
7952         case POINTER:
7953         case IPOINTER:
7954           emitcode ("inc", "%s", rname);
7955           emitcode ("mov", "a,@%s", rname);
7956           break;
7957
7958         case PPOINTER:
7959           emitcode ("inc", "%s", rname);
7960           emitcode ("movx", "a,@%s", rname);
7961           break;
7962
7963         case FPOINTER:
7964           emitcode ("inc", "dptr");
7965           emitcode ("movx", "a,@dptr");
7966           break;
7967
7968         case CPOINTER:
7969           emitcode ("clr", "a");
7970           emitcode ("inc", "dptr");
7971           emitcode ("movc", "a", "@a+dptr");
7972           break;
7973
7974         case GPOINTER:
7975           emitcode ("inc", "dptr");
7976           emitcode ("lcall", "__gptrget");
7977           break;
7978         }
7979
7980       rlen -= 8;
7981       /* if we are done */
7982       if (rlen < 8)
7983         break;
7984
7985       aopPut (AOP (result), "a", offset++);
7986
7987     }
7988
7989   if (rlen)
7990     {
7991       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
7992       aopPut (AOP (result), "a", offset);
7993     }
7994
7995   return;
7996 }
7997
7998
7999 /*-----------------------------------------------------------------*/
8000 /* genDataPointerGet - generates code when ptr offset is known     */
8001 /*-----------------------------------------------------------------*/
8002 static void
8003 genDataPointerGet (operand * left,
8004                    operand * result,
8005                    iCode * ic)
8006 {
8007   char *l;
8008   char buffer[256];
8009   int size, offset = 0;
8010   aopOp (result, ic, TRUE, FALSE);
8011
8012   /* get the string representation of the name */
8013   l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
8014   size = AOP_SIZE (result);
8015   _startLazyDPSEvaluation ();
8016   while (size--)
8017     {
8018       if (offset)
8019         sprintf (buffer, "(%s + %d)", l + 1, offset);
8020       else
8021         sprintf (buffer, "%s", l + 1);
8022       aopPut (AOP (result), buffer, offset++);
8023     }
8024   _endLazyDPSEvaluation ();
8025
8026   freeAsmop (left, NULL, ic, TRUE);
8027   freeAsmop (result, NULL, ic, TRUE);
8028 }
8029
8030 /*-----------------------------------------------------------------*/
8031 /* genNearPointerGet - emitcode for near pointer fetch             */
8032 /*-----------------------------------------------------------------*/
8033 static void
8034 genNearPointerGet (operand * left,
8035                    operand * result,
8036                    iCode * ic)
8037 {
8038   asmop *aop = NULL;
8039   regs *preg = NULL;
8040   char *rname;
8041   sym_link *rtype, *retype, *letype;
8042   sym_link *ltype = operandType (left);
8043   char buffer[80];
8044
8045   rtype = operandType (result);
8046   retype = getSpec (rtype);
8047   letype = getSpec (ltype);
8048
8049   aopOp (left, ic, FALSE, FALSE);
8050
8051   /* if left is rematerialisable and
8052      result is not bit variable type and
8053      the left is pointer to data space i.e
8054      lower 128 bytes of space */
8055   if (AOP_TYPE (left) == AOP_IMMD &&
8056       !IS_BITVAR (retype) &&
8057       !IS_BITVAR (letype) &&
8058       DCL_TYPE (ltype) == POINTER)
8059     {
8060       genDataPointerGet (left, result, ic);
8061       return;
8062     }
8063
8064   /* if the value is already in a pointer register
8065      then don't need anything more */
8066   if (!AOP_INPREG (AOP (left)))
8067     {
8068       /* otherwise get a free pointer register */
8069       aop = newAsmop (0);
8070       preg = getFreePtr (ic, &aop, FALSE);
8071       emitcode ("mov", "%s,%s",
8072                 preg->name,
8073                 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8074       rname = preg->name;
8075     }
8076   else
8077     rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8078
8079   freeAsmop (left, NULL, ic, TRUE);
8080   aopOp (result, ic, FALSE, FALSE);
8081
8082   /* if bitfield then unpack the bits */
8083   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8084     genUnpackBits (result, rname, POINTER);
8085   else
8086     {
8087       /* we have can just get the values */
8088       int size = AOP_SIZE (result);
8089       int offset = 0;
8090
8091       while (size--)
8092         {
8093           if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8094             {
8095
8096               emitcode ("mov", "a,@%s", rname);
8097               aopPut (AOP (result), "a", offset);
8098             }
8099           else
8100             {
8101               sprintf (buffer, "@%s", rname);
8102               aopPut (AOP (result), buffer, offset);
8103             }
8104           offset++;
8105           if (size)
8106             emitcode ("inc", "%s", rname);
8107         }
8108     }
8109
8110   /* now some housekeeping stuff */
8111   if (aop)
8112     {
8113       /* we had to allocate for this iCode */
8114       freeAsmop (NULL, aop, ic, TRUE);
8115     }
8116   else
8117     {
8118       /* we did not allocate which means left
8119          already in a pointer register, then
8120          if size > 0 && this could be used again
8121          we have to point it back to where it
8122          belongs */
8123       if (AOP_SIZE (result) > 1 &&
8124           !OP_SYMBOL (left)->remat &&
8125           (OP_SYMBOL (left)->liveTo > ic->seq ||
8126            ic->depth))
8127         {
8128           int size = AOP_SIZE (result) - 1;
8129           while (size--)
8130             emitcode ("dec", "%s", rname);
8131         }
8132     }
8133
8134   /* done */
8135   freeAsmop (result, NULL, ic, TRUE);
8136
8137 }
8138
8139 /*-----------------------------------------------------------------*/
8140 /* genPagedPointerGet - emitcode for paged pointer fetch           */
8141 /*-----------------------------------------------------------------*/
8142 static void
8143 genPagedPointerGet (operand * left,
8144                     operand * result,
8145                     iCode * ic)
8146 {
8147   asmop *aop = NULL;
8148   regs *preg = NULL;
8149   char *rname;
8150   sym_link *rtype, *retype, *letype;
8151
8152   rtype = operandType (result);
8153   retype = getSpec (rtype);
8154   letype = getSpec (operandType (left));
8155   aopOp (left, ic, FALSE, FALSE);
8156
8157   /* if the value is already in a pointer register
8158      then don't need anything more */
8159   if (!AOP_INPREG (AOP (left)))
8160     {
8161       /* otherwise get a free pointer register */
8162       aop = newAsmop (0);
8163       preg = getFreePtr (ic, &aop, FALSE);
8164       emitcode ("mov", "%s,%s",
8165                 preg->name,
8166                 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8167       rname = preg->name;
8168     }
8169   else
8170     rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8171
8172   freeAsmop (left, NULL, ic, TRUE);
8173   aopOp (result, ic, FALSE, FALSE);
8174
8175   /* if bitfield then unpack the bits */
8176   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8177     genUnpackBits (result, rname, PPOINTER);
8178   else
8179     {
8180       /* we have can just get the values */
8181       int size = AOP_SIZE (result);
8182       int offset = 0;
8183
8184       while (size--)
8185         {
8186
8187           emitcode ("movx", "a,@%s", rname);
8188           aopPut (AOP (result), "a", offset);
8189
8190           offset++;
8191
8192           if (size)
8193             emitcode ("inc", "%s", rname);
8194         }
8195     }
8196
8197   /* now some housekeeping stuff */
8198   if (aop)
8199     {
8200       /* we had to allocate for this iCode */
8201       freeAsmop (NULL, aop, ic, TRUE);
8202     }
8203   else
8204     {
8205       /* we did not allocate which means left
8206          already in a pointer register, then
8207          if size > 0 && this could be used again
8208          we have to point it back to where it
8209          belongs */
8210       if (AOP_SIZE (result) > 1 &&
8211           !OP_SYMBOL (left)->remat &&
8212           (OP_SYMBOL (left)->liveTo > ic->seq ||
8213            ic->depth))
8214         {
8215           int size = AOP_SIZE (result) - 1;
8216           while (size--)
8217             emitcode ("dec", "%s", rname);
8218         }
8219     }
8220
8221   /* done */
8222   freeAsmop (result, NULL, ic, TRUE);
8223
8224
8225 }
8226
8227 /*-----------------------------------------------------------------*/
8228 /* genFarPointerGet - gget value from far space                    */
8229 /*-----------------------------------------------------------------*/
8230 static void
8231 genFarPointerGet (operand * left,
8232                   operand * result, iCode * ic)
8233 {
8234   int size, offset;
8235   sym_link *retype = getSpec (operandType (result));
8236   sym_link *letype = getSpec (operandType (left));
8237   D (emitcode (";", "genFarPointerGet");
8238     );
8239
8240   aopOp (left, ic, FALSE, FALSE);
8241
8242   /* if the operand is already in dptr
8243      then we do nothing else we move the value to dptr */
8244   if (AOP_TYPE (left) != AOP_STR)
8245     {
8246       /* if this is remateriazable */
8247       if (AOP_TYPE (left) == AOP_IMMD)
8248         {
8249           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8250         }
8251       else
8252         {
8253           /* we need to get it byte by byte */
8254           _startLazyDPSEvaluation ();
8255           if (AOP_TYPE (left) != AOP_DPTR)
8256             {
8257               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8258               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8259               emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8260             }
8261           else
8262             {
8263               /* We need to generate a load to DPTR indirect through DPTR. */
8264               D (emitcode (";", "genFarPointerGet -- indirection special case.");
8265                 );
8266               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8267               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8268               emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8269               emitcode ("pop", "dph");
8270               emitcode ("pop", "dpl");
8271             }
8272           _endLazyDPSEvaluation ();
8273         }
8274     }
8275   /* so dptr know contains the address */
8276   freeAsmop (left, NULL, ic, TRUE);
8277   aopOp (result, ic, FALSE, TRUE);
8278
8279   /* if bit then unpack */
8280   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8281     genUnpackBits (result, "dptr", FPOINTER);
8282   else
8283     {
8284       size = AOP_SIZE (result);
8285       offset = 0;
8286
8287       _startLazyDPSEvaluation ();
8288       while (size--)
8289         {
8290
8291           genSetDPTR (0);
8292           _flushLazyDPS ();
8293
8294           emitcode ("movx", "a,@dptr");
8295           if (size)
8296             emitcode ("inc", "dptr");
8297
8298           aopPut (AOP (result), "a", offset++);
8299         }
8300       _endLazyDPSEvaluation ();
8301     }
8302
8303   freeAsmop (result, NULL, ic, TRUE);
8304 }
8305
8306 /*-----------------------------------------------------------------*/
8307 /* emitcodePointerGet - gget value from code space                  */
8308 /*-----------------------------------------------------------------*/
8309 static void
8310 emitcodePointerGet (operand * left,
8311                     operand * result, iCode * ic)
8312 {
8313   int size, offset;
8314   sym_link *retype = getSpec (operandType (result));
8315
8316   aopOp (left, ic, FALSE, FALSE);
8317
8318   /* if the operand is already in dptr
8319      then we do nothing else we move the value to dptr */
8320   if (AOP_TYPE (left) != AOP_STR)
8321     {
8322       /* if this is remateriazable */
8323       if (AOP_TYPE (left) == AOP_IMMD)
8324         {
8325           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8326         }
8327       else
8328         {                       /* we need to get it byte by byte */
8329           _startLazyDPSEvaluation ();
8330           if (AOP_TYPE (left) != AOP_DPTR)
8331             {
8332               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8333               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8334               emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8335             }
8336           else
8337             {
8338               /* We need to generate a load to DPTR indirect through DPTR. */
8339               D (emitcode (";", "gencodePointerGet -- indirection special case.");
8340                 );
8341               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8342               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8343               emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8344               emitcode ("pop", "dph");
8345               emitcode ("pop", "dpl");
8346             }
8347           _endLazyDPSEvaluation ();
8348         }
8349     }
8350   /* so dptr know contains the address */
8351   freeAsmop (left, NULL, ic, TRUE);
8352   aopOp (result, ic, FALSE, TRUE);
8353
8354   /* if bit then unpack */
8355   if (IS_BITVAR (retype))
8356     genUnpackBits (result, "dptr", CPOINTER);
8357   else
8358     {
8359       size = AOP_SIZE (result);
8360       offset = 0;
8361
8362       _startLazyDPSEvaluation ();
8363       while (size--)
8364         {
8365           genSetDPTR (0);
8366           _flushLazyDPS ();
8367
8368           emitcode ("clr", "a");
8369           emitcode ("movc", "a,@a+dptr");
8370           if (size)
8371             emitcode ("inc", "dptr");
8372           aopPut (AOP (result), "a", offset++);
8373         }
8374       _endLazyDPSEvaluation ();
8375     }
8376
8377   freeAsmop (result, NULL, ic, TRUE);
8378 }
8379
8380 /*-----------------------------------------------------------------*/
8381 /* genGenPointerGet - gget value from generic pointer space        */
8382 /*-----------------------------------------------------------------*/
8383 static void
8384 genGenPointerGet (operand * left,
8385                   operand * result, iCode * ic)
8386 {
8387   int size, offset;
8388   sym_link *retype = getSpec (operandType (result));
8389   sym_link *letype = getSpec (operandType (left));
8390
8391   D (emitcode (";", "genGenPointerGet "); );
8392
8393   aopOp (left, ic, FALSE, TRUE);
8394
8395   /* if the operand is already in dptr
8396      then we do nothing else we move the value to dptr */
8397   if (AOP_TYPE (left) != AOP_STR)
8398     {
8399       /* if this is remateriazable */
8400       if (AOP_TYPE (left) == AOP_IMMD)
8401         {
8402           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8403           emitcode ("mov", "b,#%d", pointerCode (retype));
8404         }
8405       else
8406         {                       /* we need to get it byte by byte */
8407           _startLazyDPSEvaluation ();
8408           if (AOP(left)->type==AOP_DPTR2) {
8409             char *l;
8410             l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
8411             genSetDPTR(0);
8412             _flushLazyDPS();
8413             emitcode ("mov", "dpl,%s", l);
8414             l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
8415             genSetDPTR(0);
8416             _flushLazyDPS();
8417             emitcode ("mov", "dph,%s", l);
8418             l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
8419             genSetDPTR(0);
8420             _flushLazyDPS();
8421             emitcode ("mov", "dpx,%s", l);
8422             emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8423           } else {
8424             emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
8425             emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
8426             emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8427             emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8428           }
8429           _endLazyDPSEvaluation ();
8430         }
8431     }
8432   /* so dptr know contains the address */
8433   freeAsmop (left, NULL, ic, TRUE);
8434   aopOp (result, ic, FALSE, TRUE);
8435
8436   /* if bit then unpack */
8437   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8438     genUnpackBits (result, "dptr", GPOINTER);
8439   else
8440     {
8441       size = AOP_SIZE (result);
8442       offset = 0;
8443
8444       while (size--)
8445         {
8446           emitcode ("lcall", "__gptrget");
8447           aopPut (AOP (result), "a", offset++);
8448           if (size)
8449             emitcode ("inc", "dptr");
8450         }
8451     }
8452
8453   freeAsmop (result, NULL, ic, TRUE);
8454 }
8455
8456 /*-----------------------------------------------------------------*/
8457 /* genPointerGet - generate code for pointer get                   */
8458 /*-----------------------------------------------------------------*/
8459 static void
8460 genPointerGet (iCode * ic)
8461 {
8462   operand *left, *result;
8463   sym_link *type, *etype;
8464   int p_type;
8465
8466   D (emitcode (";", "genPointerGet ");
8467     );
8468
8469   left = IC_LEFT (ic);
8470   result = IC_RESULT (ic);
8471
8472   /* depending on the type of pointer we need to
8473      move it to the correct pointer register */
8474   type = operandType (left);
8475   etype = getSpec (type);
8476   /* if left is of type of pointer then it is simple */
8477   if (IS_PTR (type) && !IS_FUNC (type->next))
8478     p_type = DCL_TYPE (type);
8479   else
8480     {
8481       /* we have to go by the storage class */
8482       p_type = PTR_TYPE (SPEC_OCLS (etype));
8483     }
8484
8485   /* now that we have the pointer type we assign
8486      the pointer values */
8487   switch (p_type)
8488     {
8489
8490     case POINTER:
8491     case IPOINTER:
8492       genNearPointerGet (left, result, ic);
8493       break;
8494
8495     case PPOINTER:
8496       genPagedPointerGet (left, result, ic);
8497       break;
8498
8499     case FPOINTER:
8500       genFarPointerGet (left, result, ic);
8501       break;
8502
8503     case CPOINTER:
8504       emitcodePointerGet (left, result, ic);
8505       break;
8506
8507     case GPOINTER:
8508       genGenPointerGet (left, result, ic);
8509       break;
8510     }
8511
8512 }
8513
8514 /*-----------------------------------------------------------------*/
8515 /* genPackBits - generates code for packed bit storage             */
8516 /*-----------------------------------------------------------------*/
8517 static void
8518 genPackBits (sym_link * etype,
8519              operand * right,
8520              char *rname, int p_type)
8521 {
8522   int shCount = 0;
8523   int offset = 0;
8524   int rLen = 0;
8525   int blen, bstr;
8526   char *l;
8527
8528   blen = SPEC_BLEN (etype);
8529   bstr = SPEC_BSTR (etype);
8530
8531   l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8532   MOVA (l);
8533
8534   /* if the bit lenth is less than or    */
8535   /* it exactly fits a byte then         */
8536   if (SPEC_BLEN (etype) <= 8)
8537     {
8538       shCount = SPEC_BSTR (etype);
8539
8540       /* shift left acc */
8541       AccLsh (shCount);
8542
8543       if (SPEC_BLEN (etype) < 8)
8544         {                       /* if smaller than a byte */
8545
8546
8547           switch (p_type)
8548             {
8549             case POINTER:
8550               emitcode ("mov", "b,a");
8551               emitcode ("mov", "a,@%s", rname);
8552               break;
8553
8554             case FPOINTER:
8555               emitcode ("mov", "b,a");
8556               emitcode ("movx", "a,@dptr");
8557               break;
8558
8559             case GPOINTER:
8560               emitcode ("push", "b");
8561               emitcode ("push", "acc");
8562               emitcode ("lcall", "__gptrget");
8563               emitcode ("pop", "b");
8564               break;
8565             }
8566
8567           emitcode ("anl", "a,#0x%02x", (unsigned char)
8568                     ((unsigned char) (0xFF << (blen + bstr)) |
8569                      (unsigned char) (0xFF >> (8 - bstr))));
8570           emitcode ("orl", "a,b");
8571           if (p_type == GPOINTER)
8572             emitcode ("pop", "b");
8573         }
8574     }
8575
8576   switch (p_type)
8577     {
8578     case POINTER:
8579       emitcode ("mov", "@%s,a", rname);
8580       break;
8581
8582     case FPOINTER:
8583       emitcode ("movx", "@dptr,a");
8584       break;
8585
8586     case GPOINTER:
8587       emitcode ("lcall", "__gptrput");
8588       break;
8589     }
8590
8591   /* if we r done */
8592   if (SPEC_BLEN (etype) <= 8)
8593     return;
8594
8595   emitcode ("inc", "%s", rname);
8596   rLen = SPEC_BLEN (etype);
8597
8598   /* now generate for lengths greater than one byte */
8599   while (1)
8600     {
8601
8602       l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
8603
8604       rLen -= 8;
8605       if (rLen < 8)
8606         break;
8607
8608       switch (p_type)
8609         {
8610         case POINTER:
8611           if (*l == '@')
8612             {
8613               MOVA (l);
8614               emitcode ("mov", "@%s,a", rname);
8615             }
8616           else
8617             emitcode ("mov", "@%s,%s", rname, l);
8618           break;
8619
8620         case FPOINTER:
8621           MOVA (l);
8622           emitcode ("movx", "@dptr,a");
8623           break;
8624
8625         case GPOINTER:
8626           MOVA (l);
8627           emitcode ("lcall", "__gptrput");
8628           break;
8629         }
8630       emitcode ("inc", "%s", rname);
8631     }
8632
8633   MOVA (l);
8634
8635   /* last last was not complete */
8636   if (rLen)
8637     {
8638       /* save the byte & read byte */
8639       switch (p_type)
8640         {
8641         case POINTER:
8642           emitcode ("mov", "b,a");
8643           emitcode ("mov", "a,@%s", rname);
8644           break;
8645
8646         case FPOINTER:
8647           emitcode ("mov", "b,a");
8648           emitcode ("movx", "a,@dptr");
8649           break;
8650
8651         case GPOINTER:
8652           emitcode ("push", "b");
8653           emitcode ("push", "acc");
8654           emitcode ("lcall", "__gptrget");
8655           emitcode ("pop", "b");
8656           break;
8657         }
8658
8659       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
8660       emitcode ("orl", "a,b");
8661     }
8662
8663   if (p_type == GPOINTER)
8664     emitcode ("pop", "b");
8665
8666   switch (p_type)
8667     {
8668
8669     case POINTER:
8670       emitcode ("mov", "@%s,a", rname);
8671       break;
8672
8673     case FPOINTER:
8674       emitcode ("movx", "@dptr,a");
8675       break;
8676
8677     case GPOINTER:
8678       emitcode ("lcall", "__gptrput");
8679       break;
8680     }
8681 }
8682 /*-----------------------------------------------------------------*/
8683 /* genDataPointerSet - remat pointer to data space                 */
8684 /*-----------------------------------------------------------------*/
8685 static void
8686 genDataPointerSet (operand * right,
8687                    operand * result,
8688                    iCode * ic)
8689 {
8690   int size, offset = 0;
8691   char *l, buffer[256];
8692
8693   aopOp (right, ic, FALSE, FALSE);
8694
8695   l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
8696   size = AOP_SIZE (right);
8697   while (size--)
8698     {
8699       if (offset)
8700         sprintf (buffer, "(%s + %d)", l + 1, offset);
8701       else
8702         sprintf (buffer, "%s", l + 1);
8703       emitcode ("mov", "%s,%s", buffer,
8704                 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
8705     }
8706
8707   freeAsmop (right, NULL, ic, TRUE);
8708   freeAsmop (result, NULL, ic, TRUE);
8709 }
8710
8711 /*-----------------------------------------------------------------*/
8712 /* genNearPointerSet - emitcode for near pointer put                */
8713 /*-----------------------------------------------------------------*/
8714 static void
8715 genNearPointerSet (operand * right,
8716                    operand * result,
8717                    iCode * ic)
8718 {
8719   asmop *aop = NULL;
8720   regs *preg = NULL;
8721   char *rname, *l;
8722   sym_link *retype, *letype;
8723   sym_link *ptype = operandType (result);
8724
8725   retype = getSpec (operandType (right));
8726   letype = getSpec (ptype);
8727
8728   aopOp (result, ic, FALSE, FALSE);
8729
8730   /* if the result is rematerializable &
8731      in data space & not a bit variable */
8732   if (AOP_TYPE (result) == AOP_IMMD &&
8733       DCL_TYPE (ptype) == POINTER &&
8734       !IS_BITVAR (retype) &&
8735       !IS_BITVAR (letype))
8736     {
8737       genDataPointerSet (right, result, ic);
8738       return;
8739     }
8740
8741   /* if the value is already in a pointer register
8742      then don't need anything more */
8743   if (!AOP_INPREG (AOP (result)))
8744     {
8745       /* otherwise get a free pointer register */
8746       aop = newAsmop (0);
8747       preg = getFreePtr (ic, &aop, FALSE);
8748       emitcode ("mov", "%s,%s",
8749                 preg->name,
8750                 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8751       rname = preg->name;
8752     }
8753   else
8754     rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8755
8756   freeAsmop (result, NULL, ic, TRUE);
8757   aopOp (right, ic, FALSE, FALSE);
8758
8759   /* if bitfield then unpack the bits */
8760   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8761     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
8762   else
8763     {
8764       /* we have can just get the values */
8765       int size = AOP_SIZE (right);
8766       int offset = 0;
8767
8768       while (size--)
8769         {
8770           l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
8771           if (*l == '@')
8772             {
8773               MOVA (l);
8774               emitcode ("mov", "@%s,a", rname);
8775             }
8776           else
8777             emitcode ("mov", "@%s,%s", rname, l);
8778           if (size)
8779             emitcode ("inc", "%s", rname);
8780           offset++;
8781         }
8782     }
8783
8784   /* now some housekeeping stuff */
8785   if (aop)
8786     {
8787       /* we had to allocate for this iCode */
8788       freeAsmop (NULL, aop, ic, TRUE);
8789     }
8790   else
8791     {
8792       /* we did not allocate which means left
8793          already in a pointer register, then
8794          if size > 0 && this could be used again
8795          we have to point it back to where it
8796          belongs */
8797       if (AOP_SIZE (right) > 1 &&
8798           !OP_SYMBOL (result)->remat &&
8799           (OP_SYMBOL (result)->liveTo > ic->seq ||
8800            ic->depth))
8801         {
8802           int size = AOP_SIZE (right) - 1;
8803           while (size--)
8804             emitcode ("dec", "%s", rname);
8805         }
8806     }
8807
8808   /* done */
8809   freeAsmop (right, NULL, ic, TRUE);
8810
8811
8812 }
8813
8814 /*-----------------------------------------------------------------*/
8815 /* genPagedPointerSet - emitcode for Paged pointer put             */
8816 /*-----------------------------------------------------------------*/
8817 static void
8818 genPagedPointerSet (operand * right,
8819                     operand * result,
8820                     iCode * ic)
8821 {
8822   asmop *aop = NULL;
8823   regs *preg = NULL;
8824   char *rname, *l;
8825   sym_link *retype, *letype;
8826
8827   retype = getSpec (operandType (right));
8828   letype = getSpec (operandType (result));
8829
8830   aopOp (result, ic, FALSE, FALSE);
8831
8832   /* if the value is already in a pointer register
8833      then don't need anything more */
8834   if (!AOP_INPREG (AOP (result)))
8835     {
8836       /* otherwise get a free pointer register */
8837       aop = newAsmop (0);
8838       preg = getFreePtr (ic, &aop, FALSE);
8839       emitcode ("mov", "%s,%s",
8840                 preg->name,
8841                 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8842       rname = preg->name;
8843     }
8844   else
8845     rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8846
8847   freeAsmop (result, NULL, ic, TRUE);
8848   aopOp (right, ic, FALSE, FALSE);
8849
8850   /* if bitfield then unpack the bits */
8851   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8852     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8853   else
8854     {
8855       /* we have can just get the values */
8856       int size = AOP_SIZE (right);
8857       int offset = 0;
8858
8859       while (size--)
8860         {
8861           l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
8862
8863           MOVA (l);
8864           emitcode ("movx", "@%s,a", rname);
8865
8866           if (size)
8867             emitcode ("inc", "%s", rname);
8868
8869           offset++;
8870         }
8871     }
8872
8873   /* now some housekeeping stuff */
8874   if (aop)
8875     {
8876       /* we had to allocate for this iCode */
8877       freeAsmop (NULL, aop, ic, TRUE);
8878     }
8879   else
8880     {
8881       /* we did not allocate which means left
8882          already in a pointer register, then
8883          if size > 0 && this could be used again
8884          we have to point it back to where it
8885          belongs */
8886       if (AOP_SIZE (right) > 1 &&
8887           !OP_SYMBOL (result)->remat &&
8888           (OP_SYMBOL (result)->liveTo > ic->seq ||
8889            ic->depth))
8890         {
8891           int size = AOP_SIZE (right) - 1;
8892           while (size--)
8893             emitcode ("dec", "%s", rname);
8894         }
8895     }
8896
8897   /* done */
8898   freeAsmop (right, NULL, ic, TRUE);
8899
8900
8901 }
8902
8903 /*-----------------------------------------------------------------*/
8904 /* genFarPointerSet - set value from far space                     */
8905 /*-----------------------------------------------------------------*/
8906 static void
8907 genFarPointerSet (operand * right,
8908                   operand * result, iCode * ic)
8909 {
8910   int size, offset;
8911   sym_link *retype = getSpec (operandType (right));
8912   sym_link *letype = getSpec (operandType (result));
8913
8914   aopOp (result, ic, FALSE, FALSE);
8915
8916   /* if the operand is already in dptr
8917      then we do nothing else we move the value to dptr */
8918   if (AOP_TYPE (result) != AOP_STR)
8919     {
8920       /* if this is remateriazable */
8921       if (AOP_TYPE (result) == AOP_IMMD)
8922         emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8923       else
8924         {
8925           /* we need to get it byte by byte */
8926           _startLazyDPSEvaluation ();
8927           if (AOP_TYPE (result) != AOP_DPTR)
8928             {
8929               emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8930               emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8931               emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8932             }
8933           else
8934             {
8935               /* We need to generate a load to DPTR indirect through DPTR. */
8936               D (emitcode (";", "genFarPointerSet -- indirection special case.");
8937                 );
8938               emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
8939               emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
8940               emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8941               emitcode ("pop", "dph");
8942               emitcode ("pop", "dpl");
8943             }
8944           _endLazyDPSEvaluation ();
8945         }
8946     }
8947   /* so dptr know contains the address */
8948   freeAsmop (result, NULL, ic, TRUE);
8949   aopOp (right, ic, FALSE, TRUE);
8950
8951   /* if bit then unpack */
8952   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8953     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8954   else
8955     {
8956       size = AOP_SIZE (right);
8957       offset = 0;
8958
8959       _startLazyDPSEvaluation ();
8960       while (size--)
8961         {
8962           char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8963           MOVA (l);
8964
8965           genSetDPTR (0);
8966           _flushLazyDPS ();
8967
8968           emitcode ("movx", "@dptr,a");
8969           if (size)
8970             emitcode ("inc", "dptr");
8971         }
8972       _endLazyDPSEvaluation ();
8973     }
8974
8975   freeAsmop (right, NULL, ic, TRUE);
8976 }
8977
8978 /*-----------------------------------------------------------------*/
8979 /* genGenPointerSet - set value from generic pointer space         */
8980 /*-----------------------------------------------------------------*/
8981 static void
8982 genGenPointerSet (operand * right,
8983                   operand * result, iCode * ic)
8984 {
8985   int size, offset;
8986   sym_link *retype = getSpec (operandType (right));
8987   sym_link *letype = getSpec (operandType (result));
8988
8989   aopOp (result, ic, FALSE, TRUE);
8990
8991   /* if the operand is already in dptr
8992      then we do nothing else we move the value to dptr */
8993   if (AOP_TYPE (result) != AOP_STR)
8994     {
8995       _startLazyDPSEvaluation ();
8996       /* if this is remateriazable */
8997       if (AOP_TYPE (result) == AOP_IMMD)
8998         {
8999           emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9000           emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9001         }
9002       else
9003         {                       /* we need to get it byte by byte */
9004           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9005           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9006           emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9007           emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
9008         }
9009       _endLazyDPSEvaluation ();
9010     }
9011   /* so dptr know contains the address */
9012   freeAsmop (result, NULL, ic, TRUE);
9013   aopOp (right, ic, FALSE, TRUE);
9014
9015   /* if bit then unpack */
9016   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9017     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
9018   else
9019     {
9020       size = AOP_SIZE (right);
9021       offset = 0;
9022
9023       _startLazyDPSEvaluation ();
9024       while (size--)
9025         {
9026           char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9027           MOVA (l);
9028
9029           genSetDPTR (0);
9030           _flushLazyDPS ();
9031
9032           emitcode ("lcall", "__gptrput");
9033           if (size)
9034             emitcode ("inc", "dptr");
9035         }
9036       _endLazyDPSEvaluation ();
9037     }
9038
9039   freeAsmop (right, NULL, ic, TRUE);
9040 }
9041
9042 /*-----------------------------------------------------------------*/
9043 /* genPointerSet - stores the value into a pointer location        */
9044 /*-----------------------------------------------------------------*/
9045 static void
9046 genPointerSet (iCode * ic)
9047 {
9048   operand *right, *result;
9049   sym_link *type, *etype;
9050   int p_type;
9051
9052   D (emitcode (";", "genPointerSet ");
9053     );
9054
9055   right = IC_RIGHT (ic);
9056   result = IC_RESULT (ic);
9057
9058   /* depending on the type of pointer we need to
9059      move it to the correct pointer register */
9060   type = operandType (result);
9061   etype = getSpec (type);
9062   /* if left is of type of pointer then it is simple */
9063   if (IS_PTR (type) && !IS_FUNC (type->next))
9064     {
9065       p_type = DCL_TYPE (type);
9066     }
9067   else
9068     {
9069       /* we have to go by the storage class */
9070       p_type = PTR_TYPE (SPEC_OCLS (etype));
9071     }
9072
9073   /* now that we have the pointer type we assign
9074      the pointer values */
9075   switch (p_type)
9076     {
9077
9078     case POINTER:
9079     case IPOINTER:
9080       genNearPointerSet (right, result, ic);
9081       break;
9082
9083     case PPOINTER:
9084       genPagedPointerSet (right, result, ic);
9085       break;
9086
9087     case FPOINTER:
9088       genFarPointerSet (right, result, ic);
9089       break;
9090
9091     case GPOINTER:
9092       genGenPointerSet (right, result, ic);
9093       break;
9094     }
9095
9096 }
9097
9098 /*-----------------------------------------------------------------*/
9099 /* genIfx - generate code for Ifx statement                        */
9100 /*-----------------------------------------------------------------*/
9101 static void
9102 genIfx (iCode * ic, iCode * popIc)
9103 {
9104   operand *cond = IC_COND (ic);
9105   int isbit = 0;
9106
9107   D (emitcode (";", "genIfx "););
9108
9109   aopOp (cond, ic, FALSE, FALSE);
9110
9111   /* get the value into acc */
9112   if (AOP_TYPE (cond) != AOP_CRY)
9113     toBoolean (cond);
9114   else
9115     isbit = 1;
9116   /* the result is now in the accumulator */
9117   freeAsmop (cond, NULL, ic, TRUE);
9118
9119   /* if there was something to be popped then do it */
9120   if (popIc)
9121     genIpop (popIc);
9122
9123   /* if the condition is  a bit variable */
9124   if (isbit && IS_ITEMP (cond) &&
9125       SPIL_LOC (cond))
9126     genIfxJump (ic, SPIL_LOC (cond)->rname);
9127   else if (isbit && !IS_ITEMP (cond))
9128     genIfxJump (ic, OP_SYMBOL (cond)->rname);
9129   else
9130     genIfxJump (ic, "a");
9131
9132   ic->generated = 1;
9133 }
9134
9135 /*-----------------------------------------------------------------*/
9136 /* genAddrOf - generates code for address of                       */
9137 /*-----------------------------------------------------------------*/
9138 static void
9139 genAddrOf (iCode * ic)
9140 {
9141   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
9142   int size, offset;
9143
9144   D (emitcode (";", "genAddrOf ");
9145     );
9146
9147   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9148
9149   /* if the operand is on the stack then we
9150      need to get the stack offset of this
9151      variable */
9152   if (sym->onStack)
9153     {
9154       /* if it has an offset then we need to compute
9155          it */
9156       if (sym->stack)
9157         {
9158           emitcode ("mov", "a,_bp");
9159           emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
9160           aopPut (AOP (IC_RESULT (ic)), "a", 0);
9161         }
9162       else
9163         {
9164           /* we can just move _bp */
9165           aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
9166         }
9167       /* fill the result with zero */
9168       size = AOP_SIZE (IC_RESULT (ic)) - 1;
9169
9170
9171       if (options.stack10bit && size < (FPTRSIZE - 1))
9172         {
9173           fprintf (stderr,
9174                    "*** warning: pointer to stack var truncated.\n");
9175         }
9176
9177       offset = 1;
9178       while (size--)
9179         {
9180           /* Yuck! */
9181           if (options.stack10bit && offset == 2)
9182             {
9183               aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
9184             }
9185           else
9186             {
9187               aopPut (AOP (IC_RESULT (ic)), zero, offset++);
9188             }
9189         }
9190
9191       goto release;
9192     }
9193
9194   /* object not on stack then we need the name */
9195   size = AOP_SIZE (IC_RESULT (ic));
9196   offset = 0;
9197
9198   while (size--)
9199     {
9200       char s[SDCC_NAME_MAX];
9201       if (offset)
9202         sprintf (s, "#(%s >> %d)",
9203                  sym->rname,
9204                  offset * 8);
9205       else
9206         sprintf (s, "#%s", sym->rname);
9207       aopPut (AOP (IC_RESULT (ic)), s, offset++);
9208     }
9209
9210 release:
9211   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9212
9213 }
9214
9215 /*-----------------------------------------------------------------*/
9216 /* genFarFarAssign - assignment when both are in far space         */
9217 /*-----------------------------------------------------------------*/
9218 static void
9219 genFarFarAssign (operand * result, operand * right, iCode * ic)
9220 {
9221   int size = AOP_SIZE (right);
9222   int offset = 0;
9223   symbol *rSym = NULL;
9224
9225   if (size == 1)
9226   {
9227       /* quick & easy case. */
9228       D(emitcode(";","genFarFarAssign (1 byte case)"););      
9229       MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
9230       freeAsmop (right, NULL, ic, FALSE);
9231       /* now assign DPTR to result */
9232       _G.accInUse++;
9233       aopOp(result, ic, FALSE, FALSE);
9234       _G.accInUse--;
9235       aopPut(AOP(result), "a", 0);
9236       freeAsmop(result, NULL, ic, FALSE);
9237       return;
9238   }
9239   
9240   /* See if we've got an underlying symbol to abuse. */
9241   if (IS_SYMOP(result) && OP_SYMBOL(result))
9242   {
9243       if (IS_TRUE_SYMOP(result))
9244       {
9245           rSym = OP_SYMBOL(result);
9246       }
9247       else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
9248       {
9249           rSym = OP_SYMBOL(result)->usl.spillLoc;
9250       }
9251   }
9252              
9253   if (size > 1 && rSym && rSym->rname && !rSym->onStack)
9254   {
9255       /* We can use the '390 auto-toggle feature to good effect here. */
9256       
9257       D(emitcode(";","genFarFarAssign ('390 auto-toggle fun)"););
9258       emitcode("mov", "dps, #0x21");    /* Select DPTR2 & auto-toggle. */
9259       emitcode ("mov", "dptr,#%s", rSym->rname); 
9260       /* DP2 = result, DP1 = right, DP1 is current. */
9261       while (size)
9262       {
9263           emitcode("movx", "a,@dptr");
9264           emitcode("movx", "@dptr,a");
9265           if (--size)
9266           {
9267                emitcode("inc", "dptr");
9268                emitcode("inc", "dptr");
9269           }
9270       }
9271       emitcode("mov", "dps, #0");
9272       freeAsmop (right, NULL, ic, FALSE);
9273   }
9274   else
9275   {
9276       D (emitcode (";", "genFarFarAssign"););
9277       aopOp (result, ic, TRUE, TRUE);
9278
9279       _startLazyDPSEvaluation ();
9280       
9281       while (size--)
9282         {
9283           aopPut (AOP (result),
9284                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
9285           offset++;
9286         }
9287       _endLazyDPSEvaluation ();
9288       freeAsmop (result, NULL, ic, FALSE);
9289       freeAsmop (right, NULL, ic, FALSE);
9290   }
9291 }
9292
9293 /*-----------------------------------------------------------------*/
9294 /* genAssign - generate code for assignment                        */
9295 /*-----------------------------------------------------------------*/
9296 static void
9297 genAssign (iCode * ic)
9298 {
9299   operand *result, *right;
9300   int size, offset;
9301   unsigned long lit = 0L;
9302
9303   D (emitcode (";", "genAssign ");
9304     );
9305
9306   result = IC_RESULT (ic);
9307   right = IC_RIGHT (ic);
9308
9309   /* if they are the same */
9310   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9311     return;
9312
9313   aopOp (right, ic, FALSE, FALSE);
9314
9315   emitcode (";", "genAssign: resultIsFar = %s",
9316             isOperandInFarSpace (result) ?
9317             "TRUE" : "FALSE");
9318
9319   /* special case both in far space */
9320   if ((AOP_TYPE (right) == AOP_DPTR ||
9321        AOP_TYPE (right) == AOP_DPTR2) &&
9322   /* IS_TRUE_SYMOP(result)       && */
9323       isOperandInFarSpace (result))
9324     {
9325       genFarFarAssign (result, right, ic);
9326       return;
9327     }
9328
9329   aopOp (result, ic, TRUE, FALSE);
9330
9331   /* if they are the same registers */
9332   if (sameRegs (AOP (right), AOP (result)))
9333     goto release;
9334
9335   /* if the result is a bit */
9336   if (AOP_TYPE (result) == AOP_CRY)
9337     {
9338
9339       /* if the right size is a literal then
9340          we know what the value is */
9341       if (AOP_TYPE (right) == AOP_LIT)
9342         {
9343           if (((int) operandLitValue (right)))
9344             aopPut (AOP (result), one, 0);
9345           else
9346             aopPut (AOP (result), zero, 0);
9347           goto release;
9348         }
9349
9350       /* the right is also a bit variable */
9351       if (AOP_TYPE (right) == AOP_CRY)
9352         {
9353           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9354           aopPut (AOP (result), "c", 0);
9355           goto release;
9356         }
9357
9358       /* we need to or */
9359       toBoolean (right);
9360       aopPut (AOP (result), "a", 0);
9361       goto release;
9362     }
9363
9364   /* bit variables done */
9365   /* general case */
9366   size = AOP_SIZE (result);
9367   offset = 0;
9368   if (AOP_TYPE (right) == AOP_LIT)
9369     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
9370
9371   if ((size > 1) &&
9372       (AOP_TYPE (result) != AOP_REG) &&
9373       (AOP_TYPE (right) == AOP_LIT) &&
9374       !IS_FLOAT (operandType (right)))
9375     {
9376       _startLazyDPSEvaluation ();
9377       while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
9378         {
9379           aopPut (AOP (result),
9380                   aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
9381                   offset);
9382           offset++;
9383           size--;
9384         }
9385       /* And now fill the rest with zeros. */
9386       if (size)
9387         {
9388           emitcode ("clr", "a");
9389         }
9390       while (size--)
9391         {
9392           aopPut (AOP (result), "a", offset++);
9393         }
9394       _endLazyDPSEvaluation ();
9395     }
9396   else
9397     {
9398       _startLazyDPSEvaluation ();
9399       while (size--)
9400         {
9401           aopPut (AOP (result),
9402                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9403                   offset);
9404           offset++;
9405         }
9406       _endLazyDPSEvaluation ();
9407     }
9408
9409 release:
9410   freeAsmop (right, NULL, ic, FALSE);
9411   freeAsmop (result, NULL, ic, TRUE);
9412 }
9413
9414 /*-----------------------------------------------------------------*/
9415 /* genJumpTab - generates code for jump table                      */
9416 /*-----------------------------------------------------------------*/
9417 static void
9418 genJumpTab (iCode * ic)
9419 {
9420   symbol *jtab;
9421   char *l;
9422
9423   D (emitcode (";", "genJumpTab ");
9424     );
9425
9426   aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
9427   /* get the condition into accumulator */
9428   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
9429   MOVA (l);
9430   /* multiply by four! */
9431   emitcode ("add", "a,acc");
9432   emitcode ("add", "a,acc");
9433   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9434
9435   jtab = newiTempLabel (NULL);
9436   emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
9437   emitcode ("jmp", "@a+dptr");
9438   emitcode ("", "%05d$:", jtab->key + 100);
9439   /* now generate the jump labels */
9440   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9441        jtab = setNextItem (IC_JTLABELS (ic)))
9442     emitcode ("ljmp", "%05d$", jtab->key + 100);
9443
9444 }
9445
9446 /*-----------------------------------------------------------------*/
9447 /* genCast - gen code for casting                                  */
9448 /*-----------------------------------------------------------------*/
9449 static void
9450 genCast (iCode * ic)
9451 {
9452   operand *result = IC_RESULT (ic);
9453   sym_link *ctype = operandType (IC_LEFT (ic));
9454   sym_link *rtype = operandType (IC_RIGHT (ic));
9455   operand *right = IC_RIGHT (ic);
9456   int size, offset;
9457
9458   D (emitcode (";", "genCast ");
9459     );
9460
9461   /* if they are equivalent then do nothing */
9462   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9463     return;
9464
9465   aopOp (right, ic, FALSE, FALSE);
9466   aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
9467
9468   /* if the result is a bit */
9469   if (AOP_TYPE (result) == AOP_CRY)
9470     {
9471       /* if the right size is a literal then
9472          we know what the value is */
9473       if (AOP_TYPE (right) == AOP_LIT)
9474         {
9475           if (((int) operandLitValue (right)))
9476             aopPut (AOP (result), one, 0);
9477           else
9478             aopPut (AOP (result), zero, 0);
9479
9480           goto release;
9481         }
9482
9483       /* the right is also a bit variable */
9484       if (AOP_TYPE (right) == AOP_CRY)
9485         {
9486           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9487           aopPut (AOP (result), "c", 0);
9488           goto release;
9489         }
9490
9491       /* we need to or */
9492       toBoolean (right);
9493       aopPut (AOP (result), "a", 0);
9494       goto release;
9495     }
9496
9497   /* if they are the same size : or less */
9498   if (AOP_SIZE (result) <= AOP_SIZE (right))
9499     {
9500
9501       /* if they are in the same place */
9502       if (sameRegs (AOP (right), AOP (result)))
9503         goto release;
9504
9505       /* if they in different places then copy */
9506       size = AOP_SIZE (result);
9507       offset = 0;
9508       _startLazyDPSEvaluation ();
9509       while (size--)
9510         {
9511           aopPut (AOP (result),
9512                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9513                   offset);
9514           offset++;
9515         }
9516       _endLazyDPSEvaluation ();
9517       goto release;
9518     }
9519
9520
9521   /* if the result is of type pointer */
9522   if (IS_PTR (ctype))
9523     {
9524
9525       int p_type;
9526       sym_link *type = operandType (right);
9527
9528       /* pointer to generic pointer */
9529       if (IS_GENPTR (ctype))
9530         {
9531           char *l = zero;
9532
9533           if (IS_PTR (type))
9534             {
9535               p_type = DCL_TYPE (type);
9536             }
9537           else
9538             {
9539 #if OLD_CAST_BEHAVIOR
9540               /* KV: we are converting a non-pointer type to
9541                * a generic pointer. This (ifdef'd out) code
9542                * says that the resulting generic pointer
9543                * should have the same class as the storage
9544                * location of the non-pointer variable.
9545                *
9546                * For example, converting an int (which happens
9547                * to be stored in DATA space) to a pointer results
9548                * in a DATA generic pointer; if the original int
9549                * in XDATA space, so will be the resulting pointer.
9550                *
9551                * I don't like that behavior, and thus this change:
9552                * all such conversions will be forced to XDATA and
9553                * throw a warning. If you want some non-XDATA
9554                * type, or you want to suppress the warning, you
9555                * must go through an intermediate cast, like so:
9556                *
9557                * char _generic *gp = (char _xdata *)(intVar);
9558                */
9559               sym_link *etype = getSpec (type);
9560
9561               /* we have to go by the storage class */
9562               if (SPEC_OCLS (etype) != generic)
9563                 {
9564                   p_type = PTR_TYPE (SPEC_OCLS (etype));
9565                 }
9566               else
9567 #endif
9568                 {
9569                   /* Converting unknown class (i.e. register variable)
9570                    * to generic pointer. This is not good, but
9571                    * we'll make a guess (and throw a warning).
9572                    */
9573                   p_type = FPOINTER;
9574                   werror (W_INT_TO_GEN_PTR_CAST);
9575                 }
9576             }
9577
9578           /* the first two bytes are known */
9579           size = GPTRSIZE - 1;
9580           offset = 0;
9581           _startLazyDPSEvaluation ();
9582           while (size--)
9583             {
9584               aopPut (AOP (result),
9585                       aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9586                       offset);
9587               offset++;
9588             }
9589           _endLazyDPSEvaluation ();
9590
9591           /* the last byte depending on type */
9592           switch (p_type)
9593             {
9594             case IPOINTER:
9595             case POINTER:
9596               l = zero;
9597               break;
9598             case FPOINTER:
9599               l = one;
9600               break;
9601             case CPOINTER:
9602               l = "#0x02";
9603               break;
9604             case PPOINTER:
9605               l = "#0x03";
9606               break;
9607
9608             default:
9609               /* this should never happen */
9610               werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9611                       "got unknown pointer type");
9612               exit (1);
9613             }
9614           aopPut (AOP (result), l, GPTRSIZE - 1);
9615           goto release;
9616         }
9617
9618       /* just copy the pointers */
9619       size = AOP_SIZE (result);
9620       offset = 0;
9621       _startLazyDPSEvaluation ();
9622       while (size--)
9623         {
9624           aopPut (AOP (result),
9625                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9626                   offset);
9627           offset++;
9628         }
9629       _endLazyDPSEvaluation ();
9630       goto release;
9631     }
9632
9633   /* so we now know that the size of destination is greater
9634      than the size of the source */
9635   /* we move to result for the size of source */
9636   size = AOP_SIZE (right);
9637   offset = 0;
9638   _startLazyDPSEvaluation ();
9639   while (size--)
9640     {
9641       aopPut (AOP (result),
9642               aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9643               offset);
9644       offset++;
9645     }
9646   _endLazyDPSEvaluation ();
9647
9648   /* now depending on the sign of the source && destination */
9649   size = AOP_SIZE (result) - AOP_SIZE (right);
9650   /* if unsigned or not an integral type */
9651   /* also, if the source is a bit, we don't need to sign extend, because
9652    * it can't possibly have set the sign bit.
9653    */
9654   if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
9655     {
9656       while (size--)
9657         {
9658           aopPut (AOP (result), zero, offset++);
9659         }
9660     }
9661   else
9662     {
9663       /* we need to extend the sign :{ */
9664       char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
9665                         FALSE, FALSE, TRUE);
9666       MOVA (l);
9667       emitcode ("rlc", "a");
9668       emitcode ("subb", "a,acc");
9669       while (size--)
9670         aopPut (AOP (result), "a", offset++);
9671     }
9672
9673   /* we are done hurray !!!! */
9674
9675 release:
9676   freeAsmop (right, NULL, ic, TRUE);
9677   freeAsmop (result, NULL, ic, TRUE);
9678
9679 }
9680
9681 /*-----------------------------------------------------------------*/
9682 /* genDjnz - generate decrement & jump if not zero instrucion      */
9683 /*-----------------------------------------------------------------*/
9684 static int
9685 genDjnz (iCode * ic, iCode * ifx)
9686 {
9687   symbol *lbl, *lbl1;
9688   if (!ifx)
9689     return 0;
9690
9691   /* if the if condition has a false label
9692      then we cannot save */
9693   if (IC_FALSE (ifx))
9694     return 0;
9695
9696   /* if the minus is not of the form
9697      a = a - 1 */
9698   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
9699       !IS_OP_LITERAL (IC_RIGHT (ic)))
9700     return 0;
9701
9702   if (operandLitValue (IC_RIGHT (ic)) != 1)
9703     return 0;
9704
9705   /* if the size of this greater than one then no
9706      saving */
9707   if (getSize (operandType (IC_RESULT (ic))) > 1)
9708     return 0;
9709
9710   /* otherwise we can save BIG */
9711   D(emitcode(";", "genDjnz"););
9712
9713   lbl = newiTempLabel (NULL);
9714   lbl1 = newiTempLabel (NULL);
9715
9716   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9717
9718   if (AOP_NEEDSACC(IC_RESULT(ic)))
9719   {
9720       /* If the result is accessed indirectly via
9721        * the accumulator, we must explicitly write
9722        * it back after the decrement.
9723        */
9724       char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
9725       
9726       if (strcmp(rByte, "a"))
9727       {
9728            /* Something is hopelessly wrong */
9729            fprintf(stderr, "*** warning: internal error at %s:%d\n",
9730                    __FILE__, __LINE__);
9731            /* We can just give up; the generated code will be inefficient,
9732             * but what the hey.
9733             */
9734            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9735            return 0;
9736       }
9737       emitcode ("dec", "%s", rByte);
9738       aopPut(AOP(IC_RESULT(ic)), rByte, 0);
9739       emitcode ("jnz", "%05d$", lbl->key + 100);
9740   }
9741   else if (IS_AOP_PREG (IC_RESULT (ic)))
9742     {
9743       emitcode ("dec", "%s",
9744                 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9745       emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9746       emitcode ("jnz", "%05d$", lbl->key + 100);
9747     }
9748   else
9749     {
9750       emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
9751                 lbl->key + 100);
9752     }
9753   emitcode ("sjmp", "%05d$", lbl1->key + 100);
9754   emitcode ("", "%05d$:", lbl->key + 100);
9755   emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
9756   emitcode ("", "%05d$:", lbl1->key + 100);
9757
9758   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9759   ifx->generated = 1;
9760   return 1;
9761 }
9762
9763 /*-----------------------------------------------------------------*/
9764 /* genReceive - generate code for a receive iCode                  */
9765 /*-----------------------------------------------------------------*/
9766 static void
9767 genReceive (iCode * ic)
9768 {
9769
9770   D (emitcode (";", "genReceive ");
9771     );
9772
9773   if (isOperandInFarSpace (IC_RESULT (ic)) &&
9774       (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
9775        IS_TRUE_SYMOP (IC_RESULT (ic))))
9776     {
9777       int size = getSize (operandType (IC_RESULT (ic)));
9778       int offset = fReturnSizeDS390 - size;
9779       while (size--)
9780         {
9781           emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
9782                             fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
9783           offset++;
9784         }
9785       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9786       size = AOP_SIZE (IC_RESULT (ic));
9787       offset = 0;
9788       while (size--)
9789         {
9790           emitcode ("pop", "acc");
9791           aopPut (AOP (IC_RESULT (ic)), "a", offset++);
9792         }
9793
9794     }
9795   else
9796     {
9797       _G.accInUse++;
9798       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9799       _G.accInUse--;
9800       assignResultValue (IC_RESULT (ic));
9801     }
9802
9803   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9804 }
9805
9806 /*-----------------------------------------------------------------*/
9807 /* gen390Code - generate code for Dallas 390 based controllers     */
9808 /*-----------------------------------------------------------------*/
9809 void
9810 gen390Code (iCode * lic)
9811 {
9812   iCode *ic;
9813   int cln = 0;
9814
9815   lineHead = lineCurr = NULL;
9816
9817 #if 0
9818   //REMOVE ME!!!
9819   /* print the allocation information */
9820   if (allocInfo)
9821     printAllocInfo (currFunc, codeOutFile);
9822 #endif
9823   /* if debug information required */
9824   if (options.debug && currFunc)
9825     {
9826       cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
9827       _G.debugLine = 1;
9828       if (IS_STATIC (currFunc->etype))
9829         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
9830       else
9831         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
9832       _G.debugLine = 0;
9833     }
9834   /* stack pointer name */
9835   if (options.useXstack)
9836     spname = "_spx";
9837   else
9838     spname = "sp";
9839
9840
9841   for (ic = lic; ic; ic = ic->next)
9842     {
9843
9844       if (cln != ic->lineno)
9845         {
9846           if (options.debug)
9847             {
9848               _G.debugLine = 1;
9849               emitcode ("", "C$%s$%d$%d$%d ==.",
9850                         FileBaseName (ic->filename), ic->lineno,
9851                         ic->level, ic->block);
9852               _G.debugLine = 0;
9853             }
9854           emitcode (";", "%s %d", ic->filename, ic->lineno);
9855           cln = ic->lineno;
9856         }
9857       /* if the result is marked as
9858          spilt and rematerializable or code for
9859          this has already been generated then
9860          do nothing */
9861       if (resultRemat (ic) || ic->generated)
9862         continue;
9863
9864       /* depending on the operation */
9865       switch (ic->op)
9866         {
9867         case '!':
9868           genNot (ic);
9869           break;
9870
9871         case '~':
9872           genCpl (ic);
9873           break;
9874
9875         case UNARYMINUS:
9876           genUminus (ic);
9877           break;
9878
9879         case IPUSH:
9880           genIpush (ic);
9881           break;
9882
9883         case IPOP:
9884           /* IPOP happens only when trying to restore a
9885              spilt live range, if there is an ifx statement
9886              following this pop then the if statement might
9887              be using some of the registers being popped which
9888              would destory the contents of the register so
9889              we need to check for this condition and handle it */
9890           if (ic->next &&
9891               ic->next->op == IFX &&
9892               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
9893             genIfx (ic->next, ic);
9894           else
9895             genIpop (ic);
9896           break;
9897
9898         case CALL:
9899           genCall (ic);
9900           break;
9901
9902         case PCALL:
9903           genPcall (ic);
9904           break;
9905
9906         case FUNCTION:
9907           genFunction (ic);
9908           break;
9909
9910         case ENDFUNCTION:
9911           genEndFunction (ic);
9912           break;
9913
9914         case RETURN:
9915           genRet (ic);
9916           break;
9917
9918         case LABEL:
9919           genLabel (ic);
9920           break;
9921
9922         case GOTO:
9923           genGoto (ic);
9924           break;
9925
9926         case '+':
9927           genPlus (ic);
9928           break;
9929
9930         case '-':
9931           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9932             genMinus (ic);
9933           break;
9934
9935         case '*':
9936           genMult (ic);
9937           break;
9938
9939         case '/':
9940           genDiv (ic);
9941           break;
9942
9943         case '%':
9944           genMod (ic);
9945           break;
9946
9947         case '>':
9948           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9949           break;
9950
9951         case '<':
9952           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9953           break;
9954
9955         case LE_OP:
9956         case GE_OP:
9957         case NE_OP:
9958
9959           /* note these two are xlated by algebraic equivalence
9960              during parsing SDCC.y */
9961           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9962                   "got '>=' or '<=' shouldn't have come here");
9963           break;
9964
9965         case EQ_OP:
9966           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9967           break;
9968
9969         case AND_OP:
9970           genAndOp (ic);
9971           break;
9972
9973         case OR_OP:
9974           genOrOp (ic);
9975           break;
9976
9977         case '^':
9978           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9979           break;
9980
9981         case '|':
9982           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9983           break;
9984
9985         case BITWISEAND:
9986           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9987           break;
9988
9989         case INLINEASM:
9990           genInline (ic);
9991           break;
9992
9993         case RRC:
9994           genRRC (ic);
9995           break;
9996
9997         case RLC:
9998           genRLC (ic);
9999           break;
10000
10001         case GETHBIT:
10002           genGetHbit (ic);
10003           break;
10004
10005         case LEFT_OP:
10006           genLeftShift (ic);
10007           break;
10008
10009         case RIGHT_OP:
10010           genRightShift (ic);
10011           break;
10012
10013         case GET_VALUE_AT_ADDRESS:
10014           genPointerGet (ic);
10015           break;
10016
10017         case '=':
10018           if (POINTER_SET (ic))
10019             genPointerSet (ic);
10020           else
10021             genAssign (ic);
10022           break;
10023
10024         case IFX:
10025           genIfx (ic, NULL);
10026           break;
10027
10028         case ADDRESS_OF:
10029           genAddrOf (ic);
10030           break;
10031
10032         case JUMPTABLE:
10033           genJumpTab (ic);
10034           break;
10035
10036         case CAST:
10037           genCast (ic);
10038           break;
10039
10040         case RECEIVE:
10041           genReceive (ic);
10042           break;
10043
10044         case SEND:
10045           addSet (&_G.sendSet, ic);
10046           break;
10047
10048         default:
10049           ic = ic;
10050         }
10051     }
10052
10053
10054   /* now we are ready to call the
10055      peep hole optimizer */
10056   if (!options.nopeep)
10057     peepHole (&lineHead);
10058
10059   /* now do the actual printing */
10060   printLine (lineHead, codeOutFile);
10061   return;
10062 }