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