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