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