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