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