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