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