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