fix genPlus bogus code generation demonstrated by Karl's eth.c
[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           aop = newAsmop (0);
2057           r = getFreePtr (ic, &aop, FALSE);
2058
2059
2060           emitcode ("mov", "%s,_spx", r->name);
2061           emitcode ("movx", "a,@%s", r->name);
2062           emitcode ("mov", "psw,a");
2063           emitcode ("dec", "%s", r->name);
2064
2065         }
2066       else
2067         emitcode ("pop", "psw");
2068     }
2069
2070   for (i = (ds390_nRegs - 1); i >= 0; i--)
2071     {
2072       if (options.useXstack)
2073         {
2074           emitcode ("movx", "a,@%s", r->name);
2075           emitcode ("mov", "(%s+%d),a",
2076                     regs390[i].base, 8 * bank + regs390[i].offset);
2077           emitcode ("dec", "%s", r->name);
2078
2079         }
2080       else
2081         emitcode ("pop", "(%s+%d)",
2082                   regs390[i].base, 8 * bank + regs390[i].offset);
2083     }
2084
2085   if (options.useXstack)
2086     {
2087
2088       emitcode ("mov", "_spx,%s", r->name);
2089       freeAsmop (NULL, aop, ic, TRUE);
2090
2091     }
2092 }
2093
2094 /*-----------------------------------------------------------------*/
2095 /* saveRBank - saves an entire register bank on the stack          */
2096 /*-----------------------------------------------------------------*/
2097 static void
2098 saveRBank (int bank, iCode * ic, bool pushPsw)
2099 {
2100   int i;
2101   asmop *aop;
2102   regs *r = NULL;
2103
2104   if (options.useXstack)
2105     {
2106
2107       aop = newAsmop (0);
2108       r = getFreePtr (ic, &aop, FALSE);
2109       emitcode ("mov", "%s,_spx", r->name);
2110
2111     }
2112
2113   for (i = 0; i < ds390_nRegs; i++)
2114     {
2115       if (options.useXstack)
2116         {
2117           emitcode ("inc", "%s", r->name);
2118           emitcode ("mov", "a,(%s+%d)",
2119                     regs390[i].base, 8 * bank + regs390[i].offset);
2120           emitcode ("movx", "@%s,a", r->name);
2121         }
2122       else
2123         emitcode ("push", "(%s+%d)",
2124                   regs390[i].base, 8 * bank + regs390[i].offset);
2125     }
2126
2127   if (pushPsw)
2128     {
2129       if (options.useXstack)
2130         {
2131           emitcode ("mov", "a,psw");
2132           emitcode ("movx", "@%s,a", r->name);
2133           emitcode ("inc", "%s", r->name);
2134           emitcode ("mov", "_spx,%s", r->name);
2135           freeAsmop (NULL, aop, ic, TRUE);
2136
2137         }
2138       else
2139         emitcode ("push", "psw");
2140
2141       emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2142     }
2143   ic->bankSaved = 1;
2144
2145 }
2146
2147 /*-----------------------------------------------------------------*/
2148 /* genCall - generates a call statement                            */
2149 /*-----------------------------------------------------------------*/
2150 static void
2151 genCall (iCode * ic)
2152 {
2153   sym_link *detype;
2154
2155   D (emitcode (";", "genCall "););
2156
2157   /* if we are calling a function that is not using
2158      the same register bank then we need to save the
2159      destination registers on the stack */
2160   detype = getSpec (operandType (IC_LEFT (ic)));
2161   if (detype &&
2162       (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
2163       IS_ISR (currFunc->etype) &&
2164       !ic->bankSaved) {
2165     saveRBank (SPEC_BANK (detype), ic, TRUE);
2166   } else /* no need to save if we just saved the whole bank */ {
2167     /* if caller saves & we have not saved then */
2168     if (!ic->regsSaved)
2169       saveRegisters (ic);
2170   }
2171   
2172   /* if send set is not empty the assign */
2173   /* We've saved all the registers we care about;
2174   * therefore, we may clobber any register not used
2175   * in the calling convention (i.e. anything not in
2176   * fReturn.
2177   */
2178   if (_G.sendSet)
2179     {
2180       iCode *sic;
2181
2182       for (sic = setFirstItem (_G.sendSet); sic;
2183            sic = setNextItem (_G.sendSet))
2184         {
2185           int size, offset = 0;
2186
2187           aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2188           size = AOP_SIZE (IC_LEFT (sic));
2189
2190           _startLazyDPSEvaluation ();
2191           while (size--)
2192             {
2193               char *l = aopGet (AOP(IC_LEFT(sic)), offset,
2194                                 FALSE, FALSE, TRUE);
2195                 if ((AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR) && size)
2196                 {
2197                     emitcode("mov", "%s,%s", regs390[offset].name, l);
2198                 }
2199                 else if (strcmp (l, fReturn[offset]))
2200                 {
2201                     emitcode ("mov", "%s,%s",
2202                               fReturn[offset],
2203                               l);
2204                 }
2205               offset++;
2206             }
2207           _endLazyDPSEvaluation ();
2208           if (AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR)
2209           {
2210               size = AOP_SIZE (IC_LEFT (sic));
2211               if (size)
2212               {
2213                  size--;
2214               }
2215               while (size)
2216               {
2217                    size--;
2218                    emitcode("mov", "%s,%s",
2219                                     fReturn[size], regs390[size].name);
2220               }
2221           }
2222           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2223         }
2224       _G.sendSet = NULL;
2225     }  
2226
2227   /* make the call */
2228   emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2229                             OP_SYMBOL (IC_LEFT (ic))->rname :
2230                             OP_SYMBOL (IC_LEFT (ic))->name));
2231
2232   /* if we need assign a result value */
2233   if ((IS_ITEMP (IC_RESULT (ic)) &&
2234        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2235         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2236       IS_TRUE_SYMOP (IC_RESULT (ic)))
2237     {
2238       if (isOperandInFarSpace (IC_RESULT (ic))
2239           && getSize (operandType (IC_RESULT (ic))) <= 2)
2240         {
2241           int size = getSize (operandType (IC_RESULT (ic)));
2242
2243           /* Special case for 1 or 2 byte return in far space. */
2244           MOVA (fReturn[0]);
2245           if (size > 1)
2246             {
2247               emitcode ("mov", "b,%s", fReturn[1]);
2248             }
2249
2250           aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2251           aopPut (AOP (IC_RESULT (ic)), "a", 0);
2252
2253           if (size > 1)
2254             {
2255               aopPut (AOP (IC_RESULT (ic)), "b", 1);
2256             }
2257           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2258         }
2259       else
2260         {
2261           _G.accInUse++;
2262           aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2263           _G.accInUse--;
2264
2265           assignResultValue (IC_RESULT (ic));
2266
2267           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2268         }
2269     }
2270
2271   /* adjust the stack for parameters if
2272      required */
2273   if (ic->parmBytes)
2274     {
2275       int i;
2276       if (ic->parmBytes > 3)
2277         {
2278           emitcode ("mov", "a,%s", spname);
2279           emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2280           emitcode ("mov", "%s,a", spname);
2281         }
2282       else
2283         for (i = 0; i < ic->parmBytes; i++)
2284           emitcode ("dec", "%s", spname);
2285
2286     }
2287
2288   /* if register bank was saved then pop them */
2289   if (ic->bankSaved)
2290     unsaveRBank (SPEC_BANK (detype), ic, TRUE);
2291
2292   /* if we hade saved some registers then unsave them */
2293   if (ic->regsSaved && !(OP_SYMBOL (IC_LEFT (ic))->calleeSave))
2294     unsaveRegisters (ic);
2295
2296
2297 }
2298
2299 /*-----------------------------------------------------------------*/
2300 /* genPcall - generates a call by pointer statement                */
2301 /*-----------------------------------------------------------------*/
2302 static void
2303 genPcall (iCode * ic)
2304 {
2305   sym_link *detype;
2306   symbol *rlbl = newiTempLabel (NULL);
2307
2308   D (emitcode (";", "genPcall ");
2309     );
2310
2311
2312   /* if caller saves & we have not saved then */
2313   if (!ic->regsSaved)
2314     saveRegisters (ic);
2315
2316   /* if we are calling a function that is not using
2317      the same register bank then we need to save the
2318      destination registers on the stack */
2319   detype = getSpec (operandType (IC_LEFT (ic)));
2320   if (detype &&
2321       IS_ISR (currFunc->etype) &&
2322       (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)))
2323     saveRBank (SPEC_BANK (detype), ic, TRUE);
2324
2325
2326   /* push the return address on to the stack */
2327   emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2328   emitcode ("push", "acc");
2329   emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2330   emitcode ("push", "acc");
2331
2332   if (options.model == MODEL_FLAT24)
2333     {
2334       emitcode ("mov", "a,#(%05d$ >> 16)", (rlbl->key + 100));
2335       emitcode ("push", "acc");
2336     }
2337
2338   /* now push the calling address */
2339   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2340
2341   pushSide (IC_LEFT (ic), FPTRSIZE);
2342
2343   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2344
2345   /* if send set is not empty the assign */
2346   if (_G.sendSet)
2347     {
2348       iCode *sic;
2349
2350       for (sic = setFirstItem (_G.sendSet); sic;
2351            sic = setNextItem (_G.sendSet))
2352         {
2353           int size, offset = 0;
2354
2355           aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2356           size = AOP_SIZE (IC_LEFT (sic));
2357           _startLazyDPSEvaluation ();
2358           while (size--)
2359             {
2360               char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2361                                 FALSE, FALSE, TRUE);
2362               if (strcmp (l, fReturn[offset]))
2363                 {
2364                   emitcode ("mov", "%s,%s",
2365                             fReturn[offset],
2366                             l);
2367                 }
2368               offset++;
2369             }
2370           _endLazyDPSEvaluation ();
2371           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2372         }
2373       _G.sendSet = NULL;
2374     }
2375
2376   emitcode ("ret", "");
2377   emitcode ("", "%05d$:", (rlbl->key + 100));
2378
2379
2380   /* if we need assign a result value */
2381   if ((IS_ITEMP (IC_RESULT (ic)) &&
2382        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2383         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2384       IS_TRUE_SYMOP (IC_RESULT (ic)))
2385     {
2386
2387       _G.accInUse++;
2388       aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2389       _G.accInUse--;
2390
2391       assignResultValue (IC_RESULT (ic));
2392
2393       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2394     }
2395
2396   /* adjust the stack for parameters if
2397      required */
2398   if (ic->parmBytes)
2399     {
2400       int i;
2401       if (ic->parmBytes > 3)
2402         {
2403           emitcode ("mov", "a,%s", spname);
2404           emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2405           emitcode ("mov", "%s,a", spname);
2406         }
2407       else
2408         for (i = 0; i < ic->parmBytes; i++)
2409           emitcode ("dec", "%s", spname);
2410
2411     }
2412
2413   /* if register bank was saved then unsave them */
2414   if (detype &&
2415       (SPEC_BANK (currFunc->etype) !=
2416        SPEC_BANK (detype)))
2417     unsaveRBank (SPEC_BANK (detype), ic, TRUE);
2418
2419   /* if we hade saved some registers then
2420      unsave them */
2421   if (ic->regsSaved)
2422     unsaveRegisters (ic);
2423
2424 }
2425
2426 /*-----------------------------------------------------------------*/
2427 /* resultRemat - result  is rematerializable                       */
2428 /*-----------------------------------------------------------------*/
2429 static int
2430 resultRemat (iCode * ic)
2431 {
2432   if (SKIP_IC (ic) || ic->op == IFX)
2433     return 0;
2434
2435   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2436     {
2437       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2438       if (sym->remat && !POINTER_SET (ic))
2439         return 1;
2440     }
2441
2442   return 0;
2443 }
2444
2445 #if defined(__BORLANDC__) || defined(_MSC_VER)
2446 #define STRCASECMP stricmp
2447 #else
2448 #define STRCASECMP strcasecmp
2449 #endif
2450
2451 /*-----------------------------------------------------------------*/
2452 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2453 /*-----------------------------------------------------------------*/
2454 static bool
2455 inExcludeList (char *s)
2456 {
2457   int i = 0;
2458
2459   if (options.excludeRegs[i] &&
2460       STRCASECMP (options.excludeRegs[i], "none") == 0)
2461     return FALSE;
2462
2463   for (i = 0; options.excludeRegs[i]; i++)
2464     {
2465       if (options.excludeRegs[i] &&
2466           STRCASECMP (s, options.excludeRegs[i]) == 0)
2467         return TRUE;
2468     }
2469   return FALSE;
2470 }
2471
2472 /*-----------------------------------------------------------------*/
2473 /* genFunction - generated code for function entry                 */
2474 /*-----------------------------------------------------------------*/
2475 static void
2476 genFunction (iCode * ic)
2477 {
2478   symbol *sym;
2479   sym_link *fetype;
2480
2481   D (emitcode (";", "genFunction ");
2482     );
2483
2484   _G.nRegsSaved = 0;
2485   /* create the function header */
2486   emitcode (";", "-----------------------------------------");
2487   emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2488   emitcode (";", "-----------------------------------------");
2489
2490   emitcode ("", "%s:", sym->rname);
2491   fetype = getSpec (operandType (IC_LEFT (ic)));
2492
2493   /* if critical function then turn interrupts off */
2494   if (SPEC_CRTCL (fetype))
2495     emitcode ("clr", "ea");
2496
2497   /* here we need to generate the equates for the
2498      register bank if required */
2499   if (SPEC_BANK (fetype) != rbank)
2500     {
2501       int i;
2502
2503       rbank = SPEC_BANK (fetype);
2504       for (i = 0; i < ds390_nRegs; i++)
2505         {
2506           if (strcmp (regs390[i].base, "0") == 0)
2507             emitcode ("", "%s = 0x%02x",
2508                       regs390[i].dname,
2509                       8 * rbank + regs390[i].offset);
2510           else
2511             emitcode ("", "%s = %s + 0x%02x",
2512                       regs390[i].dname,
2513                       regs390[i].base,
2514                       8 * rbank + regs390[i].offset);
2515         }
2516     }
2517
2518   /* if this is an interrupt service routine then
2519      save acc, b, dpl, dph  */
2520   if (IS_ISR (sym->etype))
2521     {
2522
2523       if (!inExcludeList ("acc"))
2524         emitcode ("push", "acc");
2525       if (!inExcludeList ("b"))
2526         emitcode ("push", "b");
2527       if (!inExcludeList ("dpl"))
2528         emitcode ("push", "dpl");
2529       if (!inExcludeList ("dph"))
2530         emitcode ("push", "dph");
2531       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2532         {
2533           emitcode ("push", "dpx");
2534           /* Make sure we're using standard DPTR */
2535           emitcode ("push", "dps");
2536           emitcode ("mov", "dps, #0x00");
2537           if (options.stack10bit)
2538             {
2539               /* This ISR could conceivably use DPTR2. Better save it. */
2540               emitcode ("push", "dpl1");
2541               emitcode ("push", "dph1");
2542               emitcode ("push", "dpx1");
2543               emitcode ("push",  DP2_RESULT_REG);
2544             }
2545         }
2546       /* if this isr has no bank i.e. is going to
2547          run with bank 0 , then we need to save more
2548          registers :-) */
2549       if (!SPEC_BANK (sym->etype))
2550         {
2551
2552           /* if this function does not call any other
2553              function then we can be economical and
2554              save only those registers that are used */
2555           if (!sym->hasFcall)
2556             {
2557               int i;
2558
2559               /* if any registers used */
2560               if (sym->regsUsed)
2561                 {
2562                   /* save the registers used */
2563                   for (i = 0; i < sym->regsUsed->size; i++)
2564                     {
2565                       if (bitVectBitValue (sym->regsUsed, i) ||
2566                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2567                         emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2568                     }
2569                 }
2570
2571             }
2572           else
2573             {
2574               /* this function has  a function call cannot
2575                  determines register usage so we will have to push the
2576                  entire bank */
2577               saveRBank (0, ic, FALSE);
2578             }
2579         }
2580     }
2581   else
2582     {
2583       /* if callee-save to be used for this function
2584          then save the registers being used in this function */
2585       if (sym->calleeSave)
2586         {
2587           int i;
2588
2589           /* if any registers used */
2590           if (sym->regsUsed)
2591             {
2592               /* save the registers used */
2593               for (i = 0; i < sym->regsUsed->size; i++)
2594                 {
2595                   if (bitVectBitValue (sym->regsUsed, i) ||
2596                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2597                     {
2598                       emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2599                       _G.nRegsSaved++;
2600                     }
2601                 }
2602             }
2603         }
2604     }
2605
2606   /* set the register bank to the desired value */
2607   if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2608     {
2609       emitcode ("push", "psw");
2610       emitcode ("mov", "psw,#0x%02x", (SPEC_BANK (sym->etype) << 3) & 0x00ff);
2611     }
2612
2613   if (IS_RENT (sym->etype) || options.stackAuto)
2614     {
2615
2616       if (options.useXstack)
2617         {
2618           emitcode ("mov", "r0,%s", spname);
2619           emitcode ("mov", "a,_bp");
2620           emitcode ("movx", "@r0,a");
2621           emitcode ("inc", "%s", spname);
2622         }
2623       else
2624         {
2625           /* set up the stack */
2626           emitcode ("push", "_bp");     /* save the callers stack  */
2627         }
2628       emitcode ("mov", "_bp,%s", spname);
2629     }
2630
2631   /* adjust the stack for the function */
2632   if (sym->stack)
2633     {
2634
2635       int i = sym->stack;
2636       if (i > 256)
2637         werror (W_STACK_OVERFLOW, sym->name);
2638
2639       if (i > 3 && sym->recvSize < 4)
2640         {
2641
2642           emitcode ("mov", "a,sp");
2643           emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2644           emitcode ("mov", "sp,a");
2645
2646         }
2647       else
2648         while (i--)
2649           emitcode ("inc", "sp");
2650     }
2651
2652   if (sym->xstack)
2653     {
2654
2655       emitcode ("mov", "a,_spx");
2656       emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2657       emitcode ("mov", "_spx,a");
2658     }
2659
2660 }
2661
2662 /*-----------------------------------------------------------------*/
2663 /* genEndFunction - generates epilogue for functions               */
2664 /*-----------------------------------------------------------------*/
2665 static void
2666 genEndFunction (iCode * ic)
2667 {
2668   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2669
2670   D (emitcode (";", "genEndFunction ");
2671     );
2672
2673   if (IS_RENT (sym->etype) || options.stackAuto)
2674     {
2675       emitcode ("mov", "%s,_bp", spname);
2676     }
2677
2678   /* if use external stack but some variables were
2679      added to the local stack then decrement the
2680      local stack */
2681   if (options.useXstack && sym->stack)
2682     {
2683       emitcode ("mov", "a,sp");
2684       emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2685       emitcode ("mov", "sp,a");
2686     }
2687
2688
2689   if ((IS_RENT (sym->etype) || options.stackAuto))
2690     {
2691       if (options.useXstack)
2692         {
2693           emitcode ("mov", "r0,%s", spname);
2694           emitcode ("movx", "a,@r0");
2695           emitcode ("mov", "_bp,a");
2696           emitcode ("dec", "%s", spname);
2697         }
2698       else
2699         {
2700           emitcode ("pop", "_bp");
2701         }
2702     }
2703
2704   /* restore the register bank  */
2705   if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2706     emitcode ("pop", "psw");
2707
2708   if (IS_ISR (sym->etype))
2709     {
2710
2711       /* now we need to restore the registers */
2712       /* if this isr has no bank i.e. is going to
2713          run with bank 0 , then we need to save more
2714          registers :-) */
2715       if (!SPEC_BANK (sym->etype))
2716         {
2717
2718           /* if this function does not call any other
2719              function then we can be economical and
2720              save only those registers that are used */
2721           if (!sym->hasFcall)
2722             {
2723               int i;
2724
2725               /* if any registers used */
2726               if (sym->regsUsed)
2727                 {
2728                   /* save the registers used */
2729                   for (i = sym->regsUsed->size; i >= 0; i--)
2730                     {
2731                       if (bitVectBitValue (sym->regsUsed, i) ||
2732                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2733                         emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2734                     }
2735                 }
2736
2737             }
2738           else
2739             {
2740               /* this function has  a function call cannot
2741                  determines register usage so we will have to pop the
2742                  entire bank */
2743               unsaveRBank (0, ic, FALSE);
2744             }
2745         }
2746
2747       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2748         {
2749           if (options.stack10bit)
2750             {
2751               emitcode ("pop", DP2_RESULT_REG);
2752               emitcode ("pop", "dpx1");
2753               emitcode ("pop", "dph1");
2754               emitcode ("pop", "dpl1");
2755             }
2756           emitcode ("pop", "dps");
2757           emitcode ("pop", "dpx");
2758         }
2759       if (!inExcludeList ("dph"))
2760         emitcode ("pop", "dph");
2761       if (!inExcludeList ("dpl"))
2762         emitcode ("pop", "dpl");
2763       if (!inExcludeList ("b"))
2764         emitcode ("pop", "b");
2765       if (!inExcludeList ("acc"))
2766         emitcode ("pop", "acc");
2767
2768       if (SPEC_CRTCL (sym->etype))
2769         emitcode ("setb", "ea");
2770
2771       /* if debug then send end of function */
2772 /*  if (options.debug && currFunc) { */
2773       if (currFunc)
2774         {
2775           _G.debugLine = 1;
2776           emitcode ("", "C$%s$%d$%d$%d ==.",
2777                     FileBaseName (ic->filename), currFunc->lastLine,
2778                     ic->level, ic->block);
2779           if (IS_STATIC (currFunc->etype))
2780             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2781           else
2782             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2783           _G.debugLine = 0;
2784         }
2785
2786       emitcode ("reti", "");
2787     }
2788   else
2789     {
2790       if (SPEC_CRTCL (sym->etype))
2791         emitcode ("setb", "ea");
2792
2793       if (sym->calleeSave)
2794         {
2795           int i;
2796
2797           /* if any registers used */
2798           if (sym->regsUsed)
2799             {
2800               /* save the registers used */
2801               for (i = sym->regsUsed->size; i >= 0; i--)
2802                 {
2803                   if (bitVectBitValue (sym->regsUsed, i) ||
2804                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2805                     emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2806                 }
2807             }
2808
2809         }
2810
2811       /* if debug then send end of function */
2812       if (currFunc)
2813         {
2814           _G.debugLine = 1;
2815           emitcode ("", "C$%s$%d$%d$%d ==.",
2816                     FileBaseName (ic->filename), currFunc->lastLine,
2817                     ic->level, ic->block);
2818           if (IS_STATIC (currFunc->etype))
2819             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2820           else
2821             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2822           _G.debugLine = 0;
2823         }
2824
2825       emitcode ("ret", "");
2826     }
2827
2828 }
2829
2830 /*-----------------------------------------------------------------*/
2831 /* genRet - generate code for return statement                     */
2832 /*-----------------------------------------------------------------*/
2833 static void
2834 genRet (iCode * ic)
2835 {
2836   int size, offset = 0, pushed = 0;
2837
2838   D (emitcode (";", "genRet ");
2839     );
2840
2841   /* if we have no return value then
2842      just generate the "ret" */
2843   if (!IC_LEFT (ic))
2844     goto jumpret;
2845
2846   /* we have something to return then
2847      move the return value into place */
2848   aopOp (IC_LEFT (ic), ic, FALSE, TRUE);
2849   size = AOP_SIZE (IC_LEFT (ic));
2850
2851   _startLazyDPSEvaluation ();
2852   while (size--)
2853     {
2854       char *l;
2855       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2856         {
2857           l = aopGet (AOP (IC_LEFT (ic)), offset++,
2858                       FALSE, TRUE, FALSE);
2859           emitcode ("push", "%s", l);
2860           pushed++;
2861         }
2862       else
2863         {
2864           /* Since A is the last element of fReturn,
2865            * is is OK to clobber it in the aopGet.
2866            */
2867           l = aopGet (AOP (IC_LEFT (ic)), offset,
2868                       FALSE, FALSE, TRUE);
2869           if (strcmp (fReturn[offset], l))
2870             emitcode ("mov", "%s,%s", fReturn[offset++], l);
2871         }
2872     }
2873   _endLazyDPSEvaluation ();
2874
2875   if (pushed)
2876     {
2877       while (pushed)
2878         {
2879           pushed--;
2880           if (strcmp (fReturn[pushed], "a"))
2881             emitcode ("pop", fReturn[pushed]);
2882           else
2883             emitcode ("pop", "acc");
2884         }
2885     }
2886   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2887
2888 jumpret:
2889   /* generate a jump to the return label
2890      if the next is not the return statement */
2891   if (!(ic->next && ic->next->op == LABEL &&
2892         IC_LABEL (ic->next) == returnLabel))
2893
2894     emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2895
2896 }
2897
2898 /*-----------------------------------------------------------------*/
2899 /* genLabel - generates a label                                    */
2900 /*-----------------------------------------------------------------*/
2901 static void
2902 genLabel (iCode * ic)
2903 {
2904   /* special case never generate */
2905   if (IC_LABEL (ic) == entryLabel)
2906     return;
2907
2908   D (emitcode (";", "genLabel ");
2909     );
2910
2911   emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2912 }
2913
2914 /*-----------------------------------------------------------------*/
2915 /* genGoto - generates a ljmp                                      */
2916 /*-----------------------------------------------------------------*/
2917 static void
2918 genGoto (iCode * ic)
2919 {
2920   D (emitcode (";", "genGoto ");
2921     );
2922   emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2923 }
2924
2925 /*-----------------------------------------------------------------*/
2926 /* findLabelBackwards: walks back through the iCode chain looking  */
2927 /* for the given label. Returns number of iCode instructions     */
2928 /* between that label and given ic.          */
2929 /* Returns zero if label not found.          */
2930 /*-----------------------------------------------------------------*/
2931 static int
2932 findLabelBackwards (iCode * ic, int key)
2933 {
2934   int count = 0;
2935
2936   while (ic->prev)
2937     {
2938       ic = ic->prev;
2939       count++;
2940
2941       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2942         {
2943           /* printf("findLabelBackwards = %d\n", count); */
2944           return count;
2945         }
2946     }
2947
2948   return 0;
2949 }
2950
2951 /*-----------------------------------------------------------------*/
2952 /* genPlusIncr :- does addition with increment if possible         */
2953 /*-----------------------------------------------------------------*/
2954 static bool
2955 genPlusIncr (iCode * ic)
2956 {
2957   unsigned int icount;
2958   unsigned int size = getDataSize (IC_RESULT (ic));
2959
2960   /* will try to generate an increment */
2961   /* if the right side is not a literal
2962      we cannot */
2963   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2964     return FALSE;
2965
2966   /* if the literal value of the right hand side
2967      is greater than 4 then it is not worth it */
2968   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2969     return FALSE;
2970
2971   /* if increment 16 bits in register */
2972   if (
2973        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
2974        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
2975        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2976        (size > 1) &&
2977        (icount == 1))
2978     {
2979       symbol *tlbl;
2980       int emitTlbl;
2981       int labelRange;
2982
2983       /* If the next instruction is a goto and the goto target
2984        * is <= 5 instructions previous to this, we can generate
2985        * jumps straight to that target.
2986        */
2987       if (ic->next && ic->next->op == GOTO
2988           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2989           && labelRange <= 5)
2990         {
2991           emitcode (";", "tail increment optimized (range %d)", labelRange);
2992           tlbl = IC_LABEL (ic->next);
2993           emitTlbl = 0;
2994         }
2995       else
2996         {
2997           tlbl = newiTempLabel (NULL);
2998           emitTlbl = 1;
2999         }
3000       emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3001       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3002           IS_AOP_PREG (IC_RESULT (ic)))
3003         emitcode ("cjne", "%s,#0x00,%05d$"
3004                   ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3005                   ,tlbl->key + 100);
3006       else
3007         {
3008           emitcode ("clr", "a");
3009           emitcode ("cjne", "a,%s,%05d$"
3010                     ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3011                     ,tlbl->key + 100);
3012         }
3013
3014       emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3015       if (size > 2)
3016         {
3017           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3018               IS_AOP_PREG (IC_RESULT (ic)))
3019             emitcode ("cjne", "%s,#0x00,%05d$"
3020                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3021                       ,tlbl->key + 100);
3022           else
3023             emitcode ("cjne", "a,%s,%05d$"
3024                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3025                       ,tlbl->key + 100);
3026
3027           emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3028         }
3029       if (size > 3)
3030         {
3031           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3032               IS_AOP_PREG (IC_RESULT (ic)))
3033             emitcode ("cjne", "%s,#0x00,%05d$"
3034                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3035                       ,tlbl->key + 100);
3036           else
3037             {
3038               emitcode ("cjne", "a,%s,%05d$"
3039                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3040                         ,tlbl->key + 100);
3041             }
3042           emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3043         }
3044
3045       if (emitTlbl)
3046         {
3047           emitcode ("", "%05d$:", tlbl->key + 100);
3048         }
3049       return TRUE;
3050     }
3051
3052   /* if the sizes are greater than 1 then we cannot */
3053   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3054       AOP_SIZE (IC_LEFT (ic)) > 1)
3055     return FALSE;
3056
3057   /* we can if the aops of the left & result match or
3058      if they are in registers and the registers are the
3059      same */
3060   if (
3061        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3062        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3063        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3064     {
3065
3066       if (icount > 3)
3067         {
3068           MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3069           emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3070           aopPut (AOP (IC_RESULT (ic)), "a", 0);
3071         }
3072       else
3073         {
3074
3075           _startLazyDPSEvaluation ();
3076           while (icount--)
3077             {
3078               emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3079             }
3080           _endLazyDPSEvaluation ();
3081         }
3082
3083       return TRUE;
3084     }
3085
3086   return FALSE;
3087 }
3088
3089 /*-----------------------------------------------------------------*/
3090 /* outBitAcc - output a bit in acc                                 */
3091 /*-----------------------------------------------------------------*/
3092 static void
3093 outBitAcc (operand * result)
3094 {
3095   symbol *tlbl = newiTempLabel (NULL);
3096   /* if the result is a bit */
3097   if (AOP_TYPE (result) == AOP_CRY)
3098     {
3099       aopPut (AOP (result), "a", 0);
3100     }
3101   else
3102     {
3103       emitcode ("jz", "%05d$", tlbl->key + 100);
3104       emitcode ("mov", "a,%s", one);
3105       emitcode ("", "%05d$:", tlbl->key + 100);
3106       outAcc (result);
3107     }
3108 }
3109
3110 /*-----------------------------------------------------------------*/
3111 /* genPlusBits - generates code for addition of two bits           */
3112 /*-----------------------------------------------------------------*/
3113 static void
3114 genPlusBits (iCode * ic)
3115 {
3116   D (emitcode (";", "genPlusBits ");
3117     );
3118   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3119     {
3120       symbol *lbl = newiTempLabel (NULL);
3121       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3122       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3123       emitcode ("cpl", "c");
3124       emitcode ("", "%05d$:", (lbl->key + 100));
3125       outBitC (IC_RESULT (ic));
3126     }
3127   else
3128     {
3129       emitcode ("clr", "a");
3130       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3131       emitcode ("rlc", "a");
3132       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3133       emitcode ("addc", "a,#0x00");
3134       outAcc (IC_RESULT (ic));
3135     }
3136 }
3137
3138 static void
3139 adjustArithmeticResult (iCode * ic)
3140 {
3141   if (opIsGptr (IC_RESULT (ic)) &&
3142       opIsGptr (IC_LEFT (ic)) &&
3143       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3144     {
3145       aopPut (AOP (IC_RESULT (ic)),
3146               aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3147               GPTRSIZE - 1);
3148     }
3149
3150   if (opIsGptr (IC_RESULT (ic)) &&
3151       opIsGptr (IC_RIGHT (ic)) &&
3152       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3153     {
3154       aopPut (AOP (IC_RESULT (ic)),
3155             aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3156               GPTRSIZE - 1);
3157     }
3158
3159   if (opIsGptr (IC_RESULT (ic)) &&
3160       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3161       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3162       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3163       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3164     {
3165       char buffer[5];
3166       sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3167       aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3168     }
3169 }
3170
3171 // Macro to aopOp all three operands of an ic. Will fatal if this cannot be done
3172 // (because all three operands are in far space).
3173 #define AOP_OP_3(ic) \
3174     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3175     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3176     aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3177               (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3178     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3179         AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3180     { \
3181         /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3182         fprintf(stderr,                                  \
3183                "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno);   \
3184     }
3185
3186 // Macro to aopOp all three operands of an ic. If this cannot be done, 
3187 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3188 // will be set TRUE. The caller must then handle the case specially, noting
3189 // that the IC_RESULT operand is not aopOp'd.
3190 #define AOP_OP_3_NOFATAL(ic, rc) \
3191     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3192     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3193     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3194         isOperandInFarSpace(IC_RESULT(ic))) \
3195     { \
3196        /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3197        rc = TRUE; \
3198     }  \
3199     else \
3200     { \
3201        aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3202                                      (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3203        rc = FALSE; \
3204        if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3205            AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3206        { \
3207             /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3208             fprintf(stderr,                                  \
3209                     "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno);   \
3210        } \
3211     }
3212
3213 // aopOp the left & right operands of an ic.
3214 #define AOP_OP_2(ic) \
3215     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3216     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3217
3218 // convienience macro.
3219 #define AOP_SET_LOCALS(ic) \
3220     left = IC_LEFT(ic); \
3221     right = IC_RIGHT(ic); \
3222     result = IC_RESULT(ic);
3223
3224
3225 // Given an integer value of pushedSize bytes on the stack,
3226 // adjust it to be resultSize bytes, either by discarding
3227 // the most significant bytes or by zero-padding.
3228 //
3229 // On exit from this macro, pushedSize will have been adjusted to
3230 // equal resultSize, and ACC may be trashed.
3231 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize)            \
3232       /* If the pushed data is bigger than the result,          \
3233        * simply discard unused bytes. Icky, but works.          \
3234        */                                                       \
3235       while (pushedSize > resultSize)                           \
3236       {                                                         \
3237           D (emitcode (";", "discarding unused result byte."););\
3238           emitcode ("pop", "acc");                              \
3239           pushedSize--;                                         \
3240       }                                                         \
3241       if (pushedSize < resultSize)                              \
3242       {                                                         \
3243           emitcode ("clr", "a");                                \
3244           /* Conversly, we haven't pushed enough here.          \
3245            * just zero-pad, and all is well.                    \
3246            */                                                   \
3247           while (pushedSize < resultSize)                       \
3248           {                                                     \
3249               emitcode("push", "acc");                          \
3250               pushedSize++;                                     \
3251           }                                                     \
3252       }                                                         \
3253       assert(pushedSize == resultSize);
3254
3255 /*-----------------------------------------------------------------*/
3256 /* genPlus - generates code for addition                           */
3257 /*-----------------------------------------------------------------*/
3258 static void
3259 genPlus (iCode * ic)
3260 {
3261   int size, offset = 0;
3262   bool pushResult = FALSE;
3263   int rSize;
3264
3265   D (emitcode (";", "genPlus "););
3266
3267   /* special cases :- */
3268
3269   AOP_OP_3_NOFATAL (ic, pushResult);
3270   if (pushResult)
3271     {
3272       D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3273     }
3274
3275   if (!pushResult)
3276     {
3277       /* if literal, literal on the right or
3278          if left requires ACC or right is already
3279          in ACC */
3280       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3281        || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3282           || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3283         {
3284           operand *t = IC_RIGHT (ic);
3285           IC_RIGHT (ic) = IC_LEFT (ic);
3286           IC_LEFT (ic) = t;
3287           emitcode (";", "Swapped plus args.");
3288         }
3289
3290       /* if both left & right are in bit
3291          space */
3292       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3293           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3294         {
3295           genPlusBits (ic);
3296           goto release;
3297         }
3298
3299       /* if left in bit space & right literal */
3300       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3301           AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3302         {
3303           emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3304           /* if result in bit space */
3305           if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3306             {
3307               if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3308                 emitcode ("cpl", "c");
3309               outBitC (IC_RESULT (ic));
3310             }
3311           else
3312             {
3313               size = getDataSize (IC_RESULT (ic));
3314               _startLazyDPSEvaluation ();
3315               while (size--)
3316                 {
3317                   MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3318                   emitcode ("addc", "a,#00");
3319                   aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3320                 }
3321               _endLazyDPSEvaluation ();
3322             }
3323           goto release;
3324         }
3325
3326       /* if I can do an increment instead
3327          of add then GOOD for ME */
3328       if (genPlusIncr (ic) == TRUE)
3329         {
3330           emitcode (";", "did genPlusIncr");
3331           goto release;
3332         }
3333
3334     }
3335   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3336
3337   _startLazyDPSEvaluation ();
3338   while (size--)
3339     {
3340       if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
3341         {
3342           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3343           if (offset == 0)
3344             emitcode ("add", "a,%s",
3345                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3346           else
3347             emitcode ("addc", "a,%s",
3348                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3349         }
3350       else
3351         {
3352           if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
3353           {
3354               /* right is going to use ACC or we would have taken the
3355                * above branch.
3356                */
3357               assert(AOP_NEEDSACC(IC_RIGHT(ic)));
3358               D(emitcode(";", "+ AOP_ACC special case."););
3359               emitcode("xch", "a, %s", DP2_RESULT_REG);
3360           }
3361           MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3362           if (offset == 0)
3363           {
3364             if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
3365             {
3366                 emitcode("add", "a, %s", DP2_RESULT_REG); 
3367             }
3368             else
3369             {
3370                 emitcode ("add", "a,%s",
3371                         aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE, FALSE));
3372             }
3373           }
3374           else
3375           {
3376             emitcode ("addc", "a,%s",
3377                   aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3378           }
3379         }
3380       if (!pushResult)
3381         {
3382           aopPut (AOP (IC_RESULT (ic)), "a", offset);
3383         }
3384       else
3385         {
3386           emitcode ("push", "acc");
3387         }
3388       offset++;
3389     }
3390   _endLazyDPSEvaluation ();
3391
3392   if (pushResult)
3393     {
3394       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3395
3396       size = getDataSize (IC_LEFT (ic));
3397       rSize = getDataSize (IC_RESULT (ic));
3398
3399       ADJUST_PUSHED_RESULT(size, rSize);
3400
3401       _startLazyDPSEvaluation ();
3402       while (size--)
3403         {
3404           emitcode ("pop", "acc");
3405           aopPut (AOP (IC_RESULT (ic)), "a", size);
3406         }
3407       _endLazyDPSEvaluation ();
3408     }
3409
3410   adjustArithmeticResult (ic);
3411
3412 release:
3413   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3414   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3415   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3416 }
3417
3418 /*-----------------------------------------------------------------*/
3419 /* genMinusDec :- does subtraction with deccrement if possible     */
3420 /*-----------------------------------------------------------------*/
3421 static bool
3422 genMinusDec (iCode * ic)
3423 {
3424   unsigned int icount;
3425   unsigned int size = getDataSize (IC_RESULT (ic));
3426
3427   /* will try to generate an increment */
3428   /* if the right side is not a literal
3429      we cannot */
3430   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3431     return FALSE;
3432
3433   /* if the literal value of the right hand side
3434      is greater than 4 then it is not worth it */
3435   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3436     return FALSE;
3437
3438   /* if decrement 16 bits in register */
3439   if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3440       AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3441       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3442       (size > 1) &&
3443       (icount == 1))
3444     {
3445       symbol *tlbl;
3446       int emitTlbl;
3447       int labelRange;
3448
3449       /* If the next instruction is a goto and the goto target
3450          * is <= 5 instructions previous to this, we can generate
3451          * jumps straight to that target.
3452        */
3453       if (ic->next && ic->next->op == GOTO
3454           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3455           && labelRange <= 5)
3456         {
3457           emitcode (";", "tail decrement optimized (range %d)", labelRange);
3458           tlbl = IC_LABEL (ic->next);
3459           emitTlbl = 0;
3460         }
3461       else
3462         {
3463           tlbl = newiTempLabel (NULL);
3464           emitTlbl = 1;
3465         }
3466
3467       emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3468       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3469           AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3470           IS_AOP_PREG (IC_RESULT (ic)))
3471         emitcode ("cjne", "%s,#0xff,%05d$"
3472                   ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3473                   ,tlbl->key + 100);
3474       else
3475         {
3476           emitcode ("mov", "a,#0xff");
3477           emitcode ("cjne", "a,%s,%05d$"
3478                     ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3479                     ,tlbl->key + 100);
3480         }
3481       emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3482       if (size > 2)
3483         {
3484           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3485               AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3486               IS_AOP_PREG (IC_RESULT (ic)))
3487             emitcode ("cjne", "%s,#0xff,%05d$"
3488                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3489                       ,tlbl->key + 100);
3490           else
3491             {
3492               emitcode ("cjne", "a,%s,%05d$"
3493                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3494                         ,tlbl->key + 100);
3495             }
3496           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3497         }
3498       if (size > 3)
3499         {
3500           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3501               AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3502               IS_AOP_PREG (IC_RESULT (ic)))
3503             emitcode ("cjne", "%s,#0xff,%05d$"
3504                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3505                       ,tlbl->key + 100);
3506           else
3507             {
3508               emitcode ("cjne", "a,%s,%05d$"
3509                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3510                         ,tlbl->key + 100);
3511             }
3512           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3513         }
3514       if (emitTlbl)
3515         {
3516           emitcode ("", "%05d$:", tlbl->key + 100);
3517         }
3518       return TRUE;
3519     }
3520
3521   /* if the sizes are greater than 1 then we cannot */
3522   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3523       AOP_SIZE (IC_LEFT (ic)) > 1)
3524     return FALSE;
3525
3526   /* we can if the aops of the left & result match or
3527      if they are in registers and the registers are the
3528      same */
3529   if (
3530        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3531        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3532        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3533     {
3534
3535       _startLazyDPSEvaluation ();
3536       while (icount--)
3537         {
3538           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
3539         }
3540       _endLazyDPSEvaluation ();
3541
3542       return TRUE;
3543     }
3544
3545   return FALSE;
3546 }
3547
3548 /*-----------------------------------------------------------------*/
3549 /* addSign - complete with sign                                    */
3550 /*-----------------------------------------------------------------*/
3551 static void
3552 addSign (operand * result, int offset, int sign)
3553 {
3554   int size = (getDataSize (result) - offset);
3555   if (size > 0)
3556     {
3557       _startLazyDPSEvaluation();
3558       if (sign)
3559         {
3560           emitcode ("rlc", "a");
3561           emitcode ("subb", "a,acc");
3562           while (size--)
3563           {
3564             aopPut (AOP (result), "a", offset++);
3565           }
3566         }
3567       else
3568       {
3569         while (size--)
3570         {
3571           aopPut (AOP (result), zero, offset++);
3572         }
3573       }
3574       _endLazyDPSEvaluation();
3575     }
3576 }
3577
3578 /*-----------------------------------------------------------------*/
3579 /* genMinusBits - generates code for subtraction  of two bits      */
3580 /*-----------------------------------------------------------------*/
3581 static void
3582 genMinusBits (iCode * ic)
3583 {
3584   symbol *lbl = newiTempLabel (NULL);
3585
3586   D (emitcode (";", "genMinusBits "););
3587
3588   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3589     {
3590       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3591       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3592       emitcode ("cpl", "c");
3593       emitcode ("", "%05d$:", (lbl->key + 100));
3594       outBitC (IC_RESULT (ic));
3595     }
3596   else
3597     {
3598       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3599       emitcode ("subb", "a,acc");
3600       emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3601       emitcode ("inc", "a");
3602       emitcode ("", "%05d$:", (lbl->key + 100));
3603       aopPut (AOP (IC_RESULT (ic)), "a", 0);
3604       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3605     }
3606 }
3607
3608 /*-----------------------------------------------------------------*/
3609 /* genMinus - generates code for subtraction                       */
3610 /*-----------------------------------------------------------------*/
3611 static void
3612 genMinus (iCode * ic)
3613 {
3614   int size, offset = 0;
3615   int rSize;
3616   unsigned long lit = 0L;
3617   bool pushResult = FALSE;
3618
3619   D (emitcode (";", "genMinus "););
3620
3621   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3622   aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
3623   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
3624       (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
3625     {
3626       pushResult = TRUE;
3627     }
3628   else
3629     {
3630       aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
3631
3632       /* special cases :- */
3633       /* if both left & right are in bit space */
3634       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3635           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3636         {
3637           genMinusBits (ic);
3638           goto release;
3639         }
3640
3641       /* if I can do an decrement instead
3642          of subtract then GOOD for ME */
3643       if (genMinusDec (ic) == TRUE)
3644         goto release;
3645
3646     }
3647
3648   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3649
3650   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3651     {
3652       CLRC;
3653     }
3654   else
3655     {
3656       lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3657       lit = -(long) lit;
3658     }
3659
3660
3661   /* if literal, add a,#-lit, else normal subb */
3662   _startLazyDPSEvaluation ();
3663   while (size--)
3664     {
3665       MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3666       if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3667         emitcode ("subb", "a,%s",
3668                   aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3669       else
3670         {
3671           /* first add without previous c */
3672           if (!offset)
3673             emitcode ("add", "a,#0x%02x",
3674                       (unsigned int) (lit & 0x0FFL));
3675           else
3676             emitcode ("addc", "a,#0x%02x",
3677                       (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3678         }
3679
3680       if (pushResult)
3681         {
3682           emitcode ("push", "acc");
3683         }
3684       else
3685         {
3686           aopPut (AOP (IC_RESULT (ic)), "a", offset);
3687         }
3688       offset++;
3689     }
3690   _endLazyDPSEvaluation ();
3691
3692   if (pushResult)
3693     {
3694       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3695
3696       size = getDataSize (IC_LEFT (ic));
3697       rSize = getDataSize (IC_RESULT (ic));
3698
3699       ADJUST_PUSHED_RESULT(size, rSize);
3700
3701       _startLazyDPSEvaluation ();
3702       while (size--)
3703         {
3704           emitcode ("pop", "acc");
3705           aopPut (AOP (IC_RESULT (ic)), "a", size);
3706         }
3707       _endLazyDPSEvaluation ();
3708     }
3709
3710   adjustArithmeticResult (ic);
3711
3712 release:
3713   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3714   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3715   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3716 }
3717
3718
3719 /*-----------------------------------------------------------------*/
3720 /* genMultbits :- multiplication of bits                           */
3721 /*-----------------------------------------------------------------*/
3722 static void
3723 genMultbits (operand * left,
3724              operand * right,
3725              operand * result)
3726 {
3727   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3728   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3729   outBitC (result);
3730 }
3731
3732
3733 /*-----------------------------------------------------------------*/
3734 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
3735 /*-----------------------------------------------------------------*/
3736 static void
3737 genMultOneByte (operand * left,
3738                 operand * right,
3739                 operand * result)
3740 {
3741   sym_link *opetype = operandType (result);
3742   symbol *lbl;
3743   int size=AOP_SIZE(result);
3744
3745   if (size<1 || size>2) {
3746     // this should never happen
3747       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
3748                AOP_SIZE(result), __FILE__, lineno);
3749       exit (1);
3750   }
3751
3752   /* (if two literals: the value is computed before) */
3753   /* if one literal, literal on the right */
3754   if (AOP_TYPE (left) == AOP_LIT)
3755     {
3756       operand *t = right;
3757       right = left;
3758       left = t;
3759       emitcode (";", "swapped left and right");
3760     }
3761
3762   if (SPEC_USIGN(opetype)
3763       // ignore the sign of left and right, what else can we do?
3764       || (SPEC_USIGN(operandType(left)) && 
3765           SPEC_USIGN(operandType(right)))) {
3766     // just an unsigned 8*8=8/16 multiply
3767     //emitcode (";","unsigned");
3768     emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3769     MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3770     emitcode ("mul", "ab");
3771     aopPut (AOP (result), "a", 0);
3772     if (size==2) {
3773       aopPut (AOP (result), "b", 1);
3774     }
3775     return;
3776   }
3777
3778   // we have to do a signed multiply
3779
3780   emitcode (";", "signed");
3781   emitcode ("clr", "F0"); // reset sign flag
3782   emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3783   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3784
3785   lbl=newiTempLabel(NULL);
3786   emitcode ("jnb", "acc.7,%05d$",  lbl->key+100);
3787   // left side is negative, 8-bit two's complement, this fails for -128
3788   emitcode ("setb", "F0"); // set sign flag
3789   emitcode ("cpl", "a");
3790   emitcode ("inc", "a");
3791
3792   emitcode ("", "%05d$:", lbl->key+100);
3793   emitcode ("xch", "a,b");
3794
3795   /* if literal */
3796   if (AOP_TYPE(right)==AOP_LIT) {
3797     /* AND literal negative */
3798     if ((int) floatFromVal (AOP (right)->aopu.aop_lit) < 0) {
3799       // two's complement for literal<0
3800       emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
3801       emitcode ("cpl", "a");
3802       emitcode ("inc", "a");
3803     }
3804   } else {
3805     lbl=newiTempLabel(NULL);
3806     emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3807     // right side is negative, 8-bit two's complement
3808     emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
3809     emitcode ("cpl", "a");
3810     emitcode ("inc", "a");
3811     emitcode ("", "%05d$:", lbl->key+100);
3812   }
3813   emitcode ("mul", "ab");
3814     
3815   lbl=newiTempLabel(NULL);
3816   emitcode ("jnb", "F0,%05d$", lbl->key+100);
3817   // only ONE op was negative, we have to do a 8/16-bit two's complement
3818   emitcode ("cpl", "a"); // lsb
3819   if (size==1) {
3820     emitcode ("inc", "a");
3821   } else {
3822     emitcode ("add", "a,#1");
3823     emitcode ("xch", "a,b");
3824     emitcode ("cpl", "a"); // msb
3825     emitcode ("addc", "a,#0");
3826     emitcode ("xch", "a,b");
3827   }
3828
3829   emitcode ("", "%05d$:", lbl->key+100);
3830   aopPut (AOP (result), "a", 0);
3831   if (size==2) {
3832     aopPut (AOP (result), "b", 1);
3833   }
3834 }
3835
3836 /*-----------------------------------------------------------------*/
3837 /* genMult - generates code for multiplication                     */
3838 /*-----------------------------------------------------------------*/
3839 static void
3840 genMult (iCode * ic)
3841 {
3842   operand *left = IC_LEFT (ic);
3843   operand *right = IC_RIGHT (ic);
3844   operand *result = IC_RESULT (ic);
3845
3846   D (emitcode (";", "genMult "););
3847
3848   /* assign the amsops */
3849   AOP_OP_3 (ic);
3850
3851   /* special cases first */
3852   /* both are bits */
3853   if (AOP_TYPE (left) == AOP_CRY &&
3854       AOP_TYPE (right) == AOP_CRY)
3855     {
3856       genMultbits (left, right, result);
3857       goto release;
3858     }
3859
3860   /* if both are of size == 1 */
3861   if (AOP_SIZE (left) == 1 &&
3862       AOP_SIZE (right) == 1)
3863     {
3864       genMultOneByte (left, right, result);
3865       goto release;
3866     }
3867
3868   /* should have been converted to function call */
3869   assert (1);
3870
3871 release:
3872   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3873   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3874   freeAsmop (result, NULL, ic, TRUE);
3875 }
3876
3877 /*-----------------------------------------------------------------*/
3878 /* genDivbits :- division of bits                                  */
3879 /*-----------------------------------------------------------------*/
3880 static void
3881 genDivbits (operand * left,
3882             operand * right,
3883             operand * result)
3884 {
3885
3886   char *l;
3887
3888   /* the result must be bit */
3889   LOAD_AB_FOR_DIV (left, right, l);
3890   emitcode ("div", "ab");
3891   emitcode ("rrc", "a");
3892   aopPut (AOP (result), "c", 0);
3893 }
3894
3895 /*-----------------------------------------------------------------*/
3896 /* genDivOneByte : 8 bit division                                  */
3897 /*-----------------------------------------------------------------*/
3898 static void
3899 genDivOneByte (operand * left,
3900                operand * right,
3901                operand * result)
3902 {
3903   sym_link *opetype = operandType (result);
3904   char *l;
3905   symbol *lbl;
3906   int size, offset;
3907
3908   size = AOP_SIZE (result) - 1;
3909   offset = 1;
3910   /* signed or unsigned */
3911   if (SPEC_USIGN (opetype))
3912     {
3913       /* unsigned is easy */
3914       LOAD_AB_FOR_DIV (left, right, l);
3915       emitcode ("div", "ab");
3916       aopPut (AOP (result), "a", 0);
3917       while (size--)
3918         aopPut (AOP (result), zero, offset++);
3919       return;
3920     }
3921
3922   /* signed is a little bit more difficult */
3923
3924   /* save the signs of the operands */
3925   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
3926   MOVA (l);
3927   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
3928   emitcode ("push", "acc");     /* save it on the stack */
3929
3930   /* now sign adjust for both left & right */
3931   l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
3932   MOVA (l);
3933   lbl = newiTempLabel (NULL);
3934   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3935   emitcode ("cpl", "a");
3936   emitcode ("inc", "a");
3937   emitcode ("", "%05d$:", (lbl->key + 100));
3938   emitcode ("mov", "b,a");
3939
3940   /* sign adjust left side */
3941   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
3942   MOVA (l);
3943
3944   lbl = newiTempLabel (NULL);
3945   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3946   emitcode ("cpl", "a");
3947   emitcode ("inc", "a");
3948   emitcode ("", "%05d$:", (lbl->key + 100));
3949
3950   /* now the division */
3951   emitcode ("nop", "; workaround for DS80C390 div bug.");
3952   emitcode ("div", "ab");
3953   /* we are interested in the lower order
3954      only */
3955   emitcode ("mov", "b,a");
3956   lbl = newiTempLabel (NULL);
3957   emitcode ("pop", "acc");
3958   /* if there was an over flow we don't
3959      adjust the sign of the result */
3960   emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3961   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3962   CLRC;
3963   emitcode ("clr", "a");
3964   emitcode ("subb", "a,b");
3965   emitcode ("mov", "b,a");
3966   emitcode ("", "%05d$:", (lbl->key + 100));
3967
3968   /* now we are done */
3969   aopPut (AOP (result), "b", 0);
3970   if (size > 0)
3971     {
3972       emitcode ("mov", "c,b.7");
3973       emitcode ("subb", "a,acc");
3974     }
3975   while (size--)
3976     aopPut (AOP (result), "a", offset++);
3977
3978 }
3979
3980 /*-----------------------------------------------------------------*/
3981 /* genDiv - generates code for division                            */
3982 /*-----------------------------------------------------------------*/
3983 static void
3984 genDiv (iCode * ic)
3985 {
3986   operand *left = IC_LEFT (ic);
3987   operand *right = IC_RIGHT (ic);
3988   operand *result = IC_RESULT (ic);
3989
3990   D (emitcode (";", "genDiv ");
3991     );
3992
3993   /* assign the amsops */
3994   AOP_OP_3 (ic);
3995
3996   /* special cases first */
3997   /* both are bits */
3998   if (AOP_TYPE (left) == AOP_CRY &&
3999       AOP_TYPE (right) == AOP_CRY)
4000     {
4001       genDivbits (left, right, result);
4002       goto release;
4003     }
4004
4005   /* if both are of size == 1 */
4006   if (AOP_SIZE (left) == 1 &&
4007       AOP_SIZE (right) == 1)
4008     {
4009       genDivOneByte (left, right, result);
4010       goto release;
4011     }
4012
4013   /* should have been converted to function call */
4014   assert (1);
4015 release:
4016   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4017   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4018   freeAsmop (result, NULL, ic, TRUE);
4019 }
4020
4021 /*-----------------------------------------------------------------*/
4022 /* genModbits :- modulus of bits                                   */
4023 /*-----------------------------------------------------------------*/
4024 static void
4025 genModbits (operand * left,
4026             operand * right,
4027             operand * result)
4028 {
4029
4030   char *l;
4031
4032   /* the result must be bit */
4033   LOAD_AB_FOR_DIV (left, right, l);
4034   emitcode ("div", "ab");
4035   emitcode ("mov", "a,b");
4036   emitcode ("rrc", "a");
4037   aopPut (AOP (result), "c", 0);
4038 }
4039
4040 /*-----------------------------------------------------------------*/
4041 /* genModOneByte : 8 bit modulus                                   */
4042 /*-----------------------------------------------------------------*/
4043 static void
4044 genModOneByte (operand * left,
4045                operand * right,
4046                operand * result)
4047 {
4048   sym_link *opetype = operandType (result);
4049   char *l;
4050   symbol *lbl;
4051
4052   /* signed or unsigned */
4053   if (SPEC_USIGN (opetype))
4054     {
4055       /* unsigned is easy */
4056       LOAD_AB_FOR_DIV (left, right, l);
4057       emitcode ("div", "ab");
4058       aopPut (AOP (result), "b", 0);
4059       return;
4060     }
4061
4062   /* signed is a little bit more difficult */
4063
4064   /* save the signs of the operands */
4065   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4066   MOVA (l);
4067
4068   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4069   emitcode ("push", "acc");     /* save it on the stack */
4070
4071   /* now sign adjust for both left & right */
4072   l = aopGet (AOP (right), 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   emitcode ("mov", "b,a");
4081
4082   /* sign adjust left side */
4083   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4084   MOVA (l);
4085
4086   lbl = newiTempLabel (NULL);
4087   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4088   emitcode ("cpl", "a");
4089   emitcode ("inc", "a");
4090   emitcode ("", "%05d$:", (lbl->key + 100));
4091
4092   /* now the multiplication */
4093   emitcode ("nop", "; workaround for DS80C390 div bug.");
4094   emitcode ("div", "ab");
4095   /* we are interested in the lower order
4096      only */
4097   lbl = newiTempLabel (NULL);
4098   emitcode ("pop", "acc");
4099   /* if there was an over flow we don't
4100      adjust the sign of the result */
4101   emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4102   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4103   CLRC;
4104   emitcode ("clr", "a");
4105   emitcode ("subb", "a,b");
4106   emitcode ("mov", "b,a");
4107   emitcode ("", "%05d$:", (lbl->key + 100));
4108
4109   /* now we are done */
4110   aopPut (AOP (result), "b", 0);
4111
4112 }
4113
4114 /*-----------------------------------------------------------------*/
4115 /* genMod - generates code for division                            */
4116 /*-----------------------------------------------------------------*/
4117 static void
4118 genMod (iCode * ic)
4119 {
4120   operand *left = IC_LEFT (ic);
4121   operand *right = IC_RIGHT (ic);
4122   operand *result = IC_RESULT (ic);
4123
4124   D (emitcode (";", "genMod ");
4125     );
4126
4127   /* assign the amsops */
4128   AOP_OP_3 (ic);
4129
4130   /* special cases first */
4131   /* both are bits */
4132   if (AOP_TYPE (left) == AOP_CRY &&
4133       AOP_TYPE (right) == AOP_CRY)
4134     {
4135       genModbits (left, right, result);
4136       goto release;
4137     }
4138
4139   /* if both are of size == 1 */
4140   if (AOP_SIZE (left) == 1 &&
4141       AOP_SIZE (right) == 1)
4142     {
4143       genModOneByte (left, right, result);
4144       goto release;
4145     }
4146
4147   /* should have been converted to function call */
4148   assert (1);
4149
4150 release:
4151   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4152   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4153   freeAsmop (result, NULL, ic, TRUE);
4154 }
4155
4156 /*-----------------------------------------------------------------*/
4157 /* genIfxJump :- will create a jump depending on the ifx           */
4158 /*-----------------------------------------------------------------*/
4159 static void
4160 genIfxJump (iCode * ic, char *jval)
4161 {
4162   symbol *jlbl;
4163   symbol *tlbl = newiTempLabel (NULL);
4164   char *inst;
4165
4166   D (emitcode (";", "genIfxJump ");
4167     );
4168
4169   /* if true label then we jump if condition
4170      supplied is true */
4171   if (IC_TRUE (ic))
4172     {
4173       jlbl = IC_TRUE (ic);
4174       inst = ((strcmp (jval, "a") == 0 ? "jz" :
4175                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4176     }
4177   else
4178     {
4179       /* false label is present */
4180       jlbl = IC_FALSE (ic);
4181       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4182                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4183     }
4184   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4185     emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4186   else
4187     emitcode (inst, "%05d$", tlbl->key + 100);
4188   emitcode ("ljmp", "%05d$", jlbl->key + 100);
4189   emitcode ("", "%05d$:", tlbl->key + 100);
4190
4191   /* mark the icode as generated */
4192   ic->generated = 1;
4193 }
4194
4195 /*-----------------------------------------------------------------*/
4196 /* genCmp :- greater or less than comparison                       */
4197 /*-----------------------------------------------------------------*/
4198 static void
4199 genCmp (operand * left, operand * right,
4200         iCode * ic, iCode * ifx, int sign)
4201 {
4202   int size, offset = 0;
4203   unsigned long lit = 0L;
4204   operand *result;
4205
4206   D (emitcode (";", "genCmp");
4207     );
4208
4209   result = IC_RESULT (ic);
4210
4211   /* if left & right are bit variables */
4212   if (AOP_TYPE (left) == AOP_CRY &&
4213       AOP_TYPE (right) == AOP_CRY)
4214     {
4215       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4216       emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
4217     }
4218   else
4219     {
4220       /* subtract right from left if at the
4221          end the carry flag is set then we know that
4222          left is greater than right */
4223       size = max (AOP_SIZE (left), AOP_SIZE (right));
4224
4225       /* if unsigned char cmp with lit, do cjne left,#right,zz */
4226       if ((size == 1) && !sign &&
4227           (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4228         {
4229           symbol *lbl = newiTempLabel (NULL);
4230           emitcode ("cjne", "%s,%s,%05d$",
4231                     aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
4232                     aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4233                     lbl->key + 100);
4234           emitcode ("", "%05d$:", lbl->key + 100);
4235         }
4236       else
4237         {
4238           if (AOP_TYPE (right) == AOP_LIT)
4239             {
4240               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4241               /* optimize if(x < 0) or if(x >= 0) */
4242               if (lit == 0L)
4243                 {
4244                   if (!sign)
4245                     {
4246                       CLRC;
4247                     }
4248                   else
4249                     {
4250                       MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
4251
4252                       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4253                       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4254
4255                       aopOp (result, ic, FALSE, FALSE);
4256
4257                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4258                         {
4259                           freeAsmop (result, NULL, ic, TRUE);
4260                           genIfxJump (ifx, "acc.7");
4261                           return;
4262                         }
4263                       else
4264                         {
4265                           emitcode ("rlc", "a");
4266                         }
4267                       goto release_freedLR;
4268                     }
4269                   goto release;
4270                 }
4271             }
4272           CLRC;
4273           while (size--)
4274             {
4275               emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
4276               MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4277               emitcode (";", "genCmp #2");
4278               if (sign && (size == 0))
4279                 {
4280                   emitcode (";", "genCmp #3");
4281                   emitcode ("xrl", "a,#0x80");
4282                   if (AOP_TYPE (right) == AOP_LIT)
4283                     {
4284                       unsigned long lit = (unsigned long)
4285                       floatFromVal (AOP (right)->aopu.aop_lit);
4286                       emitcode (";", "genCmp #3.1");
4287                       emitcode ("subb", "a,#0x%02x",
4288                                 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4289                     }
4290                   else
4291                     {
4292                       emitcode (";", "genCmp #3.2");
4293                       if (AOP_NEEDSACC (right))
4294                         {
4295                           emitcode ("push", "acc");
4296                         }
4297                       emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
4298                                                        FALSE, FALSE, FALSE));
4299                       emitcode ("xrl", "b,#0x80");
4300                       if (AOP_NEEDSACC (right))
4301                         {
4302                           emitcode ("pop", "acc");
4303                         }
4304                       emitcode ("subb", "a,b");
4305                     }
4306                 }
4307               else
4308                 {
4309                   const char *s;
4310
4311                   emitcode (";", "genCmp #4");
4312                   if (AOP_NEEDSACC (right))
4313                     {
4314                       /* Yuck!! */
4315                       emitcode (";", "genCmp #4.1");
4316                       emitcode ("xch", "a, b");
4317                       MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
4318                       emitcode ("xch", "a, b");
4319                       s = "b";
4320                     }
4321                   else
4322                     {
4323                       emitcode (";", "genCmp #4.2");
4324                       s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
4325                     }
4326
4327                   emitcode ("subb", "a,%s", s);
4328                 }
4329             }
4330         }
4331     }
4332
4333 release:
4334 /* Don't need the left & right operands any more; do need the result. */
4335   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4336   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4337
4338   aopOp (result, ic, FALSE, FALSE);
4339
4340 release_freedLR:
4341
4342   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4343     {
4344       outBitC (result);
4345     }
4346   else
4347     {
4348       /* if the result is used in the next
4349          ifx conditional branch then generate
4350          code a little differently */
4351       if (ifx)
4352         {
4353           genIfxJump (ifx, "c");
4354         }
4355       else
4356         {
4357           outBitC (result);
4358         }
4359       /* leave the result in acc */
4360     }
4361   freeAsmop (result, NULL, ic, TRUE);
4362 }
4363
4364 /*-----------------------------------------------------------------*/
4365 /* genCmpGt :- greater than comparison                             */
4366 /*-----------------------------------------------------------------*/
4367 static void
4368 genCmpGt (iCode * ic, iCode * ifx)
4369 {
4370   operand *left, *right;
4371   sym_link *letype, *retype;
4372   int sign;
4373
4374   D (emitcode (";", "genCmpGt ");
4375     );
4376
4377   left = IC_LEFT (ic);
4378   right = IC_RIGHT (ic);
4379
4380   letype = getSpec (operandType (left));
4381   retype = getSpec (operandType (right));
4382   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4383
4384   /* assign the left & right amsops */
4385   AOP_OP_2 (ic);
4386
4387   genCmp (right, left, ic, ifx, sign);
4388 }
4389
4390 /*-----------------------------------------------------------------*/
4391 /* genCmpLt - less than comparisons                                */
4392 /*-----------------------------------------------------------------*/
4393 static void
4394 genCmpLt (iCode * ic, iCode * ifx)
4395 {
4396   operand *left, *right;
4397   sym_link *letype, *retype;
4398   int sign;
4399
4400   D (emitcode (";", "genCmpLt "););
4401
4402   left = IC_LEFT (ic);
4403   right = IC_RIGHT (ic);
4404
4405   letype = getSpec (operandType (left));
4406   retype = getSpec (operandType (right));
4407   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4408
4409   /* assign the left & right amsops */
4410   AOP_OP_2 (ic);
4411
4412   genCmp (left, right, ic, ifx, sign);
4413 }
4414
4415 /*-----------------------------------------------------------------*/
4416 /* gencjneshort - compare and jump if not equal                    */
4417 /*-----------------------------------------------------------------*/
4418 static void
4419 gencjneshort (operand * left, operand * right, symbol * lbl)
4420 {
4421   int size = max (AOP_SIZE (left), AOP_SIZE (right));
4422   int offset = 0;
4423   unsigned long lit = 0L;
4424
4425   D (emitcode (";", "gencjneshort");
4426     );
4427
4428   /* if the left side is a literal or
4429      if the right is in a pointer register and left
4430      is not */
4431   if ((AOP_TYPE (left) == AOP_LIT) ||
4432       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4433     {
4434       operand *t = right;
4435       right = left;
4436       left = t;
4437     }
4438
4439   if (AOP_TYPE (right) == AOP_LIT)
4440     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4441
4442   if (opIsGptr (left) || opIsGptr (right))
4443     {
4444       /* We are comparing a generic pointer to something.
4445        * Exclude the generic type byte from the comparison.
4446        */
4447       size--;
4448       D (emitcode (";", "cjneshort: generic ptr special case.");
4449         )
4450     }
4451
4452
4453   /* if the right side is a literal then anything goes */
4454   if (AOP_TYPE (right) == AOP_LIT &&
4455       AOP_TYPE (left) != AOP_DIR)
4456     {
4457       while (size--)
4458         {
4459           char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4460           MOVA (l);
4461           emitcode ("cjne", "a,%s,%05d$",
4462                     aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4463                     lbl->key + 100);
4464           offset++;
4465         }
4466     }
4467
4468   /* if the right side is in a register or in direct space or
4469      if the left is a pointer register & right is not */
4470   else if (AOP_TYPE (right) == AOP_REG ||
4471            AOP_TYPE (right) == AOP_DIR ||
4472            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4473            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4474     {
4475       while (size--)
4476         {
4477           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4478           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4479               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4480             emitcode ("jnz", "%05d$", lbl->key + 100);
4481           else
4482             emitcode ("cjne", "a,%s,%05d$",
4483                       aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
4484                       lbl->key + 100);
4485           offset++;
4486         }
4487     }
4488   else
4489     {
4490       /* right is a pointer reg need both a & b */
4491       while (size--)
4492         {
4493           char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4494           if (strcmp (l, "b"))
4495             emitcode ("mov", "b,%s", l);
4496           MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
4497           emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4498           offset++;
4499         }
4500     }
4501 }
4502
4503 /*-----------------------------------------------------------------*/
4504 /* gencjne - compare and jump if not equal                         */
4505 /*-----------------------------------------------------------------*/
4506 static void
4507 gencjne (operand * left, operand * right, symbol * lbl)
4508 {
4509   symbol *tlbl = newiTempLabel (NULL);
4510
4511   D (emitcode (";", "gencjne");
4512     );
4513
4514   gencjneshort (left, right, lbl);
4515
4516   emitcode ("mov", "a,%s", one);
4517   emitcode ("sjmp", "%05d$", tlbl->key + 100);
4518   emitcode ("", "%05d$:", lbl->key + 100);
4519   emitcode ("clr", "a");
4520   emitcode ("", "%05d$:", tlbl->key + 100);
4521 }
4522
4523 /*-----------------------------------------------------------------*/
4524 /* genCmpEq - generates code for equal to                          */
4525 /*-----------------------------------------------------------------*/
4526 static void
4527 genCmpEq (iCode * ic, iCode * ifx)
4528 {
4529   operand *left, *right, *result;
4530
4531   D (emitcode (";", "genCmpEq ");
4532     );
4533
4534   AOP_OP_2 (ic);
4535   AOP_SET_LOCALS (ic);
4536
4537   /* if literal, literal on the right or
4538      if the right is in a pointer register and left
4539      is not */
4540   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4541       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4542     {
4543       operand *t = IC_RIGHT (ic);
4544       IC_RIGHT (ic) = IC_LEFT (ic);
4545       IC_LEFT (ic) = t;
4546     }
4547
4548   if (ifx &&                    /* !AOP_SIZE(result) */
4549       OP_SYMBOL (result) &&
4550       OP_SYMBOL (result)->regType == REG_CND)
4551     {
4552       symbol *tlbl;
4553       /* if they are both bit variables */
4554       if (AOP_TYPE (left) == AOP_CRY &&
4555           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4556         {
4557           if (AOP_TYPE (right) == AOP_LIT)
4558             {
4559               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4560               if (lit == 0L)
4561                 {
4562                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4563                   emitcode ("cpl", "c");
4564                 }
4565               else if (lit == 1L)
4566                 {
4567                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4568                 }
4569               else
4570                 {
4571                   emitcode ("clr", "c");
4572                 }
4573               /* AOP_TYPE(right) == AOP_CRY */
4574             }
4575           else
4576             {
4577               symbol *lbl = newiTempLabel (NULL);
4578               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4579               emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4580               emitcode ("cpl", "c");
4581               emitcode ("", "%05d$:", (lbl->key + 100));
4582             }
4583           /* if true label then we jump if condition
4584              supplied is true */
4585           tlbl = newiTempLabel (NULL);
4586           if (IC_TRUE (ifx))
4587             {
4588               emitcode ("jnc", "%05d$", tlbl->key + 100);
4589               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4590             }
4591           else
4592             {
4593               emitcode ("jc", "%05d$", tlbl->key + 100);
4594               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4595             }
4596           emitcode ("", "%05d$:", tlbl->key + 100);
4597         }
4598       else
4599         {
4600           tlbl = newiTempLabel (NULL);
4601           gencjneshort (left, right, tlbl);
4602           if (IC_TRUE (ifx))
4603             {
4604               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4605               emitcode ("", "%05d$:", tlbl->key + 100);
4606             }
4607           else
4608             {
4609               symbol *lbl = newiTempLabel (NULL);
4610               emitcode ("sjmp", "%05d$", lbl->key + 100);
4611               emitcode ("", "%05d$:", tlbl->key + 100);
4612               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4613               emitcode ("", "%05d$:", lbl->key + 100);
4614             }
4615         }
4616       /* mark the icode as generated */
4617       ifx->generated = 1;
4618
4619       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4620       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4621       return;
4622     }
4623
4624   /* if they are both bit variables */
4625   if (AOP_TYPE (left) == AOP_CRY &&
4626       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4627     {
4628       if (AOP_TYPE (right) == AOP_LIT)
4629         {
4630           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4631           if (lit == 0L)
4632             {
4633               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4634               emitcode ("cpl", "c");
4635             }
4636           else if (lit == 1L)
4637             {
4638               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4639             }
4640           else
4641             {
4642               emitcode ("clr", "c");
4643             }
4644           /* AOP_TYPE(right) == AOP_CRY */
4645         }
4646       else
4647         {
4648           symbol *lbl = newiTempLabel (NULL);
4649           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4650           emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4651           emitcode ("cpl", "c");
4652           emitcode ("", "%05d$:", (lbl->key + 100));
4653         }
4654
4655       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4656       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4657
4658       aopOp (result, ic, TRUE, FALSE);
4659
4660       /* c = 1 if egal */
4661       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4662         {
4663           outBitC (result);
4664           goto release;
4665         }
4666       if (ifx)
4667         {
4668           genIfxJump (ifx, "c");
4669           goto release;
4670         }
4671       /* if the result is used in an arithmetic operation
4672          then put the result in place */
4673       outBitC (result);
4674     }
4675   else
4676     {
4677       gencjne (left, right, newiTempLabel (NULL));
4678
4679       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4680       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4681
4682       aopOp (result, ic, TRUE, FALSE);
4683
4684       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4685         {
4686           aopPut (AOP (result), "a", 0);
4687           goto release;
4688         }
4689       if (ifx)
4690         {
4691           genIfxJump (ifx, "a");
4692           goto release;
4693         }
4694       /* if the result is used in an arithmetic operation
4695          then put the result in place */
4696       if (AOP_TYPE (result) != AOP_CRY)
4697         outAcc (result);
4698       /* leave the result in acc */
4699     }
4700
4701 release:
4702   freeAsmop (result, NULL, ic, TRUE);
4703 }
4704
4705 /*-----------------------------------------------------------------*/
4706 /* ifxForOp - returns the icode containing the ifx for operand     */
4707 /*-----------------------------------------------------------------*/
4708 static iCode *
4709 ifxForOp (operand * op, iCode * ic)
4710 {
4711   /* if true symbol then needs to be assigned */
4712   if (IS_TRUE_SYMOP (op))
4713     return NULL;
4714
4715   /* if this has register type condition and
4716      the next instruction is ifx with the same operand
4717      and live to of the operand is upto the ifx only then */
4718   if (ic->next &&
4719       ic->next->op == IFX &&
4720       IC_COND (ic->next)->key == op->key &&
4721       OP_SYMBOL (op)->liveTo <= ic->next->seq)
4722     return ic->next;
4723
4724   return NULL;
4725 }
4726 /*-----------------------------------------------------------------*/
4727 /* genAndOp - for && operation                                     */
4728 /*-----------------------------------------------------------------*/
4729 static void
4730 genAndOp (iCode * ic)
4731 {
4732   operand *left, *right, *result;
4733   symbol *tlbl;
4734
4735   D (emitcode (";", "genAndOp "););
4736
4737   /* note here that && operations that are in an
4738      if statement are taken away by backPatchLabels
4739      only those used in arthmetic operations remain */
4740   AOP_OP_2 (ic);
4741   AOP_SET_LOCALS (ic);
4742
4743   /* if both are bit variables */
4744   if (AOP_TYPE (left) == AOP_CRY &&
4745       AOP_TYPE (right) == AOP_CRY)
4746     {
4747       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4748       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4749       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4750       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4751   
4752       aopOp (result,ic,FALSE, FALSE);
4753       outBitC (result);
4754     }
4755   else
4756     {
4757       tlbl = newiTempLabel (NULL);
4758       toBoolean (left);
4759       emitcode ("jz", "%05d$", tlbl->key + 100);
4760       toBoolean (right);
4761       emitcode ("", "%05d$:", tlbl->key + 100);
4762       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4763       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4764   
4765       aopOp (result,ic,FALSE, FALSE);
4766       outBitAcc (result);
4767     }
4768     freeAsmop (result, NULL, ic, TRUE);
4769 }
4770
4771
4772 /*-----------------------------------------------------------------*/
4773 /* genOrOp - for || operation                                      */
4774 /*-----------------------------------------------------------------*/
4775 static void
4776 genOrOp (iCode * ic)
4777 {
4778   operand *left, *right, *result;
4779   symbol *tlbl;
4780
4781   D (emitcode (";", "genOrOp "););
4782
4783   /* note here that || operations that are in an
4784      if statement are taken away by backPatchLabels
4785      only those used in arthmetic operations remain */
4786   AOP_OP_2 (ic);
4787   AOP_SET_LOCALS (ic);
4788
4789   /* if both are bit variables */
4790   if (AOP_TYPE (left) == AOP_CRY &&
4791       AOP_TYPE (right) == AOP_CRY)
4792     {
4793       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4794       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4795       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4796       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4797   
4798       aopOp (result,ic,FALSE, FALSE);
4799       
4800       outBitC (result);
4801     }
4802   else
4803     {
4804       tlbl = newiTempLabel (NULL);
4805       toBoolean (left);
4806       emitcode ("jnz", "%05d$", tlbl->key + 100);
4807       toBoolean (right);
4808       emitcode ("", "%05d$:", tlbl->key + 100);
4809       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4810       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4811   
4812       aopOp (result,ic,FALSE, FALSE);
4813       
4814       outBitAcc (result);
4815     }
4816
4817   freeAsmop (result, NULL, ic, TRUE);
4818 }
4819
4820 /*-----------------------------------------------------------------*/
4821 /* isLiteralBit - test if lit == 2^n                               */
4822 /*-----------------------------------------------------------------*/
4823 static int
4824 isLiteralBit (unsigned long lit)
4825 {
4826   unsigned long pw[32] =
4827   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4828    0x100L, 0x200L, 0x400L, 0x800L,
4829    0x1000L, 0x2000L, 0x4000L, 0x8000L,
4830    0x10000L, 0x20000L, 0x40000L, 0x80000L,
4831    0x100000L, 0x200000L, 0x400000L, 0x800000L,
4832    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4833    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4834   int idx;
4835
4836   for (idx = 0; idx < 32; idx++)
4837     if (lit == pw[idx])
4838       return idx + 1;
4839   return 0;
4840 }
4841
4842 /*-----------------------------------------------------------------*/
4843 /* continueIfTrue -                                                */
4844 /*-----------------------------------------------------------------*/
4845 static void
4846 continueIfTrue (iCode * ic)
4847 {
4848   if (IC_TRUE (ic))
4849     emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4850   ic->generated = 1;
4851 }
4852
4853 /*-----------------------------------------------------------------*/
4854 /* jmpIfTrue -                                                     */
4855 /*-----------------------------------------------------------------*/
4856 static void
4857 jumpIfTrue (iCode * ic)
4858 {
4859   if (!IC_TRUE (ic))
4860     emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4861   ic->generated = 1;
4862 }
4863
4864 /*-----------------------------------------------------------------*/
4865 /* jmpTrueOrFalse -                                                */
4866 /*-----------------------------------------------------------------*/
4867 static void
4868 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4869 {
4870   // ugly but optimized by peephole
4871   if (IC_TRUE (ic))
4872     {
4873       symbol *nlbl = newiTempLabel (NULL);
4874       emitcode ("sjmp", "%05d$", nlbl->key + 100);
4875       emitcode ("", "%05d$:", tlbl->key + 100);
4876       emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4877       emitcode ("", "%05d$:", nlbl->key + 100);
4878     }
4879   else
4880     {
4881       emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4882       emitcode ("", "%05d$:", tlbl->key + 100);
4883     }
4884   ic->generated = 1;
4885 }
4886
4887 // Generate code to perform a bit-wise logic operation
4888 // on two operands in far space (assumed to already have been 
4889 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
4890 // in far space. This requires pushing the result on the stack
4891 // then popping it into the result.
4892 static void
4893 genFarFarLogicOp(iCode *ic, char *logicOp)
4894 {
4895       int size, resultSize, compSize;
4896       int offset = 0;
4897       
4898       D(emitcode(";", "%s special case for 3 far operands.", logicOp););
4899       compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ? 
4900                   AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
4901       
4902       _startLazyDPSEvaluation();
4903       for (size = compSize; (size--); offset++)
4904       {
4905           MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
4906           emitcode ("mov", "%s, acc", DP2_RESULT_REG);
4907           MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
4908           
4909           emitcode (logicOp, "a,%s", DP2_RESULT_REG);
4910           emitcode ("push", "acc");
4911       }
4912       _endLazyDPSEvaluation();
4913      
4914       freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
4915       freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
4916       aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
4917      
4918       resultSize = AOP_SIZE(IC_RESULT(ic));
4919
4920       ADJUST_PUSHED_RESULT(compSize, resultSize);
4921
4922       _startLazyDPSEvaluation();
4923       while (compSize--)
4924       {
4925           emitcode ("pop", "acc");
4926           aopPut (AOP (IC_RESULT (ic)), "a", compSize);
4927       }
4928       _endLazyDPSEvaluation();
4929       freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
4930 }
4931
4932
4933 /*-----------------------------------------------------------------*/
4934 /* genAnd  - code for and                                          */
4935 /*-----------------------------------------------------------------*/
4936 static void
4937 genAnd (iCode * ic, iCode * ifx)
4938 {
4939   operand *left, *right, *result;
4940   int size, offset = 0;
4941   unsigned long lit = 0L;
4942   int bytelit = 0;
4943   char buffer[10];
4944   bool pushResult;
4945
4946   D (emitcode (";", "genAnd "););
4947
4948   AOP_OP_3_NOFATAL (ic, pushResult);
4949   AOP_SET_LOCALS (ic);
4950
4951   if (pushResult)
4952   {
4953       genFarFarLogicOp(ic, "anl");
4954       return;
4955   }  
4956
4957 #ifdef DEBUG_TYPE
4958   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4959             AOP_TYPE (result),
4960             AOP_TYPE (left), AOP_TYPE (right));
4961   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4962             AOP_SIZE (result),
4963             AOP_SIZE (left), AOP_SIZE (right));
4964 #endif
4965
4966   /* if left is a literal & right is not then exchange them */
4967   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4968       AOP_NEEDSACC (left))
4969     {
4970       operand *tmp = right;
4971       right = left;
4972       left = tmp;
4973     }
4974
4975   /* if result = right then exchange them */
4976   if (sameRegs (AOP (result), AOP (right)))
4977     {
4978       operand *tmp = right;
4979       right = left;
4980       left = tmp;
4981     }
4982
4983   /* if right is bit then exchange them */
4984   if (AOP_TYPE (right) == AOP_CRY &&
4985       AOP_TYPE (left) != AOP_CRY)
4986     {
4987       operand *tmp = right;
4988       right = left;
4989       left = tmp;
4990     }
4991   if (AOP_TYPE (right) == AOP_LIT)
4992     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4993
4994   size = AOP_SIZE (result);
4995
4996   // if(bit & yy)
4997   // result = bit & yy;
4998   if (AOP_TYPE (left) == AOP_CRY)
4999     {
5000       // c = bit & literal;
5001       if (AOP_TYPE (right) == AOP_LIT)
5002         {
5003           if (lit & 1)
5004             {
5005               if (size && sameRegs (AOP (result), AOP (left)))
5006                 // no change
5007                 goto release;
5008               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5009             }
5010           else
5011             {
5012               // bit(result) = 0;
5013               if (size && (AOP_TYPE (result) == AOP_CRY))
5014                 {
5015                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5016                   goto release;
5017                 }
5018               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5019                 {
5020                   jumpIfTrue (ifx);
5021                   goto release;
5022                 }
5023               emitcode ("clr", "c");
5024             }
5025         }
5026       else
5027         {
5028           if (AOP_TYPE (right) == AOP_CRY)
5029             {
5030               // c = bit & bit;
5031               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5032               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5033             }
5034           else
5035             {
5036               // c = bit & val;
5037               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
5038               // c = lsb
5039               emitcode ("rrc", "a");
5040               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5041             }
5042         }
5043       // bit = c
5044       // val = c
5045       if (size)
5046         outBitC (result);
5047       // if(bit & ...)
5048       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5049         genIfxJump (ifx, "c");
5050       goto release;
5051     }
5052
5053   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5054   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5055   if ((AOP_TYPE (right) == AOP_LIT) &&
5056       (AOP_TYPE (result) == AOP_CRY) &&
5057       (AOP_TYPE (left) != AOP_CRY))
5058     {
5059       int posbit = isLiteralBit (lit);
5060       /* left &  2^n */
5061       if (posbit)
5062         {
5063           posbit--;
5064           MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
5065           // bit = left & 2^n
5066           if (size)
5067             emitcode ("mov", "c,acc.%d", posbit & 0x07);
5068           // if(left &  2^n)
5069           else
5070             {
5071               if (ifx)
5072                 {
5073                   sprintf (buffer, "acc.%d", posbit & 0x07);
5074                   genIfxJump (ifx, buffer);
5075                 }
5076               goto release;
5077             }
5078         }
5079       else
5080         {
5081           symbol *tlbl = newiTempLabel (NULL);
5082           int sizel = AOP_SIZE (left);
5083           if (size)
5084             emitcode ("setb", "c");
5085           while (sizel--)
5086             {
5087               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5088                 {
5089                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5090                   // byte ==  2^n ?
5091                   if ((posbit = isLiteralBit (bytelit)) != 0)
5092                     emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5093                   else
5094                     {
5095                       if (bytelit != 0x0FFL)
5096                         emitcode ("anl", "a,%s",
5097                           aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
5098                       emitcode ("jnz", "%05d$", tlbl->key + 100);
5099                     }
5100                 }
5101               offset++;
5102             }
5103           // bit = left & literal
5104           if (size)
5105             {
5106               emitcode ("clr", "c");
5107               emitcode ("", "%05d$:", tlbl->key + 100);
5108             }
5109           // if(left & literal)
5110           else
5111             {
5112               if (ifx)
5113                 jmpTrueOrFalse (ifx, tlbl);
5114               goto release;
5115             }
5116         }
5117       outBitC (result);
5118       goto release;
5119     }
5120
5121   /* if left is same as result */
5122   if (sameRegs (AOP (result), AOP (left)))
5123     {
5124       for (; size--; offset++)
5125         {
5126           if (AOP_TYPE (right) == AOP_LIT)
5127             {
5128               if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5129                 continue;
5130               else if (bytelit == 0)
5131                 aopPut (AOP (result), zero, offset);
5132               else if (IS_AOP_PREG (result))
5133                 {
5134                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5135                   emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5136                   aopPut (AOP (result), "a", offset);
5137                 }
5138               else
5139                 emitcode ("anl", "%s,%s",
5140                           aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5141                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5142             }
5143           else
5144             {
5145               if (AOP_TYPE (left) == AOP_ACC)
5146                 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5147               else
5148                 {
5149                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5150                   if (IS_AOP_PREG (result))
5151                     {
5152                       emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5153                       aopPut (AOP (result), "a", offset);
5154
5155                     }
5156                   else
5157                     emitcode ("anl", "%s,a",
5158                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5159                 }
5160             }
5161         }
5162     }
5163   else
5164     {
5165       // left & result in different registers
5166       if (AOP_TYPE (result) == AOP_CRY)
5167         {
5168           // result = bit
5169           // if(size), result in bit
5170           // if(!size && ifx), conditional oper: if(left & right)
5171           symbol *tlbl = newiTempLabel (NULL);
5172           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5173           if (size)
5174             emitcode ("setb", "c");
5175           while (sizer--)
5176             {
5177               MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5178               emitcode ("anl", "a,%s",
5179                         aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5180               emitcode ("jnz", "%05d$", tlbl->key + 100);
5181               offset++;
5182             }
5183           if (size)
5184             {
5185               CLRC;
5186               emitcode ("", "%05d$:", tlbl->key + 100);
5187               outBitC (result);
5188             }
5189           else if (ifx)
5190             jmpTrueOrFalse (ifx, tlbl);
5191         }
5192       else
5193         {
5194           for (; (size--); offset++)
5195             {
5196               // normal case
5197               // result = left & right
5198               if (AOP_TYPE (right) == AOP_LIT)
5199                 {
5200                   if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5201                     {
5202                       aopPut (AOP (result),
5203                            aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5204                               offset);
5205                       continue;
5206                     }
5207                   else if (bytelit == 0)
5208                     {
5209                       aopPut (AOP (result), zero, offset);
5210                       continue;
5211                     }
5212                   D (emitcode (";", "better literal AND.");
5213                     );
5214                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5215                   emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
5216                                                     FALSE, FALSE, FALSE));
5217
5218                 }
5219               else
5220                 {
5221                   // faster than result <- left, anl result,right
5222                   // and better if result is SFR
5223                   if (AOP_TYPE (left) == AOP_ACC)
5224                     {
5225                       emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
5226                                                        FALSE, FALSE, FALSE));
5227                     }
5228                   else
5229                     {
5230                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5231                       emitcode ("anl", "a,%s",
5232                           aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5233                     }
5234                 }
5235               aopPut (AOP (result), "a", offset);
5236             }
5237         }
5238     }
5239
5240 release:
5241   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5242   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5243   freeAsmop (result, NULL, ic, TRUE);
5244 }
5245
5246
5247 /*-----------------------------------------------------------------*/
5248 /* genOr  - code for or                                            */
5249 /*-----------------------------------------------------------------*/
5250 static void
5251 genOr (iCode * ic, iCode * ifx)
5252 {
5253   operand *left, *right, *result;
5254   int size, offset = 0;
5255   unsigned long lit = 0L;
5256   bool     pushResult;
5257
5258   D (emitcode (";", "genOr "););
5259
5260   AOP_OP_3_NOFATAL (ic, pushResult);
5261   AOP_SET_LOCALS (ic);
5262
5263   if (pushResult)
5264   {
5265       genFarFarLogicOp(ic, "orl");
5266       return;
5267   }
5268
5269
5270 #ifdef DEBUG_TYPE
5271   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5272             AOP_TYPE (result),
5273             AOP_TYPE (left), AOP_TYPE (right));
5274   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5275             AOP_SIZE (result),
5276             AOP_SIZE (left), AOP_SIZE (right));
5277 #endif
5278
5279   /* if left is a literal & right is not then exchange them */
5280   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5281       AOP_NEEDSACC (left))
5282     {
5283       operand *tmp = right;
5284       right = left;
5285       left = tmp;
5286     }
5287
5288   /* if result = right then exchange them */
5289   if (sameRegs (AOP (result), AOP (right)))
5290     {
5291       operand *tmp = right;
5292       right = left;
5293       left = tmp;
5294     }
5295
5296   /* if right is bit then exchange them */
5297   if (AOP_TYPE (right) == AOP_CRY &&
5298       AOP_TYPE (left) != AOP_CRY)
5299     {
5300       operand *tmp = right;
5301       right = left;
5302       left = tmp;
5303     }
5304   if (AOP_TYPE (right) == AOP_LIT)
5305     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5306
5307   size = AOP_SIZE (result);
5308
5309   // if(bit | yy)
5310   // xx = bit | yy;
5311   if (AOP_TYPE (left) == AOP_CRY)
5312     {
5313       if (AOP_TYPE (right) == AOP_LIT)
5314         {
5315           // c = bit & literal;
5316           if (lit)
5317             {
5318               // lit != 0 => result = 1
5319               if (AOP_TYPE (result) == AOP_CRY)
5320                 {
5321                   if (size)
5322                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5323                   else if (ifx)
5324                     continueIfTrue (ifx);
5325                   goto release;
5326                 }
5327               emitcode ("setb", "c");
5328             }
5329           else
5330             {
5331               // lit == 0 => result = left
5332               if (size && sameRegs (AOP (result), AOP (left)))
5333                 goto release;
5334               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5335             }
5336         }
5337       else
5338         {
5339           if (AOP_TYPE (right) == AOP_CRY)
5340             {
5341               // c = bit | bit;
5342               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5343               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5344             }
5345           else
5346             {
5347               // c = bit | val;
5348               symbol *tlbl = newiTempLabel (NULL);
5349               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5350                 emitcode ("setb", "c");
5351               emitcode ("jb", "%s,%05d$",
5352                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
5353               toBoolean (right);
5354               emitcode ("jnz", "%05d$", tlbl->key + 100);
5355               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5356                 {
5357                   jmpTrueOrFalse (ifx, tlbl);
5358                   goto release;
5359                 }
5360               else
5361                 {
5362                   CLRC;
5363                   emitcode ("", "%05d$:", tlbl->key + 100);
5364                 }
5365             }
5366         }
5367       // bit = c
5368       // val = c
5369       if (size)
5370         outBitC (result);
5371       // if(bit | ...)
5372       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5373         genIfxJump (ifx, "c");
5374       goto release;
5375     }
5376
5377   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5378   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5379   if ((AOP_TYPE (right) == AOP_LIT) &&
5380       (AOP_TYPE (result) == AOP_CRY) &&
5381       (AOP_TYPE (left) != AOP_CRY))
5382     {
5383       if (lit)
5384         {
5385           // result = 1
5386           if (size)
5387             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5388           else
5389             continueIfTrue (ifx);
5390           goto release;
5391         }
5392       else
5393         {
5394           // lit = 0, result = boolean(left)
5395           if (size)
5396             emitcode ("setb", "c");
5397           toBoolean (right);
5398           if (size)
5399             {
5400               symbol *tlbl = newiTempLabel (NULL);
5401               emitcode ("jnz", "%05d$", tlbl->key + 100);
5402               CLRC;
5403               emitcode ("", "%05d$:", tlbl->key + 100);
5404             }
5405           else
5406             {
5407               genIfxJump (ifx, "a");
5408               goto release;
5409             }
5410         }
5411       outBitC (result);
5412       goto release;
5413     }
5414
5415   /* if left is same as result */
5416   if (sameRegs (AOP (result), AOP (left)))
5417     {
5418       for (; size--; offset++)
5419         {
5420           if (AOP_TYPE (right) == AOP_LIT)
5421             {
5422               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5423                 {
5424                   continue;
5425                 }
5426               else
5427                 {
5428                   if (IS_AOP_PREG (left))
5429                     {
5430                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5431                       emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5432                       aopPut (AOP (result), "a", offset);
5433                     }
5434                   else
5435                     {
5436                       emitcode ("orl", "%s,%s",
5437                             aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5438                          aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5439                     }
5440                 }
5441             }
5442           else
5443             {
5444               if (AOP_TYPE (left) == AOP_ACC)
5445                 {
5446                   emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5447                 }
5448               else
5449                 {
5450                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5451                   if (IS_AOP_PREG (left))
5452                     {
5453                       emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5454                       aopPut (AOP (result), "a", offset);
5455                     }
5456                   else
5457                     {
5458                       emitcode ("orl", "%s,a",
5459                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5460                     }
5461                 }
5462             }
5463         }
5464     }
5465   else
5466     {
5467       // left & result in different registers
5468       if (AOP_TYPE (result) == AOP_CRY)
5469         {
5470           // result = bit
5471           // if(size), result in bit
5472           // if(!size && ifx), conditional oper: if(left | right)
5473           symbol *tlbl = newiTempLabel (NULL);
5474           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5475           if (size)
5476             emitcode ("setb", "c");
5477           while (sizer--)
5478             {
5479               MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5480               emitcode ("orl", "a,%s",
5481                         aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5482               emitcode ("jnz", "%05d$", tlbl->key + 100);
5483               offset++;
5484             }
5485           if (size)
5486             {
5487               CLRC;
5488               emitcode ("", "%05d$:", tlbl->key + 100);
5489               outBitC (result);
5490             }
5491           else if (ifx)
5492             jmpTrueOrFalse (ifx, tlbl);
5493         }
5494       else
5495         {
5496           for (; (size--); offset++)
5497             {
5498               // normal case
5499               // result = left & right
5500               if (AOP_TYPE (right) == AOP_LIT)
5501                 {
5502                   if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5503                     {
5504                       aopPut (AOP (result),
5505                            aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5506                               offset);
5507                       continue;
5508                     }
5509                   D (emitcode (";", "better literal OR.");
5510                     );
5511                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5512                   emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
5513                                                     FALSE, FALSE, FALSE));
5514
5515                 }
5516               else
5517                 {
5518                   // faster than result <- left, anl result,right
5519                   // and better if result is SFR
5520                   if (AOP_TYPE (left) == AOP_ACC)
5521                     {
5522                       emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
5523                                                        FALSE, FALSE, FALSE));
5524                     }
5525                   else
5526                     {
5527                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5528                       emitcode ("orl", "a,%s",
5529                           aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5530                     }
5531                 }
5532               aopPut (AOP (result), "a", offset);
5533             }
5534         }
5535     }
5536
5537 release:
5538   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5539   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5540   freeAsmop (result, NULL, ic, TRUE);
5541 }
5542
5543 /*-----------------------------------------------------------------*/
5544 /* genXor - code for xclusive or                                   */
5545 /*-----------------------------------------------------------------*/
5546 static void
5547 genXor (iCode * ic, iCode * ifx)
5548 {
5549   operand *left, *right, *result;
5550   int size, offset = 0;
5551   unsigned long lit = 0L;
5552   bool pushResult;
5553
5554   D (emitcode (";", "genXor "););
5555
5556   AOP_OP_3_NOFATAL (ic, pushResult);
5557   AOP_SET_LOCALS (ic);
5558
5559   if (pushResult)
5560   {
5561       genFarFarLogicOp(ic, "xrl");
5562       return;
5563   }  
5564
5565 #ifdef DEBUG_TYPE
5566   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5567             AOP_TYPE (result),
5568             AOP_TYPE (left), AOP_TYPE (right));
5569   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5570             AOP_SIZE (result),
5571             AOP_SIZE (left), AOP_SIZE (right));
5572 #endif
5573
5574   /* if left is a literal & right is not ||
5575      if left needs acc & right does not */
5576   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5577       (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5578     {
5579       operand *tmp = right;
5580       right = left;
5581       left = tmp;
5582     }
5583
5584   /* if result = right then exchange them */
5585   if (sameRegs (AOP (result), AOP (right)))
5586     {
5587       operand *tmp = right;
5588       right = left;
5589       left = tmp;
5590     }
5591
5592   /* if right is bit then exchange them */
5593   if (AOP_TYPE (right) == AOP_CRY &&
5594       AOP_TYPE (left) != AOP_CRY)
5595     {
5596       operand *tmp = right;
5597       right = left;
5598       left = tmp;
5599     }
5600   if (AOP_TYPE (right) == AOP_LIT)
5601     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5602
5603   size = AOP_SIZE (result);
5604
5605   // if(bit ^ yy)
5606   // xx = bit ^ yy;
5607   if (AOP_TYPE (left) == AOP_CRY)
5608     {
5609       if (AOP_TYPE (right) == AOP_LIT)
5610         {
5611           // c = bit & literal;
5612           if (lit >> 1)
5613             {
5614               // lit>>1  != 0 => result = 1
5615               if (AOP_TYPE (result) == AOP_CRY)
5616                 {
5617                   if (size)
5618                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5619                   else if (ifx)
5620                     continueIfTrue (ifx);
5621                   goto release;
5622                 }
5623               emitcode ("setb", "c");
5624             }
5625           else
5626             {
5627               // lit == (0 or 1)
5628               if (lit == 0)
5629                 {
5630                   // lit == 0, result = left
5631                   if (size && sameRegs (AOP (result), AOP (left)))
5632                     goto release;
5633                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5634                 }
5635               else
5636                 {
5637                   // lit == 1, result = not(left)
5638                   if (size && sameRegs (AOP (result), AOP (left)))
5639                     {
5640                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5641                       goto release;
5642                     }
5643                   else
5644                     {
5645                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5646                       emitcode ("cpl", "c");
5647                     }
5648                 }
5649             }
5650
5651         }
5652       else
5653         {
5654           // right != literal
5655           symbol *tlbl = newiTempLabel (NULL);
5656           if (AOP_TYPE (right) == AOP_CRY)
5657             {
5658               // c = bit ^ bit;
5659               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5660             }
5661           else
5662             {
5663               int sizer = AOP_SIZE (right);
5664               // c = bit ^ val
5665               // if val>>1 != 0, result = 1
5666               emitcode ("setb", "c");
5667               while (sizer)
5668                 {
5669                   MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
5670                   if (sizer == 1)
5671                     // test the msb of the lsb
5672                     emitcode ("anl", "a,#0xfe");
5673                   emitcode ("jnz", "%05d$", tlbl->key + 100);
5674                   sizer--;
5675                 }
5676               // val = (0,1)
5677               emitcode ("rrc", "a");
5678             }
5679           emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5680           emitcode ("cpl", "c");
5681           emitcode ("", "%05d$:", (tlbl->key + 100));
5682         }
5683       // bit = c
5684       // val = c
5685       if (size)
5686         outBitC (result);
5687       // if(bit | ...)
5688       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5689         genIfxJump (ifx, "c");
5690       goto release;
5691     }
5692
5693   if (sameRegs (AOP (result), AOP (left)))
5694     {
5695       /* if left is same as result */
5696       for (; size--; offset++)
5697         {
5698           if (AOP_TYPE (right) == AOP_LIT)
5699             {
5700               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5701                 continue;
5702               else if (IS_AOP_PREG (left))
5703                 {
5704                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5705                   emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5706                   aopPut (AOP (result), "a", offset);
5707                 }
5708               else
5709                 emitcode ("xrl", "%s,%s",
5710                           aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5711                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5712             }
5713           else
5714             {
5715               if (AOP_TYPE (left) == AOP_ACC)
5716                 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5717               else
5718                 {
5719                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5720                   if (IS_AOP_PREG (left))
5721                     {
5722                       emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5723                       aopPut (AOP (result), "a", offset);
5724                     }
5725                   else
5726                     emitcode ("xrl", "%s,a",
5727                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5728                 }
5729             }
5730         }
5731     }
5732   else
5733     {
5734       // left & result in different registers
5735       if (AOP_TYPE (result) == AOP_CRY)
5736         {
5737           // result = bit
5738           // if(size), result in bit
5739           // if(!size && ifx), conditional oper: if(left ^ right)
5740           symbol *tlbl = newiTempLabel (NULL);
5741           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5742           if (size)
5743             emitcode ("setb", "c");
5744           while (sizer--)
5745             {
5746               if ((AOP_TYPE (right) == AOP_LIT) &&
5747                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5748                 {
5749                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5750                 }
5751               else
5752                 {
5753                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5754                   emitcode ("xrl", "a,%s",
5755                           aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5756                 }
5757               emitcode ("jnz", "%05d$", tlbl->key + 100);
5758               offset++;
5759             }
5760           if (size)
5761             {
5762               CLRC;
5763               emitcode ("", "%05d$:", tlbl->key + 100);
5764               outBitC (result);
5765             }
5766           else if (ifx)
5767             jmpTrueOrFalse (ifx, tlbl);
5768         }
5769       else
5770         for (; (size--); offset++)
5771           {
5772             // normal case
5773             // result = left & right
5774             if (AOP_TYPE (right) == AOP_LIT)
5775               {
5776                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5777                   {
5778                     aopPut (AOP (result),
5779                             aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5780                             offset);
5781                     continue;
5782                   }
5783                 D (emitcode (";", "better literal XOR.");
5784                   );
5785                 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5786                 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
5787                                                   FALSE, FALSE, FALSE));
5788               }
5789             else
5790               {
5791                 // faster than result <- left, anl result,right
5792                 // and better if result is SFR
5793                 if (AOP_TYPE (left) == AOP_ACC)
5794                   {
5795                     emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
5796                                                      FALSE, FALSE, FALSE));
5797                   }
5798                 else
5799                   {
5800                     MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5801                     emitcode ("xrl", "a,%s",
5802                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5803                   }
5804               }
5805             aopPut (AOP (result), "a", offset);
5806           }
5807     }
5808
5809 release:
5810   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5811   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5812   freeAsmop (result, NULL, ic, TRUE);
5813 }
5814
5815 /*-----------------------------------------------------------------*/
5816 /* genInline - write the inline code out                           */
5817 /*-----------------------------------------------------------------*/
5818 static void
5819 genInline (iCode * ic)
5820 {
5821   char *buffer, *bp, *bp1;
5822
5823   D (emitcode (";", "genInline ");
5824     );
5825
5826   _G.inLine += (!options.asmpeep);
5827
5828   buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5829   strcpy (buffer, IC_INLINE (ic));
5830
5831   /* emit each line as a code */
5832   while (*bp)
5833     {
5834       if (*bp == '\n')
5835         {
5836           *bp++ = '\0';
5837           emitcode (bp1, "");
5838           bp1 = bp;
5839         }
5840       else
5841         {
5842           if (*bp == ':')
5843             {
5844               bp++;
5845               *bp = '\0';
5846               bp++;
5847               emitcode (bp1, "");
5848               bp1 = bp;
5849             }
5850           else
5851             bp++;
5852         }
5853     }
5854   if (bp1 != bp)
5855     emitcode (bp1, "");
5856   /*     emitcode("",buffer); */
5857   _G.inLine -= (!options.asmpeep);
5858 }
5859
5860 /*-----------------------------------------------------------------*/
5861 /* genRRC - rotate right with carry                                */
5862 /*-----------------------------------------------------------------*/
5863 static void
5864 genRRC (iCode * ic)
5865 {
5866   operand *left, *result;
5867   int size, offset = 0;
5868   char *l;
5869
5870   D (emitcode (";", "genRRC ");
5871     );
5872
5873   /* rotate right with carry */
5874   left = IC_LEFT (ic);
5875   result = IC_RESULT (ic);
5876   aopOp (left, ic, FALSE, FALSE);
5877   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5878
5879   /* move it to the result */
5880   size = AOP_SIZE (result);
5881   offset = size - 1;
5882   CLRC;
5883
5884   _startLazyDPSEvaluation ();
5885   while (size--)
5886     {
5887       l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5888       MOVA (l);
5889       emitcode ("rrc", "a");
5890       if (AOP_SIZE (result) > 1)
5891         aopPut (AOP (result), "a", offset--);
5892     }
5893   _endLazyDPSEvaluation ();
5894
5895   /* now we need to put the carry into the
5896      highest order byte of the result */
5897   if (AOP_SIZE (result) > 1)
5898     {
5899       l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
5900       MOVA (l);
5901     }
5902   emitcode ("mov", "acc.7,c");
5903   aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5904   freeAsmop (left, NULL, ic, TRUE);
5905   freeAsmop (result, NULL, ic, TRUE);
5906 }
5907
5908 /*-----------------------------------------------------------------*/
5909 /* genRLC - generate code for rotate left with carry               */
5910 /*-----------------------------------------------------------------*/
5911 static void
5912 genRLC (iCode * ic)
5913 {
5914   operand *left, *result;
5915   int size, offset = 0;
5916   char *l;
5917
5918   D (emitcode (";", "genRLC ");
5919     );
5920
5921   /* rotate right with carry */
5922   left = IC_LEFT (ic);
5923   result = IC_RESULT (ic);
5924   aopOp (left, ic, FALSE, FALSE);
5925   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5926
5927   /* move it to the result */
5928   size = AOP_SIZE (result);
5929   offset = 0;
5930   if (size--)
5931     {
5932       l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5933       MOVA (l);
5934       emitcode ("add", "a,acc");
5935       if (AOP_SIZE (result) > 1)
5936         {
5937           aopPut (AOP (result), "a", offset++);
5938         }
5939
5940       _startLazyDPSEvaluation ();
5941       while (size--)
5942         {
5943           l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5944           MOVA (l);
5945           emitcode ("rlc", "a");
5946           if (AOP_SIZE (result) > 1)
5947             aopPut (AOP (result), "a", offset++);
5948         }
5949       _endLazyDPSEvaluation ();
5950     }
5951   /* now we need to put the carry into the
5952      highest order byte of the result */
5953   if (AOP_SIZE (result) > 1)
5954     {
5955       l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
5956       MOVA (l);
5957     }
5958   emitcode ("mov", "acc.0,c");
5959   aopPut (AOP (result), "a", 0);
5960   freeAsmop (left, NULL, ic, TRUE);
5961   freeAsmop (result, NULL, ic, TRUE);
5962 }
5963
5964 /*-----------------------------------------------------------------*/
5965 /* genGetHbit - generates code get highest order bit               */
5966 /*-----------------------------------------------------------------*/
5967 static void
5968 genGetHbit (iCode * ic)
5969 {
5970   operand *left, *result;
5971   left = IC_LEFT (ic);
5972   result = IC_RESULT (ic);
5973   aopOp (left, ic, FALSE, FALSE);
5974   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5975
5976   D (emitcode (";", "genGetHbit ");
5977     );
5978
5979   /* get the highest order byte into a */
5980   MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
5981   if (AOP_TYPE (result) == AOP_CRY)
5982     {
5983       emitcode ("rlc", "a");
5984       outBitC (result);
5985     }
5986   else
5987     {
5988       emitcode ("rl", "a");
5989       emitcode ("anl", "a,#0x01");
5990       outAcc (result);
5991     }
5992
5993
5994   freeAsmop (left, NULL, ic, TRUE);
5995   freeAsmop (result, NULL, ic, TRUE);
5996 }
5997
5998 /*-----------------------------------------------------------------*/
5999 /* AccRol - rotate left accumulator by known count                 */
6000 /*-----------------------------------------------------------------*/
6001 static void
6002 AccRol (int shCount)
6003 {
6004   shCount &= 0x0007;            // shCount : 0..7
6005
6006   switch (shCount)
6007     {
6008     case 0:
6009       break;
6010     case 1:
6011       emitcode ("rl", "a");
6012       break;
6013     case 2:
6014       emitcode ("rl", "a");
6015       emitcode ("rl", "a");
6016       break;
6017     case 3:
6018       emitcode ("swap", "a");
6019       emitcode ("rr", "a");
6020       break;
6021     case 4:
6022       emitcode ("swap", "a");
6023       break;
6024     case 5:
6025       emitcode ("swap", "a");
6026       emitcode ("rl", "a");
6027       break;
6028     case 6:
6029       emitcode ("rr", "a");
6030       emitcode ("rr", "a");
6031       break;
6032     case 7:
6033       emitcode ("rr", "a");
6034       break;
6035     }
6036 }
6037
6038 /*-----------------------------------------------------------------*/
6039 /* AccLsh - left shift accumulator by known count                  */
6040 /*-----------------------------------------------------------------*/
6041 static void
6042 AccLsh (int shCount)
6043 {
6044   if (shCount != 0)
6045     {
6046       if (shCount == 1)
6047         emitcode ("add", "a,acc");
6048       else if (shCount == 2)
6049         {
6050           emitcode ("add", "a,acc");
6051           emitcode ("add", "a,acc");
6052         }
6053       else
6054         {
6055           /* rotate left accumulator */
6056           AccRol (shCount);
6057           /* and kill the lower order bits */
6058           emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6059         }
6060     }
6061 }
6062
6063 /*-----------------------------------------------------------------*/
6064 /* AccRsh - right shift accumulator by known count                 */
6065 /*-----------------------------------------------------------------*/
6066 static void
6067 AccRsh (int shCount)
6068 {
6069   if (shCount != 0)
6070     {
6071       if (shCount == 1)
6072         {
6073           CLRC;
6074           emitcode ("rrc", "a");
6075         }
6076       else
6077         {
6078           /* rotate right accumulator */
6079           AccRol (8 - shCount);
6080           /* and kill the higher order bits */
6081           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6082         }
6083     }
6084 }
6085
6086 #ifdef BETTER_LITERAL_SHIFT
6087 /*-----------------------------------------------------------------*/
6088 /* AccSRsh - signed right shift accumulator by known count                 */
6089 /*-----------------------------------------------------------------*/
6090 static void
6091 AccSRsh (int shCount)
6092 {
6093   symbol *tlbl;
6094   if (shCount != 0)
6095     {
6096       if (shCount == 1)
6097         {
6098           emitcode ("mov", "c,acc.7");
6099           emitcode ("rrc", "a");
6100         }
6101       else if (shCount == 2)
6102         {
6103           emitcode ("mov", "c,acc.7");
6104           emitcode ("rrc", "a");
6105           emitcode ("mov", "c,acc.7");
6106           emitcode ("rrc", "a");
6107         }
6108       else
6109         {
6110           tlbl = newiTempLabel (NULL);
6111           /* rotate right accumulator */
6112           AccRol (8 - shCount);
6113           /* and kill the higher order bits */
6114           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6115           emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6116           emitcode ("orl", "a,#0x%02x",
6117                     (unsigned char) ~SRMask[shCount]);
6118           emitcode ("", "%05d$:", tlbl->key + 100);
6119         }
6120     }
6121 }
6122 #endif
6123
6124 #ifdef BETTER_LITERAL_SHIFT
6125 /*-----------------------------------------------------------------*/
6126 /* shiftR1Left2Result - shift right one byte from left to result   */
6127 /*-----------------------------------------------------------------*/
6128 static void
6129 shiftR1Left2Result (operand * left, int offl,
6130                     operand * result, int offr,
6131                     int shCount, int sign)
6132 {
6133   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6134   /* shift right accumulator */
6135   if (sign)
6136     AccSRsh (shCount);
6137   else
6138     AccRsh (shCount);
6139   aopPut (AOP (result), "a", offr);
6140 }
6141 #endif
6142
6143 #ifdef BETTER_LITERAL_SHIFT
6144 /*-----------------------------------------------------------------*/
6145 /* shiftL1Left2Result - shift left one byte from left to result    */
6146 /*-----------------------------------------------------------------*/
6147 static void
6148 shiftL1Left2Result (operand * left, int offl,
6149                     operand * result, int offr, int shCount)
6150 {
6151   MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6152   /* shift left accumulator */
6153   AccLsh (shCount);
6154   aopPut (AOP (result), "a", offr);
6155 }
6156 #endif
6157
6158 #ifdef BETTER_LITERAL_SHIFT
6159 /*-----------------------------------------------------------------*/
6160 /* movLeft2Result - move byte from left to result                  */
6161 /*-----------------------------------------------------------------*/
6162 static void
6163 movLeft2Result (operand * left, int offl,
6164                 operand * result, int offr, int sign)
6165 {
6166   char *l;
6167   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6168   {
6169       l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
6170
6171       if (*l == '@' && (IS_AOP_PREG (result)))
6172       {
6173           emitcode ("mov", "a,%s", l);
6174           aopPut (AOP (result), "a", offr);
6175       }
6176       else
6177       {
6178           if (!sign)
6179           {
6180             aopPut (AOP (result), l, offr);
6181           }
6182           else
6183             {
6184               /* MSB sign in acc.7 ! */
6185               if (getDataSize (left) == offl + 1)
6186                 {
6187                   emitcode ("mov", "a,%s", l);
6188                   aopPut (AOP (result), "a", offr);
6189                 }
6190             }
6191       }
6192   }
6193 }
6194 #endif
6195
6196 #ifdef BETTER_LITERAL_SHIFT
6197 /*-----------------------------------------------------------------*/
6198 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
6199 /*-----------------------------------------------------------------*/
6200 static void
6201 AccAXRrl1 (char *x)
6202 {
6203   emitcode ("rrc", "a");
6204   emitcode ("xch", "a,%s", x);
6205   emitcode ("rrc", "a");
6206   emitcode ("xch", "a,%s", x);
6207 }
6208 #endif
6209
6210 #ifdef BETTER_LITERAL_SHIFT
6211 //REMOVE ME!!!
6212 /*-----------------------------------------------------------------*/
6213 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
6214 /*-----------------------------------------------------------------*/
6215 static void
6216 AccAXLrl1 (char *x)
6217 {
6218   emitcode ("xch", "a,%s", x);
6219   emitcode ("rlc", "a");
6220   emitcode ("xch", "a,%s", x);
6221   emitcode ("rlc", "a");
6222 }
6223 #endif
6224
6225 #ifdef BETTER_LITERAL_SHIFT
6226 /*-----------------------------------------------------------------*/
6227 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
6228 /*-----------------------------------------------------------------*/
6229 static void
6230 AccAXLsh1 (char *x)
6231 {
6232   emitcode ("xch", "a,%s", x);
6233   emitcode ("add", "a,acc");
6234   emitcode ("xch", "a,%s", x);
6235   emitcode ("rlc", "a");
6236 }
6237 #endif
6238
6239 #ifdef BETTER_LITERAL_SHIFT
6240 /*-----------------------------------------------------------------*/
6241 /* AccAXLsh - left shift a:x by known count (0..7)                 */
6242 /*-----------------------------------------------------------------*/
6243 static void
6244 AccAXLsh (char *x, int shCount)
6245 {
6246   switch (shCount)
6247     {
6248     case 0:
6249       break;
6250     case 1:
6251       AccAXLsh1 (x);
6252       break;
6253     case 2:
6254       AccAXLsh1 (x);
6255       AccAXLsh1 (x);
6256       break;
6257     case 3:
6258     case 4:
6259     case 5:                     // AAAAABBB:CCCCCDDD
6260
6261       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
6262
6263       emitcode ("anl", "a,#0x%02x",
6264                 SLMask[shCount]);       // BBB00000:CCCCCDDD
6265
6266       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
6267
6268       AccRol (shCount);         // DDDCCCCC:BBB00000
6269
6270       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
6271
6272       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
6273
6274       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
6275
6276       emitcode ("anl", "a,#0x%02x",
6277                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
6278
6279       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
6280
6281       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
6282
6283       break;
6284     case 6:                     // AAAAAABB:CCCCCCDD
6285       emitcode ("anl", "a,#0x%02x",
6286                 SRMask[shCount]);       // 000000BB:CCCCCCDD
6287       emitcode ("mov", "c,acc.0");      // c = B
6288       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
6289 #if 0
6290       AccAXRrl1 (x);            // BCCCCCCD:D000000B
6291       AccAXRrl1 (x);            // BBCCCCCC:DD000000
6292 #else
6293       emitcode("rrc","a"); 
6294       emitcode("xch","a,%s", x); 
6295       emitcode("rrc","a"); 
6296       emitcode("mov","c,acc.0"); //<< get correct bit 
6297       emitcode("xch","a,%s", x); 
6298
6299       emitcode("rrc","a"); 
6300       emitcode("xch","a,%s", x); 
6301       emitcode("rrc","a"); 
6302       emitcode("xch","a,%s", x); 
6303 #endif
6304       break;
6305     case 7:                     // a:x <<= 7
6306
6307       emitcode ("anl", "a,#0x%02x",
6308                 SRMask[shCount]);       // 0000000B:CCCCCCCD
6309
6310       emitcode ("mov", "c,acc.0");      // c = B
6311
6312       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
6313
6314       AccAXRrl1 (x);            // BCCCCCCC:D0000000
6315
6316       break;
6317     default:
6318       break;
6319     }
6320 }
6321 #endif
6322
6323 #ifdef BETTER_LITERAL_SHIFT
6324 //REMOVE ME!!!
6325 /*-----------------------------------------------------------------*/
6326 /* AccAXRsh - right shift a:x known count (0..7)                   */
6327 /*-----------------------------------------------------------------*/
6328 static void
6329 AccAXRsh (char *x, int shCount)
6330 {
6331   switch (shCount)
6332     {
6333     case 0:
6334       break;
6335     case 1:
6336       CLRC;
6337       AccAXRrl1 (x);            // 0->a:x
6338
6339       break;
6340     case 2:
6341       CLRC;
6342       AccAXRrl1 (x);            // 0->a:x
6343
6344       CLRC;
6345       AccAXRrl1 (x);            // 0->a:x
6346
6347       break;
6348     case 3:
6349     case 4:
6350     case 5:                     // AAAAABBB:CCCCCDDD = a:x
6351
6352       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
6353
6354       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
6355
6356       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
6357
6358       emitcode ("anl", "a,#0x%02x",
6359                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
6360
6361       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
6362
6363       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
6364
6365       emitcode ("anl", "a,#0x%02x",
6366                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
6367
6368       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
6369
6370       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
6371
6372       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
6373
6374       break;
6375     case 6:                     // AABBBBBB:CCDDDDDD
6376
6377       emitcode ("mov", "c,acc.7");
6378       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
6379
6380       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
6381
6382       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
6383
6384       emitcode ("anl", "a,#0x%02x",
6385                 SRMask[shCount]);       // 000000AA:BBBBBBCC
6386
6387       break;
6388     case 7:                     // ABBBBBBB:CDDDDDDD
6389
6390       emitcode ("mov", "c,acc.7");      // c = A
6391
6392       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
6393
6394       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
6395
6396       emitcode ("anl", "a,#0x%02x",
6397                 SRMask[shCount]);       // 0000000A:BBBBBBBC
6398
6399       break;
6400     default:
6401       break;
6402     }
6403 }
6404 #endif
6405
6406 #ifdef BETTER_LITERAL_SHIFT
6407 //REMOVE ME!!!
6408 /*-----------------------------------------------------------------*/
6409 /* AccAXRshS - right shift signed a:x known count (0..7)           */
6410 /*-----------------------------------------------------------------*/
6411 static void
6412 AccAXRshS (char *x, int shCount)
6413 {
6414   symbol *tlbl;
6415   switch (shCount)
6416     {
6417     case 0:
6418       break;
6419     case 1:
6420       emitcode ("mov", "c,acc.7");
6421       AccAXRrl1 (x);            // s->a:x
6422
6423       break;
6424     case 2:
6425       emitcode ("mov", "c,acc.7");
6426       AccAXRrl1 (x);            // s->a:x
6427
6428       emitcode ("mov", "c,acc.7");
6429       AccAXRrl1 (x);            // s->a:x
6430
6431       break;
6432     case 3:
6433     case 4:
6434     case 5:                     // AAAAABBB:CCCCCDDD = a:x
6435
6436       tlbl = newiTempLabel (NULL);
6437       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
6438
6439       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
6440
6441       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
6442
6443       emitcode ("anl", "a,#0x%02x",
6444                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
6445
6446       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
6447
6448       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
6449
6450       emitcode ("anl", "a,#0x%02x",
6451                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
6452
6453       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
6454
6455       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
6456
6457       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
6458
6459       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6460       emitcode ("orl", "a,#0x%02x",
6461                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
6462
6463       emitcode ("", "%05d$:", tlbl->key + 100);
6464       break;                    // SSSSAAAA:BBBCCCCC
6465
6466     case 6:                     // AABBBBBB:CCDDDDDD
6467
6468       tlbl = newiTempLabel (NULL);
6469       emitcode ("mov", "c,acc.7");
6470       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
6471
6472       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
6473
6474       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
6475
6476       emitcode ("anl", "a,#0x%02x",
6477                 SRMask[shCount]);       // 000000AA:BBBBBBCC
6478
6479       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6480       emitcode ("orl", "a,#0x%02x",
6481                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
6482
6483       emitcode ("", "%05d$:", tlbl->key + 100);
6484       break;
6485     case 7:                     // ABBBBBBB:CDDDDDDD
6486
6487       tlbl = newiTempLabel (NULL);
6488       emitcode ("mov", "c,acc.7");      // c = A
6489
6490       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
6491
6492       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
6493
6494       emitcode ("anl", "a,#0x%02x",
6495                 SRMask[shCount]);       // 0000000A:BBBBBBBC
6496
6497       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6498       emitcode ("orl", "a,#0x%02x",
6499                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
6500
6501       emitcode ("", "%05d$:", tlbl->key + 100);
6502       break;
6503     default:
6504       break;
6505     }
6506 }
6507 #endif
6508
6509 #ifdef BETTER_LITERAL_SHIFT
6510 static void
6511 _loadLeftIntoAx(char    **lsb, 
6512                 operand *left, 
6513                 operand *result,
6514                 int     offl,
6515                 int     offr)
6516 {
6517   // Get the initial value from left into a pair of registers.
6518   // MSB must be in A, LSB can be any register.
6519   //
6520   // If the result is held in registers, it is an optimization
6521   // if the LSB can be held in the register which will hold the,
6522   // result LSB since this saves us from having to copy it into
6523   // the result following AccAXLsh.
6524   //
6525   // If the result is addressed indirectly, this is not a gain.
6526   if (AOP_NEEDSACC(result))
6527   {
6528        char *leftByte;
6529        
6530        _startLazyDPSEvaluation();
6531        if (AOP_TYPE(left) == AOP_DPTR2)
6532        {
6533            // Get MSB in A.
6534            MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
6535            // get LSB in DP2_RESULT_REG.
6536            leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
6537            assert(!strcmp(leftByte, DP2_RESULT_REG));
6538        }
6539        else
6540        {
6541            // get LSB into DP2_RESULT_REG
6542            leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
6543            if (strcmp(leftByte, DP2_RESULT_REG))
6544            {
6545                emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
6546            }
6547            // And MSB in A.
6548            leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
6549            assert(strcmp(leftByte, DP2_RESULT_REG));
6550            MOVA(leftByte);
6551        }
6552        _endLazyDPSEvaluation();
6553        *lsb = DP2_RESULT_REG;
6554   }
6555   else
6556   {
6557       if (sameRegs (AOP (result), AOP (left)) &&
6558         ((offl + MSB16) == offr))
6559       {
6560           /* don't crash result[offr] */
6561           MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
6562           emitcode ("xch", "a,%s", 
6563                     aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
6564       }
6565       else
6566       {
6567           movLeft2Result (left, offl, result, offr, 0);
6568           MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
6569       }
6570       *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
6571       assert(strcmp(*lsb,"a"));      
6572   }
6573 }
6574
6575 static void
6576 _storeAxResults(char    *lsb,
6577                 operand *result,
6578                 int     offr)
6579 {
6580   _startLazyDPSEvaluation();
6581   if (AOP_NEEDSACC(result))
6582   {
6583       /* We have to explicitly update the result LSB.
6584        */
6585       emitcode("xch","a,%s", lsb);
6586       aopPut(AOP(result), "a", offr);
6587       emitcode("mov","a,%s", lsb);
6588   }
6589   if (getDataSize (result) > 1)
6590   {
6591       aopPut (AOP (result), "a", offr + MSB16);
6592   }
6593   _endLazyDPSEvaluation();
6594 }
6595
6596 /*-----------------------------------------------------------------*/
6597 /* shiftL2Left2Result - shift left two bytes from left to result   */
6598 /*-----------------------------------------------------------------*/
6599 static void
6600 shiftL2Left2Result (operand * left, int offl,
6601                     operand * result, int offr, int shCount)
6602 {
6603   char *lsb;
6604
6605   _loadLeftIntoAx(&lsb, left, result, offl, offr);
6606   
6607   AccAXLsh (lsb, shCount);
6608   
6609   _storeAxResults(lsb, result, offr);
6610 }
6611 #endif
6612
6613 #ifdef BETTER_LITERAL_SHIFT
6614 /*-----------------------------------------------------------------*/
6615 /* shiftR2Left2Result - shift right two bytes from left to result  */
6616 /*-----------------------------------------------------------------*/
6617 static void
6618 shiftR2Left2Result (operand * left, int offl,
6619                     operand * result, int offr,
6620                     int shCount, int sign)
6621 {
6622   char *lsb;
6623   
6624   _loadLeftIntoAx(&lsb, left, result, offl, offr);
6625   
6626   /* a:x >> shCount (x = lsb(result)) */
6627   if (sign)
6628   {
6629     AccAXRshS(aopGet(AOP(result), offr, FALSE, FALSE, FALSE), shCount);
6630   }
6631   else
6632   {
6633     AccAXRsh(aopGet(AOP(result), offr, FALSE, FALSE, FALSE), shCount);
6634   }
6635   
6636   _storeAxResults(lsb, result, offr);
6637 }
6638 #endif
6639
6640 #if 0
6641 //REMOVE ME!!!
6642 /*-----------------------------------------------------------------*/
6643 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6644 /*-----------------------------------------------------------------*/
6645 static void
6646 shiftLLeftOrResult (operand * left, int offl,
6647                     operand * result, int offr, int shCount)
6648 {
6649   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6650   /* shift left accumulator */
6651   AccLsh (shCount);
6652   /* or with result */
6653   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6654   /* back to result */
6655   aopPut (AOP (result), "a", offr);
6656 }
6657 #endif
6658
6659 #if 0
6660 //REMOVE ME!!!
6661 /*-----------------------------------------------------------------*/
6662 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6663 /*-----------------------------------------------------------------*/
6664 static void
6665 shiftRLeftOrResult (operand * left, int offl,
6666                     operand * result, int offr, int shCount)
6667 {
6668   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6669   /* shift right accumulator */
6670   AccRsh (shCount);
6671   /* or with result */
6672   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6673   /* back to result */
6674   aopPut (AOP (result), "a", offr);
6675 }
6676 #endif
6677
6678 #ifdef BETTER_LITERAL_SHIFT
6679 /*-----------------------------------------------------------------*/
6680 /* genlshOne - left shift a one byte quantity by known count       */
6681 /*-----------------------------------------------------------------*/
6682 static void
6683 genlshOne (operand * result, operand * left, int shCount)
6684 {
6685   D (emitcode (";", "genlshOne "););
6686   shiftL1Left2Result (left, LSB, result, LSB, shCount);
6687 }
6688 #endif
6689
6690 #ifdef BETTER_LITERAL_SHIFT
6691 /*-----------------------------------------------------------------*/
6692 /* genlshTwo - left shift two bytes by known amount != 0           */
6693 /*-----------------------------------------------------------------*/
6694 static void
6695 genlshTwo (operand * result, operand * left, int shCount)
6696 {
6697   int size;
6698
6699   D (emitcode (";", "genlshTwo "););
6700
6701   size = getDataSize (result);
6702
6703   /* if shCount >= 8 */
6704   if (shCount >= 8)
6705   {
6706       shCount -= 8;
6707
6708       _startLazyDPSEvaluation();
6709
6710       if (size > 1)
6711         {
6712           if (shCount)
6713           {
6714             _endLazyDPSEvaluation();
6715             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6716             aopPut (AOP (result), zero, LSB);       
6717           }
6718           else
6719           {
6720             movLeft2Result (left, LSB, result, MSB16, 0);
6721             aopPut (AOP (result), zero, LSB);
6722             _endLazyDPSEvaluation();
6723           }
6724         }
6725         else
6726         {
6727           aopPut (AOP (result), zero, LSB);
6728           _endLazyDPSEvaluation();
6729         }
6730   }
6731
6732   /*  1 <= shCount <= 7 */
6733   else
6734     {
6735       if (size == 1)
6736       {
6737         shiftL1Left2Result (left, LSB, result, LSB, shCount);
6738       }
6739       else
6740       {
6741         shiftL2Left2Result (left, LSB, result, LSB, shCount);
6742       }
6743     }
6744 }
6745 #endif
6746
6747 #if 0
6748 //REMOVE ME!!!
6749 /*-----------------------------------------------------------------*/
6750 /* shiftLLong - shift left one long from left to result            */
6751 /* offl = LSB or MSB16                                             */
6752 /*-----------------------------------------------------------------*/
6753 static void
6754 shiftLLong (operand * left, operand * result, int offr)
6755 {
6756   char *l;
6757   int size = AOP_SIZE (result);
6758
6759   if (size >= LSB + offr)
6760     {
6761       l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
6762       MOVA (l);
6763       emitcode ("add", "a,acc");
6764       if (sameRegs (AOP (left), AOP (result)) &&
6765           size >= MSB16 + offr && offr != LSB)
6766         emitcode ("xch", "a,%s",
6767                   aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
6768       else
6769         aopPut (AOP (result), "a", LSB + offr);
6770     }
6771
6772   if (size >= MSB16 + offr)
6773     {
6774       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6775         {
6776           l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
6777           MOVA (l);
6778         }
6779       emitcode ("rlc", "a");
6780       if (sameRegs (AOP (left), AOP (result)) &&
6781           size >= MSB24 + offr && offr != LSB)
6782         emitcode ("xch", "a,%s",
6783                   aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
6784       else
6785         aopPut (AOP (result), "a", MSB16 + offr);
6786     }
6787
6788   if (size >= MSB24 + offr)
6789     {
6790       if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6791         {
6792           l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
6793           MOVA (l);
6794         }
6795       emitcode ("rlc", "a");
6796       if (sameRegs (AOP (left), AOP (result)) &&
6797           size >= MSB32 + offr && offr != LSB)
6798         emitcode ("xch", "a,%s",
6799                   aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
6800       else
6801         aopPut (AOP (result), "a", MSB24 + offr);
6802     }
6803
6804   if (size > MSB32 + offr)
6805     {
6806       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6807         {
6808           l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
6809           MOVA (l);
6810         }
6811       emitcode ("rlc", "a");
6812       aopPut (AOP (result), "a", MSB32 + offr);
6813     }
6814   if (offr != LSB)
6815     aopPut (AOP (result), zero, LSB);
6816 }
6817 #endif
6818
6819 #if 0
6820 //REMOVE ME!!!
6821 /*-----------------------------------------------------------------*/
6822 /* genlshFour - shift four byte by a known amount != 0             */
6823 /*-----------------------------------------------------------------*/
6824 static void
6825 genlshFour (operand * result, operand * left, int shCount)
6826 {
6827   int size;
6828
6829   D (emitcode (";", "genlshFour ");
6830     );
6831
6832   size = AOP_SIZE (result);
6833
6834   /* if shifting more that 3 bytes */
6835   if (shCount >= 24)
6836     {
6837       shCount -= 24;
6838       if (shCount)
6839         /* lowest order of left goes to the highest
6840            order of the destination */
6841         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6842       else
6843         movLeft2Result (left, LSB, result, MSB32, 0);
6844       aopPut (AOP (result), zero, LSB);
6845       aopPut (AOP (result), zero, MSB16);
6846       aopPut (AOP (result), zero, MSB24);
6847       return;
6848     }
6849
6850   /* more than two bytes */
6851   else if (shCount >= 16)
6852     {
6853       /* lower order two bytes goes to higher order two bytes */
6854       shCount -= 16;
6855       /* if some more remaining */
6856       if (shCount)
6857         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6858       else
6859         {
6860           movLeft2Result (left, MSB16, result, MSB32, 0);
6861           movLeft2Result (left, LSB, result, MSB24, 0);
6862         }
6863       aopPut (AOP (result), zero, MSB16);
6864       aopPut (AOP (result), zero, LSB);
6865       return;
6866     }
6867
6868   /* if more than 1 byte */
6869   else if (shCount >= 8)
6870     {
6871       /* lower order three bytes goes to higher order  three bytes */
6872       shCount -= 8;
6873       if (size == 2)
6874         {
6875           if (shCount)
6876             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6877           else
6878             movLeft2Result (left, LSB, result, MSB16, 0);
6879         }
6880       else
6881         {                       /* size = 4 */
6882           if (shCount == 0)
6883             {
6884               movLeft2Result (left, MSB24, result, MSB32, 0);
6885               movLeft2Result (left, MSB16, result, MSB24, 0);
6886               movLeft2Result (left, LSB, result, MSB16, 0);
6887               aopPut (AOP (result), zero, LSB);
6888             }
6889           else if (shCount == 1)
6890             shiftLLong (left, result, MSB16);
6891           else
6892             {
6893               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6894               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6895               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6896               aopPut (AOP (result), zero, LSB);
6897             }
6898         }
6899     }
6900
6901   /* 1 <= shCount <= 7 */
6902   else if (shCount <= 2)
6903     {
6904       shiftLLong (left, result, LSB);
6905       if (shCount == 2)
6906         shiftLLong (result, result, LSB);
6907     }
6908   /* 3 <= shCount <= 7, optimize */
6909   else
6910     {
6911       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6912       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6913       shiftL2Left2Result (left, LSB, result, LSB, shCount);
6914     }
6915 }
6916 #endif
6917
6918 #ifdef BETTER_LITERAL_SHIFT
6919 /*-----------------------------------------------------------------*/
6920 /* genLeftShiftLiteral - left shifting by known count              */
6921 /*-----------------------------------------------------------------*/
6922 static bool
6923 genLeftShiftLiteral (operand * left,
6924                      operand * right,
6925                      operand * result,
6926                      iCode * ic)
6927 {
6928   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6929   int size;
6930
6931   size = getSize (operandType (result));
6932
6933   D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
6934
6935   /* We only handle certain easy cases so far. */
6936   if ((shCount != 0)
6937    && (shCount < (size * 8))
6938    && (size != 1)
6939    && (size != 2))
6940   {
6941       D(emitcode (";", "genLeftShiftLiteral wimping out"););    
6942       return FALSE;
6943   }
6944
6945   freeAsmop (right, NULL, ic, TRUE);
6946
6947   aopOp(left, ic, FALSE, FALSE);
6948   aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
6949
6950 #if 1 // debug spew
6951   if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
6952   {
6953         emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
6954         if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
6955         {
6956            emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
6957         }
6958   }
6959   if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
6960   {
6961         emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
6962         if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
6963         {
6964            emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
6965         }       
6966   }  
6967 #endif
6968   
6969 #if VIEW_SIZE
6970   emitcode ("; shift left ", "result %d, left %d", size,
6971             AOP_SIZE (left));
6972 #endif
6973
6974   /* I suppose that the left size >= result size */
6975   if (shCount == 0)
6976   {
6977         _startLazyDPSEvaluation();
6978         while (size--)
6979         {
6980           movLeft2Result (left, size, result, size, 0);
6981         }
6982         _endLazyDPSEvaluation();
6983   }
6984   else if (shCount >= (size * 8))
6985   {
6986     _startLazyDPSEvaluation();
6987     while (size--)
6988     {
6989       aopPut (AOP (result), zero, size);
6990     }
6991     _endLazyDPSEvaluation();
6992   }
6993   else
6994   {
6995       switch (size)
6996         {
6997         case 1:
6998           genlshOne (result, left, shCount);
6999           break;
7000
7001         case 2:
7002           genlshTwo (result, left, shCount);
7003           break;
7004 #if 0
7005         case 4:
7006           genlshFour (result, left, shCount);
7007           break;
7008 #endif
7009         default:
7010           fprintf(stderr, "*** ack! mystery literal shift!\n");   
7011           break;
7012         }
7013     }
7014   freeAsmop (left, NULL, ic, TRUE);
7015   freeAsmop (result, NULL, ic, TRUE);
7016   return TRUE;
7017 }
7018 #endif
7019
7020 /*-----------------------------------------------------------------*/
7021 /* genLeftShift - generates code for left shifting                 */
7022 /*-----------------------------------------------------------------*/
7023 static void
7024 genLeftShift (iCode * ic)
7025 {
7026   operand *left, *right, *result;
7027   int size, offset;
7028   char *l;
7029   symbol *tlbl, *tlbl1;
7030
7031   D (emitcode (";", "genLeftShift "););
7032
7033   right = IC_RIGHT (ic);
7034   left = IC_LEFT (ic);
7035   result = IC_RESULT (ic);
7036
7037   aopOp (right, ic, FALSE, FALSE);
7038
7039
7040 #ifdef BETTER_LITERAL_SHIFT
7041   /* if the shift count is known then do it
7042      as efficiently as possible */
7043   if (AOP_TYPE (right) == AOP_LIT)
7044     {
7045       if (genLeftShiftLiteral (left, right, result, ic))
7046       {
7047         return;
7048       }
7049     }
7050 #endif
7051
7052   /* shift count is unknown then we have to form
7053      a loop get the loop count in B : Note: we take
7054      only the lower order byte since shifting
7055      more that 32 bits make no sense anyway, ( the
7056      largest size of an object can be only 32 bits ) */
7057
7058   if (AOP_TYPE (right) == AOP_LIT)
7059   {
7060       /* Really should be handled by genLeftShiftLiteral,
7061        * but since I'm too lazy to fix that today, at least we can make
7062        * some small improvement.
7063        */
7064        emitcode("mov", "b,#0x%02x",
7065                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7066   }
7067   else
7068   {
7069         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7070         emitcode ("inc", "b");
7071   }
7072   freeAsmop (right, NULL, ic, TRUE);
7073   aopOp (left, ic, FALSE, FALSE);
7074   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7075
7076   /* now move the left to the result if they are not the
7077      same */
7078   if (!sameRegs (AOP (left), AOP (result)) &&
7079       AOP_SIZE (result) > 1)
7080     {
7081
7082       size = AOP_SIZE (result);
7083       offset = 0;
7084       _startLazyDPSEvaluation ();
7085       while (size--)
7086         {
7087           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7088           if (*l == '@' && (IS_AOP_PREG (result)))
7089             {
7090
7091               emitcode ("mov", "a,%s", l);
7092               aopPut (AOP (result), "a", offset);
7093             }
7094           else
7095             aopPut (AOP (result), l, offset);
7096           offset++;
7097         }
7098       _endLazyDPSEvaluation ();
7099     }
7100
7101   tlbl = newiTempLabel (NULL);
7102   size = AOP_SIZE (result);
7103   offset = 0;
7104   tlbl1 = newiTempLabel (NULL);
7105
7106   /* if it is only one byte then */
7107   if (size == 1)
7108     {
7109       symbol *tlbl1 = newiTempLabel (NULL);
7110
7111       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7112       MOVA (l);
7113       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7114       emitcode ("", "%05d$:", tlbl->key + 100);
7115       emitcode ("add", "a,acc");
7116       emitcode ("", "%05d$:", tlbl1->key + 100);
7117       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7118       aopPut (AOP (result), "a", 0);
7119       goto release;
7120     }
7121
7122   reAdjustPreg (AOP (result));
7123
7124   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7125   emitcode ("", "%05d$:", tlbl->key + 100);
7126   l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7127   MOVA (l);
7128   emitcode ("add", "a,acc");
7129   aopPut (AOP (result), "a", offset++);
7130   _startLazyDPSEvaluation ();
7131   while (--size)
7132     {
7133       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7134       MOVA (l);
7135       emitcode ("rlc", "a");
7136       aopPut (AOP (result), "a", offset++);
7137     }
7138   _endLazyDPSEvaluation ();
7139   reAdjustPreg (AOP (result));
7140
7141   emitcode ("", "%05d$:", tlbl1->key + 100);
7142   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7143 release:
7144   freeAsmop (left, NULL, ic, TRUE);
7145   freeAsmop (result, NULL, ic, TRUE);
7146 }
7147
7148 #ifdef BETTER_LITERAL_SHIFT
7149 /*-----------------------------------------------------------------*/
7150 /* genrshOne - right shift a one byte quantity by known count      */
7151 /*-----------------------------------------------------------------*/
7152 static void
7153 genrshOne (operand * result, operand * left,
7154            int shCount, int sign)
7155 {
7156   D (emitcode (";", "genrshOne"););
7157   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7158 }
7159 #endif
7160
7161 #ifdef BETTER_LITERAL_SHIFT
7162 /*-----------------------------------------------------------------*/
7163 /* genrshTwo - right shift two bytes by known amount != 0          */
7164 /*-----------------------------------------------------------------*/
7165 static void
7166 genrshTwo (operand * result, operand * left,
7167            int shCount, int sign)
7168 {
7169   D (emitcode (";", "genrshTwo"););
7170
7171   /* if shCount >= 8 */
7172   if (shCount >= 8)
7173     {
7174       shCount -= 8;
7175       _startLazyDPSEvaluation();
7176       if (shCount)
7177       {
7178         shiftR1Left2Result (left, MSB16, result, LSB,
7179                             shCount, sign);
7180       }                     
7181       else
7182       {
7183         movLeft2Result (left, MSB16, result, LSB, sign);
7184       }
7185       addSign (result, MSB16, sign);
7186       _endLazyDPSEvaluation();
7187     }
7188
7189   /*  1 <= shCount <= 7 */
7190   else
7191   {
7192     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7193   }
7194 }
7195 #endif
7196
7197 #if 0
7198 //REMOVE ME!!!
7199 /*-----------------------------------------------------------------*/
7200 /* shiftRLong - shift right one long from left to result           */
7201 /* offl = LSB or MSB16                                             */
7202 /*-----------------------------------------------------------------*/
7203 static void
7204 shiftRLong (operand * left, int offl,
7205             operand * result, int sign)
7206 {
7207   if (!sign)
7208     emitcode ("clr", "c");
7209   MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE));
7210   if (sign)
7211     emitcode ("mov", "c,acc.7");
7212   emitcode ("rrc", "a");
7213   aopPut (AOP (result), "a", MSB32 - offl);
7214   if (offl == MSB16)
7215     /* add sign of "a" */
7216     addSign (result, MSB32, sign);
7217
7218   MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE));
7219   emitcode ("rrc", "a");
7220   aopPut (AOP (result), "a", MSB24 - offl);
7221
7222   MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
7223   emitcode ("rrc", "a");
7224   aopPut (AOP (result), "a", MSB16 - offl);
7225
7226   if (offl == LSB)
7227     {
7228       MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, TRUE));
7229       emitcode ("rrc", "a");
7230       aopPut (AOP (result), "a", LSB);
7231     }
7232 }
7233 #endif
7234
7235 #if 0
7236 //REMOVE ME!!!
7237 /*-----------------------------------------------------------------*/
7238 /* genrshFour - shift four byte by a known amount != 0             */
7239 /*-----------------------------------------------------------------*/
7240 static void
7241 genrshFour (operand * result, operand * left,
7242             int shCount, int sign)
7243 {
7244   D (emitcode (";", "genrshFour");
7245     );
7246
7247   /* if shifting more that 3 bytes */
7248   if (shCount >= 24)
7249     {
7250       shCount -= 24;
7251       if (shCount)
7252         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7253       else
7254         movLeft2Result (left, MSB32, result, LSB, sign);
7255       addSign (result, MSB16, sign);
7256     }
7257   else if (shCount >= 16)
7258     {
7259       shCount -= 16;
7260       if (shCount)
7261         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7262       else
7263         {
7264           movLeft2Result (left, MSB24, result, LSB, 0);
7265           movLeft2Result (left, MSB32, result, MSB16, sign);
7266         }
7267       addSign (result, MSB24, sign);
7268     }
7269   else if (shCount >= 8)
7270     {
7271       shCount -= 8;
7272       if (shCount == 1)
7273         shiftRLong (left, MSB16, result, sign);
7274       else if (shCount == 0)
7275         {
7276           movLeft2Result (left, MSB16, result, LSB, 0);
7277           movLeft2Result (left, MSB24, result, MSB16, 0);
7278           movLeft2Result (left, MSB32, result, MSB24, sign);
7279           addSign (result, MSB32, sign);
7280         }
7281       else
7282         {
7283           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7284           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7285           /* the last shift is signed */
7286           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7287           addSign (result, MSB32, sign);
7288         }
7289     }
7290   else
7291     {                           /* 1 <= shCount <= 7 */
7292       if (shCount <= 2)
7293         {
7294           shiftRLong (left, LSB, result, sign);
7295           if (shCount == 2)
7296             shiftRLong (result, LSB, result, sign);
7297         }
7298       else
7299         {
7300           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7301           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7302           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7303         }
7304     }
7305 }
7306 #endif
7307
7308 #ifdef BETTER_LITERAL_SHIFT
7309 /*-----------------------------------------------------------------*/
7310 /* genRightShiftLiteral - right shifting by known count            */
7311 /*-----------------------------------------------------------------*/
7312 static bool
7313 genRightShiftLiteral (operand * left,
7314                       operand * right,
7315                       operand * result,
7316                       iCode * ic,
7317                       int sign)
7318 {
7319   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7320   int size;
7321
7322   size = getSize (operandType (result));
7323
7324   D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
7325
7326   /* We only handle certain easy cases so far. */
7327   if ((shCount != 0)
7328    && (shCount < (size * 8))
7329    && (size != 1)
7330    && (size != 2))
7331   {
7332       D(emitcode (";", "genRightShiftLiteral wimping out"););   
7333       return FALSE;
7334   }
7335
7336   freeAsmop (right, NULL, ic, TRUE);
7337
7338   aopOp (left, ic, FALSE, FALSE);
7339   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7340
7341 #if VIEW_SIZE
7342   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7343             AOP_SIZE (left));
7344 #endif
7345
7346   /* test the LEFT size !!! */
7347
7348   /* I suppose that the left size >= result size */
7349   if (shCount == 0)
7350   {
7351       size = getDataSize (result);
7352       _startLazyDPSEvaluation();
7353       while (size--)
7354       {
7355         movLeft2Result (left, size, result, size, 0);
7356       }
7357       _endLazyDPSEvaluation();
7358   }
7359   else if (shCount >= (size * 8))
7360     {
7361       if (sign)
7362       {
7363         /* get sign in acc.7 */
7364         MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
7365       }
7366       addSign (result, LSB, sign);
7367     }
7368   else
7369     {
7370       switch (size)
7371         {
7372         case 1:
7373           genrshOne (result, left, shCount, sign);
7374           break;
7375
7376         case 2:
7377           genrshTwo (result, left, shCount, sign);
7378           break;
7379 #if 0
7380         case 4:
7381           genrshFour (result, left, shCount, sign);
7382           break;
7383 #endif    
7384         default:
7385           break;
7386         }
7387
7388       freeAsmop (left, NULL, ic, TRUE);
7389       freeAsmop (result, NULL, ic, TRUE);
7390     }
7391     return TRUE;
7392 }
7393 #endif
7394
7395 /*-----------------------------------------------------------------*/
7396 /* genSignedRightShift - right shift of signed number              */
7397 /*-----------------------------------------------------------------*/
7398 static void
7399 genSignedRightShift (iCode * ic)
7400 {
7401   operand *right, *left, *result;
7402   int size, offset;
7403   char *l;
7404   symbol *tlbl, *tlbl1;
7405
7406   D (emitcode (";", "genSignedRightShift "););
7407
7408   /* we do it the hard way put the shift count in b
7409      and loop thru preserving the sign */
7410
7411   right = IC_RIGHT (ic);
7412   left = IC_LEFT (ic);
7413   result = IC_RESULT (ic);
7414
7415   aopOp (right, ic, FALSE, FALSE);
7416
7417 #ifdef BETTER_LITERAL_SHIFT
7418   if (AOP_TYPE (right) == AOP_LIT)
7419     {
7420       if (genRightShiftLiteral (left, right, result, ic, 1))
7421       {
7422         return;
7423       }
7424     }
7425 #endif
7426   /* shift count is unknown then we have to form
7427      a loop get the loop count in B : Note: we take
7428      only the lower order byte since shifting
7429      more that 32 bits make no sense anyway, ( the
7430      largest size of an object can be only 32 bits ) */
7431
7432   if (AOP_TYPE (right) == AOP_LIT)
7433   {
7434       /* Really should be handled by genRightShiftLiteral,
7435        * but since I'm too lazy to fix that today, at least we can make
7436        * some small improvement.
7437        */
7438        emitcode("mov", "b,#0x%02x",
7439                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7440   }
7441   else
7442   {
7443         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7444         emitcode ("inc", "b");
7445   }
7446   freeAsmop (right, NULL, ic, TRUE);
7447   aopOp (left, ic, FALSE, FALSE);
7448   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7449
7450   /* now move the left to the result if they are not the
7451      same */
7452   if (!sameRegs (AOP (left), AOP (result)) &&
7453       AOP_SIZE (result) > 1)
7454     {
7455
7456       size = AOP_SIZE (result);
7457       offset = 0;
7458       _startLazyDPSEvaluation ();
7459       while (size--)
7460         {
7461           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7462           if (*l == '@' && IS_AOP_PREG (result))
7463             {
7464
7465               emitcode ("mov", "a,%s", l);
7466               aopPut (AOP (result), "a", offset);
7467             }
7468           else
7469             aopPut (AOP (result), l, offset);
7470           offset++;
7471         }
7472       _endLazyDPSEvaluation ();
7473     }
7474
7475   /* mov the highest order bit to OVR */
7476   tlbl = newiTempLabel (NULL);
7477   tlbl1 = newiTempLabel (NULL);
7478
7479   size = AOP_SIZE (result);
7480   offset = size - 1;
7481   emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
7482   emitcode ("rlc", "a");
7483   emitcode ("mov", "ov,c");
7484   /* if it is only one byte then */
7485   if (size == 1)
7486     {
7487       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7488       MOVA (l);
7489       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7490       emitcode ("", "%05d$:", tlbl->key + 100);
7491       emitcode ("mov", "c,ov");
7492       emitcode ("rrc", "a");
7493       emitcode ("", "%05d$:", tlbl1->key + 100);
7494       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7495       aopPut (AOP (result), "a", 0);
7496       goto release;
7497     }
7498
7499   reAdjustPreg (AOP (result));
7500   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7501   emitcode ("", "%05d$:", tlbl->key + 100);
7502   emitcode ("mov", "c,ov");
7503   _startLazyDPSEvaluation ();
7504   while (size--)
7505     {
7506       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7507       MOVA (l);
7508       emitcode ("rrc", "a");
7509       aopPut (AOP (result), "a", offset--);
7510     }
7511   _endLazyDPSEvaluation ();
7512   reAdjustPreg (AOP (result));
7513   emitcode ("", "%05d$:", tlbl1->key + 100);
7514   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7515
7516 release:
7517   freeAsmop (left, NULL, ic, TRUE);
7518   freeAsmop (result, NULL, ic, TRUE);
7519 }
7520
7521 /*-----------------------------------------------------------------*/
7522 /* genRightShift - generate code for right shifting                */
7523 /*-----------------------------------------------------------------*/
7524 static void
7525 genRightShift (iCode * ic)
7526 {
7527   operand *right, *left, *result;
7528   sym_link *retype;
7529   int size, offset;
7530   char *l;
7531   symbol *tlbl, *tlbl1;
7532
7533   D (emitcode (";", "genRightShift "););
7534
7535   /* if signed then we do it the hard way preserve the
7536      sign bit moving it inwards */
7537   retype = getSpec (operandType (IC_RESULT (ic)));
7538
7539   if (!SPEC_USIGN (retype))
7540     {
7541       genSignedRightShift (ic);
7542       return;
7543     }
7544
7545   /* signed & unsigned types are treated the same : i.e. the
7546      signed is NOT propagated inwards : quoting from the
7547      ANSI - standard : "for E1 >> E2, is equivalent to division
7548      by 2**E2 if unsigned or if it has a non-negative value,
7549      otherwise the result is implementation defined ", MY definition
7550      is that the sign does not get propagated */
7551
7552   right = IC_RIGHT (ic);
7553   left = IC_LEFT (ic);
7554   result = IC_RESULT (ic);
7555
7556   aopOp (right, ic, FALSE, FALSE);
7557
7558 #ifdef BETTER_LITERAL_SHIFT
7559   /* if the shift count is known then do it
7560      as efficiently as possible */
7561   if (AOP_TYPE (right) == AOP_LIT)
7562     {
7563       if (genRightShiftLiteral (left, right, result, ic, 0))
7564       {
7565         return;
7566       }
7567     }
7568 #endif
7569
7570   /* shift count is unknown then we have to form
7571      a loop get the loop count in B : Note: we take
7572      only the lower order byte since shifting
7573      more that 32 bits make no sense anyway, ( the
7574      largest size of an object can be only 32 bits ) */
7575   
7576   if (AOP_TYPE (right) == AOP_LIT)
7577   {
7578       /* Really should be handled by genRightShiftLiteral,
7579        * but since I'm too lazy to fix that today, at least we can make
7580        * some small improvement.
7581        */
7582        emitcode("mov", "b,#0x%02x",
7583                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7584   }
7585   else
7586   {
7587         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7588         emitcode ("inc", "b");
7589   }
7590   freeAsmop (right, NULL, ic, TRUE);
7591   aopOp (left, ic, FALSE, FALSE);
7592   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7593
7594   /* now move the left to the result if they are not the
7595      same */
7596   if (!sameRegs (AOP (left), AOP (result)) &&
7597       AOP_SIZE (result) > 1)
7598     {
7599
7600       size = AOP_SIZE (result);
7601       offset = 0;
7602       _startLazyDPSEvaluation ();
7603       while (size--)
7604         {
7605           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7606           if (*l == '@' && IS_AOP_PREG (result))
7607             {
7608
7609               emitcode ("mov", "a,%s", l);
7610               aopPut (AOP (result), "a", offset);
7611             }
7612           else
7613             aopPut (AOP (result), l, offset);
7614           offset++;
7615         }
7616       _endLazyDPSEvaluation ();
7617     }
7618
7619   tlbl = newiTempLabel (NULL);
7620   tlbl1 = newiTempLabel (NULL);
7621   size = AOP_SIZE (result);
7622   offset = size - 1;
7623
7624   /* if it is only one byte then */
7625   if (size == 1)
7626     {
7627       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7628       MOVA (l);
7629       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7630       emitcode ("", "%05d$:", tlbl->key + 100);
7631       CLRC;
7632       emitcode ("rrc", "a");
7633       emitcode ("", "%05d$:", tlbl1->key + 100);
7634       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7635       aopPut (AOP (result), "a", 0);
7636       goto release;
7637     }
7638
7639   reAdjustPreg (AOP (result));
7640   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7641   emitcode ("", "%05d$:", tlbl->key + 100);
7642   CLRC;
7643   _startLazyDPSEvaluation ();
7644   while (size--)
7645     {
7646       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7647       MOVA (l);
7648       emitcode ("rrc", "a");
7649       aopPut (AOP (result), "a", offset--);
7650     }
7651   _endLazyDPSEvaluation ();
7652   reAdjustPreg (AOP (result));
7653
7654   emitcode ("", "%05d$:", tlbl1->key + 100);
7655   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7656
7657 release:
7658   freeAsmop (left, NULL, ic, TRUE);
7659   freeAsmop (result, NULL, ic, TRUE);
7660 }
7661
7662 /*-----------------------------------------------------------------*/
7663 /* genUnpackBits - generates code for unpacking bits               */
7664 /*-----------------------------------------------------------------*/
7665 static void
7666 genUnpackBits (operand * result, char *rname, int ptype)
7667 {
7668   int shCnt;
7669   int rlen = 0;
7670   sym_link *etype;
7671   int offset = 0;
7672
7673   D (emitcode (";", "genUnpackBits ");
7674     );
7675
7676   etype = getSpec (operandType (result));
7677
7678   /* read the first byte  */
7679   switch (ptype)
7680     {
7681
7682     case POINTER:
7683     case IPOINTER:
7684       emitcode ("mov", "a,@%s", rname);
7685       break;
7686
7687     case PPOINTER:
7688       emitcode ("movx", "a,@%s", rname);
7689       break;
7690
7691     case FPOINTER:
7692       emitcode ("movx", "a,@dptr");
7693       break;
7694
7695     case CPOINTER:
7696       emitcode ("clr", "a");
7697       emitcode ("movc", "a", "@a+dptr");
7698       break;
7699
7700     case GPOINTER:
7701       emitcode ("lcall", "__gptrget");
7702       break;
7703     }
7704
7705   /* if we have bitdisplacement then it fits   */
7706   /* into this byte completely or if length is */
7707   /* less than a byte                          */
7708   if ((shCnt = SPEC_BSTR (etype)) ||
7709       (SPEC_BLEN (etype) <= 8))
7710     {
7711
7712       /* shift right acc */
7713       AccRsh (shCnt);
7714
7715       emitcode ("anl", "a,#0x%02x",
7716                 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
7717       aopPut (AOP (result), "a", offset);
7718       return;
7719     }
7720
7721   /* bit field did not fit in a byte  */
7722   rlen = SPEC_BLEN (etype) - 8;
7723   aopPut (AOP (result), "a", offset++);
7724
7725   while (1)
7726     {
7727
7728       switch (ptype)
7729         {
7730         case POINTER:
7731         case IPOINTER:
7732           emitcode ("inc", "%s", rname);
7733           emitcode ("mov", "a,@%s", rname);
7734           break;
7735
7736         case PPOINTER:
7737           emitcode ("inc", "%s", rname);
7738           emitcode ("movx", "a,@%s", rname);
7739           break;
7740
7741         case FPOINTER:
7742           emitcode ("inc", "dptr");
7743           emitcode ("movx", "a,@dptr");
7744           break;
7745
7746         case CPOINTER:
7747           emitcode ("clr", "a");
7748           emitcode ("inc", "dptr");
7749           emitcode ("movc", "a", "@a+dptr");
7750           break;
7751
7752         case GPOINTER:
7753           emitcode ("inc", "dptr");
7754           emitcode ("lcall", "__gptrget");
7755           break;
7756         }
7757
7758       rlen -= 8;
7759       /* if we are done */
7760       if (rlen < 8)
7761         break;
7762
7763       aopPut (AOP (result), "a", offset++);
7764
7765     }
7766
7767   if (rlen)
7768     {
7769       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
7770       aopPut (AOP (result), "a", offset);
7771     }
7772
7773   return;
7774 }
7775
7776
7777 /*-----------------------------------------------------------------*/
7778 /* genDataPointerGet - generates code when ptr offset is known     */
7779 /*-----------------------------------------------------------------*/
7780 static void
7781 genDataPointerGet (operand * left,
7782                    operand * result,
7783                    iCode * ic)
7784 {
7785   char *l;
7786   char buffer[256];
7787   int size, offset = 0;
7788   aopOp (result, ic, TRUE, FALSE);
7789
7790   /* get the string representation of the name */
7791   l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
7792   size = AOP_SIZE (result);
7793   _startLazyDPSEvaluation ();
7794   while (size--)
7795     {
7796       if (offset)
7797         sprintf (buffer, "(%s + %d)", l + 1, offset);
7798       else
7799         sprintf (buffer, "%s", l + 1);
7800       aopPut (AOP (result), buffer, offset++);
7801     }
7802   _endLazyDPSEvaluation ();
7803
7804   freeAsmop (left, NULL, ic, TRUE);
7805   freeAsmop (result, NULL, ic, TRUE);
7806 }
7807
7808 /*-----------------------------------------------------------------*/
7809 /* genNearPointerGet - emitcode for near pointer fetch             */
7810 /*-----------------------------------------------------------------*/
7811 static void
7812 genNearPointerGet (operand * left,
7813                    operand * result,
7814                    iCode * ic)
7815 {
7816   asmop *aop = NULL;
7817   regs *preg = NULL;
7818   char *rname;
7819   sym_link *rtype, *retype, *letype;
7820   sym_link *ltype = operandType (left);
7821   char buffer[80];
7822
7823   rtype = operandType (result);
7824   retype = getSpec (rtype);
7825   letype = getSpec (ltype);
7826
7827   aopOp (left, ic, FALSE, FALSE);
7828
7829   /* if left is rematerialisable and
7830      result is not bit variable type and
7831      the left is pointer to data space i.e
7832      lower 128 bytes of space */
7833   if (AOP_TYPE (left) == AOP_IMMD &&
7834       !IS_BITVAR (retype) &&
7835       !IS_BITVAR (letype) &&
7836       DCL_TYPE (ltype) == POINTER)
7837     {
7838       genDataPointerGet (left, result, ic);
7839       return;
7840     }
7841
7842   /* if the value is already in a pointer register
7843      then don't need anything more */
7844   if (!AOP_INPREG (AOP (left)))
7845     {
7846       /* otherwise get a free pointer register */
7847       aop = newAsmop (0);
7848       preg = getFreePtr (ic, &aop, FALSE);
7849       emitcode ("mov", "%s,%s",
7850                 preg->name,
7851                 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
7852       rname = preg->name;
7853     }
7854   else
7855     rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
7856
7857   freeAsmop (left, NULL, ic, TRUE);
7858   aopOp (result, ic, FALSE, FALSE);
7859
7860   /* if bitfield then unpack the bits */
7861   if (IS_BITVAR (retype) || IS_BITVAR (letype))
7862     genUnpackBits (result, rname, POINTER);
7863   else
7864     {
7865       /* we have can just get the values */
7866       int size = AOP_SIZE (result);
7867       int offset = 0;
7868
7869       while (size--)
7870         {
7871           if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7872             {
7873
7874               emitcode ("mov", "a,@%s", rname);
7875               aopPut (AOP (result), "a", offset);
7876             }
7877           else
7878             {
7879               sprintf (buffer, "@%s", rname);
7880               aopPut (AOP (result), buffer, offset);
7881             }
7882           offset++;
7883           if (size)
7884             emitcode ("inc", "%s", rname);
7885         }
7886     }
7887
7888   /* now some housekeeping stuff */
7889   if (aop)
7890     {
7891       /* we had to allocate for this iCode */
7892       freeAsmop (NULL, aop, ic, TRUE);
7893     }
7894   else
7895     {
7896       /* we did not allocate which means left
7897          already in a pointer register, then
7898          if size > 0 && this could be used again
7899          we have to point it back to where it
7900          belongs */
7901       if (AOP_SIZE (result) > 1 &&
7902           !OP_SYMBOL (left)->remat &&
7903           (OP_SYMBOL (left)->liveTo > ic->seq ||
7904            ic->depth))
7905         {
7906           int size = AOP_SIZE (result) - 1;
7907           while (size--)
7908             emitcode ("dec", "%s", rname);
7909         }
7910     }
7911
7912   /* done */
7913   freeAsmop (result, NULL, ic, TRUE);
7914
7915 }
7916
7917 /*-----------------------------------------------------------------*/
7918 /* genPagedPointerGet - emitcode for paged pointer fetch           */
7919 /*-----------------------------------------------------------------*/
7920 static void
7921 genPagedPointerGet (operand * left,
7922                     operand * result,
7923                     iCode * ic)
7924 {
7925   asmop *aop = NULL;
7926   regs *preg = NULL;
7927   char *rname;
7928   sym_link *rtype, *retype, *letype;
7929
7930   rtype = operandType (result);
7931   retype = getSpec (rtype);
7932   letype = getSpec (operandType (left));
7933   aopOp (left, ic, FALSE, FALSE);
7934
7935   /* if the value is already in a pointer register
7936      then don't need anything more */
7937   if (!AOP_INPREG (AOP (left)))
7938     {
7939       /* otherwise get a free pointer register */
7940       aop = newAsmop (0);
7941       preg = getFreePtr (ic, &aop, FALSE);
7942       emitcode ("mov", "%s,%s",
7943                 preg->name,
7944                 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
7945       rname = preg->name;
7946     }
7947   else
7948     rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
7949
7950   freeAsmop (left, NULL, ic, TRUE);
7951   aopOp (result, ic, FALSE, FALSE);
7952
7953   /* if bitfield then unpack the bits */
7954   if (IS_BITVAR (retype) || IS_BITVAR (letype))
7955     genUnpackBits (result, rname, PPOINTER);
7956   else
7957     {
7958       /* we have can just get the values */
7959       int size = AOP_SIZE (result);
7960       int offset = 0;
7961
7962       while (size--)
7963         {
7964
7965           emitcode ("movx", "a,@%s", rname);
7966           aopPut (AOP (result), "a", offset);
7967
7968           offset++;
7969
7970           if (size)
7971             emitcode ("inc", "%s", rname);
7972         }
7973     }
7974
7975   /* now some housekeeping stuff */
7976   if (aop)
7977     {
7978       /* we had to allocate for this iCode */
7979       freeAsmop (NULL, aop, ic, TRUE);
7980     }
7981   else
7982     {
7983       /* we did not allocate which means left
7984          already in a pointer register, then
7985          if size > 0 && this could be used again
7986          we have to point it back to where it
7987          belongs */
7988       if (AOP_SIZE (result) > 1 &&
7989           !OP_SYMBOL (left)->remat &&
7990           (OP_SYMBOL (left)->liveTo > ic->seq ||
7991            ic->depth))
7992         {
7993           int size = AOP_SIZE (result) - 1;
7994           while (size--)
7995             emitcode ("dec", "%s", rname);
7996         }
7997     }
7998
7999   /* done */
8000   freeAsmop (result, NULL, ic, TRUE);
8001
8002
8003 }
8004
8005 /*-----------------------------------------------------------------*/
8006 /* genFarPointerGet - gget value from far space                    */
8007 /*-----------------------------------------------------------------*/
8008 static void
8009 genFarPointerGet (operand * left,
8010                   operand * result, iCode * ic)
8011 {
8012   int size, offset;
8013   sym_link *retype = getSpec (operandType (result));
8014   sym_link *letype = getSpec (operandType (left));
8015   D (emitcode (";", "genFarPointerGet");
8016     );
8017
8018   aopOp (left, ic, FALSE, FALSE);
8019
8020   /* if the operand is already in dptr
8021      then we do nothing else we move the value to dptr */
8022   if (AOP_TYPE (left) != AOP_STR)
8023     {
8024       /* if this is remateriazable */
8025       if (AOP_TYPE (left) == AOP_IMMD)
8026         {
8027           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8028         }
8029       else
8030         {
8031           /* we need to get it byte by byte */
8032           _startLazyDPSEvaluation ();
8033           if (AOP_TYPE (left) != AOP_DPTR)
8034             {
8035               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8036               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8037               emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8038             }
8039           else
8040             {
8041               /* We need to generate a load to DPTR indirect through DPTR. */
8042               D (emitcode (";", "genFarPointerGet -- indirection special case.");
8043                 );
8044               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8045               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8046               emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8047               emitcode ("pop", "dph");
8048               emitcode ("pop", "dpl");
8049             }
8050           _endLazyDPSEvaluation ();
8051         }
8052     }
8053   /* so dptr know contains the address */
8054   freeAsmop (left, NULL, ic, TRUE);
8055   aopOp (result, ic, FALSE, TRUE);
8056
8057   /* if bit then unpack */
8058   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8059     genUnpackBits (result, "dptr", FPOINTER);
8060   else
8061     {
8062       size = AOP_SIZE (result);
8063       offset = 0;
8064
8065       _startLazyDPSEvaluation ();
8066       while (size--)
8067         {
8068
8069           genSetDPTR (0);
8070           _flushLazyDPS ();
8071
8072           emitcode ("movx", "a,@dptr");
8073           if (size)
8074             emitcode ("inc", "dptr");
8075
8076           aopPut (AOP (result), "a", offset++);
8077         }
8078       _endLazyDPSEvaluation ();
8079     }
8080
8081   freeAsmop (result, NULL, ic, TRUE);
8082 }
8083
8084 /*-----------------------------------------------------------------*/
8085 /* emitcodePointerGet - gget value from code space                  */
8086 /*-----------------------------------------------------------------*/
8087 static void
8088 emitcodePointerGet (operand * left,
8089                     operand * result, iCode * ic)
8090 {
8091   int size, offset;
8092   sym_link *retype = getSpec (operandType (result));
8093
8094   aopOp (left, ic, FALSE, FALSE);
8095
8096   /* if the operand is already in dptr
8097      then we do nothing else we move the value to dptr */
8098   if (AOP_TYPE (left) != AOP_STR)
8099     {
8100       /* if this is remateriazable */
8101       if (AOP_TYPE (left) == AOP_IMMD)
8102         {
8103           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8104         }
8105       else
8106         {                       /* we need to get it byte by byte */
8107           _startLazyDPSEvaluation ();
8108           if (AOP_TYPE (left) != AOP_DPTR)
8109             {
8110               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8111               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8112               emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8113             }
8114           else
8115             {
8116               /* We need to generate a load to DPTR indirect through DPTR. */
8117               D (emitcode (";", "gencodePointerGet -- indirection special case.");
8118                 );
8119               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8120               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8121               emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8122               emitcode ("pop", "dph");
8123               emitcode ("pop", "dpl");
8124             }
8125           _endLazyDPSEvaluation ();
8126         }
8127     }
8128   /* so dptr know contains the address */
8129   freeAsmop (left, NULL, ic, TRUE);
8130   aopOp (result, ic, FALSE, TRUE);
8131
8132   /* if bit then unpack */
8133   if (IS_BITVAR (retype))
8134     genUnpackBits (result, "dptr", CPOINTER);
8135   else
8136     {
8137       size = AOP_SIZE (result);
8138       offset = 0;
8139
8140       _startLazyDPSEvaluation ();
8141       while (size--)
8142         {
8143           genSetDPTR (0);
8144           _flushLazyDPS ();
8145
8146           emitcode ("clr", "a");
8147           emitcode ("movc", "a,@a+dptr");
8148           if (size)
8149             emitcode ("inc", "dptr");
8150           aopPut (AOP (result), "a", offset++);
8151         }
8152       _endLazyDPSEvaluation ();
8153     }
8154
8155   freeAsmop (result, NULL, ic, TRUE);
8156 }
8157
8158 /*-----------------------------------------------------------------*/
8159 /* genGenPointerGet - gget value from generic pointer space        */
8160 /*-----------------------------------------------------------------*/
8161 static void
8162 genGenPointerGet (operand * left,
8163                   operand * result, iCode * ic)
8164 {
8165   int size, offset;
8166   sym_link *retype = getSpec (operandType (result));
8167   sym_link *letype = getSpec (operandType (left));
8168
8169   D (emitcode (";", "genGenPointerGet "); );
8170
8171   aopOp (left, ic, FALSE, TRUE);
8172
8173   /* if the operand is already in dptr
8174      then we do nothing else we move the value to dptr */
8175   if (AOP_TYPE (left) != AOP_STR)
8176     {
8177       /* if this is remateriazable */
8178       if (AOP_TYPE (left) == AOP_IMMD)
8179         {
8180           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8181           emitcode ("mov", "b,#%d", pointerCode (retype));
8182         }
8183       else
8184         {                       /* we need to get it byte by byte */
8185           _startLazyDPSEvaluation ();
8186           if (AOP(left)->type==AOP_DPTR2) {
8187             char *l;
8188             l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
8189             genSetDPTR(0);
8190             _flushLazyDPS();
8191             emitcode ("mov", "dpl,%s", l);
8192             l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
8193             genSetDPTR(0);
8194             _flushLazyDPS();
8195             emitcode ("mov", "dph,%s", l);
8196             l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
8197             genSetDPTR(0);
8198             _flushLazyDPS();
8199             emitcode ("mov", "dpx,%s", l);
8200             emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8201           } else {
8202             emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
8203             emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
8204             emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8205             emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8206           }
8207           _endLazyDPSEvaluation ();
8208         }
8209     }
8210   /* so dptr know contains the address */
8211   freeAsmop (left, NULL, ic, TRUE);
8212   aopOp (result, ic, FALSE, TRUE);
8213
8214   /* if bit then unpack */
8215   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8216     genUnpackBits (result, "dptr", GPOINTER);
8217   else
8218     {
8219       size = AOP_SIZE (result);
8220       offset = 0;
8221
8222       while (size--)
8223         {
8224           emitcode ("lcall", "__gptrget");
8225           aopPut (AOP (result), "a", offset++);
8226           if (size)
8227             emitcode ("inc", "dptr");
8228         }
8229     }
8230
8231   freeAsmop (result, NULL, ic, TRUE);
8232 }
8233
8234 /*-----------------------------------------------------------------*/
8235 /* genPointerGet - generate code for pointer get                   */
8236 /*-----------------------------------------------------------------*/
8237 static void
8238 genPointerGet (iCode * ic)
8239 {
8240   operand *left, *result;
8241   sym_link *type, *etype;
8242   int p_type;
8243
8244   D (emitcode (";", "genPointerGet ");
8245     );
8246
8247   left = IC_LEFT (ic);
8248   result = IC_RESULT (ic);
8249
8250   /* depending on the type of pointer we need to
8251      move it to the correct pointer register */
8252   type = operandType (left);
8253   etype = getSpec (type);
8254   /* if left is of type of pointer then it is simple */
8255   if (IS_PTR (type) && !IS_FUNC (type->next))
8256     p_type = DCL_TYPE (type);
8257   else
8258     {
8259       /* we have to go by the storage class */
8260       p_type = PTR_TYPE (SPEC_OCLS (etype));
8261     }
8262
8263   /* now that we have the pointer type we assign
8264      the pointer values */
8265   switch (p_type)
8266     {
8267
8268     case POINTER:
8269     case IPOINTER:
8270       genNearPointerGet (left, result, ic);
8271       break;
8272
8273     case PPOINTER:
8274       genPagedPointerGet (left, result, ic);
8275       break;
8276
8277     case FPOINTER:
8278       genFarPointerGet (left, result, ic);
8279       break;
8280
8281     case CPOINTER:
8282       emitcodePointerGet (left, result, ic);
8283       break;
8284
8285     case GPOINTER:
8286       genGenPointerGet (left, result, ic);
8287       break;
8288     }
8289
8290 }
8291
8292 /*-----------------------------------------------------------------*/
8293 /* genPackBits - generates code for packed bit storage             */
8294 /*-----------------------------------------------------------------*/
8295 static void
8296 genPackBits (sym_link * etype,
8297              operand * right,
8298              char *rname, int p_type)
8299 {
8300   int shCount = 0;
8301   int offset = 0;
8302   int rLen = 0;
8303   int blen, bstr;
8304   char *l;
8305
8306   blen = SPEC_BLEN (etype);
8307   bstr = SPEC_BSTR (etype);
8308
8309   l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8310   MOVA (l);
8311
8312   /* if the bit lenth is less than or    */
8313   /* it exactly fits a byte then         */
8314   if (SPEC_BLEN (etype) <= 8)
8315     {
8316       shCount = SPEC_BSTR (etype);
8317
8318       /* shift left acc */
8319       AccLsh (shCount);
8320
8321       if (SPEC_BLEN (etype) < 8)
8322         {                       /* if smaller than a byte */
8323
8324
8325           switch (p_type)
8326             {
8327             case POINTER:
8328               emitcode ("mov", "b,a");
8329               emitcode ("mov", "a,@%s", rname);
8330               break;
8331
8332             case FPOINTER:
8333               emitcode ("mov", "b,a");
8334               emitcode ("movx", "a,@dptr");
8335               break;
8336
8337             case GPOINTER:
8338               emitcode ("push", "b");
8339               emitcode ("push", "acc");
8340               emitcode ("lcall", "__gptrget");
8341               emitcode ("pop", "b");
8342               break;
8343             }
8344
8345           emitcode ("anl", "a,#0x%02x", (unsigned char)
8346                     ((unsigned char) (0xFF << (blen + bstr)) |
8347                      (unsigned char) (0xFF >> (8 - bstr))));
8348           emitcode ("orl", "a,b");
8349           if (p_type == GPOINTER)
8350             emitcode ("pop", "b");
8351         }
8352     }
8353
8354   switch (p_type)
8355     {
8356     case POINTER:
8357       emitcode ("mov", "@%s,a", rname);
8358       break;
8359
8360     case FPOINTER:
8361       emitcode ("movx", "@dptr,a");
8362       break;
8363
8364     case GPOINTER:
8365       emitcode ("lcall", "__gptrput");
8366       break;
8367     }
8368
8369   /* if we r done */
8370   if (SPEC_BLEN (etype) <= 8)
8371     return;
8372
8373   emitcode ("inc", "%s", rname);
8374   rLen = SPEC_BLEN (etype);
8375
8376   /* now generate for lengths greater than one byte */
8377   while (1)
8378     {
8379
8380       l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
8381
8382       rLen -= 8;
8383       if (rLen < 8)
8384         break;
8385
8386       switch (p_type)
8387         {
8388         case POINTER:
8389           if (*l == '@')
8390             {
8391               MOVA (l);
8392               emitcode ("mov", "@%s,a", rname);
8393             }
8394           else
8395             emitcode ("mov", "@%s,%s", rname, l);
8396           break;
8397
8398         case FPOINTER:
8399           MOVA (l);
8400           emitcode ("movx", "@dptr,a");
8401           break;
8402
8403         case GPOINTER:
8404           MOVA (l);
8405           emitcode ("lcall", "__gptrput");
8406           break;
8407         }
8408       emitcode ("inc", "%s", rname);
8409     }
8410
8411   MOVA (l);
8412
8413   /* last last was not complete */
8414   if (rLen)
8415     {
8416       /* save the byte & read byte */
8417       switch (p_type)
8418         {
8419         case POINTER:
8420           emitcode ("mov", "b,a");
8421           emitcode ("mov", "a,@%s", rname);
8422           break;
8423
8424         case FPOINTER:
8425           emitcode ("mov", "b,a");
8426           emitcode ("movx", "a,@dptr");
8427           break;
8428
8429         case GPOINTER:
8430           emitcode ("push", "b");
8431           emitcode ("push", "acc");
8432           emitcode ("lcall", "__gptrget");
8433           emitcode ("pop", "b");
8434           break;
8435         }
8436
8437       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
8438       emitcode ("orl", "a,b");
8439     }
8440
8441   if (p_type == GPOINTER)
8442     emitcode ("pop", "b");
8443
8444   switch (p_type)
8445     {
8446
8447     case POINTER:
8448       emitcode ("mov", "@%s,a", rname);
8449       break;
8450
8451     case FPOINTER:
8452       emitcode ("movx", "@dptr,a");
8453       break;
8454
8455     case GPOINTER:
8456       emitcode ("lcall", "__gptrput");
8457       break;
8458     }
8459 }
8460 /*-----------------------------------------------------------------*/
8461 /* genDataPointerSet - remat pointer to data space                 */
8462 /*-----------------------------------------------------------------*/
8463 static void
8464 genDataPointerSet (operand * right,
8465                    operand * result,
8466                    iCode * ic)
8467 {
8468   int size, offset = 0;
8469   char *l, buffer[256];
8470
8471   aopOp (right, ic, FALSE, FALSE);
8472
8473   l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
8474   size = AOP_SIZE (right);
8475   while (size--)
8476     {
8477       if (offset)
8478         sprintf (buffer, "(%s + %d)", l + 1, offset);
8479       else
8480         sprintf (buffer, "%s", l + 1);
8481       emitcode ("mov", "%s,%s", buffer,
8482                 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
8483     }
8484
8485   freeAsmop (right, NULL, ic, TRUE);
8486   freeAsmop (result, NULL, ic, TRUE);
8487 }
8488
8489 /*-----------------------------------------------------------------*/
8490 /* genNearPointerSet - emitcode for near pointer put                */
8491 /*-----------------------------------------------------------------*/
8492 static void
8493 genNearPointerSet (operand * right,
8494                    operand * result,
8495                    iCode * ic)
8496 {
8497   asmop *aop = NULL;
8498   regs *preg = NULL;
8499   char *rname, *l;
8500   sym_link *retype, *letype;
8501   sym_link *ptype = operandType (result);
8502
8503   retype = getSpec (operandType (right));
8504   letype = getSpec (ptype);
8505
8506   aopOp (result, ic, FALSE, FALSE);
8507
8508   /* if the result is rematerializable &
8509      in data space & not a bit variable */
8510   if (AOP_TYPE (result) == AOP_IMMD &&
8511       DCL_TYPE (ptype) == POINTER &&
8512       !IS_BITVAR (retype) &&
8513       !IS_BITVAR (letype))
8514     {
8515       genDataPointerSet (right, result, ic);
8516       return;
8517     }
8518
8519   /* if the value is already in a pointer register
8520      then don't need anything more */
8521   if (!AOP_INPREG (AOP (result)))
8522     {
8523       /* otherwise get a free pointer register */
8524       aop = newAsmop (0);
8525       preg = getFreePtr (ic, &aop, FALSE);
8526       emitcode ("mov", "%s,%s",
8527                 preg->name,
8528                 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8529       rname = preg->name;
8530     }
8531   else
8532     rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8533
8534   freeAsmop (result, NULL, ic, TRUE);
8535   aopOp (right, ic, FALSE, FALSE);
8536
8537   /* if bitfield then unpack the bits */
8538   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8539     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
8540   else
8541     {
8542       /* we have can just get the values */
8543       int size = AOP_SIZE (right);
8544       int offset = 0;
8545
8546       while (size--)
8547         {
8548           l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
8549           if (*l == '@')
8550             {
8551               MOVA (l);
8552               emitcode ("mov", "@%s,a", rname);
8553             }
8554           else
8555             emitcode ("mov", "@%s,%s", rname, l);
8556           if (size)
8557             emitcode ("inc", "%s", rname);
8558           offset++;
8559         }
8560     }
8561
8562   /* now some housekeeping stuff */
8563   if (aop)
8564     {
8565       /* we had to allocate for this iCode */
8566       freeAsmop (NULL, aop, ic, TRUE);
8567     }
8568   else
8569     {
8570       /* we did not allocate which means left
8571          already in a pointer register, then
8572          if size > 0 && this could be used again
8573          we have to point it back to where it
8574          belongs */
8575       if (AOP_SIZE (right) > 1 &&
8576           !OP_SYMBOL (result)->remat &&
8577           (OP_SYMBOL (result)->liveTo > ic->seq ||
8578            ic->depth))
8579         {
8580           int size = AOP_SIZE (right) - 1;
8581           while (size--)
8582             emitcode ("dec", "%s", rname);
8583         }
8584     }
8585
8586   /* done */
8587   freeAsmop (right, NULL, ic, TRUE);
8588
8589
8590 }
8591
8592 /*-----------------------------------------------------------------*/
8593 /* genPagedPointerSet - emitcode for Paged pointer put             */
8594 /*-----------------------------------------------------------------*/
8595 static void
8596 genPagedPointerSet (operand * right,
8597                     operand * result,
8598                     iCode * ic)
8599 {
8600   asmop *aop = NULL;
8601   regs *preg = NULL;
8602   char *rname, *l;
8603   sym_link *retype, *letype;
8604
8605   retype = getSpec (operandType (right));
8606   letype = getSpec (operandType (result));
8607
8608   aopOp (result, ic, FALSE, FALSE);
8609
8610   /* if the value is already in a pointer register
8611      then don't need anything more */
8612   if (!AOP_INPREG (AOP (result)))
8613     {
8614       /* otherwise get a free pointer register */
8615       aop = newAsmop (0);
8616       preg = getFreePtr (ic, &aop, FALSE);
8617       emitcode ("mov", "%s,%s",
8618                 preg->name,
8619                 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8620       rname = preg->name;
8621     }
8622   else
8623     rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8624
8625   freeAsmop (result, NULL, ic, TRUE);
8626   aopOp (right, ic, FALSE, FALSE);
8627
8628   /* if bitfield then unpack the bits */
8629   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8630     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8631   else
8632     {
8633       /* we have can just get the values */
8634       int size = AOP_SIZE (right);
8635       int offset = 0;
8636
8637       while (size--)
8638         {
8639           l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
8640
8641           MOVA (l);
8642           emitcode ("movx", "@%s,a", rname);
8643
8644           if (size)
8645             emitcode ("inc", "%s", rname);
8646
8647           offset++;
8648         }
8649     }
8650
8651   /* now some housekeeping stuff */
8652   if (aop)
8653     {
8654       /* we had to allocate for this iCode */
8655       freeAsmop (NULL, aop, ic, TRUE);
8656     }
8657   else
8658     {
8659       /* we did not allocate which means left
8660          already in a pointer register, then
8661          if size > 0 && this could be used again
8662          we have to point it back to where it
8663          belongs */
8664       if (AOP_SIZE (right) > 1 &&
8665           !OP_SYMBOL (result)->remat &&
8666           (OP_SYMBOL (result)->liveTo > ic->seq ||
8667            ic->depth))
8668         {
8669           int size = AOP_SIZE (right) - 1;
8670           while (size--)
8671             emitcode ("dec", "%s", rname);
8672         }
8673     }
8674
8675   /* done */
8676   freeAsmop (right, NULL, ic, TRUE);
8677
8678
8679 }
8680
8681 /*-----------------------------------------------------------------*/
8682 /* genFarPointerSet - set value from far space                     */
8683 /*-----------------------------------------------------------------*/
8684 static void
8685 genFarPointerSet (operand * right,
8686                   operand * result, iCode * ic)
8687 {
8688   int size, offset;
8689   sym_link *retype = getSpec (operandType (right));
8690   sym_link *letype = getSpec (operandType (result));
8691
8692   aopOp (result, ic, FALSE, FALSE);
8693
8694   /* if the operand is already in dptr
8695      then we do nothing else we move the value to dptr */
8696   if (AOP_TYPE (result) != AOP_STR)
8697     {
8698       /* if this is remateriazable */
8699       if (AOP_TYPE (result) == AOP_IMMD)
8700         emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8701       else
8702         {
8703           /* we need to get it byte by byte */
8704           _startLazyDPSEvaluation ();
8705           if (AOP_TYPE (result) != AOP_DPTR)
8706             {
8707               emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8708               emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8709               emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8710             }
8711           else
8712             {
8713               /* We need to generate a load to DPTR indirect through DPTR. */
8714               D (emitcode (";", "genFarPointerSet -- indirection special case.");
8715                 );
8716               emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
8717               emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
8718               emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8719               emitcode ("pop", "dph");
8720               emitcode ("pop", "dpl");
8721             }
8722           _endLazyDPSEvaluation ();
8723         }
8724     }
8725   /* so dptr know contains the address */
8726   freeAsmop (result, NULL, ic, TRUE);
8727   aopOp (right, ic, FALSE, TRUE);
8728
8729   /* if bit then unpack */
8730   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8731     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8732   else
8733     {
8734       size = AOP_SIZE (right);
8735       offset = 0;
8736
8737       _startLazyDPSEvaluation ();
8738       while (size--)
8739         {
8740           char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8741           MOVA (l);
8742
8743           genSetDPTR (0);
8744           _flushLazyDPS ();
8745
8746           emitcode ("movx", "@dptr,a");
8747           if (size)
8748             emitcode ("inc", "dptr");
8749         }
8750       _endLazyDPSEvaluation ();
8751     }
8752
8753   freeAsmop (right, NULL, ic, TRUE);
8754 }
8755
8756 /*-----------------------------------------------------------------*/
8757 /* genGenPointerSet - set value from generic pointer space         */
8758 /*-----------------------------------------------------------------*/
8759 static void
8760 genGenPointerSet (operand * right,
8761                   operand * result, iCode * ic)
8762 {
8763   int size, offset;
8764   sym_link *retype = getSpec (operandType (right));
8765   sym_link *letype = getSpec (operandType (result));
8766
8767   aopOp (result, ic, FALSE, TRUE);
8768
8769   /* if the operand is already in dptr
8770      then we do nothing else we move the value to dptr */
8771   if (AOP_TYPE (result) != AOP_STR)
8772     {
8773       _startLazyDPSEvaluation ();
8774       /* if this is remateriazable */
8775       if (AOP_TYPE (result) == AOP_IMMD)
8776         {
8777           emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8778           emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8779         }
8780       else
8781         {                       /* we need to get it byte by byte */
8782           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8783           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8784           emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8785           emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
8786         }
8787       _endLazyDPSEvaluation ();
8788     }
8789   /* so dptr know contains the address */
8790   freeAsmop (result, NULL, ic, TRUE);
8791   aopOp (right, ic, FALSE, TRUE);
8792
8793   /* if bit then unpack */
8794   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8795     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8796   else
8797     {
8798       size = AOP_SIZE (right);
8799       offset = 0;
8800
8801       _startLazyDPSEvaluation ();
8802       while (size--)
8803         {
8804           char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8805           MOVA (l);
8806
8807           genSetDPTR (0);
8808           _flushLazyDPS ();
8809
8810           emitcode ("lcall", "__gptrput");
8811           if (size)
8812             emitcode ("inc", "dptr");
8813         }
8814       _endLazyDPSEvaluation ();
8815     }
8816
8817   freeAsmop (right, NULL, ic, TRUE);
8818 }
8819
8820 /*-----------------------------------------------------------------*/
8821 /* genPointerSet - stores the value into a pointer location        */
8822 /*-----------------------------------------------------------------*/
8823 static void
8824 genPointerSet (iCode * ic)
8825 {
8826   operand *right, *result;
8827   sym_link *type, *etype;
8828   int p_type;
8829
8830   D (emitcode (";", "genPointerSet ");
8831     );
8832
8833   right = IC_RIGHT (ic);
8834   result = IC_RESULT (ic);
8835
8836   /* depending on the type of pointer we need to
8837      move it to the correct pointer register */
8838   type = operandType (result);
8839   etype = getSpec (type);
8840   /* if left is of type of pointer then it is simple */
8841   if (IS_PTR (type) && !IS_FUNC (type->next))
8842     {
8843       p_type = DCL_TYPE (type);
8844     }
8845   else
8846     {
8847       /* we have to go by the storage class */
8848       p_type = PTR_TYPE (SPEC_OCLS (etype));
8849     }
8850
8851   /* now that we have the pointer type we assign
8852      the pointer values */
8853   switch (p_type)
8854     {
8855
8856     case POINTER:
8857     case IPOINTER:
8858       genNearPointerSet (right, result, ic);
8859       break;
8860
8861     case PPOINTER:
8862       genPagedPointerSet (right, result, ic);
8863       break;
8864
8865     case FPOINTER:
8866       genFarPointerSet (right, result, ic);
8867       break;
8868
8869     case GPOINTER:
8870       genGenPointerSet (right, result, ic);
8871       break;
8872     }
8873
8874 }
8875
8876 /*-----------------------------------------------------------------*/
8877 /* genIfx - generate code for Ifx statement                        */
8878 /*-----------------------------------------------------------------*/
8879 static void
8880 genIfx (iCode * ic, iCode * popIc)
8881 {
8882   operand *cond = IC_COND (ic);
8883   int isbit = 0;
8884
8885   D (emitcode (";", "genIfx "););
8886
8887   aopOp (cond, ic, FALSE, FALSE);
8888
8889   /* get the value into acc */
8890   if (AOP_TYPE (cond) != AOP_CRY)
8891     toBoolean (cond);
8892   else
8893     isbit = 1;
8894   /* the result is now in the accumulator */
8895   freeAsmop (cond, NULL, ic, TRUE);
8896
8897   /* if there was something to be popped then do it */
8898   if (popIc)
8899     genIpop (popIc);
8900
8901   /* if the condition is  a bit variable */
8902   if (isbit && IS_ITEMP (cond) &&
8903       SPIL_LOC (cond))
8904     genIfxJump (ic, SPIL_LOC (cond)->rname);
8905   else if (isbit && !IS_ITEMP (cond))
8906     genIfxJump (ic, OP_SYMBOL (cond)->rname);
8907   else
8908     genIfxJump (ic, "a");
8909
8910   ic->generated = 1;
8911 }
8912
8913 /*-----------------------------------------------------------------*/
8914 /* genAddrOf - generates code for address of                       */
8915 /*-----------------------------------------------------------------*/
8916 static void
8917 genAddrOf (iCode * ic)
8918 {
8919   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8920   int size, offset;
8921
8922   D (emitcode (";", "genAddrOf ");
8923     );
8924
8925   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
8926
8927   /* if the operand is on the stack then we
8928      need to get the stack offset of this
8929      variable */
8930   if (sym->onStack)
8931     {
8932       /* if it has an offset then we need to compute
8933          it */
8934       if (sym->stack)
8935         {
8936           emitcode ("mov", "a,_bp");
8937           emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
8938           aopPut (AOP (IC_RESULT (ic)), "a", 0);
8939         }
8940       else
8941         {
8942           /* we can just move _bp */
8943           aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
8944         }
8945       /* fill the result with zero */
8946       size = AOP_SIZE (IC_RESULT (ic)) - 1;
8947
8948
8949       if (options.stack10bit && size < (FPTRSIZE - 1))
8950         {
8951           fprintf (stderr,
8952                    "*** warning: pointer to stack var truncated.\n");
8953         }
8954
8955       offset = 1;
8956       while (size--)
8957         {
8958           /* Yuck! */
8959           if (options.stack10bit && offset == 2)
8960             {
8961               aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
8962             }
8963           else
8964             {
8965               aopPut (AOP (IC_RESULT (ic)), zero, offset++);
8966             }
8967         }
8968
8969       goto release;
8970     }
8971
8972   /* object not on stack then we need the name */
8973   size = AOP_SIZE (IC_RESULT (ic));
8974   offset = 0;
8975
8976   while (size--)
8977     {
8978       char s[SDCC_NAME_MAX];
8979       if (offset)
8980         sprintf (s, "#(%s >> %d)",
8981                  sym->rname,
8982                  offset * 8);
8983       else
8984         sprintf (s, "#%s", sym->rname);
8985       aopPut (AOP (IC_RESULT (ic)), s, offset++);
8986     }
8987
8988 release:
8989   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8990
8991 }
8992
8993 /*-----------------------------------------------------------------*/
8994 /* genFarFarAssign - assignment when both are in far space         */
8995 /*-----------------------------------------------------------------*/
8996 static void
8997 genFarFarAssign (operand * result, operand * right, iCode * ic)
8998 {
8999   int size = AOP_SIZE (right);
9000   int offset = 0;
9001   symbol *rSym = NULL;
9002
9003   if (size == 1)
9004   {
9005       /* quick & easy case. */
9006       D(emitcode(";","genFarFarAssign (1 byte case)"););      
9007       MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
9008       freeAsmop (right, NULL, ic, FALSE);
9009       /* now assign DPTR to result */
9010       _G.accInUse++;
9011       aopOp(result, ic, FALSE, FALSE);
9012       _G.accInUse--;
9013       aopPut(AOP(result), "a", 0);
9014       freeAsmop(result, NULL, ic, FALSE);
9015       return;
9016   }
9017   
9018   /* See if we've got an underlying symbol to abuse. */
9019   if (IS_SYMOP(result) && OP_SYMBOL(result))
9020   {
9021       if (IS_TRUE_SYMOP(result))
9022       {
9023           rSym = OP_SYMBOL(result);
9024       }
9025       else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
9026       {
9027           rSym = OP_SYMBOL(result)->usl.spillLoc;
9028       }
9029   }
9030              
9031   if (size > 1 && rSym && rSym->rname && !rSym->onStack)
9032   {
9033       /* We can use the '390 auto-toggle feature to good effect here. */
9034       
9035       D(emitcode(";","genFarFarAssign ('390 auto-toggle fun)"););
9036       emitcode("mov", "dps, #0x21");    /* Select DPTR2 & auto-toggle. */
9037       emitcode ("mov", "dptr,#%s", rSym->rname); 
9038       /* DP2 = result, DP1 = right, DP1 is current. */
9039       while (size)
9040       {
9041           emitcode("movx", "a,@dptr");
9042           emitcode("movx", "@dptr,a");
9043           if (--size)
9044           {
9045                emitcode("inc", "dptr");
9046                emitcode("inc", "dptr");
9047           }
9048       }
9049       emitcode("mov", "dps, #0");
9050       freeAsmop (right, NULL, ic, FALSE);
9051   }
9052   else
9053   {
9054       D (emitcode (";", "genFarFarAssign"););
9055       aopOp (result, ic, TRUE, TRUE);
9056
9057       _startLazyDPSEvaluation ();
9058       
9059       while (size--)
9060         {
9061           aopPut (AOP (result),
9062                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
9063           offset++;
9064         }
9065       _endLazyDPSEvaluation ();
9066       freeAsmop (result, NULL, ic, FALSE);
9067       freeAsmop (right, NULL, ic, FALSE);
9068   }
9069 }
9070
9071 /*-----------------------------------------------------------------*/
9072 /* genAssign - generate code for assignment                        */
9073 /*-----------------------------------------------------------------*/
9074 static void
9075 genAssign (iCode * ic)
9076 {
9077   operand *result, *right;
9078   int size, offset;
9079   unsigned long lit = 0L;
9080
9081   D (emitcode (";", "genAssign ");
9082     );
9083
9084   result = IC_RESULT (ic);
9085   right = IC_RIGHT (ic);
9086
9087   /* if they are the same */
9088   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9089     return;
9090
9091   aopOp (right, ic, FALSE, FALSE);
9092
9093   emitcode (";", "genAssign: resultIsFar = %s",
9094             isOperandInFarSpace (result) ?
9095             "TRUE" : "FALSE");
9096
9097   /* special case both in far space */
9098   if ((AOP_TYPE (right) == AOP_DPTR ||
9099        AOP_TYPE (right) == AOP_DPTR2) &&
9100   /* IS_TRUE_SYMOP(result)       && */
9101       isOperandInFarSpace (result))
9102     {
9103       genFarFarAssign (result, right, ic);
9104       return;
9105     }
9106
9107   aopOp (result, ic, TRUE, FALSE);
9108
9109   /* if they are the same registers */
9110   if (sameRegs (AOP (right), AOP (result)))
9111     goto release;
9112
9113   /* if the result is a bit */
9114   if (AOP_TYPE (result) == AOP_CRY)
9115     {
9116
9117       /* if the right size is a literal then
9118          we know what the value is */
9119       if (AOP_TYPE (right) == AOP_LIT)
9120         {
9121           if (((int) operandLitValue (right)))
9122             aopPut (AOP (result), one, 0);
9123           else
9124             aopPut (AOP (result), zero, 0);
9125           goto release;
9126         }
9127
9128       /* the right is also a bit variable */
9129       if (AOP_TYPE (right) == AOP_CRY)
9130         {
9131           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9132           aopPut (AOP (result), "c", 0);
9133           goto release;
9134         }
9135
9136       /* we need to or */
9137       toBoolean (right);
9138       aopPut (AOP (result), "a", 0);
9139       goto release;
9140     }
9141
9142   /* bit variables done */
9143   /* general case */
9144   size = AOP_SIZE (result);
9145   offset = 0;
9146   if (AOP_TYPE (right) == AOP_LIT)
9147     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
9148
9149   if ((size > 1) &&
9150       (AOP_TYPE (result) != AOP_REG) &&
9151       (AOP_TYPE (right) == AOP_LIT) &&
9152       !IS_FLOAT (operandType (right)))
9153     {
9154       _startLazyDPSEvaluation ();
9155       while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
9156         {
9157           aopPut (AOP (result),
9158                   aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
9159                   offset);
9160           offset++;
9161           size--;
9162         }
9163       /* And now fill the rest with zeros. */
9164       if (size)
9165         {
9166           emitcode ("clr", "a");
9167         }
9168       while (size--)
9169         {
9170           aopPut (AOP (result), "a", offset++);
9171         }
9172       _endLazyDPSEvaluation ();
9173     }
9174   else
9175     {
9176       _startLazyDPSEvaluation ();
9177       while (size--)
9178         {
9179           aopPut (AOP (result),
9180                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9181                   offset);
9182           offset++;
9183         }
9184       _endLazyDPSEvaluation ();
9185     }
9186
9187 release:
9188   freeAsmop (right, NULL, ic, FALSE);
9189   freeAsmop (result, NULL, ic, TRUE);
9190 }
9191
9192 /*-----------------------------------------------------------------*/
9193 /* genJumpTab - generates code for jump table                      */
9194 /*-----------------------------------------------------------------*/
9195 static void
9196 genJumpTab (iCode * ic)
9197 {
9198   symbol *jtab;
9199   char *l;
9200
9201   D (emitcode (";", "genJumpTab ");
9202     );
9203
9204   aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
9205   /* get the condition into accumulator */
9206   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
9207   MOVA (l);
9208   /* multiply by four! */
9209   emitcode ("add", "a,acc");
9210   emitcode ("add", "a,acc");
9211   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9212
9213   jtab = newiTempLabel (NULL);
9214   emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
9215   emitcode ("jmp", "@a+dptr");
9216   emitcode ("", "%05d$:", jtab->key + 100);
9217   /* now generate the jump labels */
9218   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9219        jtab = setNextItem (IC_JTLABELS (ic)))
9220     emitcode ("ljmp", "%05d$", jtab->key + 100);
9221
9222 }
9223
9224 /*-----------------------------------------------------------------*/
9225 /* genCast - gen code for casting                                  */
9226 /*-----------------------------------------------------------------*/
9227 static void
9228 genCast (iCode * ic)
9229 {
9230   operand *result = IC_RESULT (ic);
9231   sym_link *ctype = operandType (IC_LEFT (ic));
9232   sym_link *rtype = operandType (IC_RIGHT (ic));
9233   operand *right = IC_RIGHT (ic);
9234   int size, offset;
9235
9236   D (emitcode (";", "genCast ");
9237     );
9238
9239   /* if they are equivalent then do nothing */
9240   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9241     return;
9242
9243   aopOp (right, ic, FALSE, FALSE);
9244   aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
9245
9246   /* if the result is a bit */
9247   if (AOP_TYPE (result) == AOP_CRY)
9248     {
9249       /* if the right size is a literal then
9250          we know what the value is */
9251       if (AOP_TYPE (right) == AOP_LIT)
9252         {
9253           if (((int) operandLitValue (right)))
9254             aopPut (AOP (result), one, 0);
9255           else
9256             aopPut (AOP (result), zero, 0);
9257
9258           goto release;
9259         }
9260
9261       /* the right is also a bit variable */
9262       if (AOP_TYPE (right) == AOP_CRY)
9263         {
9264           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9265           aopPut (AOP (result), "c", 0);
9266           goto release;
9267         }
9268
9269       /* we need to or */
9270       toBoolean (right);
9271       aopPut (AOP (result), "a", 0);
9272       goto release;
9273     }
9274
9275   /* if they are the same size : or less */
9276   if (AOP_SIZE (result) <= AOP_SIZE (right))
9277     {
9278
9279       /* if they are in the same place */
9280       if (sameRegs (AOP (right), AOP (result)))
9281         goto release;
9282
9283       /* if they in different places then copy */
9284       size = AOP_SIZE (result);
9285       offset = 0;
9286       _startLazyDPSEvaluation ();
9287       while (size--)
9288         {
9289           aopPut (AOP (result),
9290                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9291                   offset);
9292           offset++;
9293         }
9294       _endLazyDPSEvaluation ();
9295       goto release;
9296     }
9297
9298
9299   /* if the result is of type pointer */
9300   if (IS_PTR (ctype))
9301     {
9302
9303       int p_type;
9304       sym_link *type = operandType (right);
9305
9306       /* pointer to generic pointer */
9307       if (IS_GENPTR (ctype))
9308         {
9309           char *l = zero;
9310
9311           if (IS_PTR (type))
9312             {
9313               p_type = DCL_TYPE (type);
9314             }
9315           else
9316             {
9317 #if OLD_CAST_BEHAVIOR
9318               /* KV: we are converting a non-pointer type to
9319                * a generic pointer. This (ifdef'd out) code
9320                * says that the resulting generic pointer
9321                * should have the same class as the storage
9322                * location of the non-pointer variable.
9323                *
9324                * For example, converting an int (which happens
9325                * to be stored in DATA space) to a pointer results
9326                * in a DATA generic pointer; if the original int
9327                * in XDATA space, so will be the resulting pointer.
9328                *
9329                * I don't like that behavior, and thus this change:
9330                * all such conversions will be forced to XDATA and
9331                * throw a warning. If you want some non-XDATA
9332                * type, or you want to suppress the warning, you
9333                * must go through an intermediate cast, like so:
9334                *
9335                * char _generic *gp = (char _xdata *)(intVar);
9336                */
9337               sym_link *etype = getSpec (type);
9338
9339               /* we have to go by the storage class */
9340               if (SPEC_OCLS (etype) != generic)
9341                 {
9342                   p_type = PTR_TYPE (SPEC_OCLS (etype));
9343                 }
9344               else
9345 #endif
9346                 {
9347                   /* Converting unknown class (i.e. register variable)
9348                    * to generic pointer. This is not good, but
9349                    * we'll make a guess (and throw a warning).
9350                    */
9351                   p_type = FPOINTER;
9352                   werror (W_INT_TO_GEN_PTR_CAST);
9353                 }
9354             }
9355
9356           /* the first two bytes are known */
9357           size = GPTRSIZE - 1;
9358           offset = 0;
9359           _startLazyDPSEvaluation ();
9360           while (size--)
9361             {
9362               aopPut (AOP (result),
9363                       aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9364                       offset);
9365               offset++;
9366             }
9367           _endLazyDPSEvaluation ();
9368
9369           /* the last byte depending on type */
9370           switch (p_type)
9371             {
9372             case IPOINTER:
9373             case POINTER:
9374               l = zero;
9375               break;
9376             case FPOINTER:
9377               l = one;
9378               break;
9379             case CPOINTER:
9380               l = "#0x02";
9381               break;
9382             case PPOINTER:
9383               l = "#0x03";
9384               break;
9385
9386             default:
9387               /* this should never happen */
9388               werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9389                       "got unknown pointer type");
9390               exit (1);
9391             }
9392           aopPut (AOP (result), l, GPTRSIZE - 1);
9393           goto release;
9394         }
9395
9396       /* just copy the pointers */
9397       size = AOP_SIZE (result);
9398       offset = 0;
9399       _startLazyDPSEvaluation ();
9400       while (size--)
9401         {
9402           aopPut (AOP (result),
9403                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9404                   offset);
9405           offset++;
9406         }
9407       _endLazyDPSEvaluation ();
9408       goto release;
9409     }
9410
9411   /* so we now know that the size of destination is greater
9412      than the size of the source */
9413   /* we move to result for the size of source */
9414   size = AOP_SIZE (right);
9415   offset = 0;
9416   _startLazyDPSEvaluation ();
9417   while (size--)
9418     {
9419       aopPut (AOP (result),
9420               aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9421               offset);
9422       offset++;
9423     }
9424   _endLazyDPSEvaluation ();
9425
9426   /* now depending on the sign of the source && destination */
9427   size = AOP_SIZE (result) - AOP_SIZE (right);
9428   /* if unsigned or not an integral type */
9429   /* also, if the source is a bit, we don't need to sign extend, because
9430    * it can't possibly have set the sign bit.
9431    */
9432   if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
9433     {
9434       while (size--)
9435         {
9436           aopPut (AOP (result), zero, offset++);
9437         }
9438     }
9439   else
9440     {
9441       /* we need to extend the sign :{ */
9442       char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
9443                         FALSE, FALSE, TRUE);
9444       MOVA (l);
9445       emitcode ("rlc", "a");
9446       emitcode ("subb", "a,acc");
9447       while (size--)
9448         aopPut (AOP (result), "a", offset++);
9449     }
9450
9451   /* we are done hurray !!!! */
9452
9453 release:
9454   freeAsmop (right, NULL, ic, TRUE);
9455   freeAsmop (result, NULL, ic, TRUE);
9456
9457 }
9458
9459 /*-----------------------------------------------------------------*/
9460 /* genDjnz - generate decrement & jump if not zero instrucion      */
9461 /*-----------------------------------------------------------------*/
9462 static int
9463 genDjnz (iCode * ic, iCode * ifx)
9464 {
9465   symbol *lbl, *lbl1;
9466   if (!ifx)
9467     return 0;
9468
9469   /* if the if condition has a false label
9470      then we cannot save */
9471   if (IC_FALSE (ifx))
9472     return 0;
9473
9474   /* if the minus is not of the form
9475      a = a - 1 */
9476   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
9477       !IS_OP_LITERAL (IC_RIGHT (ic)))
9478     return 0;
9479
9480   if (operandLitValue (IC_RIGHT (ic)) != 1)
9481     return 0;
9482
9483   /* if the size of this greater than one then no
9484      saving */
9485   if (getSize (operandType (IC_RESULT (ic))) > 1)
9486     return 0;
9487
9488   /* otherwise we can save BIG */
9489   D(emitcode(";", "genDjnz"););
9490
9491   lbl = newiTempLabel (NULL);
9492   lbl1 = newiTempLabel (NULL);
9493
9494   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9495
9496   if (AOP_NEEDSACC(IC_RESULT(ic)))
9497   {
9498       /* If the result is accessed indirectly via
9499        * the accumulator, we must explicitly write
9500        * it back after the decrement.
9501        */
9502       char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
9503       
9504       if (strcmp(rByte, "a"))
9505       {
9506            /* Something is hopelessly wrong */
9507            fprintf(stderr, "*** warning: internal error at %s:%d\n",
9508                    __FILE__, __LINE__);
9509            /* We can just give up; the generated code will be inefficient,
9510             * but what the hey.
9511             */
9512            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9513            return 0;
9514       }
9515       emitcode ("dec", "%s", rByte);
9516       aopPut(AOP(IC_RESULT(ic)), rByte, 0);
9517       emitcode ("jnz", "%05d$", lbl->key + 100);
9518   }
9519   else if (IS_AOP_PREG (IC_RESULT (ic)))
9520     {
9521       emitcode ("dec", "%s",
9522                 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9523       emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9524       emitcode ("jnz", "%05d$", lbl->key + 100);
9525     }
9526   else
9527     {
9528       emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
9529                 lbl->key + 100);
9530     }
9531   emitcode ("sjmp", "%05d$", lbl1->key + 100);
9532   emitcode ("", "%05d$:", lbl->key + 100);
9533   emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
9534   emitcode ("", "%05d$:", lbl1->key + 100);
9535
9536   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9537   ifx->generated = 1;
9538   return 1;
9539 }
9540
9541 /*-----------------------------------------------------------------*/
9542 /* genReceive - generate code for a receive iCode                  */
9543 /*-----------------------------------------------------------------*/
9544 static void
9545 genReceive (iCode * ic)
9546 {
9547
9548   D (emitcode (";", "genReceive ");
9549     );
9550
9551   if (isOperandInFarSpace (IC_RESULT (ic)) &&
9552       (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
9553        IS_TRUE_SYMOP (IC_RESULT (ic))))
9554     {
9555       int size = getSize (operandType (IC_RESULT (ic)));
9556       int offset = fReturnSizeDS390 - size;
9557       while (size--)
9558         {
9559           emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
9560                             fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
9561           offset++;
9562         }
9563       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9564       size = AOP_SIZE (IC_RESULT (ic));
9565       offset = 0;
9566       while (size--)
9567         {
9568           emitcode ("pop", "acc");
9569           aopPut (AOP (IC_RESULT (ic)), "a", offset++);
9570         }
9571
9572     }
9573   else
9574     {
9575       _G.accInUse++;
9576       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9577       _G.accInUse--;
9578       assignResultValue (IC_RESULT (ic));
9579     }
9580
9581   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9582 }
9583
9584 /*-----------------------------------------------------------------*/
9585 /* gen390Code - generate code for Dallas 390 based controllers     */
9586 /*-----------------------------------------------------------------*/
9587 void
9588 gen390Code (iCode * lic)
9589 {
9590   iCode *ic;
9591   int cln = 0;
9592
9593   lineHead = lineCurr = NULL;
9594
9595 #if 0
9596   //REMOVE ME!!!
9597   /* print the allocation information */
9598   if (allocInfo)
9599     printAllocInfo (currFunc, codeOutFile);
9600 #endif
9601   /* if debug information required */
9602   if (options.debug && currFunc)
9603     {
9604       cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
9605       _G.debugLine = 1;
9606       if (IS_STATIC (currFunc->etype))
9607         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
9608       else
9609         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
9610       _G.debugLine = 0;
9611     }
9612   /* stack pointer name */
9613   if (options.useXstack)
9614     spname = "_spx";
9615   else
9616     spname = "sp";
9617
9618
9619   for (ic = lic; ic; ic = ic->next)
9620     {
9621
9622       if (cln != ic->lineno)
9623         {
9624           if (options.debug)
9625             {
9626               _G.debugLine = 1;
9627               emitcode ("", "C$%s$%d$%d$%d ==.",
9628                         FileBaseName (ic->filename), ic->lineno,
9629                         ic->level, ic->block);
9630               _G.debugLine = 0;
9631             }
9632           emitcode (";", "%s %d", ic->filename, ic->lineno);
9633           cln = ic->lineno;
9634         }
9635       /* if the result is marked as
9636          spilt and rematerializable or code for
9637          this has already been generated then
9638          do nothing */
9639       if (resultRemat (ic) || ic->generated)
9640         continue;
9641
9642       /* depending on the operation */
9643       switch (ic->op)
9644         {
9645         case '!':
9646           genNot (ic);
9647           break;
9648
9649         case '~':
9650           genCpl (ic);
9651           break;
9652
9653         case UNARYMINUS:
9654           genUminus (ic);
9655           break;
9656
9657         case IPUSH:
9658           genIpush (ic);
9659           break;
9660
9661         case IPOP:
9662           /* IPOP happens only when trying to restore a
9663              spilt live range, if there is an ifx statement
9664              following this pop then the if statement might
9665              be using some of the registers being popped which
9666              would destory the contents of the register so
9667              we need to check for this condition and handle it */
9668           if (ic->next &&
9669               ic->next->op == IFX &&
9670               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
9671             genIfx (ic->next, ic);
9672           else
9673             genIpop (ic);
9674           break;
9675
9676         case CALL:
9677           genCall (ic);
9678           break;
9679
9680         case PCALL:
9681           genPcall (ic);
9682           break;
9683
9684         case FUNCTION:
9685           genFunction (ic);
9686           break;
9687
9688         case ENDFUNCTION:
9689           genEndFunction (ic);
9690           break;
9691
9692         case RETURN:
9693           genRet (ic);
9694           break;
9695
9696         case LABEL:
9697           genLabel (ic);
9698           break;
9699
9700         case GOTO:
9701           genGoto (ic);
9702           break;
9703
9704         case '+':
9705           genPlus (ic);
9706           break;
9707
9708         case '-':
9709           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9710             genMinus (ic);
9711           break;
9712
9713         case '*':
9714           genMult (ic);
9715           break;
9716
9717         case '/':
9718           genDiv (ic);
9719           break;
9720
9721         case '%':
9722           genMod (ic);
9723           break;
9724
9725         case '>':
9726           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9727           break;
9728
9729         case '<':
9730           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9731           break;
9732
9733         case LE_OP:
9734         case GE_OP:
9735         case NE_OP:
9736
9737           /* note these two are xlated by algebraic equivalence
9738              during parsing SDCC.y */
9739           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9740                   "got '>=' or '<=' shouldn't have come here");
9741           break;
9742
9743         case EQ_OP:
9744           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9745           break;
9746
9747         case AND_OP:
9748           genAndOp (ic);
9749           break;
9750
9751         case OR_OP:
9752           genOrOp (ic);
9753           break;
9754
9755         case '^':
9756           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9757           break;
9758
9759         case '|':
9760           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9761           break;
9762
9763         case BITWISEAND:
9764           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9765           break;
9766
9767         case INLINEASM:
9768           genInline (ic);
9769           break;
9770
9771         case RRC:
9772           genRRC (ic);
9773           break;
9774
9775         case RLC:
9776           genRLC (ic);
9777           break;
9778
9779         case GETHBIT:
9780           genGetHbit (ic);
9781           break;
9782
9783         case LEFT_OP:
9784           genLeftShift (ic);
9785           break;
9786
9787         case RIGHT_OP:
9788           genRightShift (ic);
9789           break;
9790
9791         case GET_VALUE_AT_ADDRESS:
9792           genPointerGet (ic);
9793           break;
9794
9795         case '=':
9796           if (POINTER_SET (ic))
9797             genPointerSet (ic);
9798           else
9799             genAssign (ic);
9800           break;
9801
9802         case IFX:
9803           genIfx (ic, NULL);
9804           break;
9805
9806         case ADDRESS_OF:
9807           genAddrOf (ic);
9808           break;
9809
9810         case JUMPTABLE:
9811           genJumpTab (ic);
9812           break;
9813
9814         case CAST:
9815           genCast (ic);
9816           break;
9817
9818         case RECEIVE:
9819           genReceive (ic);
9820           break;
9821
9822         case SEND:
9823           addSet (&_G.sendSet, ic);
9824           break;
9825
9826         default:
9827           ic = ic;
9828         }
9829     }
9830
9831
9832   /* now we are ready to call the
9833      peep hole optimizer */
9834   if (!options.nopeep)
9835     peepHole (&lineHead);
9836
9837   /* now do the actual printing */
9838   printLine (lineHead, codeOutFile);
9839   return;
9840 }