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