Many changes. Started a second pass to the register allocator & true 10bit stack
[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   DS390 adaptation by Kevin Vigor <kevin@vigor.nu>
8
9   This program is free software; you can redistribute it and/or modify it
10   under the terms of the GNU General Public License as published by the
11   Free Software Foundation; either version 2, or (at your option) any
12   later version.
13
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License for more details.
18
19   You should have received a copy of the GNU General Public License
20   along with this program; if not, write to the Free Software
21   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22
23   In other words, you are welcome to use, share and improve this program.
24   You are forbidden to forbid anyone else to use, share and improve
25   what you give them.   Help stamp out software-hoarding!
26 -------------------------------------------------------------------------*/
27
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <ctype.h>
32
33 #include <common.h>
34 #include "ralloc.h"
35 #include "gen.h"
36 #include "SDCCglobl.h"
37 #include "newalloc.h"
38
39 #ifdef HAVE_SYS_ISA_DEFS_H
40 #include <sys/isa_defs.h>
41 #else
42 #ifdef HAVE_MACHINE_ENDIAN_H
43 #include <machine/endian.h>
44 #else
45 #ifdef HAVE_ENDIAN_H
46 #include <endian.h>
47 #else
48 #if !defined(__BORLANDC__) && !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__CYGWIN__)
49 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
50 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
51 #endif
52 #endif
53 #endif
54 #endif
55
56 #define BETTER_LITERAL_SHIFT
57
58 char *aopLiteral (value * val, int offset);
59
60 /* this is the down and dirty file with all kinds of
61    kludgy & hacky stuff. This is what it is all about
62    CODE GENERATION for a specific MCU . some of the
63    routines may be reusable, will have to see */
64
65 static char *zero = "#0x00";
66 static char *one = "#0x01";
67 static char *spname;
68
69 #define D(x) x
70
71 #define TR_DPTR(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_DPTR1 %s ", s); }
72 #define TR_AP(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_AP %s ", s); }
73
74 unsigned fReturnSizeDS390 = 5;  /* shared with ralloc.c */
75 static char *fReturn24[] =
76 {"dpl", "dph", "dpx", "b", "a"};
77 static char *fReturn16[] =
78 {"dpl", "dph", "b", "a"};
79 static char **fReturn = fReturn24;
80 static char *accUse[] =
81 {"a", "b"};
82
83 static short rbank = -1;
84
85 static struct
86   {
87     short r0Pushed;
88     short r1Pushed;
89     short accInUse;
90     short inLine;
91     short debugLine;
92     short nRegsSaved;
93     set *sendSet;
94   }
95 _G;
96
97 static void saveRBank (int, iCode *, bool);
98
99 #define RESULTONSTACK(x) \
100                          (IC_RESULT(x) && IC_RESULT(x)->aop && \
101                          IC_RESULT(x)->aop->type == AOP_STK )
102
103 /* #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x); */
104 #define MOVA(x) { char *_mova_tmp = strdup(x); \
105                  if (strcmp(_mova_tmp,"a") && strcmp(_mova_tmp,"acc")) \
106                  { \
107                     emitcode("mov","a,%s",_mova_tmp); \
108                  } \
109                  free(_mova_tmp); \
110                 }
111 #define CLRC    emitcode("clr","c")
112 #define SETC    emitcode("setb","c")
113
114 // A scratch register which will be used to hold
115 // result bytes from operands in far space via DPTR2.
116 #define DP2_RESULT_REG  "ap"
117
118 static lineNode *lineHead = NULL;
119 static lineNode *lineCurr = NULL;
120
121 static unsigned char SLMask[] =
122 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
123  0xE0, 0xC0, 0x80, 0x00};
124 static unsigned char SRMask[] =
125 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
126  0x07, 0x03, 0x01, 0x00};
127
128 #define LSB     0
129 #define MSB16   1
130 #define MSB24   2
131 #define MSB32   3
132
133 /*-----------------------------------------------------------------*/
134 /* emitcode - writes the code into a file : for now it is simple    */
135 /*-----------------------------------------------------------------*/
136 static void
137 emitcode (char *inst, char *fmt,...)
138 {
139   va_list ap;
140   char lb[INITIAL_INLINEASM];
141   char *lbp = lb;
142
143   va_start (ap, fmt);
144
145   if (inst && *inst)
146     {
147       if (fmt && *fmt)
148         sprintf (lb, "%s\t", inst);
149       else
150         sprintf (lb, "%s", inst);
151       vsprintf (lb + (strlen (lb)), fmt, ap);
152     }
153   else
154     vsprintf (lb, fmt, ap);
155
156   while (isspace (*lbp))
157     lbp++;
158
159   if (lbp && *lbp)
160     lineCurr = (lineCurr ?
161                 connectLine (lineCurr, newLineNode (lb)) :
162                 (lineHead = newLineNode (lb)));
163   lineCurr->isInline = _G.inLine;
164   lineCurr->isDebug = _G.debugLine;
165   va_end (ap);
166 }
167
168 /*-----------------------------------------------------------------*/
169 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
170 /*-----------------------------------------------------------------*/
171 static regs *
172 getFreePtr (iCode * ic, asmop ** aopp, bool result)
173 {
174   bool r0iu = FALSE, r1iu = FALSE;
175   bool r0ou = FALSE, r1ou = FALSE;
176
177   /* the logic: if r0 & r1 used in the instruction
178      then we are in trouble otherwise */
179
180   /* first check if r0 & r1 are used by this
181      instruction, in which case we are in trouble */
182   r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
183   r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
184   if (r0iu && r1iu) {
185       goto endOfWorld;
186     }
187
188   r0ou = bitVectBitValue (ic->rMask, R0_IDX);
189   r1ou = bitVectBitValue (ic->rMask, R1_IDX);
190
191   /* if no usage of r0 then return it */
192   if (!r0iu && !r0ou)
193     {
194       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
195       (*aopp)->type = AOP_R0;
196
197       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
198     }
199
200   /* if no usage of r1 then return it */
201   if (!r1iu && !r1ou)
202     {
203       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
204       (*aopp)->type = AOP_R1;
205
206       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R1_IDX);
207     }
208
209   /* now we know they both have usage */
210   /* if r0 not used in this instruction */
211   if (!r0iu)
212     {
213       /* push it if not already pushed */
214       if (!_G.r0Pushed)
215         {
216           emitcode ("push", "%s",
217                     ds390_regWithIdx (R0_IDX)->dname);
218           _G.r0Pushed++;
219         }
220
221       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
222       (*aopp)->type = AOP_R0;
223
224       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
225     }
226
227   /* if r1 not used then */
228
229   if (!r1iu)
230     {
231       /* push it if not already pushed */
232       if (!_G.r1Pushed)
233         {
234           emitcode ("push", "%s",
235                     ds390_regWithIdx (R1_IDX)->dname);
236           _G.r1Pushed++;
237         }
238
239       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
240       (*aopp)->type = AOP_R1;
241       return ds390_regWithIdx (R1_IDX);
242     }
243
244 endOfWorld:
245   /* I said end of world but not quite end of world yet */
246   /* if this is a result then we can push it on the stack */
247   if (result)
248     {
249       (*aopp)->type = AOP_STK;
250       return NULL;
251     }
252
253   /* other wise this is true end of the world */
254   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
255           "getFreePtr should never reach here");
256   exit (1);
257 }
258
259 /*-----------------------------------------------------------------*/
260 /* newAsmop - creates a new asmOp                                  */
261 /*-----------------------------------------------------------------*/
262 static asmop *
263 newAsmop (short type)
264 {
265   asmop *aop;
266
267   aop = Safe_calloc (1, sizeof (asmop));
268   aop->type = type;
269   return aop;
270 }
271
272 static int _currentDPS;         /* Current processor DPS. */
273 static int _desiredDPS;         /* DPS value compiler thinks we should be using. */
274 static int _lazyDPS = 0;        /* if non-zero, we are doing lazy evaluation of DPS changes. */
275
276 /*-----------------------------------------------------------------*/
277 /* genSetDPTR: generate code to select which DPTR is in use (zero  */
278 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390     */
279 /* alternate DPTR (DPL1/DPH1/DPX1).          */
280 /*-----------------------------------------------------------------*/
281 static void
282 genSetDPTR (int n)
283 {
284
285   /* If we are doing lazy evaluation, simply note the desired
286    * change, but don't emit any code yet.
287    */
288   if (_lazyDPS)
289     {
290       _desiredDPS = n;
291       return;
292     }
293
294   if (!n)
295     {
296       emitcode ("mov", "dps, #0x00");
297     }
298   else
299     {
300       TR_DPTR("#1");
301       emitcode ("mov", "dps, #0x01");
302     }
303 }
304
305 /*-----------------------------------------------------------------*/
306 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
307 /*                   */
308 /* Any code that operates on DPTR (NB: not on the individual     */
309 /* components, like DPH) *must* call _flushLazyDPS() before using  */
310 /* DPTR within a lazy DPS evaluation block.        */
311 /*                   */
312 /* Note that aopPut and aopGet already contain the proper calls to */
313 /* _flushLazyDPS, so it is safe to use these calls within a lazy   */
314 /* DPS evaluation block.             */
315 /*                   */
316 /* Also, _flushLazyDPS must be called before any flow control      */
317 /* operations that could potentially branch out of the block.    */
318 /*                         */
319 /* Lazy DPS evaluation is simply an optimization (though an      */
320 /* important one), so if in doubt, leave it out.       */
321 /*-----------------------------------------------------------------*/
322 static void
323 _startLazyDPSEvaluation (void)
324 {
325   _currentDPS = 0;
326   _desiredDPS = 0;
327 #ifdef BETTER_LITERAL_SHIFT  
328   _lazyDPS++;
329 #else
330   _lazyDPS = 1;
331 #endif  
332 }
333
334 /*-----------------------------------------------------------------*/
335 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
336 /* desired one. Call before using DPTR within a lazy DPS evaluation */
337 /* block.                */
338 /*-----------------------------------------------------------------*/
339 static void
340 _flushLazyDPS (void)
341 {
342   if (!_lazyDPS)
343     {
344       /* nothing to do. */
345       return;
346     }
347
348   if (_desiredDPS != _currentDPS)
349     {
350       if (_desiredDPS)
351         {
352           emitcode ("inc", "dps");
353         }
354       else
355         {
356           emitcode ("dec", "dps");
357         }
358       _currentDPS = _desiredDPS;
359     }
360 }
361
362 /*-----------------------------------------------------------------*/
363 /* _endLazyDPSEvaluation: end lazy DPS evaluation block.     */
364 /*                   */
365 /* Forces us back to the safe state (standard DPTR selected).    */
366 /*-----------------------------------------------------------------*/
367 static void
368 _endLazyDPSEvaluation (void)
369 {
370 #ifdef BETTER_LITERAL_SHIFT  
371   _lazyDPS--;
372 #else
373   _lazyDPS = 0;
374 #endif    
375   if (!_lazyDPS)
376   {
377     if (_currentDPS)
378     {
379       genSetDPTR (0);
380       _flushLazyDPS ();
381     }
382     _currentDPS = 0;
383     _desiredDPS = 0;
384   }
385 }
386
387
388
389 /*-----------------------------------------------------------------*/
390 /* pointerCode - returns the code for a pointer type               */
391 /*-----------------------------------------------------------------*/
392 static int
393 pointerCode (sym_link * etype)
394 {
395
396   return PTR_TYPE (SPEC_OCLS (etype));
397
398 }
399
400 /*-----------------------------------------------------------------*/
401 /* aopForSym - for a true symbol                                   */
402 /*-----------------------------------------------------------------*/
403 static asmop *
404 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
405 {
406   asmop *aop;
407   memmap *space = SPEC_OCLS (sym->etype);
408
409   /* if already has one */
410   if (sym->aop)
411     return sym->aop;
412
413   /* assign depending on the storage class */
414   /* if it is on the stack or indirectly addressable */
415   /* space we need to assign either r0 or r1 to it   */
416   if ((sym->onStack && !options.stack10bit) || sym->iaccess)
417     {
418       sym->aop = aop = newAsmop (0);
419       aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
420       aop->size = getSize (sym->type);
421
422       /* now assign the address of the variable to
423          the pointer register */
424       if (aop->type != AOP_STK)
425         {
426
427           if (sym->onStack)
428             {
429               if (_G.accInUse)
430                 emitcode ("push", "acc");
431
432               emitcode ("mov", "a,_bp");
433               emitcode ("add", "a,#0x%02x",
434                         ((sym->stack < 0) ?
435                          ((char) (sym->stack - _G.nRegsSaved)) :
436                          ((char) sym->stack)) & 0xff);
437               emitcode ("mov", "%s,a",
438                         aop->aopu.aop_ptr->name);
439
440               if (_G.accInUse)
441                 emitcode ("pop", "acc");
442             }
443           else
444             emitcode ("mov", "%s,#%s",
445                       aop->aopu.aop_ptr->name,
446                       sym->rname);
447           aop->paged = space->paged;
448         }
449       else
450         aop->aopu.aop_stk = sym->stack;
451       return aop;
452     }
453
454   if (sym->onStack && options.stack10bit)
455     {
456       /* It's on the 10 bit stack, which is located in
457        * far data space.
458        */
459
460       if (_G.accInUse)
461         emitcode ("push", "acc");
462
463       emitcode ("mov", "a,_bpx");
464       emitcode ("clr","c");
465       emitcode ("subb", "a,#0x%02x",
466                 -((sym->stack < 0) ?
467                   ((short) (sym->stack - _G.nRegsSaved)) :
468                   ((short) sym->stack)) & 0xff);
469       emitcode ("mov","b,a");
470       emitcode ("mov","a,#0x%02x",(-((sym->stack < 0) ?
471                                      ((short) (sym->stack - _G.nRegsSaved)) :
472                                      ((short) sym->stack)) >> 8) & 0xff);
473       emitcode ("subb","a,_bpx+1");
474       if (useDP2) {
475           if (options.model == MODEL_FLAT24)
476               emitcode ("mov", "dpx1,#0x40");
477           TR_DPTR("#2");
478           emitcode ("mov", "dph1,a");
479           emitcode ("mov", "dpl1,b");
480       } else {
481           if (options.model == MODEL_FLAT24)
482               emitcode ("mov", "dpx,#0x40");
483           emitcode ("mov", "dph,a");
484           emitcode ("mov", "dpl,b");
485       }
486
487       if (_G.accInUse)
488         emitcode ("pop", "acc");
489
490       sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
491       aop->size = getSize (sym->type);
492       return aop;
493     }
494
495   /* if in bit space */
496   if (IN_BITSPACE (space))
497     {
498       sym->aop = aop = newAsmop (AOP_CRY);
499       aop->aopu.aop_dir = sym->rname;
500       aop->size = getSize (sym->type);
501       return aop;
502     }
503   /* if it is in direct space */
504   if (IN_DIRSPACE (space))
505     {
506       sym->aop = aop = newAsmop (AOP_DIR);
507       aop->aopu.aop_dir = sym->rname;
508       aop->size = getSize (sym->type);
509       return aop;
510     }
511
512   /* special case for a function */
513   if (IS_FUNC (sym->type))
514     {
515       sym->aop = aop = newAsmop (AOP_IMMD);
516       aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
517       strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
518       aop->size = FPTRSIZE;
519       return aop;
520     }
521
522   /* only remaining is far space */
523   /* in which case DPTR gets the address */
524   sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
525   if (useDP2)
526     {
527       genSetDPTR (1);
528       _flushLazyDPS ();
529       emitcode ("mov", "dptr,#%s", sym->rname);
530       genSetDPTR (0);
531     }
532   else
533     {
534       emitcode ("mov", "dptr,#%s", sym->rname);
535     }
536   aop->size = getSize (sym->type);
537
538   /* if it is in code space */
539   if (IN_CODESPACE (space))
540     aop->code = 1;
541
542   return aop;
543 }
544
545 /*-----------------------------------------------------------------*/
546 /* aopForRemat - rematerialzes an object                           */
547 /*-----------------------------------------------------------------*/
548 static asmop *
549 aopForRemat (symbol * sym)
550 {
551   iCode *ic = sym->rematiCode;
552   asmop *aop = newAsmop (AOP_IMMD);
553   int ptr_type =0;
554   int val = 0;
555
556   for (;;)
557     {
558       if (ic->op == '+')
559         val += (int) operandLitValue (IC_RIGHT (ic));
560       else if (ic->op == '-')
561         val -= (int) operandLitValue (IC_RIGHT (ic));
562       else if (IS_CAST_ICODE(ic)) {
563               sym_link *from_type = operandType(IC_RIGHT(ic));
564               aop->aopu.aop_immd.from_cast_remat = 1;
565               ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
566               ptr_type = DCL_TYPE(from_type);
567               if (ptr_type == IPOINTER) {
568                 // bug #481053
569                 ptr_type = POINTER;
570               }
571               continue ;
572       } else break;
573       
574       ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
575     }
576
577   if (val)
578     sprintf (buffer, "(%s %c 0x%04x)",
579              OP_SYMBOL (IC_LEFT (ic))->rname,
580              val >= 0 ? '+' : '-',
581              abs (val) & 0xffff);
582   else
583     strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
584
585   aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
586   strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
587   /* set immd2 field if required */
588   if (aop->aopu.aop_immd.from_cast_remat) {
589           sprintf(buffer,"#0x%02x",ptr_type);
590           aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
591           strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
592   }
593
594   return aop;
595 }
596
597 /*-----------------------------------------------------------------*/
598 /* regsInCommon - two operands have some registers in common       */
599 /*-----------------------------------------------------------------*/
600 static bool
601 regsInCommon (operand * op1, operand * op2)
602 {
603   symbol *sym1, *sym2;
604   int i;
605
606   /* if they have registers in common */
607   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
608     return FALSE;
609
610   sym1 = OP_SYMBOL (op1);
611   sym2 = OP_SYMBOL (op2);
612
613   if (sym1->nRegs == 0 || sym2->nRegs == 0)
614     return FALSE;
615
616   for (i = 0; i < sym1->nRegs; i++)
617     {
618       int j;
619       if (!sym1->regs[i])
620         continue;
621
622       for (j = 0; j < sym2->nRegs; j++)
623         {
624           if (!sym2->regs[j])
625             continue;
626
627           if (sym2->regs[j] == sym1->regs[i])
628             return TRUE;
629         }
630     }
631
632   return FALSE;
633 }
634
635 /*-----------------------------------------------------------------*/
636 /* operandsEqu - equivalent                                        */
637 /*-----------------------------------------------------------------*/
638 static bool
639 operandsEqu (operand * op1, operand * op2)
640 {
641   symbol *sym1, *sym2;
642
643   /* if they not symbols */
644   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
645     return FALSE;
646
647   sym1 = OP_SYMBOL (op1);
648   sym2 = OP_SYMBOL (op2);
649
650   /* if both are itemps & one is spilt
651      and the other is not then false */
652   if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
653       sym1->isspilt != sym2->isspilt)
654     return FALSE;
655
656   /* if they are the same */
657   if (sym1 == sym2)
658     return TRUE;
659
660   if (strcmp (sym1->rname, sym2->rname) == 0)
661     return TRUE;
662
663
664   /* if left is a tmp & right is not */
665   if (IS_ITEMP (op1) &&
666       !IS_ITEMP (op2) &&
667       sym1->isspilt &&
668       (sym1->usl.spillLoc == sym2))
669     return TRUE;
670
671   if (IS_ITEMP (op2) &&
672       !IS_ITEMP (op1) &&
673       sym2->isspilt &&
674       sym1->level > 0 &&
675       (sym2->usl.spillLoc == sym1))
676     return TRUE;
677
678   return FALSE;
679 }
680
681 /*-----------------------------------------------------------------*/
682 /* sameRegs - two asmops have the same registers                   */
683 /*-----------------------------------------------------------------*/
684 static bool
685 sameRegs (asmop * aop1, asmop * aop2)
686 {
687   int i;
688
689   if (aop1 == aop2)
690     {
691       if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
692         {
693           return FALSE;
694         }
695       return TRUE;
696     }
697
698   if (aop1->type != AOP_REG ||
699       aop2->type != AOP_REG)
700     return FALSE;
701
702   if (aop1->size != aop2->size)
703     return FALSE;
704
705   for (i = 0; i < aop1->size; i++)
706     if (aop1->aopu.aop_reg[i] !=
707         aop2->aopu.aop_reg[i])
708       return FALSE;
709
710   return TRUE;
711 }
712
713 /*-----------------------------------------------------------------*/
714 /* aopOp - allocates an asmop for an operand  :                    */
715 /*-----------------------------------------------------------------*/
716 static void
717 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
718 {
719   asmop *aop;
720   symbol *sym;
721   int i;
722
723   if (!op)
724     return;
725
726   /* if this a literal */
727   if (IS_OP_LITERAL (op))
728     {
729       op->aop = aop = newAsmop (AOP_LIT);
730       aop->aopu.aop_lit = op->operand.valOperand;
731       aop->size = getSize (operandType (op));
732       return;
733     }
734
735   /* if already has a asmop then continue */
736   if (op->aop)
737     return;
738
739   /* if the underlying symbol has a aop */
740   if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
741     {
742       op->aop = OP_SYMBOL (op)->aop;
743       return;
744     }
745
746   /* if this is a true symbol */
747   if (IS_TRUE_SYMOP (op))
748     {
749       op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
750       return;
751     }
752
753   /* this is a temporary : this has
754      only four choices :
755      a) register
756      b) spillocation
757      c) rematerialize
758      d) conditional
759      e) can be a return use only */
760
761   sym = OP_SYMBOL (op);
762
763
764   /* if the type is a conditional */
765   if (sym->regType == REG_CND)
766     {
767       aop = op->aop = sym->aop = newAsmop (AOP_CRY);
768       aop->size = 0;
769       return;
770     }
771
772   /* if it is spilt then two situations
773      a) is rematerialize
774      b) has a spill location */
775   if (sym->isspilt || sym->nRegs == 0)
776     {
777
778       /* rematerialize it NOW */
779       if (sym->remat)
780         {
781           sym->aop = op->aop = aop =
782             aopForRemat (sym);
783           aop->size = getSize (sym->type);
784           return;
785         }
786
787       if (sym->accuse)
788         {
789           int i;
790           aop = op->aop = sym->aop = newAsmop (AOP_ACC);
791           aop->size = getSize (sym->type);
792           for (i = 0; i < 2; i++)
793             aop->aopu.aop_str[i] = accUse[i];
794           return;
795         }
796
797       if (sym->ruonly)
798         {
799           int i;
800
801           if (useDP2)
802             {
803               /* a AOP_STR uses DPTR, but DPTR is already in use;
804                * we're just hosed.
805                */
806               fprintf (stderr, "*** Internal error: AOP_STR with DPTR in use! for operand %s\n",sym->name);
807             }
808
809           aop = op->aop = sym->aop = newAsmop (AOP_STR);
810           aop->size = getSize (sym->type);
811           for (i = 0; i < (int) fReturnSizeDS390; i++)
812             aop->aopu.aop_str[i] = fReturn[i];
813           return;
814         }
815
816       /* else spill location  */
817       sym->aop = op->aop = aop =
818         aopForSym (ic, sym->usl.spillLoc, result, useDP2);
819       aop->size = getSize (sym->type);
820       return;
821     }
822
823   /* must be in a register */
824   sym->aop = op->aop = aop = newAsmop (AOP_REG);
825   aop->size = sym->nRegs;
826   for (i = 0; i < sym->nRegs; i++)
827     aop->aopu.aop_reg[i] = sym->regs[i];
828 }
829
830 /*-----------------------------------------------------------------*/
831 /* freeAsmop - free up the asmop given to an operand               */
832 /*----------------------------------------------------------------*/
833 static void
834 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
835 {
836   asmop *aop;
837
838   if (!op)
839     aop = aaop;
840   else
841     aop = op->aop;
842
843   if (!aop)
844     return;
845
846   if (aop->freed)
847     goto dealloc;
848
849   aop->freed = 1;
850
851   /* depending on the asmop type only three cases need work AOP_RO
852      , AOP_R1 && AOP_STK */
853   switch (aop->type)
854     {
855     case AOP_R0:
856       if (_G.r0Pushed)
857         {
858           if (pop)
859             {
860               emitcode ("pop", "ar0");
861               _G.r0Pushed--;
862             }
863         }
864       bitVectUnSetBit (ic->rUsed, R0_IDX);
865       break;
866
867     case AOP_R1:
868       if (_G.r1Pushed)
869         {
870           if (pop)
871             {
872               emitcode ("pop", "ar1");
873               _G.r1Pushed--;
874             }
875         }
876       bitVectUnSetBit (ic->rUsed, R1_IDX);
877       break;
878
879     case AOP_STK:
880       {
881         int sz = aop->size;
882         int stk = aop->aopu.aop_stk + aop->size;
883         bitVectUnSetBit (ic->rUsed, R0_IDX);
884         bitVectUnSetBit (ic->rUsed, R1_IDX);
885
886         getFreePtr (ic, &aop, FALSE);
887
888         if (options.stack10bit)
889           {
890             /* I'm not sure what to do here yet... */
891             /* #STUB */
892             fprintf (stderr,
893                      "*** Warning: probably generating bad code for "
894                      "10 bit stack mode.\n");
895           }
896
897         if (stk)
898           {
899             emitcode ("mov", "a,_bp");
900             emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
901             emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
902           }
903         else
904           {
905             emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
906           }
907
908         while (sz--)
909           {
910             emitcode ("pop", "acc");
911             emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
912             if (!sz)
913               break;
914             emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
915           }
916         op->aop = aop;
917         freeAsmop (op, NULL, ic, TRUE);
918         if (_G.r0Pushed)
919           {
920             emitcode ("pop", "ar0");
921             _G.r0Pushed--;
922           }
923
924         if (_G.r1Pushed)
925           {
926             emitcode ("pop", "ar1");
927             _G.r1Pushed--;
928           }
929       }
930     }
931
932 dealloc:
933   /* all other cases just dealloc */
934   if (op)
935     {
936       op->aop = NULL;
937       if (IS_SYMOP (op))
938         {
939           OP_SYMBOL (op)->aop = NULL;
940           /* if the symbol has a spill */
941           if (SPIL_LOC (op))
942             SPIL_LOC (op)->aop = NULL;
943         }
944     }
945 }
946
947 /*------------------------------------------------------------------*/
948 /* aopGet - for fetching value of the aop                           */
949 /*                    */
950 /* Set canClobberACC if you are sure it is OK to clobber the value  */
951 /* in the accumulator. Set it FALSE otherwise; FALSE is always safe, */
952 /* just less efficient.               */
953 /*------------------------------------------------------------------*/
954
955 static char *
956 aopGet (asmop * aop,
957         int offset,
958         bool bit16,
959         bool dname,
960         bool canClobberACC)
961 {
962   char *s = buffer;
963   char *rs;
964
965   /* offset is greater than
966      size then zero */
967   if (offset > (aop->size - 1) &&
968       aop->type != AOP_LIT)
969     return zero;
970
971   /* depending on type */
972   switch (aop->type)
973     {
974
975     case AOP_R0:
976     case AOP_R1:
977       /* if we need to increment it */
978       while (offset > aop->coff)
979         {
980           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
981           aop->coff++;
982         }
983
984       while (offset < aop->coff)
985         {
986           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
987           aop->coff--;
988         }
989
990       aop->coff = offset;
991       if (aop->paged)
992         {
993           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
994           return (dname ? "acc" : "a");
995         }
996       sprintf (s, "@%s", aop->aopu.aop_ptr->name);
997       rs = Safe_calloc (1, strlen (s) + 1);
998       strcpy (rs, s);
999       return rs;
1000
1001     case AOP_DPTR:
1002     case AOP_DPTR2:
1003
1004       if (aop->type == AOP_DPTR2)
1005         {
1006           genSetDPTR (1);
1007           if (!canClobberACC)
1008             {
1009                     TR_AP("#1");
1010                     emitcode ("xch", "a, %s", DP2_RESULT_REG);
1011             }
1012         }
1013
1014       _flushLazyDPS ();
1015
1016       while (offset > aop->coff)
1017         {
1018           emitcode ("inc", "dptr");
1019           aop->coff++;
1020         }
1021
1022       while (offset < aop->coff)
1023         {
1024           emitcode ("lcall", "__decdptr");
1025           aop->coff--;
1026         }
1027
1028       aop->coff = offset;
1029       if (aop->code)
1030         {
1031           emitcode ("clr", "a");
1032           emitcode ("movc", "a,@a+dptr");
1033         }
1034       else
1035         {
1036           emitcode ("movx", "a,@dptr");
1037         }
1038
1039       if (aop->type == AOP_DPTR2)
1040         {
1041           genSetDPTR (0);
1042           if (!canClobberACC)
1043             {
1044        TR_AP("#2");
1045               emitcode ("xch", "a, %s", DP2_RESULT_REG);
1046               return DP2_RESULT_REG;
1047             }
1048         }
1049       return (dname ? "acc" : "a");
1050
1051     case AOP_IMMD:
1052       if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
1053               sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
1054       } else if (bit16)
1055         sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
1056       else if (offset)
1057         sprintf (s, "#(%s >> %d)",
1058                  aop->aopu.aop_immd.aop_immd1,
1059                  offset * 8);
1060       else
1061         sprintf (s, "#%s",
1062                  aop->aopu.aop_immd.aop_immd1);
1063       rs = Safe_calloc (1, strlen (s) + 1);
1064       strcpy (rs, s);
1065       return rs;
1066
1067     case AOP_DIR:
1068       if (offset)
1069         sprintf (s, "(%s + %d)",
1070                  aop->aopu.aop_dir,
1071                  offset);
1072       else
1073         sprintf (s, "%s", aop->aopu.aop_dir);
1074       rs = Safe_calloc (1, strlen (s) + 1);
1075       strcpy (rs, s);
1076       return rs;
1077
1078     case AOP_REG:
1079       if (dname)
1080         return aop->aopu.aop_reg[offset]->dname;
1081       else
1082         return aop->aopu.aop_reg[offset]->name;
1083
1084     case AOP_CRY:
1085       emitcode ("clr", "a");
1086       emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1087       emitcode ("rlc", "a");
1088       return (dname ? "acc" : "a");
1089
1090     case AOP_ACC:
1091       if (!offset && dname)
1092         return "acc";
1093       return aop->aopu.aop_str[offset];
1094
1095     case AOP_LIT:
1096       return aopLiteral (aop->aopu.aop_lit, offset);
1097
1098     case AOP_STR:
1099       aop->coff = offset;
1100       if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1101           dname)
1102         return "acc";
1103
1104       return aop->aopu.aop_str[offset];
1105
1106     }
1107
1108   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1109           "aopget got unsupported aop->type");
1110   exit (1);
1111 }
1112 /*-----------------------------------------------------------------*/
1113 /* aopPut - puts a string for a aop                                */
1114 /*-----------------------------------------------------------------*/
1115 static void
1116 aopPut (asmop * aop, char *s, int offset)
1117 {
1118   char *d = buffer;
1119
1120   if (aop->size && offset > (aop->size - 1))
1121     {
1122       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1123               "aopPut got offset > aop->size");
1124       exit (1);
1125     }
1126
1127   /* will assign value to value */
1128   /* depending on where it is ofcourse */
1129   switch (aop->type)
1130     {
1131     case AOP_DIR:
1132       if (offset)
1133         sprintf (d, "(%s + %d)",
1134                  aop->aopu.aop_dir, offset);
1135       else
1136         sprintf (d, "%s", aop->aopu.aop_dir);
1137
1138       if (strcmp (d, s))
1139         emitcode ("mov", "%s,%s", d, s);
1140
1141       break;
1142
1143     case AOP_REG:
1144       if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1145           strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1146         {
1147           if (*s == '@' ||
1148               strcmp (s, "r0") == 0 ||
1149               strcmp (s, "r1") == 0 ||
1150               strcmp (s, "r2") == 0 ||
1151               strcmp (s, "r3") == 0 ||
1152               strcmp (s, "r4") == 0 ||
1153               strcmp (s, "r5") == 0 ||
1154               strcmp (s, "r6") == 0 ||
1155               strcmp (s, "r7") == 0)
1156             emitcode ("mov", "%s,%s",
1157                       aop->aopu.aop_reg[offset]->dname, s);
1158           else
1159             emitcode ("mov", "%s,%s",
1160                       aop->aopu.aop_reg[offset]->name, s);
1161         }
1162       break;
1163
1164     case AOP_DPTR:
1165     case AOP_DPTR2:
1166
1167       if (aop->type == AOP_DPTR2)
1168         {
1169           genSetDPTR (1);
1170         }
1171       _flushLazyDPS ();
1172
1173       if (aop->code)
1174         {
1175           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1176                   "aopPut writting to code space");
1177           exit (1);
1178         }
1179
1180       while (offset > aop->coff)
1181         {
1182           aop->coff++;
1183           emitcode ("inc", "dptr");
1184         }
1185
1186       while (offset < aop->coff)
1187         {
1188           aop->coff--;
1189           emitcode ("lcall", "__decdptr");
1190         }
1191
1192       aop->coff = offset;
1193
1194       /* if not in accumulater */
1195       MOVA (s);
1196
1197       emitcode ("movx", "@dptr,a");
1198
1199       if (aop->type == AOP_DPTR2)
1200         {
1201           genSetDPTR (0);
1202         }
1203       break;
1204
1205     case AOP_R0:
1206     case AOP_R1:
1207       while (offset > aop->coff)
1208         {
1209           aop->coff++;
1210           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1211         }
1212       while (offset < aop->coff)
1213         {
1214           aop->coff--;
1215           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1216         }
1217       aop->coff = offset;
1218
1219       if (aop->paged)
1220         {
1221           MOVA (s);
1222           emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1223
1224         }
1225       else if (*s == '@')
1226         {
1227           MOVA (s);
1228           emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1229         }
1230       else if (strcmp (s, "r0") == 0 ||
1231                strcmp (s, "r1") == 0 ||
1232                strcmp (s, "r2") == 0 ||
1233                strcmp (s, "r3") == 0 ||
1234                strcmp (s, "r4") == 0 ||
1235                strcmp (s, "r5") == 0 ||
1236                strcmp (s, "r6") == 0 ||
1237                strcmp (s, "r7") == 0)
1238         {
1239           char buffer[10];
1240           sprintf (buffer, "a%s", s);
1241           emitcode ("mov", "@%s,%s",
1242                     aop->aopu.aop_ptr->name, buffer);
1243         }
1244       else
1245         emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1246
1247       break;
1248
1249     case AOP_STK:
1250       if (strcmp (s, "a") == 0)
1251         emitcode ("push", "acc");
1252       else
1253         if (*s=='@') {
1254           MOVA(s);
1255           emitcode ("push", "acc");
1256         } else {
1257           emitcode ("push", s);
1258         }
1259
1260       break;
1261
1262     case AOP_CRY:
1263       /* if bit variable */
1264       if (!aop->aopu.aop_dir)
1265         {
1266           emitcode ("clr", "a");
1267           emitcode ("rlc", "a");
1268         }
1269       else
1270         {
1271           if (s == zero)
1272             emitcode ("clr", "%s", aop->aopu.aop_dir);
1273           else if (s == one)
1274             emitcode ("setb", "%s", aop->aopu.aop_dir);
1275           else if (!strcmp (s, "c"))
1276             emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1277           else
1278             {
1279               if (strcmp (s, "a"))
1280                 {
1281                   MOVA (s);
1282                 }
1283               {
1284                 symbol *lbl = newiTempLabel (NULL);
1285                 emitcode ("clr", "c");
1286                 emitcode ("jz", "%05d$", lbl->key + 100);
1287                 emitcode ("cpl", "c");
1288                 emitcode ("", "%05d$:", lbl->key + 100);
1289                 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1290               }
1291             }
1292         }
1293       break;
1294
1295     case AOP_STR:
1296       aop->coff = offset;
1297       if (strcmp (aop->aopu.aop_str[offset], s))
1298         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1299       break;
1300
1301     case AOP_ACC:
1302       aop->coff = offset;
1303       if (!offset && (strcmp (s, "acc") == 0))
1304         break;
1305
1306       if (strcmp (aop->aopu.aop_str[offset], s))
1307         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1308       break;
1309
1310     default:
1311       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1312               "aopPut got unsupported aop->type");
1313       exit (1);
1314     }
1315
1316 }
1317
1318
1319 /*--------------------------------------------------------------------*/
1320 /* reAdjustPreg - points a register back to where it should (coff==0) */
1321 /*--------------------------------------------------------------------*/
1322 static void
1323 reAdjustPreg (asmop * aop)
1324 {
1325   if ((aop->coff==0) || (aop->size <= 1)) {
1326     return;
1327   }
1328
1329   switch (aop->type)
1330     {
1331     case AOP_R0:
1332     case AOP_R1:
1333       while (aop->coff--)
1334         emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1335       break;
1336     case AOP_DPTR:
1337     case AOP_DPTR2:
1338       if (aop->type == AOP_DPTR2)
1339         {
1340           genSetDPTR (1);
1341           _flushLazyDPS ();
1342         }
1343       while (aop->coff--)
1344         {
1345           emitcode ("lcall", "__decdptr");
1346         }
1347
1348       if (aop->type == AOP_DPTR2)
1349         {
1350           genSetDPTR (0);
1351         }
1352       break;
1353
1354     }
1355   aop->coff=0;
1356 }
1357
1358 #define AOP(op) op->aop
1359 #define AOP_TYPE(op) AOP(op)->type
1360 #define AOP_SIZE(op) AOP(op)->size
1361 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1362                        AOP_TYPE(x) == AOP_R0))
1363
1364 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
1365                         AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1366                          AOP(x)->paged))
1367
1368 #define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
1369                       (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1370                       x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1371
1372 /* Workaround for DS80C390 bug: div ab may return bogus results
1373  * if A is accessed in instruction immediately before the div.
1374  *
1375  * Will be fixed in B4 rev of processor, Dallas claims.
1376  */
1377
1378 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L)       \
1379     if (!AOP_NEEDSACC(RIGHT))         \
1380     {               \
1381       /* We can load A first, then B, since     \
1382        * B (the RIGHT operand) won't clobber A,   \
1383        * thus avoiding touching A right before the div. \
1384        */             \
1385       D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1386       L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE);     \
1387       MOVA(L);            \
1388       emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1389     }               \
1390     else              \
1391     {               \
1392       /* Just stuff in a nop after loading A. */    \
1393       emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1394       L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE);   \
1395       MOVA(L);            \
1396       emitcode("nop", "; workaround for DS80C390 div bug.");  \
1397     }
1398
1399 /*-----------------------------------------------------------------*/
1400 /* genNotFloat - generates not for float operations              */
1401 /*-----------------------------------------------------------------*/
1402 static void
1403 genNotFloat (operand * op, operand * res)
1404 {
1405   int size, offset;
1406   char *l;
1407   symbol *tlbl;
1408
1409   D (emitcode (";", "genNotFloat ");
1410     );
1411
1412   /* we will put 127 in the first byte of
1413      the result */
1414   aopPut (AOP (res), "#127", 0);
1415   size = AOP_SIZE (op) - 1;
1416   offset = 1;
1417
1418   _startLazyDPSEvaluation ();
1419   l = aopGet (op->aop, offset++, FALSE, FALSE, TRUE);
1420   MOVA (l);
1421
1422   while (size--)
1423     {
1424       emitcode ("orl", "a,%s",
1425                 aopGet (op->aop,
1426                         offset++, FALSE, FALSE, FALSE));
1427     }
1428   _endLazyDPSEvaluation ();
1429
1430   tlbl = newiTempLabel (NULL);
1431   aopPut (res->aop, one, 1);
1432   emitcode ("jz", "%05d$", (tlbl->key + 100));
1433   aopPut (res->aop, zero, 1);
1434   emitcode ("", "%05d$:", (tlbl->key + 100));
1435
1436   size = res->aop->size - 2;
1437   offset = 2;
1438   /* put zeros in the rest */
1439   while (size--)
1440     aopPut (res->aop, zero, offset++);
1441 }
1442
1443 /*-----------------------------------------------------------------*/
1444 /* opIsGptr: returns non-zero if the passed operand is       */
1445 /* a generic pointer type.             */
1446 /*-----------------------------------------------------------------*/
1447 static int
1448 opIsGptr (operand * op)
1449 {
1450   sym_link *type = operandType (op);
1451
1452   if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1453     {
1454       return 1;
1455     }
1456   return 0;
1457 }
1458
1459 /*-----------------------------------------------------------------*/
1460 /* getDataSize - get the operand data size                         */
1461 /*-----------------------------------------------------------------*/
1462 static int
1463 getDataSize (operand * op)
1464 {
1465   int size;
1466   size = AOP_SIZE (op);
1467   if (size == GPTRSIZE)
1468     {
1469       sym_link *type = operandType (op);
1470       if (IS_GENPTR (type))
1471         {
1472           /* generic pointer; arithmetic operations
1473            * should ignore the high byte (pointer type).
1474            */
1475           size--;
1476         }
1477     }
1478   return size;
1479 }
1480
1481 /*-----------------------------------------------------------------*/
1482 /* outAcc - output Acc                                             */
1483 /*-----------------------------------------------------------------*/
1484 static void
1485 outAcc (operand * result)
1486 {
1487   int size, offset;
1488   size = getDataSize (result);
1489   if (size)
1490     {
1491       aopPut (AOP (result), "a", 0);
1492       size--;
1493       offset = 1;
1494       /* unsigned or positive */
1495       while (size--)
1496         {
1497           aopPut (AOP (result), zero, offset++);
1498         }
1499     }
1500 }
1501
1502 /*-----------------------------------------------------------------*/
1503 /* outBitC - output a bit C                                        */
1504 /*-----------------------------------------------------------------*/
1505 static void
1506 outBitC (operand * result)
1507 {
1508   /* if the result is bit */
1509   if (AOP_TYPE (result) == AOP_CRY)
1510     {
1511       aopPut (AOP (result), "c", 0);
1512     }
1513   else
1514     {
1515       emitcode ("clr", "a");
1516       emitcode ("rlc", "a");
1517       outAcc (result);
1518     }
1519 }
1520
1521 /*-----------------------------------------------------------------*/
1522 /* toBoolean - emit code for orl a,operator(sizeop)                */
1523 /*-----------------------------------------------------------------*/
1524 static void
1525 toBoolean (operand * oper)
1526 {
1527   int   size = AOP_SIZE (oper) - 1;
1528   int   offset = 1;
1529   bool usedB = FALSE;
1530
1531   /* The generic part of a generic pointer should
1532    * not participate in it's truth value.
1533    *
1534    * i.e. 0x10000000 is zero.
1535    */
1536   if (opIsGptr (oper))
1537     {
1538       D (emitcode (";", "toBoolean: generic ptr special case.");
1539         );
1540       size--;
1541     }
1542
1543   _startLazyDPSEvaluation ();
1544   if (AOP_NEEDSACC (oper) && size)
1545     {
1546       usedB = TRUE;
1547       emitcode ("push", "b");
1548       emitcode ("mov", "b, %s", aopGet (AOP (oper), 0, FALSE, FALSE, FALSE));
1549     }
1550   else
1551     {
1552       MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, TRUE));
1553     }
1554   while (size--)
1555     {
1556       if (usedB)
1557         {
1558           emitcode ("orl", "b,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1559         }
1560       else
1561         {
1562           emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1563         }
1564     }
1565   _endLazyDPSEvaluation ();
1566
1567   if (usedB)
1568     {
1569       emitcode ("mov", "a,b");
1570       emitcode ("pop", "b");
1571     }
1572 }
1573
1574
1575 /*-----------------------------------------------------------------*/
1576 /* genNot - generate code for ! operation                          */
1577 /*-----------------------------------------------------------------*/
1578 static void
1579 genNot (iCode * ic)
1580 {
1581   symbol *tlbl;
1582   sym_link *optype = operandType (IC_LEFT (ic));
1583
1584   D (emitcode (";", "genNot ");
1585     );
1586
1587   /* assign asmOps to operand & result */
1588   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1589   aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1590
1591   /* if in bit space then a special case */
1592   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1593     {
1594       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1595       emitcode ("cpl", "c");
1596       outBitC (IC_RESULT (ic));
1597       goto release;
1598     }
1599
1600   /* if type float then do float */
1601   if (IS_FLOAT (optype))
1602     {
1603       genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1604       goto release;
1605     }
1606
1607   toBoolean (IC_LEFT (ic));
1608
1609   tlbl = newiTempLabel (NULL);
1610   emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1611   emitcode ("", "%05d$:", tlbl->key + 100);
1612   outBitC (IC_RESULT (ic));
1613
1614 release:
1615   /* release the aops */
1616   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1617   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1618 }
1619
1620
1621 /*-----------------------------------------------------------------*/
1622 /* genCpl - generate code for complement                           */
1623 /*-----------------------------------------------------------------*/
1624 static void
1625 genCpl (iCode * ic)
1626 {
1627   int offset = 0;
1628   int size;
1629
1630   D (emitcode (";", "genCpl ");
1631     );
1632
1633
1634   /* assign asmOps to operand & result */
1635   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1636   aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1637
1638   /* if both are in bit space then
1639      a special case */
1640   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1641       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1642     {
1643
1644       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1645       emitcode ("cpl", "c");
1646       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1647       goto release;
1648     }
1649
1650   size = AOP_SIZE (IC_RESULT (ic));
1651   _startLazyDPSEvaluation ();
1652   while (size--)
1653     {
1654       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1655       MOVA (l);
1656       emitcode ("cpl", "a");
1657       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1658     }
1659   _endLazyDPSEvaluation ();
1660
1661
1662 release:
1663   /* release the aops */
1664   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1665   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1666 }
1667
1668 /*-----------------------------------------------------------------*/
1669 /* genUminusFloat - unary minus for floating points                */
1670 /*-----------------------------------------------------------------*/
1671 static void
1672 genUminusFloat (operand * op, operand * result)
1673 {
1674   int size, offset = 0;
1675   char *l;
1676   /* for this we just need to flip the
1677      first it then copy the rest in place */
1678   D (emitcode (";", "genUminusFloat");
1679     );
1680
1681   _startLazyDPSEvaluation ();
1682   size = AOP_SIZE (op) - 1;
1683   l = aopGet (AOP (op), 3, FALSE, FALSE, TRUE);
1684   MOVA (l);
1685
1686   emitcode ("cpl", "acc.7");
1687   aopPut (AOP (result), "a", 3);
1688
1689   while (size--)
1690     {
1691       aopPut (AOP (result),
1692               aopGet (AOP (op), offset, FALSE, FALSE, FALSE),
1693               offset);
1694       offset++;
1695     }
1696   _endLazyDPSEvaluation ();
1697 }
1698
1699 /*-----------------------------------------------------------------*/
1700 /* genUminus - unary minus code generation                         */
1701 /*-----------------------------------------------------------------*/
1702 static void
1703 genUminus (iCode * ic)
1704 {
1705   int offset, size;
1706   sym_link *optype, *rtype;
1707
1708   D (emitcode (";", "genUminus ");
1709     );
1710
1711
1712   /* assign asmops */
1713   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1714   aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1715
1716   /* if both in bit space then special
1717      case */
1718   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1719       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1720     {
1721
1722       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1723       emitcode ("cpl", "c");
1724       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1725       goto release;
1726     }
1727
1728   optype = operandType (IC_LEFT (ic));
1729   rtype = operandType (IC_RESULT (ic));
1730
1731   /* if float then do float stuff */
1732   if (IS_FLOAT (optype))
1733     {
1734       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1735       goto release;
1736     }
1737
1738   /* otherwise subtract from zero */
1739   size = AOP_SIZE (IC_LEFT (ic));
1740   offset = 0;
1741   _startLazyDPSEvaluation ();
1742   while (size--)
1743     {
1744       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1745       if (!strcmp (l, "a"))
1746         {
1747           if (offset == 0)
1748             SETC;
1749           emitcode ("cpl", "a");
1750           emitcode ("addc", "a,#0");
1751         }
1752       else
1753         {
1754           if (offset == 0)
1755             CLRC;
1756           emitcode ("clr", "a");
1757           emitcode ("subb", "a,%s", l);
1758         }
1759       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1760     }
1761   _endLazyDPSEvaluation ();
1762
1763   /* if any remaining bytes in the result */
1764   /* we just need to propagate the sign   */
1765   if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1766     {
1767       emitcode ("rlc", "a");
1768       emitcode ("subb", "a,acc");
1769       while (size--)
1770         aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1771     }
1772
1773 release:
1774   /* release the aops */
1775   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1776   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1777 }
1778
1779 /*-----------------------------------------------------------------*/
1780 /* saveRegisters - will look for a call and save the registers     */
1781 /*-----------------------------------------------------------------*/
1782 static void
1783 saveRegisters (iCode * lic)
1784 {
1785   int i;
1786   iCode *ic;
1787   bitVect *rsave;
1788   sym_link *detype;
1789
1790   /* look for call */
1791   for (ic = lic; ic; ic = ic->next)
1792     if (ic->op == CALL || ic->op == PCALL)
1793       break;
1794
1795   if (!ic)
1796     {
1797       fprintf (stderr, "found parameter push with no function call\n");
1798       return;
1799     }
1800
1801   /* if the registers have been saved already then
1802      do nothing */
1803   if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type) ||
1804       IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic))))
1805     return;
1806
1807   /* find the registers in use at this time
1808      and push them away to safety */
1809   rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1810                          ic->rUsed);
1811
1812   ic->regsSaved = 1;
1813   if (options.useXstack)
1814     {
1815       if (bitVectBitValue (rsave, R0_IDX))
1816         emitcode ("mov", "b,r0");
1817       emitcode ("mov", "r0,%s", spname);
1818       for (i = 0; i < ds390_nRegs; i++)
1819         {
1820           if (bitVectBitValue (rsave, i))
1821             {
1822               if (i == R0_IDX)
1823                 emitcode ("mov", "a,b");
1824               else
1825                 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
1826               emitcode ("movx", "@r0,a");
1827               emitcode ("inc", "r0");
1828             }
1829         }
1830       emitcode ("mov", "%s,r0", spname);
1831       if (bitVectBitValue (rsave, R0_IDX))
1832         emitcode ("mov", "r0,b");
1833     }
1834   else
1835     for (i = 0; i < ds390_nRegs; i++)
1836       {
1837         if (bitVectBitValue (rsave, i))
1838           emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
1839       }
1840
1841   detype = getSpec (operandType (IC_LEFT (ic)));
1842 }
1843
1844 /*-----------------------------------------------------------------*/
1845 /* unsaveRegisters - pop the pushed registers                      */
1846 /*-----------------------------------------------------------------*/
1847 static void
1848 unsaveRegisters (iCode * ic)
1849 {
1850   int i;
1851   bitVect *rsave;
1852   /* find the registers in use at this time
1853      and push them away to safety */
1854   rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1855                          ic->rUsed);
1856
1857   if (options.useXstack)
1858     {
1859       emitcode ("mov", "r0,%s", spname);
1860       for (i = ds390_nRegs; i >= 0; i--)
1861         {
1862           if (bitVectBitValue (rsave, i))
1863             {
1864               emitcode ("dec", "r0");
1865               emitcode ("movx", "a,@r0");
1866               if (i == R0_IDX)
1867                 emitcode ("mov", "b,a");
1868               else
1869                 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
1870             }
1871
1872         }
1873       emitcode ("mov", "%s,r0", spname);
1874       if (bitVectBitValue (rsave, R0_IDX))
1875         emitcode ("mov", "r0,b");
1876     }
1877   else
1878     for (i = ds390_nRegs; i >= 0; i--)
1879       {
1880         if (bitVectBitValue (rsave, i))
1881           emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
1882       }
1883
1884 }
1885
1886
1887 /*-----------------------------------------------------------------*/
1888 /* pushSide -                */
1889 /*-----------------------------------------------------------------*/
1890 static void
1891 pushSide (operand * oper, int size)
1892 {
1893   int offset = 0;
1894   _startLazyDPSEvaluation ();
1895   while (size--)
1896     {
1897       char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, FALSE);
1898       if (AOP_TYPE (oper) != AOP_REG &&
1899           AOP_TYPE (oper) != AOP_DIR &&
1900           strcmp (l, "a"))
1901         {
1902           emitcode ("mov", "a,%s", l);
1903           emitcode ("push", "acc");
1904         }
1905       else
1906         emitcode ("push", "%s", l);
1907     }
1908   _endLazyDPSEvaluation ();
1909 }
1910
1911 /*-----------------------------------------------------------------*/
1912 /* assignResultValue -               */
1913 /*-----------------------------------------------------------------*/
1914 static void
1915 assignResultValue (operand * oper)
1916 {
1917   int offset = 0;
1918   int size = AOP_SIZE (oper);
1919
1920   _startLazyDPSEvaluation ();
1921   while (size--)
1922     {
1923       aopPut (AOP (oper), fReturn[offset], offset);
1924       offset++;
1925     }
1926   _endLazyDPSEvaluation ();
1927 }
1928
1929
1930 /*-----------------------------------------------------------------*/
1931 /* genXpush - pushes onto the external stack                       */
1932 /*-----------------------------------------------------------------*/
1933 static void
1934 genXpush (iCode * ic)
1935 {
1936   asmop *aop = newAsmop (0);
1937   regs *r;
1938   int size, offset = 0;
1939
1940   D (emitcode (";", "genXpush ");
1941     );
1942
1943   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1944   r = getFreePtr (ic, &aop, FALSE);
1945
1946
1947   emitcode ("mov", "%s,_spx", r->name);
1948
1949   size = AOP_SIZE (IC_LEFT (ic));
1950   _startLazyDPSEvaluation ();
1951   while (size--)
1952     {
1953
1954       char *l = aopGet (AOP (IC_LEFT (ic)),
1955                         offset++, FALSE, FALSE, TRUE);
1956       MOVA (l);
1957       emitcode ("movx", "@%s,a", r->name);
1958       emitcode ("inc", "%s", r->name);
1959
1960     }
1961   _endLazyDPSEvaluation ();
1962
1963
1964   emitcode ("mov", "_spx,%s", r->name);
1965
1966   freeAsmop (NULL, aop, ic, TRUE);
1967   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1968 }
1969
1970 /*-----------------------------------------------------------------*/
1971 /* genIpush - genrate code for pushing this gets a little complex  */
1972 /*-----------------------------------------------------------------*/
1973 static void
1974 genIpush (iCode * ic)
1975 {
1976   int size, offset = 0;
1977   char *l;
1978
1979   D (emitcode (";", "genIpush ");
1980     );
1981
1982   /* if this is not a parm push : ie. it is spill push
1983      and spill push is always done on the local stack */
1984   if (!ic->parmPush)
1985     {
1986
1987       /* and the item is spilt then do nothing */
1988       if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1989         return;
1990
1991       aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1992       size = AOP_SIZE (IC_LEFT (ic));
1993       /* push it on the stack */
1994       _startLazyDPSEvaluation ();
1995       while (size--)
1996         {
1997           l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, TRUE);
1998           if (*l == '#')
1999             {
2000               MOVA (l);
2001               l = "acc";
2002             }
2003           emitcode ("push", "%s", l);
2004         }
2005       _endLazyDPSEvaluation ();
2006       return;
2007     }
2008
2009   /* this is a paramter push: in this case we call
2010      the routine to find the call and save those
2011      registers that need to be saved */
2012   saveRegisters (ic);
2013
2014   /* if use external stack then call the external
2015      stack pushing routine */
2016   if (options.useXstack)
2017     {
2018       genXpush (ic);
2019       return;
2020     }
2021
2022   /* then do the push */
2023   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2024
2025   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2026   size = AOP_SIZE (IC_LEFT (ic));
2027
2028   _startLazyDPSEvaluation ();
2029   while (size--)
2030     {
2031       l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, FALSE);
2032       if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2033           AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2034           strcmp (l, "a"))
2035         {
2036           emitcode ("mov", "a,%s", l);
2037           emitcode ("push", "acc");
2038         }
2039       else
2040         emitcode ("push", "%s", l);
2041     }
2042   _endLazyDPSEvaluation ();
2043
2044   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2045 }
2046
2047 /*-----------------------------------------------------------------*/
2048 /* genIpop - recover the registers: can happen only for spilling   */
2049 /*-----------------------------------------------------------------*/
2050 static void
2051 genIpop (iCode * ic)
2052 {
2053   int size, offset;
2054
2055   D (emitcode (";", "genIpop ");
2056     );
2057
2058
2059   /* if the temp was not pushed then */
2060   if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2061     return;
2062
2063   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2064   size = AOP_SIZE (IC_LEFT (ic));
2065   offset = (size - 1);
2066   _startLazyDPSEvaluation ();
2067   while (size--)
2068     {
2069       emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2070                                      FALSE, TRUE, TRUE));
2071     }
2072   _endLazyDPSEvaluation ();
2073
2074   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2075 }
2076
2077 /*-----------------------------------------------------------------*/
2078 /* unsaveRBank - restores the resgister bank from stack            */
2079 /*-----------------------------------------------------------------*/
2080 static void
2081 unsaveRBank (int bank, iCode * ic, bool popPsw)
2082 {
2083   int i;
2084   asmop *aop = NULL;
2085   regs *r = NULL;
2086
2087   if (options.useXstack)
2088   {
2089       if (!ic)
2090       {
2091           /* Assume r0 is available for use. */
2092           r = ds390_regWithIdx (R0_IDX);;          
2093       } 
2094       else
2095       {
2096           aop = newAsmop (0);
2097           r = getFreePtr (ic, &aop, FALSE);
2098       }
2099       emitcode ("mov", "%s,_spx", r->name);      
2100   }
2101   
2102   if (popPsw)
2103     {
2104       if (options.useXstack)
2105       {
2106           emitcode ("movx", "a,@%s", r->name);
2107           emitcode ("mov", "psw,a");
2108           emitcode ("dec", "%s", r->name);
2109         }
2110       else
2111       {
2112         emitcode ("pop", "psw");
2113       }
2114     }
2115
2116   for (i = (ds390_nRegs - 1); i >= 0; i--)
2117     {
2118       if (options.useXstack)
2119         {
2120           emitcode ("movx", "a,@%s", r->name);
2121           emitcode ("mov", "(%s+%d),a",
2122                     regs390[i].base, 8 * bank + regs390[i].offset);
2123           emitcode ("dec", "%s", r->name);
2124
2125         }
2126       else
2127         emitcode ("pop", "(%s+%d)",
2128                   regs390[i].base, 8 * bank + regs390[i].offset);
2129     }
2130
2131   if (options.useXstack)
2132     {
2133       emitcode ("mov", "_spx,%s", r->name);
2134     }
2135     
2136   if (aop)
2137   {
2138       freeAsmop (NULL, aop, ic, TRUE);  
2139   }    
2140 }
2141
2142 /*-----------------------------------------------------------------*/
2143 /* saveRBank - saves an entire register bank on the stack          */
2144 /*-----------------------------------------------------------------*/
2145 static void
2146 saveRBank (int bank, iCode * ic, bool pushPsw)
2147 {
2148   int i;
2149   asmop *aop = NULL;
2150   regs *r = NULL;
2151
2152   if (options.useXstack)
2153     {
2154         if (!ic)
2155         {
2156           /* Assume r0 is available for use. */
2157                   r = ds390_regWithIdx (R0_IDX);;
2158         }
2159         else
2160         {
2161           aop = newAsmop (0);
2162           r = getFreePtr (ic, &aop, FALSE);
2163         }
2164         emitcode ("mov", "%s,_spx", r->name);    
2165     }
2166
2167   for (i = 0; i < ds390_nRegs; i++)
2168     {
2169       if (options.useXstack)
2170         {
2171           emitcode ("inc", "%s", r->name);
2172           emitcode ("mov", "a,(%s+%d)",
2173                     regs390[i].base, 8 * bank + regs390[i].offset);
2174           emitcode ("movx", "@%s,a", r->name);
2175         }
2176       else
2177         emitcode ("push", "(%s+%d)",
2178                   regs390[i].base, 8 * bank + regs390[i].offset);
2179     }
2180
2181   if (pushPsw)
2182     {
2183       if (options.useXstack)
2184         {
2185           emitcode ("mov", "a,psw");
2186           emitcode ("movx", "@%s,a", r->name);
2187           emitcode ("inc", "%s", r->name);
2188           emitcode ("mov", "_spx,%s", r->name);
2189         }
2190       else
2191       {
2192         emitcode ("push", "psw");
2193       }
2194
2195       emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2196     }
2197   
2198   if (aop)
2199   {
2200        freeAsmop (NULL, aop, ic, TRUE);
2201   }    
2202     
2203   if (ic)
2204   {  
2205       ic->bankSaved = 1;
2206   }
2207 }
2208
2209 /*-----------------------------------------------------------------*/
2210 /* genCall - generates a call statement                            */
2211 /*-----------------------------------------------------------------*/
2212 static void
2213 genCall (iCode * ic)
2214 {
2215   sym_link *dtype;
2216   bool restoreBank = FALSE;
2217   bool swapBanks = FALSE;
2218
2219   D (emitcode (";", "genCall "););
2220
2221   /* if we are calling a not _naked function that is not using
2222      the same register bank then we need to save the
2223      destination registers on the stack */
2224   dtype = operandType (IC_LEFT (ic));
2225   if (dtype && !IFFUNC_ISNAKED(dtype) &&
2226       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2227       IFFUNC_ISISR (currFunc->type))
2228   {
2229       if (!ic->bankSaved) 
2230       {
2231            /* This is unexpected; the bank should have been saved in
2232             * genFunction.
2233             */
2234            saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2235            restoreBank = TRUE;
2236       }
2237       swapBanks = TRUE;
2238   }
2239   
2240     /* if caller saves & we have not saved then */
2241     if (!ic->regsSaved)
2242       saveRegisters (ic);
2243   
2244   /* if send set is not empty the assign */
2245   /* We've saved all the registers we care about;
2246   * therefore, we may clobber any register not used
2247   * in the calling convention (i.e. anything not in
2248   * fReturn.
2249   */
2250   if (_G.sendSet)
2251     {
2252       iCode *sic;
2253
2254       for (sic = setFirstItem (_G.sendSet); sic;
2255            sic = setNextItem (_G.sendSet))
2256         {
2257           int size, offset = 0;
2258
2259           aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2260           size = AOP_SIZE (IC_LEFT (sic));
2261
2262           _startLazyDPSEvaluation ();
2263           while (size--)
2264             {
2265               char *l = aopGet (AOP(IC_LEFT(sic)), offset,
2266                                 FALSE, FALSE, TRUE);
2267                 if ((AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR) && size)
2268                 {
2269                     emitcode("mov", "%s,%s", regs390[offset].name, l);
2270                 }
2271                 else if (strcmp (l, fReturn[offset]))
2272                 {
2273                     emitcode ("mov", "%s,%s",
2274                               fReturn[offset],
2275                               l);
2276                 }
2277               offset++;
2278             }
2279           _endLazyDPSEvaluation ();
2280           if (AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR)
2281           {
2282               size = AOP_SIZE (IC_LEFT (sic));
2283               if (size)
2284               {
2285                  size--;
2286               }
2287               while (size)
2288               {
2289                    size--;
2290                    emitcode("mov", "%s,%s",
2291                                     fReturn[size], regs390[size].name);
2292               }
2293           }
2294           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2295         }
2296       _G.sendSet = NULL;
2297     }  
2298     
2299   if (swapBanks)
2300   {
2301         emitcode ("mov", "psw,#0x%02x", 
2302            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2303   }
2304
2305   /* make the call */
2306   emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2307                             OP_SYMBOL (IC_LEFT (ic))->rname :
2308                             OP_SYMBOL (IC_LEFT (ic))->name));
2309
2310   if (swapBanks)
2311   {
2312        emitcode ("mov", "psw,#0x%02x", 
2313           ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2314   }
2315
2316   /* if we need assign a result value */
2317   if ((IS_ITEMP (IC_RESULT (ic)) &&
2318        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2319         OP_SYMBOL (IC_RESULT (ic))->accuse ||
2320         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2321       IS_TRUE_SYMOP (IC_RESULT (ic)))
2322     {
2323       if (isOperandInFarSpace (IC_RESULT (ic))
2324           && getSize (operandType (IC_RESULT (ic))) <= 2)
2325         {
2326           int size = getSize (operandType (IC_RESULT (ic)));
2327
2328           /* Special case for 1 or 2 byte return in far space. */
2329           MOVA (fReturn[0]);
2330           if (size > 1)
2331             {
2332               emitcode ("mov", "b,%s", fReturn[1]);
2333             }
2334
2335           aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2336           aopPut (AOP (IC_RESULT (ic)), "a", 0);
2337
2338           if (size > 1)
2339             {
2340               aopPut (AOP (IC_RESULT (ic)), "b", 1);
2341             }
2342           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2343         }
2344       else
2345         {
2346           _G.accInUse++;
2347           aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2348           _G.accInUse--;
2349
2350           assignResultValue (IC_RESULT (ic));
2351
2352           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2353         }
2354     }
2355
2356   /* adjust the stack for parameters if
2357      required */
2358   if (ic->parmBytes) {
2359       if (options.stack10bit) {
2360           emitcode ("clr","c");
2361           emitcode ("mov","a,sp");
2362           emitcode ("subb","a,#0x%02x",ic->parmBytes & 0xff);
2363           emitcode ("mov","sp,a");
2364           emitcode ("mov","a,#0x%02x",(ic->parmBytes >> 8) & 0xff);
2365           emitcode ("subb","a,_ESP");
2366           emitcode ("mov","_ESP,a");      
2367       } else {
2368           int i;
2369           if (ic->parmBytes > 3) {
2370               emitcode ("mov", "a,%s", spname);
2371               emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2372               emitcode ("mov", "%s,a", spname);
2373           } else
2374               for (i = 0; i < ic->parmBytes; i++)
2375                   emitcode ("dec", "%s", spname);
2376       }
2377   }
2378
2379   /* if we hade saved some registers then unsave them */
2380   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2381     unsaveRegisters (ic);
2382
2383   /* if register bank was saved then pop them */
2384   if (restoreBank)
2385     unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2386 }
2387
2388 /*-----------------------------------------------------------------*/
2389 /* genPcall - generates a call by pointer statement                */
2390 /*-----------------------------------------------------------------*/
2391 static void
2392 genPcall (iCode * ic)
2393 {
2394   sym_link *dtype;
2395   symbol *rlbl = newiTempLabel (NULL);
2396   bool restoreBank=FALSE;
2397
2398   D (emitcode (";", "genPcall ");
2399     );
2400
2401
2402   /* if caller saves & we have not saved then */
2403   if (!ic->regsSaved)
2404     saveRegisters (ic);
2405
2406   /* if we are calling a function that is not using
2407      the same register bank then we need to save the
2408      destination registers on the stack */
2409   dtype = operandType (IC_LEFT (ic));
2410   if (dtype && !IFFUNC_ISNAKED(dtype) &&
2411       IFFUNC_ISISR (currFunc->type) &&
2412       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2413     saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2414     restoreBank=TRUE;
2415   }
2416
2417   /* push the return address on to the stack */
2418   emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2419   emitcode ("push", "acc");
2420   emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2421   emitcode ("push", "acc");
2422
2423   if (options.model == MODEL_FLAT24)
2424     {
2425       emitcode ("mov", "a,#(%05d$ >> 16)", (rlbl->key + 100));
2426       emitcode ("push", "acc");
2427     }
2428
2429   /* now push the calling address */
2430   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2431
2432   pushSide (IC_LEFT (ic), FPTRSIZE);
2433
2434   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2435
2436   /* if send set is not empty the assign */
2437   if (_G.sendSet)
2438     {
2439       iCode *sic;
2440
2441       for (sic = setFirstItem (_G.sendSet); sic;
2442            sic = setNextItem (_G.sendSet))
2443         {
2444           int size, offset = 0;
2445
2446           aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2447           size = AOP_SIZE (IC_LEFT (sic));
2448           _startLazyDPSEvaluation ();
2449           while (size--)
2450             {
2451               char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2452                                 FALSE, FALSE, TRUE);
2453               if (strcmp (l, fReturn[offset]))
2454                 {
2455                   emitcode ("mov", "%s,%s",
2456                             fReturn[offset],
2457                             l);
2458                 }
2459               offset++;
2460             }
2461           _endLazyDPSEvaluation ();
2462           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2463         }
2464       _G.sendSet = NULL;
2465     }
2466
2467   emitcode ("ret", "");
2468   emitcode ("", "%05d$:", (rlbl->key + 100));
2469
2470
2471   /* if we need assign a result value */
2472   if ((IS_ITEMP (IC_RESULT (ic)) &&
2473        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2474         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2475       IS_TRUE_SYMOP (IC_RESULT (ic)))
2476     {
2477
2478       _G.accInUse++;
2479       aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2480       _G.accInUse--;
2481
2482       assignResultValue (IC_RESULT (ic));
2483
2484       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2485     }
2486
2487   /* adjust the stack for parameters if
2488      required */
2489   if (ic->parmBytes)
2490     {
2491       int i;
2492       if (ic->parmBytes > 3)
2493         {
2494           emitcode ("mov", "a,%s", spname);
2495           emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2496           emitcode ("mov", "%s,a", spname);
2497         }
2498       else
2499         for (i = 0; i < ic->parmBytes; i++)
2500           emitcode ("dec", "%s", spname);
2501
2502     }
2503
2504   /* if register bank was saved then unsave them */
2505   if (restoreBank)
2506     unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2507   
2508   /* if we hade saved some registers then
2509      unsave them */
2510   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2511     unsaveRegisters (ic);
2512
2513 }
2514
2515 /*-----------------------------------------------------------------*/
2516 /* resultRemat - result  is rematerializable                       */
2517 /*-----------------------------------------------------------------*/
2518 static int
2519 resultRemat (iCode * ic)
2520 {
2521   if (SKIP_IC (ic) || ic->op == IFX)
2522     return 0;
2523
2524   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2525     {
2526       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2527       if (sym->remat && !POINTER_SET (ic))
2528         return 1;
2529     }
2530
2531   return 0;
2532 }
2533
2534 #if defined(__BORLANDC__) || defined(_MSC_VER)
2535 #define STRCASECMP stricmp
2536 #else
2537 #define STRCASECMP strcasecmp
2538 #endif
2539
2540 /*-----------------------------------------------------------------*/
2541 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2542 /*-----------------------------------------------------------------*/
2543 static bool
2544 inExcludeList (char *s)
2545 {
2546   int i = 0;
2547
2548   if (options.excludeRegs[i] &&
2549       STRCASECMP (options.excludeRegs[i], "none") == 0)
2550     return FALSE;
2551
2552   for (i = 0; options.excludeRegs[i]; i++)
2553     {
2554       if (options.excludeRegs[i] &&
2555           STRCASECMP (s, options.excludeRegs[i]) == 0)
2556         return TRUE;
2557     }
2558   return FALSE;
2559 }
2560
2561 /*-----------------------------------------------------------------*/
2562 /* genFunction - generated code for function entry                 */
2563 /*-----------------------------------------------------------------*/
2564 static void
2565 genFunction (iCode * ic)
2566 {
2567   symbol *sym;
2568   sym_link *ftype;
2569   bool   switchedPSW = FALSE;
2570
2571   D (emitcode (";", "genFunction "););
2572
2573   _G.nRegsSaved = 0;
2574   /* create the function header */
2575   emitcode (";", "-----------------------------------------");
2576   emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2577   emitcode (";", "-----------------------------------------");
2578
2579   emitcode ("", "%s:", sym->rname);
2580   ftype = operandType (IC_LEFT (ic));
2581
2582   if (IFFUNC_ISNAKED(ftype))
2583   {
2584       emitcode(";", "naked function: no prologue.");
2585       return;
2586   }
2587
2588   /* if critical function then turn interrupts off */
2589   if (IFFUNC_ISCRITICAL (ftype))
2590     emitcode ("clr", "ea");
2591
2592   /* here we need to generate the equates for the
2593      register bank if required */
2594   if (FUNC_REGBANK (ftype) != rbank)
2595     {
2596       int i;
2597
2598       rbank = FUNC_REGBANK (ftype);
2599       for (i = 0; i < ds390_nRegs; i++)
2600         {
2601           if (regs390[i].print) {
2602               if (strcmp (regs390[i].base, "0") == 0)
2603                   emitcode ("", "%s = 0x%02x",
2604                             regs390[i].dname,
2605                             8 * rbank + regs390[i].offset);
2606               else
2607                   emitcode ("", "%s = %s + 0x%02x",
2608                             regs390[i].dname,
2609                             regs390[i].base,
2610                             8 * rbank + regs390[i].offset);
2611           }
2612         }
2613     }
2614
2615   /* if this is an interrupt service routine then
2616      save acc, b, dpl, dph  */
2617   if (IFFUNC_ISISR (sym->type))
2618     {
2619
2620       if (!inExcludeList ("acc"))
2621         emitcode ("push", "acc");
2622       if (!inExcludeList ("b"))
2623         emitcode ("push", "b");
2624       if (!inExcludeList ("dpl"))
2625         emitcode ("push", "dpl");
2626       if (!inExcludeList ("dph"))
2627         emitcode ("push", "dph");
2628       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2629         {
2630           emitcode ("push", "dpx");
2631           /* Make sure we're using standard DPTR */
2632           emitcode ("push", "dps");
2633           emitcode ("mov", "dps, #0x00");
2634           if (options.stack10bit)
2635             {
2636               /* This ISR could conceivably use DPTR2. Better save it. */
2637               emitcode ("push", "dpl1");
2638               emitcode ("push", "dph1");
2639               emitcode ("push", "dpx1");
2640               emitcode ("push",  DP2_RESULT_REG);
2641             }
2642         }
2643       /* if this isr has no bank i.e. is going to
2644          run with bank 0 , then we need to save more
2645          registers :-) */
2646       if (!FUNC_REGBANK (sym->type))
2647         {
2648
2649           /* if this function does not call any other
2650              function then we can be economical and
2651              save only those registers that are used */
2652           if (!IFFUNC_HASFCALL(sym->type))
2653             {
2654               int i;
2655
2656               /* if any registers used */
2657               if (sym->regsUsed)
2658                 {
2659                   /* save the registers used */
2660                   for (i = 0; i < sym->regsUsed->size; i++)
2661                     {
2662                       if (bitVectBitValue (sym->regsUsed, i) ||
2663                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2664                         emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2665                     }
2666                 }
2667
2668             }
2669           else
2670             {
2671               /* this function has  a function call cannot
2672                  determines register usage so we will have to push the
2673                  entire bank */
2674               saveRBank (0, ic, FALSE);
2675             }
2676         }
2677         else
2678         {
2679             /* This ISR uses a non-zero bank.
2680              *
2681              * We assume that the bank is available for our
2682              * exclusive use.
2683              *
2684              * However, if this ISR calls a function which uses some
2685              * other bank, we must save that bank entirely.
2686              */
2687             unsigned long banksToSave = 0;
2688             
2689             if (IFFUNC_HASFCALL(sym->type))
2690             {
2691
2692 #define MAX_REGISTER_BANKS 4
2693
2694                 iCode *i;
2695                 int ix;
2696
2697                 for (i = ic; i; i = i->next)
2698                 {
2699                     if (i->op == ENDFUNCTION)
2700                     {
2701                         /* we got to the end OK. */
2702                         break;
2703                     }
2704                     
2705                     if (i->op == CALL)
2706                     {
2707                         sym_link *dtype;
2708                         
2709                         dtype = operandType (IC_LEFT(i));
2710                         if (dtype 
2711                          && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2712                         {
2713                              /* Mark this bank for saving. */
2714                              if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2715                              {
2716                                  werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2717                              }
2718                              else
2719                              {
2720                                  banksToSave |= (1 << FUNC_REGBANK(dtype));
2721                              }
2722                              
2723                              /* And note that we don't need to do it in 
2724                               * genCall.
2725                               */
2726                              i->bankSaved = 1;
2727                         }
2728                     }
2729                     if (i->op == PCALL)
2730                     {
2731                         /* This is a mess; we have no idea what
2732                          * register bank the called function might
2733                          * use.
2734                          *
2735                          * The only thing I can think of to do is
2736                          * throw a warning and hope.
2737                          */
2738                         werror(W_FUNCPTR_IN_USING_ISR);   
2739                     }
2740                 }
2741
2742                 if (banksToSave && options.useXstack)
2743                 {
2744                     /* Since we aren't passing it an ic, 
2745                      * saveRBank will assume r0 is available to abuse.
2746                      *
2747                      * So switch to our (trashable) bank now, so
2748                      * the caller's R0 isn't trashed.
2749                      */
2750                     emitcode ("push", "psw");
2751                     emitcode ("mov", "psw,#0x%02x", 
2752                               (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2753                     switchedPSW = TRUE;
2754                 }
2755                 
2756                 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2757                 {
2758                      if (banksToSave & (1 << ix))
2759                      {
2760                          saveRBank(ix, NULL, FALSE);
2761                      }
2762                 }
2763             }
2764             // jwk: this needs a closer look
2765             SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2766         }
2767     }
2768   else
2769     {
2770       /* if callee-save to be used for this function
2771          then save the registers being used in this function */
2772       if (IFFUNC_CALLEESAVES(sym->type))
2773         {
2774           int i;
2775
2776           /* if any registers used */
2777           if (sym->regsUsed)
2778             {
2779               /* save the registers used */
2780               for (i = 0; i < sym->regsUsed->size; i++)
2781                 {
2782                   if (bitVectBitValue (sym->regsUsed, i) ||
2783                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2784                     {
2785                       emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2786                       _G.nRegsSaved++;
2787                     }
2788                 }
2789             }
2790         }
2791     }
2792
2793   /* set the register bank to the desired value */
2794   if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
2795    && !switchedPSW)
2796     {
2797       emitcode ("push", "psw");
2798       emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2799     }
2800
2801   if (IFFUNC_ISREENT (sym->type) || options.stackAuto) {
2802       if (options.stack10bit) {
2803           emitcode ("push","_bpx");
2804           emitcode ("push","_bpx+1");
2805           emitcode ("mov","_bpx,%s",spname);
2806           emitcode ("mov","_bpx+1,_ESP");
2807           emitcode ("anl","_bpx+1,#3");
2808       } else {
2809           if (options.useXstack) {
2810               emitcode ("mov", "r0,%s", spname);
2811               emitcode ("mov", "a,_bp");
2812               emitcode ("movx", "@r0,a");
2813               emitcode ("inc", "%s", spname);
2814           } else {
2815               /* set up the stack */
2816               emitcode ("push", "_bp"); /* save the callers stack  */
2817           }
2818           emitcode ("mov", "_bp,%s", spname);
2819       }
2820   }
2821
2822   /* adjust the stack for the function */
2823   if (sym->stack) {
2824       int i = sym->stack;
2825       if (options.stack10bit) {
2826           if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);
2827           assert (sym->recvSize <= 4);
2828           emitcode ("mov","a,sp");
2829           emitcode ("add","a,#0x%02x", ((short) sym->stack & 0xff));
2830           emitcode ("mov","sp,a");
2831           emitcode ("mov","a,_ESP");
2832           emitcode ("addc","a,0x%02x", (((short) sym->stack) >> 8) & 0xff);
2833           emitcode ("mov","_ESP,a");
2834       } else {
2835           if (i > 256)
2836               werror (W_STACK_OVERFLOW, sym->name);
2837           
2838           if (i > 3 && sym->recvSize < 4) {
2839               
2840               emitcode ("mov", "a,sp");
2841               emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2842               emitcode ("mov", "sp,a");
2843               
2844           } else
2845               while (i--)
2846                   emitcode ("inc", "sp");
2847       }
2848   }
2849
2850   if (sym->xstack)
2851     {
2852
2853       emitcode ("mov", "a,_spx");
2854       emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2855       emitcode ("mov", "_spx,a");
2856     }
2857
2858 }
2859
2860 /*-----------------------------------------------------------------*/
2861 /* genEndFunction - generates epilogue for functions               */
2862 /*-----------------------------------------------------------------*/
2863 static void
2864 genEndFunction (iCode * ic)
2865 {
2866   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2867
2868   D (emitcode (";", "genEndFunction "););
2869
2870   if (IFFUNC_ISNAKED(sym->type))
2871   {
2872       emitcode(";", "naked function: no epilogue.");
2873       return;
2874   }
2875
2876   if (IFFUNC_ISREENT (sym->type) || options.stackAuto) {
2877       if (options.stack10bit) {
2878           emitcode ("mov", "sp,_bpx", spname);
2879           emitcode ("mov", "_ESP,_bpx+1", spname);
2880       } else {
2881           emitcode ("mov", "%s,_bp", spname);
2882       }
2883   }
2884
2885   /* if use external stack but some variables were
2886      added to the local stack then decrement the
2887      local stack */
2888   if (options.useXstack && sym->stack) {
2889       emitcode ("mov", "a,sp");
2890       emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2891       emitcode ("mov", "sp,a");
2892   }
2893
2894
2895   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto)) {
2896       if (options.useXstack) {
2897           emitcode ("mov", "r0,%s", spname);
2898           emitcode ("movx", "a,@r0");
2899           emitcode ("mov", "_bp,a");
2900           emitcode ("dec", "%s", spname);
2901       } else {
2902           if (options.stack10bit) {
2903               emitcode ("pop", "_bpx+1");
2904               emitcode ("pop", "_bpx");
2905           } else {
2906               emitcode ("pop", "_bp");
2907           }
2908       }
2909   }
2910
2911   /* restore the register bank  */
2912   if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
2913   {
2914     if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
2915      || !options.useXstack)
2916     {
2917         /* Special case of ISR using non-zero bank with useXstack
2918          * is handled below.
2919          */
2920         emitcode ("pop", "psw");
2921     }
2922   }
2923
2924   if (IFFUNC_ISISR (sym->type))
2925     {
2926
2927       /* now we need to restore the registers */
2928       /* if this isr has no bank i.e. is going to
2929          run with bank 0 , then we need to save more
2930          registers :-) */
2931       if (!FUNC_REGBANK (sym->type))
2932         {
2933           /* if this function does not call any other
2934              function then we can be economical and
2935              save only those registers that are used */
2936           if (!IFFUNC_HASFCALL(sym->type))
2937             {
2938               int i;
2939
2940               /* if any registers used */
2941               if (sym->regsUsed)
2942                 {
2943                   /* save the registers used */
2944                   for (i = sym->regsUsed->size; i >= 0; i--)
2945                     {
2946                       if (bitVectBitValue (sym->regsUsed, i) ||
2947                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2948                         emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2949                     }
2950                 }
2951
2952             }
2953           else
2954             {
2955               /* this function has  a function call cannot
2956                  determines register usage so we will have to pop the
2957                  entire bank */
2958               unsaveRBank (0, ic, FALSE);
2959             }
2960         }
2961         else
2962         {
2963             /* This ISR uses a non-zero bank.
2964              *
2965              * Restore any register banks saved by genFunction
2966              * in reverse order.
2967              */
2968           // jwk: this needs a closer look
2969             unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2970             int ix;
2971           
2972             for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2973             {
2974                 if (savedBanks & (1 << ix))
2975                 {
2976                     unsaveRBank(ix, NULL, FALSE);
2977                 }
2978             }
2979             
2980             if (options.useXstack)
2981             {
2982                 /* Restore bank AFTER calling unsaveRBank,
2983                  * since it can trash r0.
2984                  */
2985                 emitcode ("pop", "psw");
2986             }
2987         }
2988
2989       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2990         {
2991           if (options.stack10bit)
2992             {
2993               emitcode ("pop", DP2_RESULT_REG);
2994               emitcode ("pop", "dpx1");
2995               emitcode ("pop", "dph1");
2996               emitcode ("pop", "dpl1");
2997             }
2998           emitcode ("pop", "dps");
2999           emitcode ("pop", "dpx");
3000         }
3001       if (!inExcludeList ("dph"))
3002         emitcode ("pop", "dph");
3003       if (!inExcludeList ("dpl"))
3004         emitcode ("pop", "dpl");
3005       if (!inExcludeList ("b"))
3006         emitcode ("pop", "b");
3007       if (!inExcludeList ("acc"))
3008         emitcode ("pop", "acc");
3009
3010       if (IFFUNC_ISCRITICAL (sym->type))
3011         emitcode ("setb", "ea");
3012
3013       /* if debug then send end of function */
3014       if (options.debug && currFunc) {
3015           _G.debugLine = 1;
3016           emitcode ("", "C$%s$%d$%d$%d ==.",
3017                     FileBaseName (ic->filename), currFunc->lastLine,
3018                     ic->level, ic->block);
3019           if (IS_STATIC (currFunc->etype))
3020             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3021           else
3022             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3023           _G.debugLine = 0;
3024         }
3025
3026       emitcode ("reti", "");
3027     }
3028   else
3029     {
3030       if (IFFUNC_ISCRITICAL (sym->type))
3031         emitcode ("setb", "ea");
3032
3033       if (IFFUNC_CALLEESAVES(sym->type))
3034         {
3035           int i;
3036
3037           /* if any registers used */
3038           if (sym->regsUsed)
3039             {
3040               /* save the registers used */
3041               for (i = sym->regsUsed->size; i >= 0; i--)
3042                 {
3043                   if (bitVectBitValue (sym->regsUsed, i) ||
3044                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3045                     emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3046                 }
3047             }
3048
3049         }
3050
3051       /* if debug then send end of function */
3052       if (options.debug && currFunc)
3053         {
3054           _G.debugLine = 1;
3055           emitcode ("", "C$%s$%d$%d$%d ==.",
3056                     FileBaseName (ic->filename), currFunc->lastLine,
3057                     ic->level, ic->block);
3058           if (IS_STATIC (currFunc->etype))
3059             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3060           else
3061             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3062           _G.debugLine = 0;
3063         }
3064
3065       emitcode ("ret", "");
3066     }
3067
3068 }
3069
3070 /*-----------------------------------------------------------------*/
3071 /* genRet - generate code for return statement                     */
3072 /*-----------------------------------------------------------------*/
3073 static void
3074 genRet (iCode * ic)
3075 {
3076   int size, offset = 0, pushed = 0;
3077
3078   D (emitcode (";", "genRet ");
3079     );
3080
3081   /* if we have no return value then
3082      just generate the "ret" */
3083   if (!IC_LEFT (ic))
3084     goto jumpret;
3085
3086   /* we have something to return then
3087      move the return value into place */
3088   aopOp (IC_LEFT (ic), ic, FALSE, TRUE);
3089   size = AOP_SIZE (IC_LEFT (ic));
3090
3091   _startLazyDPSEvaluation ();
3092   while (size--)
3093     {
3094       char *l;
3095       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3096         {
3097           l = aopGet (AOP (IC_LEFT (ic)), offset++,
3098                       FALSE, TRUE, FALSE);
3099           emitcode ("push", "%s", l);
3100           pushed++;
3101         }
3102       else
3103         {
3104           /* Since A is the last element of fReturn,
3105            * is is OK to clobber it in the aopGet.
3106            */
3107           l = aopGet (AOP (IC_LEFT (ic)), offset,
3108                       FALSE, FALSE, TRUE);
3109           if (strcmp (fReturn[offset], l))
3110             emitcode ("mov", "%s,%s", fReturn[offset++], l);
3111         }
3112     }
3113   _endLazyDPSEvaluation ();
3114
3115   if (pushed)
3116     {
3117       while (pushed)
3118         {
3119           pushed--;
3120           if (strcmp (fReturn[pushed], "a"))
3121             emitcode ("pop", fReturn[pushed]);
3122           else
3123             emitcode ("pop", "acc");
3124         }
3125     }
3126   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3127
3128 jumpret:
3129   /* generate a jump to the return label
3130      if the next is not the return statement */
3131   if (!(ic->next && ic->next->op == LABEL &&
3132         IC_LABEL (ic->next) == returnLabel))
3133
3134     emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3135
3136 }
3137
3138 /*-----------------------------------------------------------------*/
3139 /* genLabel - generates a label                                    */
3140 /*-----------------------------------------------------------------*/
3141 static void
3142 genLabel (iCode * ic)
3143 {
3144   /* special case never generate */
3145   if (IC_LABEL (ic) == entryLabel)
3146     return;
3147
3148   D (emitcode (";", "genLabel ");
3149     );
3150
3151   emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3152 }
3153
3154 /*-----------------------------------------------------------------*/
3155 /* genGoto - generates a ljmp                                      */
3156 /*-----------------------------------------------------------------*/
3157 static void
3158 genGoto (iCode * ic)
3159 {
3160   D (emitcode (";", "genGoto ");
3161     );
3162   emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
3163 }
3164
3165 /*-----------------------------------------------------------------*/
3166 /* findLabelBackwards: walks back through the iCode chain looking  */
3167 /* for the given label. Returns number of iCode instructions     */
3168 /* between that label and given ic.          */
3169 /* Returns zero if label not found.          */
3170 /*-----------------------------------------------------------------*/
3171 static int
3172 findLabelBackwards (iCode * ic, int key)
3173 {
3174   int count = 0;
3175
3176   while (ic->prev)
3177     {
3178       ic = ic->prev;
3179       count++;
3180
3181       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3182         {
3183           /* printf("findLabelBackwards = %d\n", count); */
3184           return count;
3185         }
3186     }
3187
3188   return 0;
3189 }
3190
3191 /*-----------------------------------------------------------------*/
3192 /* genPlusIncr :- does addition with increment if possible         */
3193 /*-----------------------------------------------------------------*/
3194 static bool
3195 genPlusIncr (iCode * ic)
3196 {
3197   unsigned int icount;
3198   unsigned int size = getDataSize (IC_RESULT (ic));
3199
3200   /* will try to generate an increment */
3201   /* if the right side is not a literal
3202      we cannot */
3203   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3204     return FALSE;
3205
3206   /* if the literal value of the right hand side
3207      is greater than 4 then it is not worth it */
3208   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3209     return FALSE;
3210
3211   /* if increment 16 bits in register */
3212   if (
3213        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3214        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3215        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3216        (size > 1) &&
3217        (icount == 1))
3218     {
3219       symbol *tlbl;
3220       int emitTlbl;
3221       int labelRange;
3222
3223       /* If the next instruction is a goto and the goto target
3224        * is <= 5 instructions previous to this, we can generate
3225        * jumps straight to that target.
3226        */
3227       if (ic->next && ic->next->op == GOTO
3228           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3229           && labelRange <= 5)
3230         {
3231           emitcode (";", "tail increment optimized (range %d)", labelRange);
3232           tlbl = IC_LABEL (ic->next);
3233           emitTlbl = 0;
3234         }
3235       else
3236         {
3237           tlbl = newiTempLabel (NULL);
3238           emitTlbl = 1;
3239         }
3240       emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3241       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3242           IS_AOP_PREG (IC_RESULT (ic)))
3243         emitcode ("cjne", "%s,#0x00,%05d$"
3244                   ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3245                   ,tlbl->key + 100);
3246       else
3247         {
3248           emitcode ("clr", "a");
3249           emitcode ("cjne", "a,%s,%05d$"
3250                     ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3251                     ,tlbl->key + 100);
3252         }
3253
3254       emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3255       if (size > 2)
3256         {
3257           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3258               IS_AOP_PREG (IC_RESULT (ic)))
3259             emitcode ("cjne", "%s,#0x00,%05d$"
3260                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3261                       ,tlbl->key + 100);
3262           else
3263             emitcode ("cjne", "a,%s,%05d$"
3264                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3265                       ,tlbl->key + 100);
3266
3267           emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3268         }
3269       if (size > 3)
3270         {
3271           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3272               IS_AOP_PREG (IC_RESULT (ic)))
3273             emitcode ("cjne", "%s,#0x00,%05d$"
3274                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3275                       ,tlbl->key + 100);
3276           else
3277             {
3278               emitcode ("cjne", "a,%s,%05d$"
3279                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3280                         ,tlbl->key + 100);
3281             }
3282           emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3283         }
3284
3285       if (emitTlbl)
3286         {
3287           emitcode ("", "%05d$:", tlbl->key + 100);
3288         }
3289       return TRUE;
3290     }
3291
3292   /* if the sizes are greater than 1 then we cannot */
3293   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3294       AOP_SIZE (IC_LEFT (ic)) > 1)
3295     return FALSE;
3296
3297   /* we can if the aops of the left & result match or
3298      if they are in registers and the registers are the
3299      same */
3300   if (
3301        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3302        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3303        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3304     {
3305
3306       if (icount > 3)
3307         {
3308           MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3309           emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3310           aopPut (AOP (IC_RESULT (ic)), "a", 0);
3311         }
3312       else
3313         {
3314
3315           _startLazyDPSEvaluation ();
3316           while (icount--)
3317             {
3318               emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3319             }
3320           _endLazyDPSEvaluation ();
3321         }
3322
3323       return TRUE;
3324     }
3325
3326   return FALSE;
3327 }
3328
3329 /*-----------------------------------------------------------------*/
3330 /* outBitAcc - output a bit in acc                                 */
3331 /*-----------------------------------------------------------------*/
3332 static void
3333 outBitAcc (operand * result)
3334 {
3335   symbol *tlbl = newiTempLabel (NULL);
3336   /* if the result is a bit */
3337   if (AOP_TYPE (result) == AOP_CRY)
3338     {
3339       aopPut (AOP (result), "a", 0);
3340     }
3341   else
3342     {
3343       emitcode ("jz", "%05d$", tlbl->key + 100);
3344       emitcode ("mov", "a,%s", one);
3345       emitcode ("", "%05d$:", tlbl->key + 100);
3346       outAcc (result);
3347     }
3348 }
3349
3350 /*-----------------------------------------------------------------*/
3351 /* genPlusBits - generates code for addition of two bits           */
3352 /*-----------------------------------------------------------------*/
3353 static void
3354 genPlusBits (iCode * ic)
3355 {
3356   D (emitcode (";", "genPlusBits ");
3357     );
3358   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3359     {
3360       symbol *lbl = newiTempLabel (NULL);
3361       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3362       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3363       emitcode ("cpl", "c");
3364       emitcode ("", "%05d$:", (lbl->key + 100));
3365       outBitC (IC_RESULT (ic));
3366     }
3367   else
3368     {
3369       emitcode ("clr", "a");
3370       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3371       emitcode ("rlc", "a");
3372       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3373       emitcode ("addc", "a,#0x00");
3374       outAcc (IC_RESULT (ic));
3375     }
3376 }
3377
3378 static void
3379 adjustArithmeticResult (iCode * ic)
3380 {
3381   if (opIsGptr (IC_RESULT (ic)) &&
3382       opIsGptr (IC_LEFT (ic)) &&
3383       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3384     {
3385       aopPut (AOP (IC_RESULT (ic)),
3386               aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3387               GPTRSIZE - 1);
3388     }
3389
3390   if (opIsGptr (IC_RESULT (ic)) &&
3391       opIsGptr (IC_RIGHT (ic)) &&
3392       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3393     {
3394       aopPut (AOP (IC_RESULT (ic)),
3395             aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3396               GPTRSIZE - 1);
3397     }
3398
3399   if (opIsGptr (IC_RESULT (ic)) &&
3400       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3401       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3402       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3403       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3404     {
3405       char buffer[5];
3406       sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3407       aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3408     }
3409 }
3410
3411 #if 0 // AOP_OP_3 is deprecated; nobody likes Ack errors.
3412       // Please don't bring it back without a really good reason.
3413 // Macro to aopOp all three operands of an ic. Will fatal if this cannot be done
3414 // (because all three operands are in far space).
3415 #define AOP_OP_3(ic) \
3416     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3417     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3418     aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3419               (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3420     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3421         AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3422     { \
3423         /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3424         fprintf(stderr,                                  \
3425                "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno);   \
3426     }
3427 #endif
3428
3429 // Macro to aopOp all three operands of an ic. If this cannot be done, 
3430 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3431 // will be set TRUE. The caller must then handle the case specially, noting
3432 // that the IC_RESULT operand is not aopOp'd.
3433 #define AOP_OP_3_NOFATAL(ic, rc) \
3434     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3435     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR) || \
3436                                   (OP_SYMBOL(IC_RESULT(ic))->ruonly)); \
3437     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3438         (isOperandInFarSpace(IC_RESULT(ic)) || OP_SYMBOL(IC_RESULT(ic))->ruonly )) \
3439     { \
3440        /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3441        rc = TRUE; \
3442     }  \
3443     else \
3444     { \
3445        aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3446                                      (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3447        rc = FALSE; \
3448        if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3449            AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3450        { \
3451             /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3452             fprintf(stderr,                                  \
3453                     "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno);   \
3454        } \
3455     }
3456
3457 // aopOp the left & right operands of an ic.
3458 #define AOP_OP_2(ic) \
3459     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3460     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3461
3462 // convienience macro.
3463 #define AOP_SET_LOCALS(ic) \
3464     left = IC_LEFT(ic); \
3465     right = IC_RIGHT(ic); \
3466     result = IC_RESULT(ic);
3467
3468
3469 // Given an integer value of pushedSize bytes on the stack,
3470 // adjust it to be resultSize bytes, either by discarding
3471 // the most significant bytes or by zero-padding.
3472 //
3473 // On exit from this macro, pushedSize will have been adjusted to
3474 // equal resultSize, and ACC may be trashed.
3475 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize)            \
3476       /* If the pushed data is bigger than the result,          \
3477        * simply discard unused bytes. Icky, but works.          \
3478        */                                                       \
3479       while (pushedSize > resultSize)                           \
3480       {                                                         \
3481           D (emitcode (";", "discarding unused result byte."););\
3482           emitcode ("pop", "acc");                              \
3483           pushedSize--;                                         \
3484       }                                                         \
3485       if (pushedSize < resultSize)                              \
3486       {                                                         \
3487           emitcode ("clr", "a");                                \
3488           /* Conversly, we haven't pushed enough here.          \
3489            * just zero-pad, and all is well.                    \
3490            */                                                   \
3491           while (pushedSize < resultSize)                       \
3492           {                                                     \
3493               emitcode("push", "acc");                          \
3494               pushedSize++;                                     \
3495           }                                                     \
3496       }                                                         \
3497       assert(pushedSize == resultSize);
3498
3499 /*-----------------------------------------------------------------*/
3500 /* genPlus - generates code for addition                           */
3501 /*-----------------------------------------------------------------*/
3502 static void
3503 genPlus (iCode * ic)
3504 {
3505   int size, offset = 0;
3506   bool pushResult = FALSE;
3507   int rSize;
3508
3509   D (emitcode (";", "genPlus "););
3510
3511   /* special cases :- */
3512   if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)) &&
3513       isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
3514       aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
3515       size = floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
3516       while (size--) emitcode ("inc","dptr");
3517       freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
3518       return ;
3519   }
3520   if ( IS_SYMOP(IC_LEFT(ic)) && 
3521        OP_SYMBOL(IC_LEFT(ic))->remat &&
3522        isOperandInFarSpace(IC_RIGHT(ic))) {
3523       operand *op = IC_RIGHT(ic);
3524       IC_RIGHT(ic) = IC_LEFT(ic);
3525       IC_LEFT(ic) = op;
3526   }
3527                 
3528   AOP_OP_3_NOFATAL (ic, pushResult);
3529   if (pushResult)
3530     {
3531       D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3532     }
3533
3534   if (!pushResult)
3535     {
3536       /* if literal, literal on the right or
3537          if left requires ACC or right is already
3538          in ACC */
3539       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3540        || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3541           || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3542         {
3543           operand *t = IC_RIGHT (ic);
3544           IC_RIGHT (ic) = IC_LEFT (ic);
3545           IC_LEFT (ic) = t;
3546           emitcode (";", "Swapped plus args.");
3547         }
3548
3549       /* if both left & right are in bit
3550          space */
3551       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3552           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3553         {
3554           genPlusBits (ic);
3555           goto release;
3556         }
3557
3558       /* if left in bit space & right literal */
3559       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3560           AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3561         {
3562           emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3563           /* if result in bit space */
3564           if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3565             {
3566               if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3567                 emitcode ("cpl", "c");
3568               outBitC (IC_RESULT (ic));
3569             }
3570           else
3571             {
3572               size = getDataSize (IC_RESULT (ic));
3573               _startLazyDPSEvaluation ();
3574               while (size--)
3575                 {
3576                   MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3577                   emitcode ("addc", "a,#00");
3578                   aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3579                 }
3580               _endLazyDPSEvaluation ();
3581             }
3582           goto release;
3583         }
3584
3585       /* if I can do an increment instead
3586          of add then GOOD for ME */
3587       if (genPlusIncr (ic) == TRUE)
3588         {
3589           emitcode (";", "did genPlusIncr");
3590           goto release;
3591         }
3592
3593     }
3594   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3595
3596   _startLazyDPSEvaluation ();
3597   while (size--)
3598     {
3599       if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
3600         {
3601           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3602           if (offset == 0)
3603             emitcode ("add", "a,%s",
3604                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3605           else
3606             emitcode ("addc", "a,%s",
3607                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3608         }
3609       else
3610         {
3611           if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
3612           {
3613               /* right is going to use ACC or we would have taken the
3614                * above branch.
3615                */
3616               assert(AOP_NEEDSACC(IC_RIGHT(ic)));
3617        TR_AP("#3");
3618               D(emitcode(";", "+ AOP_ACC special case."););
3619               emitcode("xch", "a, %s", DP2_RESULT_REG);
3620           }
3621           MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3622           if (offset == 0)
3623           {
3624             if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
3625             {
3626          TR_AP("#4");
3627                 emitcode("add", "a, %s", DP2_RESULT_REG); 
3628             }
3629             else
3630             {
3631                 emitcode ("add", "a,%s",
3632                         aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE, FALSE));
3633             }
3634           }
3635           else
3636           {
3637             emitcode ("addc", "a,%s",
3638                   aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3639           }
3640         }
3641       if (!pushResult)
3642         {
3643           aopPut (AOP (IC_RESULT (ic)), "a", offset);
3644         }
3645       else
3646         {
3647           emitcode ("push", "acc");
3648         }
3649       offset++;
3650     }
3651   _endLazyDPSEvaluation ();
3652
3653   if (pushResult)
3654     {
3655       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3656
3657       size = getDataSize (IC_LEFT (ic));
3658       rSize = getDataSize (IC_RESULT (ic));
3659
3660       ADJUST_PUSHED_RESULT(size, rSize);
3661
3662       _startLazyDPSEvaluation ();
3663       while (size--)
3664         {
3665           emitcode ("pop", "acc");
3666           aopPut (AOP (IC_RESULT (ic)), "a", size);
3667         }
3668       _endLazyDPSEvaluation ();
3669     }
3670
3671   adjustArithmeticResult (ic);
3672
3673 release:
3674   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3675   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3676   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3677 }
3678
3679 /*-----------------------------------------------------------------*/
3680 /* genMinusDec :- does subtraction with deccrement if possible     */
3681 /*-----------------------------------------------------------------*/
3682 static bool
3683 genMinusDec (iCode * ic)
3684 {
3685   unsigned int icount;
3686   unsigned int size = getDataSize (IC_RESULT (ic));
3687
3688   /* will try to generate an increment */
3689   /* if the right side is not a literal
3690      we cannot */
3691   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3692     return FALSE;
3693
3694   /* if the literal value of the right hand side
3695      is greater than 4 then it is not worth it */
3696   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3697     return FALSE;
3698
3699   /* if decrement 16 bits in register */
3700   if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3701       AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3702       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3703       (size > 1) &&
3704       (icount == 1))
3705     {
3706       symbol *tlbl;
3707       int emitTlbl;
3708       int labelRange;
3709
3710       /* If the next instruction is a goto and the goto target
3711          * is <= 5 instructions previous to this, we can generate
3712          * jumps straight to that target.
3713        */
3714       if (ic->next && ic->next->op == GOTO
3715           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3716           && labelRange <= 5)
3717         {
3718           emitcode (";", "tail decrement optimized (range %d)", labelRange);
3719           tlbl = IC_LABEL (ic->next);
3720           emitTlbl = 0;
3721         }
3722       else
3723         {
3724           tlbl = newiTempLabel (NULL);
3725           emitTlbl = 1;
3726         }
3727
3728       emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3729       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3730           AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3731           IS_AOP_PREG (IC_RESULT (ic)))
3732         emitcode ("cjne", "%s,#0xff,%05d$"
3733                   ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3734                   ,tlbl->key + 100);
3735       else
3736         {
3737           emitcode ("mov", "a,#0xff");
3738           emitcode ("cjne", "a,%s,%05d$"
3739                     ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3740                     ,tlbl->key + 100);
3741         }
3742       emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3743       if (size > 2)
3744         {
3745           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3746               AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3747               IS_AOP_PREG (IC_RESULT (ic)))
3748             emitcode ("cjne", "%s,#0xff,%05d$"
3749                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3750                       ,tlbl->key + 100);
3751           else
3752             {
3753               emitcode ("cjne", "a,%s,%05d$"
3754                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3755                         ,tlbl->key + 100);
3756             }
3757           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3758         }
3759       if (size > 3)
3760         {
3761           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3762               AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3763               IS_AOP_PREG (IC_RESULT (ic)))
3764             emitcode ("cjne", "%s,#0xff,%05d$"
3765                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3766                       ,tlbl->key + 100);
3767           else
3768             {
3769               emitcode ("cjne", "a,%s,%05d$"
3770                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3771                         ,tlbl->key + 100);
3772             }
3773           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3774         }
3775       if (emitTlbl)
3776         {
3777           emitcode ("", "%05d$:", tlbl->key + 100);
3778         }
3779       return TRUE;
3780     }
3781
3782   /* if the sizes are greater than 1 then we cannot */
3783   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3784       AOP_SIZE (IC_LEFT (ic)) > 1)
3785     return FALSE;
3786
3787   /* we can if the aops of the left & result match or
3788      if they are in registers and the registers are the
3789      same */
3790   if (
3791        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3792        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3793        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3794     {
3795
3796       _startLazyDPSEvaluation ();
3797       while (icount--)
3798         {
3799           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
3800         }
3801       _endLazyDPSEvaluation ();
3802
3803       return TRUE;
3804     }
3805
3806   return FALSE;
3807 }
3808
3809 /*-----------------------------------------------------------------*/
3810 /* addSign - complete with sign                                    */
3811 /*-----------------------------------------------------------------*/
3812 static void
3813 addSign (operand * result, int offset, int sign)
3814 {
3815   int size = (getDataSize (result) - offset);
3816   if (size > 0)
3817     {
3818       _startLazyDPSEvaluation();
3819       if (sign)
3820         {
3821           emitcode ("rlc", "a");
3822           emitcode ("subb", "a,acc");
3823           while (size--)
3824           {
3825             aopPut (AOP (result), "a", offset++);
3826           }
3827         }
3828       else
3829       {
3830         while (size--)
3831         {
3832           aopPut (AOP (result), zero, offset++);
3833         }
3834       }
3835       _endLazyDPSEvaluation();
3836     }
3837 }
3838
3839 /*-----------------------------------------------------------------*/
3840 /* genMinusBits - generates code for subtraction  of two bits      */
3841 /*-----------------------------------------------------------------*/
3842 static void
3843 genMinusBits (iCode * ic)
3844 {
3845   symbol *lbl = newiTempLabel (NULL);
3846
3847   D (emitcode (";", "genMinusBits "););
3848
3849   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3850     {
3851       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3852       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3853       emitcode ("cpl", "c");
3854       emitcode ("", "%05d$:", (lbl->key + 100));
3855       outBitC (IC_RESULT (ic));
3856     }
3857   else
3858     {
3859       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3860       emitcode ("subb", "a,acc");
3861       emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3862       emitcode ("inc", "a");
3863       emitcode ("", "%05d$:", (lbl->key + 100));
3864       aopPut (AOP (IC_RESULT (ic)), "a", 0);
3865       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3866     }
3867 }
3868
3869 /*-----------------------------------------------------------------*/
3870 /* genMinus - generates code for subtraction                       */
3871 /*-----------------------------------------------------------------*/
3872 static void
3873 genMinus (iCode * ic)
3874 {
3875   int size, offset = 0;
3876   int rSize;
3877   unsigned long lit = 0L;
3878   bool pushResult = FALSE;
3879
3880   D (emitcode (";", "genMinus "););
3881
3882   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3883   aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
3884   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
3885       (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
3886     {
3887       pushResult = TRUE;
3888     }
3889   else
3890     {
3891       aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
3892
3893       /* special cases :- */
3894       /* if both left & right are in bit space */
3895       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3896           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3897         {
3898           genMinusBits (ic);
3899           goto release;
3900         }
3901
3902       /* if I can do an decrement instead
3903          of subtract then GOOD for ME */
3904       if (genMinusDec (ic) == TRUE)
3905         goto release;
3906
3907     }
3908
3909   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3910
3911   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3912     {
3913       CLRC;
3914     }
3915   else
3916     {
3917       lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3918       lit = -(long) lit;
3919     }
3920
3921
3922   /* if literal, add a,#-lit, else normal subb */
3923   _startLazyDPSEvaluation ();
3924   while (size--)
3925     {
3926       MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3927       if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3928         emitcode ("subb", "a,%s",
3929                   aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3930       else
3931         {
3932           /* first add without previous c */
3933           if (!offset) {
3934             if (!size && lit==-1) {
3935               emitcode ("dec", "a");
3936             } else {
3937               emitcode ("add", "a,#0x%02x",
3938                         (unsigned int) (lit & 0x0FFL));
3939             }
3940           } else {
3941             emitcode ("addc", "a,#0x%02x",
3942                       (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3943           }
3944         }
3945
3946       if (pushResult)
3947         {
3948           emitcode ("push", "acc");
3949         }
3950       else
3951         {
3952           aopPut (AOP (IC_RESULT (ic)), "a", offset);
3953         }
3954       offset++;
3955     }
3956   _endLazyDPSEvaluation ();
3957
3958   if (pushResult)
3959     {
3960       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3961
3962       size = getDataSize (IC_LEFT (ic));
3963       rSize = getDataSize (IC_RESULT (ic));
3964
3965       ADJUST_PUSHED_RESULT(size, rSize);
3966
3967       _startLazyDPSEvaluation ();
3968       while (size--)
3969         {
3970           emitcode ("pop", "acc");
3971           aopPut (AOP (IC_RESULT (ic)), "a", size);
3972         }
3973       _endLazyDPSEvaluation ();
3974     }
3975
3976   adjustArithmeticResult (ic);
3977
3978 release:
3979   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3980   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3981   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3982 }
3983
3984
3985 /*-----------------------------------------------------------------*/
3986 /* genMultbits :- multiplication of bits                           */
3987 /*-----------------------------------------------------------------*/
3988 static void
3989 genMultbits (operand * left,
3990              operand * right,
3991              operand * result,
3992              iCode   * ic)
3993 {
3994   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3995   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3996   aopOp(result, ic, TRUE, FALSE);
3997   outBitC (result);
3998 }
3999
4000
4001 /*-----------------------------------------------------------------*/
4002 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
4003 /*-----------------------------------------------------------------*/
4004 static void
4005 genMultOneByte (operand * left,
4006                 operand * right,
4007                 operand * result,
4008                 iCode   * ic)
4009 {
4010   sym_link *opetype = operandType (result);
4011   symbol *lbl;
4012
4013
4014   /* (if two literals: the value is computed before) */
4015   /* if one literal, literal on the right */
4016   if (AOP_TYPE (left) == AOP_LIT)
4017     {
4018       operand *t = right;
4019       right = left;
4020       left = t;
4021       emitcode (";", "swapped left and right");
4022     }
4023
4024   if (SPEC_USIGN(opetype)
4025       // ignore the sign of left and right, what else can we do?
4026       || (SPEC_USIGN(operandType(left)) && 
4027           SPEC_USIGN(operandType(right)))) {
4028     // just an unsigned 8*8=8/16 multiply
4029     //emitcode (";","unsigned");
4030     emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4031     MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4032     emitcode ("mul", "ab");
4033    
4034     _G.accInUse++;
4035     aopOp(result, ic, TRUE, FALSE);
4036       
4037       if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4038       {
4039           // this should never happen
4040           fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4041                    AOP_SIZE(result), __FILE__, lineno);
4042           exit (1);
4043       }      
4044       
4045     aopPut (AOP (result), "a", 0);
4046     _G.accInUse--;
4047     if (AOP_SIZE(result)==2) 
4048     {
4049       aopPut (AOP (result), "b", 1);
4050     }
4051     return;
4052   }
4053
4054   // we have to do a signed multiply
4055
4056   emitcode (";", "signed");
4057   emitcode ("clr", "F0"); // reset sign flag
4058   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4059
4060   lbl=newiTempLabel(NULL);
4061   emitcode ("jnb", "acc.7,%05d$",  lbl->key+100);
4062   // left side is negative, 8-bit two's complement, this fails for -128
4063   emitcode ("setb", "F0"); // set sign flag
4064   emitcode ("cpl", "a");
4065   emitcode ("inc", "a");
4066
4067   emitcode ("", "%05d$:", lbl->key+100);
4068
4069   /* if literal */
4070   if (AOP_TYPE(right)==AOP_LIT) {
4071     signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
4072     /* AND literal negative */
4073     if ((int) val < 0) {
4074       emitcode ("cpl", "F0"); // complement sign flag
4075       emitcode ("mov", "b,#0x%02x", -val);
4076     } else {
4077       emitcode ("mov", "b,#0x%02x", val);
4078     }
4079   } else {
4080     lbl=newiTempLabel(NULL);
4081     emitcode ("mov", "b,a");
4082     emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4083     emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
4084     // right side is negative, 8-bit two's complement
4085     emitcode ("cpl", "F0"); // complement sign flag
4086     emitcode ("cpl", "a");
4087     emitcode ("inc", "a");
4088     emitcode ("", "%05d$:", lbl->key+100);
4089   }
4090   emitcode ("mul", "ab");
4091     
4092   _G.accInUse++;
4093   aopOp(result, ic, TRUE, FALSE);
4094     
4095   if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4096   {
4097     // this should never happen
4098       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4099                AOP_SIZE(result), __FILE__, lineno);
4100       exit (1);
4101   }    
4102     
4103   lbl=newiTempLabel(NULL);
4104   emitcode ("jnb", "F0,%05d$", lbl->key+100);
4105   // only ONE op was negative, we have to do a 8/16-bit two's complement
4106   emitcode ("cpl", "a"); // lsb
4107   if (AOP_SIZE(result)==1) {
4108     emitcode ("inc", "a");
4109   } else {
4110     emitcode ("add", "a,#1");
4111     emitcode ("xch", "a,b");
4112     emitcode ("cpl", "a"); // msb
4113     emitcode ("addc", "a,#0");
4114     emitcode ("xch", "a,b");
4115   }
4116
4117   emitcode ("", "%05d$:", lbl->key+100);
4118   aopPut (AOP (result), "a", 0);
4119   _G.accInUse--;
4120   if (AOP_SIZE(result)==2) {
4121     aopPut (AOP (result), "b", 1);
4122   }
4123 }
4124
4125 /*-----------------------------------------------------------------*/
4126 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply    */
4127 /*-----------------------------------------------------------------*/
4128 static void genMultTwoByte (operand *left, operand *right, 
4129                             operand *result, iCode *ic)
4130 {
4131         sym_link *retype = getSpec(operandType(right));
4132         sym_link *letype = getSpec(operandType(left));
4133         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4134         symbol *lbl;
4135
4136         if (AOP_TYPE (left) == AOP_LIT) {
4137                 operand *t = right;
4138                 right = left;
4139                 left = t;
4140         }
4141         /* save EA bit in F1 */
4142         lbl = newiTempLabel(NULL);
4143         emitcode ("setb","F1");
4144         emitcode ("jbc","EA,%05d$",lbl->key+100);
4145         emitcode ("clr","F1");
4146         emitcode("","%05d$:",lbl->key+100);
4147
4148         /* load up MB with right */
4149         if (!umult) {
4150                 emitcode("clr","F0");
4151                 if (AOP_TYPE(right) == AOP_LIT) {
4152                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
4153                         if (val < 0) {
4154                                 emitcode("setb","F0");
4155                                 val = -val;
4156                         }
4157                         emitcode ("mov","mb,#0x%02x",val & 0xff);
4158                         emitcode ("mov","mb,#0x%02x",(val >> 8) & 0xff);                    
4159                 } else {
4160                         lbl = newiTempLabel(NULL);
4161                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4162                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4163                         emitcode ("jnb","acc.7,%05d$",lbl->key+100);            
4164                         emitcode ("xch", "a,b");
4165                         emitcode ("cpl","a");
4166                         emitcode ("add", "a,#1");
4167                         emitcode ("xch", "a,b");
4168                         emitcode ("cpl", "a"); // msb
4169                         emitcode ("addc", "a,#0");
4170                         emitcode ("setb","F0");
4171                         emitcode ("","%05d$:",lbl->key+100);
4172                         emitcode ("mov","mb,b");
4173                         emitcode ("mov","mb,a");
4174                 }
4175         } else {
4176                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4177                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4178         }
4179         /* load up MA with left */
4180         if (!umult) {
4181                 lbl = newiTempLabel(NULL);
4182                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4183                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4184                 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4185                 emitcode ("xch", "a,b");
4186                 emitcode ("cpl","a");
4187                 emitcode ("add", "a,#1");
4188                 emitcode ("xch", "a,b");
4189                 emitcode ("cpl", "a"); // msb
4190                 emitcode ("addc","a,#0");
4191                 emitcode ("jbc","F0,%05d$",lbl->key+100);
4192                 emitcode ("setb","F0");
4193                 emitcode ("","%05d$:",lbl->key+100);
4194                 emitcode ("mov","ma,b");
4195                 emitcode ("mov","ma,a");
4196         } else {
4197                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4198                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4199         }
4200         /* wait for multiplication to finish */
4201         lbl = newiTempLabel(NULL);
4202         emitcode("","%05d$:", lbl->key+100);
4203         emitcode("mov","a,mcnt1");
4204         emitcode("anl","a,#0x80");
4205         emitcode("jnz","%05d$",lbl->key+100);
4206         
4207         freeAsmop (left, NULL, ic, TRUE);
4208         freeAsmop (right, NULL, ic,TRUE);
4209         aopOp(result, ic, TRUE, FALSE);
4210
4211         /* if unsigned then simple */   
4212         if (umult) {
4213                 emitcode ("mov","a,ma");
4214                 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4215                 emitcode ("mov","a,ma");
4216                 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4217                 aopPut(AOP(result),"ma",1);
4218                 aopPut(AOP(result),"ma",0);
4219         } else {
4220                 emitcode("push","ma");
4221                 emitcode("push","ma");
4222                 emitcode("push","ma");
4223                 MOVA("ma");
4224                 /* negate result if needed */
4225                 lbl = newiTempLabel(NULL);      
4226                 emitcode("jnb","F0,%05d$",lbl->key+100);
4227                 emitcode("cpl","a");
4228                 emitcode("add","a,#1");
4229                 emitcode("","%05d$:", lbl->key+100);
4230                 if (AOP_TYPE(result) == AOP_ACC)
4231                 {
4232                     D(emitcode(";", "ACC special case."););
4233                     /* We know result is the only live aop, and 
4234                      * it's obviously not a DPTR2, so AP is available.
4235                      */
4236                     emitcode("mov", "%s,acc", DP2_RESULT_REG);
4237                 }
4238                 else
4239                 {
4240                     aopPut(AOP(result),"a",0);
4241                 }
4242             
4243                 emitcode("pop","acc");
4244                 lbl = newiTempLabel(NULL);      
4245                 emitcode("jnb","F0,%05d$",lbl->key+100);
4246                 emitcode("cpl","a");
4247                 emitcode("addc","a,#0");
4248                 emitcode("","%05d$:", lbl->key+100);
4249                 aopPut(AOP(result),"a",1);
4250                 emitcode("pop","acc");
4251                 if (AOP_SIZE(result) >= 3) {
4252                         lbl = newiTempLabel(NULL);      
4253                         emitcode("jnb","F0,%05d$",lbl->key+100);
4254                         emitcode("cpl","a");
4255                         emitcode("addc","a,#0");                        
4256                         emitcode("","%05d$:", lbl->key+100);
4257                         aopPut(AOP(result),"a",2);
4258                 }
4259                 emitcode("pop","acc");
4260                 if (AOP_SIZE(result) >= 4) {
4261                         lbl = newiTempLabel(NULL);      
4262                         emitcode("jnb","F0,%05d$",lbl->key+100);
4263                         emitcode("cpl","a");
4264                         emitcode("addc","a,#0");                        
4265                         emitcode("","%05d$:", lbl->key+100);
4266                         aopPut(AOP(result),"a",3);
4267                 }
4268                 if (AOP_TYPE(result) == AOP_ACC)
4269                 {
4270                     /* We stashed the result away above. */
4271                     emitcode("mov", "acc,%s", DP2_RESULT_REG);
4272                 }           
4273                 
4274         }
4275         freeAsmop (result, NULL, ic, TRUE);
4276
4277         /* restore EA bit in F1 */
4278         lbl = newiTempLabel(NULL);
4279         emitcode ("jnb","F1,%05d$",lbl->key+100);
4280         emitcode ("setb","EA");
4281         emitcode("","%05d$:",lbl->key+100);
4282         return ;
4283 }
4284
4285 /*-----------------------------------------------------------------*/
4286 /* genMult - generates code for multiplication                     */
4287 /*-----------------------------------------------------------------*/
4288 static void
4289 genMult (iCode * ic)
4290 {
4291   operand *left = IC_LEFT (ic);
4292   operand *right = IC_RIGHT (ic);
4293   operand *result = IC_RESULT (ic);
4294
4295   D (emitcode (";", "genMult "););
4296
4297   /* assign the amsops */
4298   AOP_OP_2 (ic);
4299
4300   /* special cases first */
4301   /* both are bits */
4302   if (AOP_TYPE (left) == AOP_CRY &&
4303       AOP_TYPE (right) == AOP_CRY)
4304     {
4305       genMultbits (left, right, result, ic);
4306       goto release;
4307     }
4308
4309   /* if both are of size == 1 */
4310   if (AOP_SIZE (left) == 1 &&
4311       AOP_SIZE (right) == 1)
4312     {
4313       genMultOneByte (left, right, result, ic);
4314       goto release;
4315     }
4316
4317   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4318           /* use the ds390 ARITHMETIC accel UNIT */
4319           genMultTwoByte (left, right, result, ic);
4320           return ;
4321   }
4322   /* should have been converted to function call */
4323   assert (0);
4324
4325 release:
4326   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4327   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4328   freeAsmop (result, NULL, ic, TRUE);
4329 }
4330
4331 /*-----------------------------------------------------------------*/
4332 /* genDivbits :- division of bits                                  */
4333 /*-----------------------------------------------------------------*/
4334 static void
4335 genDivbits (operand * left,
4336             operand * right,
4337             operand * result,
4338             iCode   * ic)
4339 {
4340
4341   char *l;
4342
4343   /* the result must be bit */
4344   LOAD_AB_FOR_DIV (left, right, l);
4345   emitcode ("div", "ab");
4346   emitcode ("rrc", "a");
4347   aopOp(result, ic, TRUE, FALSE);
4348     
4349   aopPut (AOP (result), "c", 0);
4350 }
4351
4352 /*-----------------------------------------------------------------*/
4353 /* genDivOneByte : 8 bit division                                  */
4354 /*-----------------------------------------------------------------*/
4355 static void
4356 genDivOneByte (operand * left,
4357                operand * right,
4358                operand * result,
4359                iCode   * ic)
4360 {
4361   sym_link *opetype = operandType (result);
4362   char *l;
4363   symbol *lbl;
4364   int size, offset;
4365
4366   offset = 1;
4367   /* signed or unsigned */
4368   if (SPEC_USIGN (opetype))
4369     {
4370         /* unsigned is easy */
4371         LOAD_AB_FOR_DIV (left, right, l);
4372         emitcode ("div", "ab");
4373
4374         _G.accInUse++;
4375         aopOp(result, ic, TRUE, FALSE);
4376         aopPut (AOP (result), "a", 0);
4377         _G.accInUse--;
4378
4379         size = AOP_SIZE (result) - 1;
4380         
4381         while (size--)
4382         {
4383             aopPut (AOP (result), zero, offset++);
4384         }
4385       return;
4386     }
4387
4388   /* signed is a little bit more difficult */
4389
4390   /* save the signs of the operands */
4391   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4392   MOVA (l);
4393   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4394   emitcode ("push", "acc");     /* save it on the stack */
4395
4396   /* now sign adjust for both left & right */
4397   l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4398   MOVA (l);
4399   lbl = newiTempLabel (NULL);
4400   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4401   emitcode ("cpl", "a");
4402   emitcode ("inc", "a");
4403   emitcode ("", "%05d$:", (lbl->key + 100));
4404   emitcode ("mov", "b,a");
4405
4406   /* sign adjust left side */
4407   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4408   MOVA (l);
4409
4410   lbl = newiTempLabel (NULL);
4411   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4412   emitcode ("cpl", "a");
4413   emitcode ("inc", "a");
4414   emitcode ("", "%05d$:", (lbl->key + 100));
4415
4416   /* now the division */
4417   emitcode ("nop", "; workaround for DS80C390 div bug.");
4418   emitcode ("div", "ab");
4419   /* we are interested in the lower order
4420      only */
4421   emitcode ("mov", "b,a");
4422   lbl = newiTempLabel (NULL);
4423   emitcode ("pop", "acc");
4424   /* if there was an over flow we don't
4425      adjust the sign of the result */
4426   emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4427   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4428   CLRC;
4429   emitcode ("clr", "a");
4430   emitcode ("subb", "a,b");
4431   emitcode ("mov", "b,a");
4432   emitcode ("", "%05d$:", (lbl->key + 100));
4433
4434   /* now we are done */
4435     _G.accInUse++;
4436     aopOp(result, ic, TRUE, FALSE);
4437     
4438     aopPut (AOP (result), "b", 0);
4439     
4440     size = AOP_SIZE (result) - 1;
4441     
4442     if (size > 0)
4443     {
4444       emitcode ("mov", "c,b.7");
4445       emitcode ("subb", "a,acc");
4446     }
4447     while (size--)
4448     {
4449         aopPut (AOP (result), "a", offset++);
4450     }
4451     _G.accInUse--;
4452
4453 }
4454
4455 /*-----------------------------------------------------------------*/
4456 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide       */
4457 /*-----------------------------------------------------------------*/
4458 static void genDivTwoByte (operand *left, operand *right, 
4459                             operand *result, iCode *ic)
4460 {
4461         sym_link *retype = getSpec(operandType(right));
4462         sym_link *letype = getSpec(operandType(left));
4463         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4464         symbol *lbl;
4465
4466         /* save EA bit in F1 */
4467         lbl = newiTempLabel(NULL);
4468         emitcode ("setb","F1");
4469         emitcode ("jbc","EA,%05d$",lbl->key+100);
4470         emitcode ("clr","F1");
4471         emitcode("","%05d$:",lbl->key+100);
4472
4473         /* load up MA with left */
4474         if (!umult) {
4475                 emitcode("clr","F0");
4476                 lbl = newiTempLabel(NULL);
4477                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4478                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4479                 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4480                 emitcode ("xch", "a,b");
4481                 emitcode ("cpl","a");
4482                 emitcode ("add", "a,#1");
4483                 emitcode ("xch", "a,b");
4484                 emitcode ("cpl", "a"); // msb
4485                 emitcode ("addc","a,#0");
4486                 emitcode ("setb","F0");
4487                 emitcode ("","%05d$:",lbl->key+100);
4488                 emitcode ("mov","ma,b");
4489                 emitcode ("mov","ma,a");
4490         } else {
4491                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4492                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4493         }
4494
4495         /* load up MB with right */
4496         if (!umult) {
4497                 if (AOP_TYPE(right) == AOP_LIT) {
4498                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
4499                         if (val < 0) {
4500                                 lbl = newiTempLabel(NULL);
4501                                 emitcode ("jbc","F0,%05d$",lbl->key+100);
4502                                 emitcode("setb","F0");
4503                                 emitcode ("","%05d$:",lbl->key+100);
4504                                 val = -val;
4505                         } 
4506                         emitcode ("mov","mb,#0x%02x",val & 0xff);                   
4507                         emitcode ("mov","mb,#0x%02x",(val >> 8) & 0xff);
4508                 } else {
4509                         lbl = newiTempLabel(NULL);
4510                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4511                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4512                         emitcode ("jnb","acc.7,%05d$",lbl->key+100);            
4513                         emitcode ("xch", "a,b");
4514                         emitcode ("cpl","a");
4515                         emitcode ("add", "a,#1");
4516                         emitcode ("xch", "a,b");
4517                         emitcode ("cpl", "a"); // msb
4518                         emitcode ("addc", "a,#0");
4519                         emitcode ("jbc","F0,%05d$",lbl->key+100);
4520                         emitcode ("setb","F0");
4521                         emitcode ("","%05d$:",lbl->key+100);
4522                         emitcode ("mov","mb,b");
4523                         emitcode ("mov","mb,a");
4524                 }
4525         } else {
4526                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4527                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4528         }
4529
4530         /* wait for multiplication to finish */
4531         lbl = newiTempLabel(NULL);
4532         emitcode("","%05d$:", lbl->key+100);
4533         emitcode("mov","a,mcnt1");
4534         emitcode("anl","a,#0x80");
4535         emitcode("jnz","%05d$",lbl->key+100);
4536         
4537         freeAsmop (left, NULL, ic, TRUE);
4538         freeAsmop (right, NULL, ic,TRUE);
4539         aopOp(result, ic, TRUE, FALSE);
4540
4541         /* if unsigned then simple */   
4542         if (umult) {
4543                 aopPut(AOP(result),"ma",1);
4544                 aopPut(AOP(result),"ma",0);
4545         } else {
4546                 emitcode("push","ma");
4547                 MOVA("ma");
4548                 /* negate result if needed */
4549                 lbl = newiTempLabel(NULL);      
4550                 emitcode("jnb","F0,%05d$",lbl->key+100);
4551                 emitcode("cpl","a");
4552                 emitcode("add","a,#1");
4553                 emitcode("","%05d$:", lbl->key+100);
4554                 aopPut(AOP(result),"a",0);
4555                 emitcode("pop","acc");
4556                 lbl = newiTempLabel(NULL);      
4557                 emitcode("jnb","F0,%05d$",lbl->key+100);
4558                 emitcode("cpl","a");
4559                 emitcode("addc","a,#0");
4560                 emitcode("","%05d$:", lbl->key+100);
4561                 aopPut(AOP(result),"a",1);
4562         }
4563         freeAsmop (result, NULL, ic, TRUE);
4564         /* restore EA bit in F1 */
4565         lbl = newiTempLabel(NULL);
4566         emitcode ("jnb","F1,%05d$",lbl->key+100);
4567         emitcode ("setb","EA");
4568         emitcode("","%05d$:",lbl->key+100);
4569         return ;
4570 }
4571
4572 /*-----------------------------------------------------------------*/
4573 /* genDiv - generates code for division                            */
4574 /*-----------------------------------------------------------------*/
4575 static void
4576 genDiv (iCode * ic)
4577 {
4578   operand *left = IC_LEFT (ic);
4579   operand *right = IC_RIGHT (ic);
4580   operand *result = IC_RESULT (ic);
4581
4582   D (emitcode (";", "genDiv "););
4583
4584   /* assign the amsops */
4585   AOP_OP_2 (ic);
4586
4587   /* special cases first */
4588   /* both are bits */
4589   if (AOP_TYPE (left) == AOP_CRY &&
4590       AOP_TYPE (right) == AOP_CRY)
4591     {
4592       genDivbits (left, right, result, ic);
4593       goto release;
4594     }
4595
4596   /* if both are of size == 1 */
4597   if (AOP_SIZE (left) == 1 &&
4598       AOP_SIZE (right) == 1)
4599     {
4600       genDivOneByte (left, right, result, ic);
4601       goto release;
4602     }
4603
4604   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4605           /* use the ds390 ARITHMETIC accel UNIT */
4606           genDivTwoByte (left, right, result, ic);
4607           return ;
4608   }
4609   /* should have been converted to function call */
4610   assert (0);
4611 release:
4612   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4613   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4614   freeAsmop (result, NULL, ic, TRUE);
4615 }
4616
4617 /*-----------------------------------------------------------------*/
4618 /* genModbits :- modulus of bits                                   */
4619 /*-----------------------------------------------------------------*/
4620 static void
4621 genModbits (operand * left,
4622             operand * right,
4623             operand * result,
4624             iCode   * ic)
4625 {
4626
4627   char *l;
4628
4629   /* the result must be bit */
4630   LOAD_AB_FOR_DIV (left, right, l);
4631   emitcode ("div", "ab");
4632   emitcode ("mov", "a,b");
4633   emitcode ("rrc", "a");
4634   aopOp(result, ic, TRUE, FALSE);
4635   aopPut (AOP (result), "c", 0);
4636 }
4637
4638 /*-----------------------------------------------------------------*/
4639 /* genModOneByte : 8 bit modulus                                   */
4640 /*-----------------------------------------------------------------*/
4641 static void
4642 genModOneByte (operand * left,
4643                operand * right,
4644                operand * result,
4645                iCode   * ic)
4646 {
4647   sym_link *opetype = operandType (result);
4648   char *l;
4649   symbol *lbl;
4650
4651   /* signed or unsigned */
4652   if (SPEC_USIGN (opetype))
4653     {
4654       /* unsigned is easy */
4655       LOAD_AB_FOR_DIV (left, right, l);
4656       emitcode ("div", "ab");
4657       aopOp(result, ic, TRUE, FALSE);   
4658       aopPut (AOP (result), "b", 0);
4659       return;
4660     }
4661
4662   /* signed is a little bit more difficult */
4663
4664   /* save the signs of the operands */
4665   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4666   MOVA (l);
4667
4668   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4669   emitcode ("push", "acc");     /* save it on the stack */
4670
4671   /* now sign adjust for both left & right */
4672   l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4673   MOVA (l);
4674
4675   lbl = newiTempLabel (NULL);
4676   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4677   emitcode ("cpl", "a");
4678   emitcode ("inc", "a");
4679   emitcode ("", "%05d$:", (lbl->key + 100));
4680   emitcode ("mov", "b,a");
4681
4682   /* sign adjust left side */
4683   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4684   MOVA (l);
4685
4686   lbl = newiTempLabel (NULL);
4687   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4688   emitcode ("cpl", "a");
4689   emitcode ("inc", "a");
4690   emitcode ("", "%05d$:", (lbl->key + 100));
4691
4692   /* now the multiplication */
4693   emitcode ("nop", "; workaround for DS80C390 div bug.");
4694   emitcode ("div", "ab");
4695   /* we are interested in the lower order
4696      only */
4697   lbl = newiTempLabel (NULL);
4698   emitcode ("pop", "acc");
4699   /* if there was an over flow we don't
4700      adjust the sign of the result */
4701   emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4702   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4703   CLRC;
4704   emitcode ("clr", "a");
4705   emitcode ("subb", "a,b");
4706   emitcode ("mov", "b,a");
4707   emitcode ("", "%05d$:", (lbl->key + 100));
4708
4709   /* now we are done */
4710   aopOp(result, ic, TRUE, FALSE);    
4711   aopPut (AOP (result), "b", 0);
4712
4713 }
4714
4715 /*-----------------------------------------------------------------*/
4716 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus      */
4717 /*-----------------------------------------------------------------*/
4718 static void genModTwoByte (operand *left, operand *right, 
4719                             operand *result, iCode *ic)
4720 {
4721         sym_link *retype = getSpec(operandType(right));
4722         sym_link *letype = getSpec(operandType(left));
4723         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4724         symbol *lbl;
4725
4726         /* load up MA with left */
4727         /* save EA bit in F1 */
4728         lbl = newiTempLabel(NULL);
4729         emitcode ("setb","F1");
4730         emitcode ("jbc","EA,%05d$",lbl->key+100);
4731         emitcode ("clr","F1");
4732         emitcode("","%05d$:",lbl->key+100);
4733
4734         if (!umult) {
4735                 lbl = newiTempLabel(NULL);
4736                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4737                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4738                 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4739                 emitcode ("xch", "a,b");
4740                 emitcode ("cpl","a");
4741                 emitcode ("add", "a,#1");
4742                 emitcode ("xch", "a,b");
4743                 emitcode ("cpl", "a"); // msb
4744                 emitcode ("addc","a,#0");
4745                 emitcode ("","%05d$:",lbl->key+100);
4746                 emitcode ("mov","ma,b");
4747                 emitcode ("mov","ma,a");
4748         } else {
4749                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4750                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4751         }
4752
4753         /* load up MB with right */
4754         if (!umult) {
4755                 if (AOP_TYPE(right) == AOP_LIT) {
4756                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
4757                         if (val < 0) {
4758                                 val = -val;
4759                         } 
4760                         emitcode ("mov","mb,#0x%02x",val & 0xff);
4761                         emitcode ("mov","mb,#0x%02x",(val >> 8) & 0xff);                    
4762                 } else {
4763                         lbl = newiTempLabel(NULL);
4764                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4765                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4766                         emitcode ("jnb","acc.7,%05d$",lbl->key+100);            
4767                         emitcode ("xch", "a,b");
4768                         emitcode ("cpl","a");
4769                         emitcode ("add", "a,#1");
4770                         emitcode ("xch", "a,b");
4771                         emitcode ("cpl", "a"); // msb
4772                         emitcode ("addc", "a,#0");
4773                         emitcode ("","%05d$:",lbl->key+100);
4774                         emitcode ("mov","mb,b");
4775                         emitcode ("mov","mb,a");
4776                 }
4777         } else {
4778                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4779                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4780         }
4781
4782         /* wait for multiplication to finish */
4783         lbl = newiTempLabel(NULL);
4784         emitcode("","%05d$:", lbl->key+100);
4785         emitcode("mov","a,mcnt1");
4786         emitcode("anl","a,#0x80");
4787         emitcode("jnz","%05d$",lbl->key+100);
4788         
4789         freeAsmop (left, NULL, ic, TRUE);
4790         freeAsmop (right, NULL, ic,TRUE);
4791         aopOp(result, ic, TRUE, FALSE);
4792
4793         aopPut(AOP(result),"mb",1);
4794         aopPut(AOP(result),"mb",0);
4795         freeAsmop (result, NULL, ic, TRUE);
4796
4797         /* restore EA bit in F1 */
4798         lbl = newiTempLabel(NULL);
4799         emitcode ("jnb","F1,%05d$",lbl->key+100);
4800         emitcode ("setb","EA");
4801         emitcode("","%05d$:",lbl->key+100);
4802         return ;
4803 }
4804
4805 /*-----------------------------------------------------------------*/
4806 /* genMod - generates code for division                            */
4807 /*-----------------------------------------------------------------*/
4808 static void
4809 genMod (iCode * ic)
4810 {
4811   operand *left = IC_LEFT (ic);
4812   operand *right = IC_RIGHT (ic);
4813   operand *result = IC_RESULT (ic);
4814
4815   D (emitcode (";", "genMod "); );
4816
4817   /* assign the amsops */
4818   AOP_OP_2 (ic);
4819
4820   /* special cases first */
4821   /* both are bits */
4822   if (AOP_TYPE (left) == AOP_CRY &&
4823       AOP_TYPE (right) == AOP_CRY)
4824     {
4825       genModbits (left, right, result, ic);
4826       goto release;
4827     }
4828
4829   /* if both are of size == 1 */
4830   if (AOP_SIZE (left) == 1 &&
4831       AOP_SIZE (right) == 1)
4832     {
4833       genModOneByte (left, right, result, ic);
4834       goto release;
4835     }
4836
4837   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4838           /* use the ds390 ARITHMETIC accel UNIT */
4839           genModTwoByte (left, right, result, ic);
4840           return ;
4841   }
4842
4843   /* should have been converted to function call */
4844   assert (0);
4845
4846 release:
4847   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4848   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4849   freeAsmop (result, NULL, ic, TRUE);
4850 }
4851
4852 /*-----------------------------------------------------------------*/
4853 /* genIfxJump :- will create a jump depending on the ifx           */
4854 /*-----------------------------------------------------------------*/
4855 static void
4856 genIfxJump (iCode * ic, char *jval)
4857 {
4858   symbol *jlbl;
4859   symbol *tlbl = newiTempLabel (NULL);
4860   char *inst;
4861
4862   D (emitcode (";", "genIfxJump ");
4863     );
4864
4865   /* if true label then we jump if condition
4866      supplied is true */
4867   if (IC_TRUE (ic))
4868     {
4869       jlbl = IC_TRUE (ic);
4870       inst = ((strcmp (jval, "a") == 0 ? "jz" :
4871                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4872     }
4873   else
4874     {
4875       /* false label is present */
4876       jlbl = IC_FALSE (ic);
4877       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4878                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4879     }
4880   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4881     emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4882   else
4883     emitcode (inst, "%05d$", tlbl->key + 100);
4884   emitcode ("ljmp", "%05d$", jlbl->key + 100);
4885   emitcode ("", "%05d$:", tlbl->key + 100);
4886
4887   /* mark the icode as generated */
4888   ic->generated = 1;
4889 }
4890
4891 /*-----------------------------------------------------------------*/
4892 /* genCmp :- greater or less than comparison                       */
4893 /*-----------------------------------------------------------------*/
4894 static void
4895 genCmp (operand * left, operand * right,
4896         iCode * ic, iCode * ifx, int sign)
4897 {
4898   int size, offset = 0;
4899   unsigned long lit = 0L;
4900   operand *result;
4901
4902   D (emitcode (";", "genCmp");
4903     );
4904
4905   result = IC_RESULT (ic);
4906
4907   /* if left & right are bit variables */
4908   if (AOP_TYPE (left) == AOP_CRY &&
4909       AOP_TYPE (right) == AOP_CRY)
4910     {
4911       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4912       emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
4913     }
4914   else
4915     {
4916       /* subtract right from left if at the
4917          end the carry flag is set then we know that
4918          left is greater than right */
4919       size = max (AOP_SIZE (left), AOP_SIZE (right));
4920
4921       /* if unsigned char cmp with lit, do cjne left,#right,zz */
4922       if ((size == 1) && !sign &&
4923           (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4924         {
4925           symbol *lbl = newiTempLabel (NULL);
4926           emitcode ("cjne", "%s,%s,%05d$",
4927                     aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
4928                     aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4929                     lbl->key + 100);
4930           emitcode ("", "%05d$:", lbl->key + 100);
4931         }
4932       else
4933         {
4934           if (AOP_TYPE (right) == AOP_LIT)
4935             {
4936               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4937               /* optimize if(x < 0) or if(x >= 0) */
4938               if (lit == 0L)
4939                 {
4940                   if (!sign)
4941                     {
4942                       CLRC;
4943                     }
4944                   else
4945                     {
4946                       MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
4947
4948                       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4949                       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4950
4951                       aopOp (result, ic, FALSE, FALSE);
4952
4953                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4954                         {
4955                           freeAsmop (result, NULL, ic, TRUE);
4956                           genIfxJump (ifx, "acc.7");
4957                           return;
4958                         }
4959                       else
4960                         {
4961                           emitcode ("rlc", "a");
4962                         }
4963                       goto release_freedLR;
4964                     }
4965                   goto release;
4966                 }
4967             }
4968           CLRC;
4969           while (size--)
4970             {
4971               emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
4972               MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4973               emitcode (";", "genCmp #2");
4974               if (sign && (size == 0))
4975                 {
4976                   emitcode (";", "genCmp #3");
4977                   emitcode ("xrl", "a,#0x80");
4978                   if (AOP_TYPE (right) == AOP_LIT)
4979                     {
4980                       unsigned long lit = (unsigned long)
4981                       floatFromVal (AOP (right)->aopu.aop_lit);
4982                       emitcode (";", "genCmp #3.1");
4983                       emitcode ("subb", "a,#0x%02x",
4984                                 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4985                     }
4986                   else
4987                     {
4988                       emitcode (";", "genCmp #3.2");
4989                       if (AOP_NEEDSACC (right))
4990                         {
4991                           emitcode ("push", "acc");
4992                         }
4993                       emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
4994                                                        FALSE, FALSE, FALSE));
4995                       emitcode ("xrl", "b,#0x80");
4996                       if (AOP_NEEDSACC (right))
4997                         {
4998                           emitcode ("pop", "acc");
4999                         }
5000                       emitcode ("subb", "a,b");
5001                     }
5002                 }
5003               else
5004                 {
5005                   const char *s;
5006
5007                   emitcode (";", "genCmp #4");
5008                   if (AOP_NEEDSACC (right))
5009                     {
5010                       /* Yuck!! */
5011                       emitcode (";", "genCmp #4.1");
5012                       emitcode ("xch", "a, b");
5013                       MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
5014                       emitcode ("xch", "a, b");
5015                       s = "b";
5016                     }
5017                   else
5018                     {
5019                       emitcode (";", "genCmp #4.2");
5020                       s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
5021                     }
5022
5023                   emitcode ("subb", "a,%s", s);
5024                 }
5025             }
5026         }
5027     }
5028
5029 release:
5030 /* Don't need the left & right operands any more; do need the result. */
5031   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5032   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5033
5034   aopOp (result, ic, FALSE, FALSE);
5035
5036 release_freedLR:
5037
5038   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5039     {
5040       outBitC (result);
5041     }
5042   else
5043     {
5044       /* if the result is used in the next
5045          ifx conditional branch then generate
5046          code a little differently */
5047       if (ifx)
5048         {
5049           genIfxJump (ifx, "c");
5050         }
5051       else
5052         {
5053           outBitC (result);
5054         }
5055       /* leave the result in acc */
5056     }
5057   freeAsmop (result, NULL, ic, TRUE);
5058 }
5059
5060 /*-----------------------------------------------------------------*/
5061 /* genCmpGt :- greater than comparison                             */
5062 /*-----------------------------------------------------------------*/
5063 static void
5064 genCmpGt (iCode * ic, iCode * ifx)
5065 {
5066   operand *left, *right;
5067   sym_link *letype, *retype;
5068   int sign;
5069
5070   D (emitcode (";", "genCmpGt ");
5071     );
5072
5073   left = IC_LEFT (ic);
5074   right = IC_RIGHT (ic);
5075
5076   letype = getSpec (operandType (left));
5077   retype = getSpec (operandType (right));
5078   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5079
5080   /* assign the left & right amsops */
5081   AOP_OP_2 (ic);
5082
5083   genCmp (right, left, ic, ifx, sign);
5084 }
5085
5086 /*-----------------------------------------------------------------*/
5087 /* genCmpLt - less than comparisons                                */
5088 /*-----------------------------------------------------------------*/
5089 static void
5090 genCmpLt (iCode * ic, iCode * ifx)
5091 {
5092   operand *left, *right;
5093   sym_link *letype, *retype;
5094   int sign;
5095
5096   D (emitcode (";", "genCmpLt "););
5097
5098   left = IC_LEFT (ic);
5099   right = IC_RIGHT (ic);
5100
5101   letype = getSpec (operandType (left));
5102   retype = getSpec (operandType (right));
5103   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5104
5105   /* assign the left & right amsops */
5106   AOP_OP_2 (ic);
5107
5108   genCmp (left, right, ic, ifx, sign);
5109 }
5110
5111 /*-----------------------------------------------------------------*/
5112 /* gencjneshort - compare and jump if not equal                    */
5113 /*-----------------------------------------------------------------*/
5114 static void
5115 gencjneshort (operand * left, operand * right, symbol * lbl)
5116 {
5117   int size = max (AOP_SIZE (left), AOP_SIZE (right));
5118   int offset = 0;
5119   unsigned long lit = 0L;
5120
5121   D (emitcode (";", "gencjneshort");
5122     );
5123
5124   /* if the left side is a literal or
5125      if the right is in a pointer register and left
5126      is not */
5127   if ((AOP_TYPE (left) == AOP_LIT) ||
5128       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5129     {
5130       operand *t = right;
5131       right = left;
5132       left = t;
5133     }
5134
5135   if (AOP_TYPE (right) == AOP_LIT)
5136     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5137
5138   if (opIsGptr (left) || opIsGptr (right))
5139     {
5140       /* We are comparing a generic pointer to something.
5141        * Exclude the generic type byte from the comparison.
5142        */
5143       size--;
5144       D (emitcode (";", "cjneshort: generic ptr special case.");
5145         )
5146     }
5147
5148
5149   /* if the right side is a literal then anything goes */
5150   if (AOP_TYPE (right) == AOP_LIT &&
5151       AOP_TYPE (left) != AOP_DIR)
5152     {
5153       while (size--)
5154         {
5155           char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5156           MOVA (l);
5157           emitcode ("cjne", "a,%s,%05d$",
5158                     aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
5159                     lbl->key + 100);
5160           offset++;
5161         }
5162     }
5163
5164   /* if the right side is in a register or in direct space or
5165      if the left is a pointer register & right is not */
5166   else if (AOP_TYPE (right) == AOP_REG ||
5167            AOP_TYPE (right) == AOP_DIR ||
5168            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5169            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5170     {
5171       while (size--)
5172         {
5173           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5174           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5175               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5176             emitcode ("jnz", "%05d$", lbl->key + 100);
5177           else
5178             emitcode ("cjne", "a,%s,%05d$",
5179                       aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
5180                       lbl->key + 100);
5181           offset++;
5182         }
5183     }
5184   else
5185     {
5186       /* right is a pointer reg need both a & b */
5187       while (size--)
5188         {
5189           char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5190           if (strcmp (l, "b"))
5191             emitcode ("mov", "b,%s", l);
5192           MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5193           emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
5194           offset++;
5195         }
5196     }
5197 }
5198
5199 /*-----------------------------------------------------------------*/
5200 /* gencjne - compare and jump if not equal                         */
5201 /*-----------------------------------------------------------------*/
5202 static void
5203 gencjne (operand * left, operand * right, symbol * lbl)
5204 {
5205   symbol *tlbl = newiTempLabel (NULL);
5206
5207   D (emitcode (";", "gencjne");
5208     );
5209
5210   gencjneshort (left, right, lbl);
5211
5212   emitcode ("mov", "a,%s", one);
5213   emitcode ("sjmp", "%05d$", tlbl->key + 100);
5214   emitcode ("", "%05d$:", lbl->key + 100);
5215   emitcode ("clr", "a");
5216   emitcode ("", "%05d$:", tlbl->key + 100);
5217 }
5218
5219 /*-----------------------------------------------------------------*/
5220 /* genCmpEq - generates code for equal to                          */
5221 /*-----------------------------------------------------------------*/
5222 static void
5223 genCmpEq (iCode * ic, iCode * ifx)
5224 {
5225   operand *left, *right, *result;
5226
5227   D (emitcode (";", "genCmpEq ");
5228     );
5229
5230   AOP_OP_2 (ic);
5231   AOP_SET_LOCALS (ic);
5232
5233   /* if literal, literal on the right or
5234      if the right is in a pointer register and left
5235      is not */
5236   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5237       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5238     {
5239       operand *t = IC_RIGHT (ic);
5240       IC_RIGHT (ic) = IC_LEFT (ic);
5241       IC_LEFT (ic) = t;
5242     }
5243
5244   if (ifx &&                    /* !AOP_SIZE(result) */
5245       OP_SYMBOL (result) &&
5246       OP_SYMBOL (result)->regType == REG_CND)
5247     {
5248       symbol *tlbl;
5249       /* if they are both bit variables */
5250       if (AOP_TYPE (left) == AOP_CRY &&
5251           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5252         {
5253           if (AOP_TYPE (right) == AOP_LIT)
5254             {
5255               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5256               if (lit == 0L)
5257                 {
5258                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5259                   emitcode ("cpl", "c");
5260                 }
5261               else if (lit == 1L)
5262                 {
5263                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5264                 }
5265               else
5266                 {
5267                   emitcode ("clr", "c");
5268                 }
5269               /* AOP_TYPE(right) == AOP_CRY */
5270             }
5271           else
5272             {
5273               symbol *lbl = newiTempLabel (NULL);
5274               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5275               emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5276               emitcode ("cpl", "c");
5277               emitcode ("", "%05d$:", (lbl->key + 100));
5278             }
5279           /* if true label then we jump if condition
5280              supplied is true */
5281           tlbl = newiTempLabel (NULL);
5282           if (IC_TRUE (ifx))
5283             {
5284               emitcode ("jnc", "%05d$", tlbl->key + 100);
5285               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5286             }
5287           else
5288             {
5289               emitcode ("jc", "%05d$", tlbl->key + 100);
5290               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5291             }
5292           emitcode ("", "%05d$:", tlbl->key + 100);
5293         }
5294       else
5295         {
5296           tlbl = newiTempLabel (NULL);
5297           gencjneshort (left, right, tlbl);
5298           if (IC_TRUE (ifx))
5299             {
5300               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5301               emitcode ("", "%05d$:", tlbl->key + 100);
5302             }
5303           else
5304             {
5305               symbol *lbl = newiTempLabel (NULL);
5306               emitcode ("sjmp", "%05d$", lbl->key + 100);
5307               emitcode ("", "%05d$:", tlbl->key + 100);
5308               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5309               emitcode ("", "%05d$:", lbl->key + 100);
5310             }
5311         }
5312       /* mark the icode as generated */
5313       ifx->generated = 1;
5314
5315       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5316       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5317       return;
5318     }
5319
5320   /* if they are both bit variables */
5321   if (AOP_TYPE (left) == AOP_CRY &&
5322       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5323     {
5324       if (AOP_TYPE (right) == AOP_LIT)
5325         {
5326           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5327           if (lit == 0L)
5328             {
5329               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5330               emitcode ("cpl", "c");
5331             }
5332           else if (lit == 1L)
5333             {
5334               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5335             }
5336           else
5337             {
5338               emitcode ("clr", "c");
5339             }
5340           /* AOP_TYPE(right) == AOP_CRY */
5341         }
5342       else
5343         {
5344           symbol *lbl = newiTempLabel (NULL);
5345           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5346           emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5347           emitcode ("cpl", "c");
5348           emitcode ("", "%05d$:", (lbl->key + 100));
5349         }
5350
5351       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5352       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5353
5354       aopOp (result, ic, TRUE, FALSE);
5355
5356       /* c = 1 if egal */
5357       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5358         {
5359           outBitC (result);
5360           goto release;
5361         }
5362       if (ifx)
5363         {
5364           genIfxJump (ifx, "c");
5365           goto release;
5366         }
5367       /* if the result is used in an arithmetic operation
5368          then put the result in place */
5369       outBitC (result);
5370     }
5371   else
5372     {
5373       gencjne (left, right, newiTempLabel (NULL));
5374
5375       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5376       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5377
5378       aopOp (result, ic, TRUE, FALSE);
5379
5380       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5381         {
5382           aopPut (AOP (result), "a", 0);
5383           goto release;
5384         }
5385       if (ifx)
5386         {
5387           genIfxJump (ifx, "a");
5388           goto release;
5389         }
5390       /* if the result is used in an arithmetic operation
5391          then put the result in place */
5392       if (AOP_TYPE (result) != AOP_CRY)
5393         outAcc (result);
5394       /* leave the result in acc */
5395     }
5396
5397 release:
5398   freeAsmop (result, NULL, ic, TRUE);
5399 }
5400
5401 /*-----------------------------------------------------------------*/
5402 /* ifxForOp - returns the icode containing the ifx for operand     */
5403 /*-----------------------------------------------------------------*/
5404 static iCode *
5405 ifxForOp (operand * op, iCode * ic)
5406 {
5407   /* if true symbol then needs to be assigned */
5408   if (IS_TRUE_SYMOP (op))
5409     return NULL;
5410
5411   /* if this has register type condition and
5412      the next instruction is ifx with the same operand
5413      and live to of the operand is upto the ifx only then */
5414   if (ic->next &&
5415       ic->next->op == IFX &&
5416       IC_COND (ic->next)->key == op->key &&
5417       OP_SYMBOL (op)->liveTo <= ic->next->seq)
5418     return ic->next;
5419
5420   return NULL;
5421 }
5422 /*-----------------------------------------------------------------*/
5423 /* hasInc - operand is incremented before any other use            */
5424 /*-----------------------------------------------------------------*/
5425 static iCode *
5426 hasInc (operand *op, iCode *ic)
5427 {
5428   sym_link *type = operandType(op);
5429   sym_link *retype = getSpec (type);
5430   iCode *lic = ic->next;
5431   int isize ;
5432   
5433   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5434   if (!IS_SYMOP(op)) return NULL;
5435
5436   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5437   isize = getSize(type->next);
5438   while (lic) {
5439       /* if operand of the form op = op + <sizeof *op> */
5440       if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5441           isOperandEqual(IC_RESULT(lic),op) && 
5442           isOperandLiteral(IC_RIGHT(lic)) &&
5443           operandLitValue(IC_RIGHT(lic)) == isize) {
5444           return lic;
5445       }
5446       /* if the operand used or deffed */
5447       if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5448           return NULL;
5449       }
5450       /* if GOTO or IFX */
5451       if (lic->op == IFX || lic->op == GOTO) break;
5452       lic = lic->next;
5453   }
5454   return NULL;
5455 }
5456
5457 /*-----------------------------------------------------------------*/
5458 /* genAndOp - for && operation                                     */
5459 /*-----------------------------------------------------------------*/
5460 static void
5461 genAndOp (iCode * ic)
5462 {
5463   operand *left, *right, *result;
5464   symbol *tlbl;
5465
5466   D (emitcode (";", "genAndOp "););
5467
5468   /* note here that && operations that are in an
5469      if statement are taken away by backPatchLabels
5470      only those used in arthmetic operations remain */
5471   AOP_OP_2 (ic);
5472   AOP_SET_LOCALS (ic);
5473
5474   /* if both are bit variables */
5475   if (AOP_TYPE (left) == AOP_CRY &&
5476       AOP_TYPE (right) == AOP_CRY)
5477     {
5478       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5479       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5480       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5481       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5482   
5483       aopOp (result,ic,FALSE, FALSE);
5484       outBitC (result);
5485     }
5486   else
5487     {
5488       tlbl = newiTempLabel (NULL);
5489       toBoolean (left);
5490       emitcode ("jz", "%05d$", tlbl->key + 100);
5491       toBoolean (right);
5492       emitcode ("", "%05d$:", tlbl->key + 100);
5493       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5494       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5495   
5496       aopOp (result,ic,FALSE, FALSE);
5497       outBitAcc (result);
5498     }
5499     freeAsmop (result, NULL, ic, TRUE);
5500 }
5501
5502
5503 /*-----------------------------------------------------------------*/
5504 /* genOrOp - for || operation                                      */
5505 /*-----------------------------------------------------------------*/
5506 static void
5507 genOrOp (iCode * ic)
5508 {
5509   operand *left, *right, *result;
5510   symbol *tlbl;
5511
5512   D (emitcode (";", "genOrOp "););
5513
5514   /* note here that || operations that are in an
5515      if statement are taken away by backPatchLabels
5516      only those used in arthmetic operations remain */
5517   AOP_OP_2 (ic);
5518   AOP_SET_LOCALS (ic);
5519
5520   /* if both are bit variables */
5521   if (AOP_TYPE (left) == AOP_CRY &&
5522       AOP_TYPE (right) == AOP_CRY)
5523     {
5524       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5525       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5526       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5527       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5528   
5529       aopOp (result,ic,FALSE, FALSE);
5530       
5531       outBitC (result);
5532     }
5533   else
5534     {
5535       tlbl = newiTempLabel (NULL);
5536       toBoolean (left);
5537       emitcode ("jnz", "%05d$", tlbl->key + 100);
5538       toBoolean (right);
5539       emitcode ("", "%05d$:", tlbl->key + 100);
5540       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5541       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5542   
5543       aopOp (result,ic,FALSE, FALSE);
5544       
5545       outBitAcc (result);
5546     }
5547
5548   freeAsmop (result, NULL, ic, TRUE);
5549 }
5550
5551 /*-----------------------------------------------------------------*/
5552 /* isLiteralBit - test if lit == 2^n                               */
5553 /*-----------------------------------------------------------------*/
5554 static int
5555 isLiteralBit (unsigned long lit)
5556 {
5557   unsigned long pw[32] =
5558   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5559    0x100L, 0x200L, 0x400L, 0x800L,
5560    0x1000L, 0x2000L, 0x4000L, 0x8000L,
5561    0x10000L, 0x20000L, 0x40000L, 0x80000L,
5562    0x100000L, 0x200000L, 0x400000L, 0x800000L,
5563    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5564    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5565   int idx;
5566
5567   for (idx = 0; idx < 32; idx++)
5568     if (lit == pw[idx])
5569       return idx + 1;
5570   return 0;
5571 }
5572
5573 /*-----------------------------------------------------------------*/
5574 /* continueIfTrue -                                                */
5575 /*-----------------------------------------------------------------*/
5576 static void
5577 continueIfTrue (iCode * ic)
5578 {
5579   if (IC_TRUE (ic))
5580     emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5581   ic->generated = 1;
5582 }
5583
5584 /*-----------------------------------------------------------------*/
5585 /* jmpIfTrue -                                                     */
5586 /*-----------------------------------------------------------------*/
5587 static void
5588 jumpIfTrue (iCode * ic)
5589 {
5590   if (!IC_TRUE (ic))
5591     emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5592   ic->generated = 1;
5593 }
5594
5595 /*-----------------------------------------------------------------*/
5596 /* jmpTrueOrFalse -                                                */
5597 /*-----------------------------------------------------------------*/
5598 static void
5599 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
5600 {
5601   // ugly but optimized by peephole
5602   if (IC_TRUE (ic))
5603     {
5604       symbol *nlbl = newiTempLabel (NULL);
5605       emitcode ("sjmp", "%05d$", nlbl->key + 100);
5606       emitcode ("", "%05d$:", tlbl->key + 100);
5607       emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5608       emitcode ("", "%05d$:", nlbl->key + 100);
5609     }
5610   else
5611     {
5612       emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5613       emitcode ("", "%05d$:", tlbl->key + 100);
5614     }
5615   ic->generated = 1;
5616 }
5617
5618 // Generate code to perform a bit-wise logic operation
5619 // on two operands in far space (assumed to already have been 
5620 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
5621 // in far space. This requires pushing the result on the stack
5622 // then popping it into the result.
5623 static void
5624 genFarFarLogicOp(iCode *ic, char *logicOp)
5625 {
5626       int size, resultSize, compSize;
5627       int offset = 0;
5628       
5629       TR_AP("#5");
5630       D(emitcode(";", "%s special case for 3 far operands.", logicOp););
5631       compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ? 
5632                   AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
5633       
5634       _startLazyDPSEvaluation();
5635       for (size = compSize; (size--); offset++)
5636       {
5637           MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
5638           emitcode ("mov", "%s, acc", DP2_RESULT_REG);
5639           MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
5640           
5641           emitcode (logicOp, "a,%s", DP2_RESULT_REG);
5642           emitcode ("push", "acc");
5643       }
5644       _endLazyDPSEvaluation();
5645      
5646       freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5647       freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5648       aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
5649      
5650       resultSize = AOP_SIZE(IC_RESULT(ic));
5651
5652       ADJUST_PUSHED_RESULT(compSize, resultSize);
5653
5654       _startLazyDPSEvaluation();
5655       while (compSize--)
5656       {
5657           emitcode ("pop", "acc");
5658           aopPut (AOP (IC_RESULT (ic)), "a", compSize);
5659       }
5660       _endLazyDPSEvaluation();
5661       freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
5662 }
5663
5664
5665 /*-----------------------------------------------------------------*/
5666 /* genAnd  - code for and                                          */
5667 /*-----------------------------------------------------------------*/
5668 static void
5669 genAnd (iCode * ic, iCode * ifx)
5670 {
5671   operand *left, *right, *result;
5672   int size, offset = 0;
5673   unsigned long lit = 0L;
5674   int bytelit = 0;
5675   char buffer[10];
5676   bool pushResult;
5677
5678   D (emitcode (";", "genAnd "););
5679
5680   AOP_OP_3_NOFATAL (ic, pushResult);
5681   AOP_SET_LOCALS (ic);
5682
5683   if (pushResult)
5684   {
5685       genFarFarLogicOp(ic, "anl");
5686       return;
5687   }  
5688
5689 #ifdef DEBUG_TYPE
5690   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5691             AOP_TYPE (result),
5692             AOP_TYPE (left), AOP_TYPE (right));
5693   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5694             AOP_SIZE (result),
5695             AOP_SIZE (left), AOP_SIZE (right));
5696 #endif
5697
5698   /* if left is a literal & right is not then exchange them */
5699   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5700 #ifdef LOGIC_OPS_BROKEN      
5701     ||  AOP_NEEDSACC (left)
5702 #endif
5703     )
5704     {
5705       operand *tmp = right;
5706       right = left;
5707       left = tmp;
5708     }
5709
5710   /* if result = right then exchange them */
5711   if (sameRegs (AOP (result), AOP (right)))
5712     {
5713       operand *tmp = right;
5714       right = left;
5715       left = tmp;
5716     }
5717
5718   /* if right is bit then exchange them */
5719   if (AOP_TYPE (right) == AOP_CRY &&
5720       AOP_TYPE (left) != AOP_CRY)
5721     {
5722       operand *tmp = right;
5723       right = left;
5724       left = tmp;
5725     }
5726   if (AOP_TYPE (right) == AOP_LIT)
5727     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5728
5729   size = AOP_SIZE (result);
5730
5731   // if(bit & yy)
5732   // result = bit & yy;
5733   if (AOP_TYPE (left) == AOP_CRY)
5734     {
5735       // c = bit & literal;
5736       if (AOP_TYPE (right) == AOP_LIT)
5737         {
5738           if (lit & 1)
5739             {
5740               if (size && sameRegs (AOP (result), AOP (left)))
5741                 // no change
5742                 goto release;
5743               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5744             }
5745           else
5746             {
5747               // bit(result) = 0;
5748               if (size && (AOP_TYPE (result) == AOP_CRY))
5749                 {
5750                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5751                   goto release;
5752                 }
5753               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5754                 {
5755                   jumpIfTrue (ifx);
5756                   goto release;
5757                 }
5758               emitcode ("clr", "c");
5759             }
5760         }
5761       else
5762         {
5763           if (AOP_TYPE (right) == AOP_CRY)
5764             {
5765               // c = bit & bit;
5766               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5767               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5768             }
5769           else
5770             {
5771               // c = bit & val;
5772               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
5773               // c = lsb
5774               emitcode ("rrc", "a");
5775               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5776             }
5777         }
5778       // bit = c
5779       // val = c
5780       if (size)
5781         outBitC (result);
5782       // if(bit & ...)
5783       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5784         genIfxJump (ifx, "c");
5785       goto release;
5786     }
5787
5788   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5789   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5790   if ((AOP_TYPE (right) == AOP_LIT) &&
5791       (AOP_TYPE (result) == AOP_CRY) &&
5792       (AOP_TYPE (left) != AOP_CRY))
5793     {
5794       int posbit = isLiteralBit (lit);
5795       /* left &  2^n */
5796       if (posbit)
5797         {
5798           posbit--;
5799           MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
5800           // bit = left & 2^n
5801           if (size)
5802             emitcode ("mov", "c,acc.%d", posbit & 0x07);
5803           // if(left &  2^n)
5804           else
5805             {
5806               if (ifx)
5807                 {
5808                   sprintf (buffer, "acc.%d", posbit & 0x07);
5809                   genIfxJump (ifx, buffer);
5810                 }
5811               goto release;
5812             }
5813         }
5814       else
5815         {
5816           symbol *tlbl = newiTempLabel (NULL);
5817           int sizel = AOP_SIZE (left);
5818           if (size)
5819             emitcode ("setb", "c");
5820           while (sizel--)
5821             {
5822               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5823                 {
5824                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5825                   // byte ==  2^n ?
5826                   if ((posbit = isLiteralBit (bytelit)) != 0)
5827                     emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5828                   else
5829                     {
5830                       if (bytelit != 0x0FFL)
5831                         emitcode ("anl", "a,%s",
5832                           aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
5833                       emitcode ("jnz", "%05d$", tlbl->key + 100);
5834                     }
5835                 }
5836               offset++;
5837             }
5838           // bit = left & literal
5839           if (size)
5840             {
5841               emitcode ("clr", "c");
5842               emitcode ("", "%05d$:", tlbl->key + 100);
5843             }
5844           // if(left & literal)
5845           else
5846             {
5847               if (ifx)
5848                 jmpTrueOrFalse (ifx, tlbl);
5849               goto release;
5850             }
5851         }
5852       outBitC (result);
5853       goto release;
5854     }
5855
5856   /* if left is same as result */
5857   if (sameRegs (AOP (result), AOP (left)))
5858     {
5859       for (; size--; offset++)
5860         {
5861           if (AOP_TYPE (right) == AOP_LIT)
5862             {
5863               if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5864                 continue;
5865               else if (bytelit == 0)
5866                 aopPut (AOP (result), zero, offset);
5867               else if (IS_AOP_PREG (result))
5868                 {
5869                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5870                   emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5871                   aopPut (AOP (result), "a", offset);
5872                 }
5873               else
5874                 emitcode ("anl", "%s,%s",
5875                           aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5876                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5877             }
5878           else
5879             {
5880               if (AOP_TYPE (left) == AOP_ACC)
5881                 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5882               else
5883                 {
5884                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5885                   if (IS_AOP_PREG (result))
5886                     {
5887                       emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5888                       aopPut (AOP (result), "a", offset);
5889
5890                     }
5891                   else
5892                     emitcode ("anl", "%s,a",
5893                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5894                 }
5895             }
5896         }
5897     }
5898   else
5899     {
5900       // left & result in different registers
5901       if (AOP_TYPE (result) == AOP_CRY)
5902         {
5903           // result = bit
5904           // if(size), result in bit
5905           // if(!size && ifx), conditional oper: if(left & right)
5906           symbol *tlbl = newiTempLabel (NULL);
5907           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5908           if (size)
5909             emitcode ("setb", "c");
5910           while (sizer--)
5911             {
5912               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5913                 emitcode ("anl", "a,%s",
5914                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5915               } else {
5916                 if (AOP_TYPE(left)==AOP_ACC) {
5917                   emitcode("mov", "b,a");
5918                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5919                   emitcode("anl", "a,b");
5920                 }else {
5921                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5922                   emitcode ("anl", "a,%s",
5923                             aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5924                 }
5925               }
5926               emitcode ("jnz", "%05d$", tlbl->key + 100);
5927               offset++;
5928             }
5929           if (size)
5930             {
5931               CLRC;
5932               emitcode ("", "%05d$:", tlbl->key + 100);
5933               outBitC (result);
5934             }
5935           else if (ifx)
5936             jmpTrueOrFalse (ifx, tlbl);
5937         }
5938       else
5939         {
5940           for (; (size--); offset++)
5941             {
5942               // normal case
5943               // result = left & right
5944               if (AOP_TYPE (right) == AOP_LIT)
5945                 {
5946                   if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5947                     {
5948                       aopPut (AOP (result),
5949                            aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5950                               offset);
5951                       continue;
5952                     }
5953                   else if (bytelit == 0)
5954                     {
5955                       aopPut (AOP (result), zero, offset);
5956                       continue;
5957                     }
5958                   D (emitcode (";", "better literal AND."););
5959                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5960                   emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
5961                                                     FALSE, FALSE, FALSE));
5962
5963                 }
5964               else
5965                 {
5966                   // faster than result <- left, anl result,right
5967                   // and better if result is SFR
5968                   if (AOP_TYPE (left) == AOP_ACC)
5969                     {
5970                       emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
5971                                                        FALSE, FALSE, FALSE));
5972                     }
5973                   else
5974                     {
5975                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
5976                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
5977                       {
5978                           emitcode("mov", "b,a");
5979                           rOp = "b";
5980                       }
5981                         
5982                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5983                       emitcode ("anl", "a,%s", rOp);
5984                     }                   
5985                 }
5986               aopPut (AOP (result), "a", offset);
5987             }
5988         }
5989     }
5990
5991 release:
5992   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5993   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5994   freeAsmop (result, NULL, ic, TRUE);
5995 }
5996
5997
5998 /*-----------------------------------------------------------------*/
5999 /* genOr  - code for or                                            */
6000 /*-----------------------------------------------------------------*/
6001 static void
6002 genOr (iCode * ic, iCode * ifx)
6003 {
6004   operand *left, *right, *result;
6005   int size, offset = 0;
6006   unsigned long lit = 0L;
6007   bool     pushResult;
6008
6009   D (emitcode (";", "genOr "););
6010
6011   AOP_OP_3_NOFATAL (ic, pushResult);
6012   AOP_SET_LOCALS (ic);
6013
6014   if (pushResult)
6015   {
6016       genFarFarLogicOp(ic, "orl");
6017       return;
6018   }
6019
6020
6021 #ifdef DEBUG_TYPE
6022   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6023             AOP_TYPE (result),
6024             AOP_TYPE (left), AOP_TYPE (right));
6025   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6026             AOP_SIZE (result),
6027             AOP_SIZE (left), AOP_SIZE (right));
6028 #endif
6029
6030   /* if left is a literal & right is not then exchange them */
6031   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6032 #ifdef LOGIC_OPS_BROKEN
6033    || AOP_NEEDSACC (left) // I think this is a net loss now.
6034 #endif      
6035       )
6036     {
6037       operand *tmp = right;
6038       right = left;
6039       left = tmp;
6040     }
6041
6042   /* if result = right then exchange them */
6043   if (sameRegs (AOP (result), AOP (right)))
6044     {
6045       operand *tmp = right;
6046       right = left;
6047       left = tmp;
6048     }
6049
6050   /* if right is bit then exchange them */
6051   if (AOP_TYPE (right) == AOP_CRY &&
6052       AOP_TYPE (left) != AOP_CRY)
6053     {
6054       operand *tmp = right;
6055       right = left;
6056       left = tmp;
6057     }
6058   if (AOP_TYPE (right) == AOP_LIT)
6059     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6060
6061   size = AOP_SIZE (result);
6062
6063   // if(bit | yy)
6064   // xx = bit | yy;
6065   if (AOP_TYPE (left) == AOP_CRY)
6066     {
6067       if (AOP_TYPE (right) == AOP_LIT)
6068         {
6069           // c = bit & literal;
6070           if (lit)
6071             {
6072               // lit != 0 => result = 1
6073               if (AOP_TYPE (result) == AOP_CRY)
6074                 {
6075                   if (size)
6076                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6077                   else if (ifx)
6078                     continueIfTrue (ifx);
6079                   goto release;
6080                 }
6081               emitcode ("setb", "c");
6082             }
6083           else
6084             {
6085               // lit == 0 => result = left
6086               if (size && sameRegs (AOP (result), AOP (left)))
6087                 goto release;
6088               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6089             }
6090         }
6091       else
6092         {
6093           if (AOP_TYPE (right) == AOP_CRY)
6094             {
6095               // c = bit | bit;
6096               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6097               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6098             }
6099           else
6100             {
6101               // c = bit | val;
6102               symbol *tlbl = newiTempLabel (NULL);
6103               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6104                 emitcode ("setb", "c");
6105               emitcode ("jb", "%s,%05d$",
6106                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
6107               toBoolean (right);
6108               emitcode ("jnz", "%05d$", tlbl->key + 100);
6109               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6110                 {
6111                   jmpTrueOrFalse (ifx, tlbl);
6112                   goto release;
6113                 }
6114               else
6115                 {
6116                   CLRC;
6117                   emitcode ("", "%05d$:", tlbl->key + 100);
6118                 }
6119             }
6120         }
6121       // bit = c
6122       // val = c
6123       if (size)
6124         outBitC (result);
6125       // if(bit | ...)
6126       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6127         genIfxJump (ifx, "c");
6128       goto release;
6129     }
6130
6131   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6132   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6133   if ((AOP_TYPE (right) == AOP_LIT) &&
6134       (AOP_TYPE (result) == AOP_CRY) &&
6135       (AOP_TYPE (left) != AOP_CRY))
6136     {
6137       if (lit)
6138         {
6139           // result = 1
6140           if (size)
6141             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6142           else
6143             continueIfTrue (ifx);
6144           goto release;
6145         }
6146       else
6147         {
6148           // lit = 0, result = boolean(left)
6149           if (size)
6150             emitcode ("setb", "c");
6151           toBoolean (right);
6152           if (size)
6153             {
6154               symbol *tlbl = newiTempLabel (NULL);
6155               emitcode ("jnz", "%05d$", tlbl->key + 100);
6156               CLRC;
6157               emitcode ("", "%05d$:", tlbl->key + 100);
6158             }
6159           else
6160             {
6161               genIfxJump (ifx, "a");
6162               goto release;
6163             }
6164         }
6165       outBitC (result);
6166       goto release;
6167     }
6168
6169   /* if left is same as result */
6170   if (sameRegs (AOP (result), AOP (left)))
6171     {
6172       for (; size--; offset++)
6173         {
6174           if (AOP_TYPE (right) == AOP_LIT)
6175             {
6176               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6177                 {
6178                   continue;
6179                 }
6180               else
6181                 {
6182                   if (IS_AOP_PREG (left))
6183                     {
6184                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6185                       emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6186                       aopPut (AOP (result), "a", offset);
6187                     }
6188                   else
6189                     {
6190                       emitcode ("orl", "%s,%s",
6191                             aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6192                          aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6193                     }
6194                 }
6195             }
6196           else
6197             {
6198               if (AOP_TYPE (left) == AOP_ACC)
6199                 {
6200                   emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6201                 }
6202               else
6203                 {
6204                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6205                   if (IS_AOP_PREG (left))
6206                     {
6207                       emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6208                       aopPut (AOP (result), "a", offset);
6209                     }
6210                   else
6211                     {
6212                       emitcode ("orl", "%s,a",
6213                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6214                     }
6215                 }
6216             }
6217         }
6218     }
6219   else
6220     {
6221       // left & result in different registers
6222       if (AOP_TYPE (result) == AOP_CRY)
6223         {
6224           // result = bit
6225           // if(size), result in bit
6226           // if(!size && ifx), conditional oper: if(left | right)
6227           symbol *tlbl = newiTempLabel (NULL);
6228           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6229           if (size)
6230             emitcode ("setb", "c");
6231           while (sizer--)
6232             {
6233               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6234                 emitcode ("orl", "a,%s",
6235                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6236               } else {
6237                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6238                 emitcode ("orl", "a,%s",
6239                           aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6240               }
6241               emitcode ("jnz", "%05d$", tlbl->key + 100);
6242               offset++;
6243             }
6244           if (size)
6245             {
6246               CLRC;
6247               emitcode ("", "%05d$:", tlbl->key + 100);
6248               outBitC (result);
6249             }
6250           else if (ifx)
6251             jmpTrueOrFalse (ifx, tlbl);
6252         }
6253       else
6254         {
6255             _startLazyDPSEvaluation();
6256           for (; (size--); offset++)
6257             {
6258               // normal case
6259               // result = left & right
6260               if (AOP_TYPE (right) == AOP_LIT)
6261                 {
6262                   if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6263                     {
6264                       aopPut (AOP (result),
6265                            aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6266                               offset);
6267                       continue;
6268                     }
6269                   D (emitcode (";", "better literal OR."););
6270                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6271                   emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
6272                                                     FALSE, FALSE, FALSE));
6273
6274                 }
6275               else
6276                 {
6277                   // faster than result <- left, anl result,right
6278                   // and better if result is SFR
6279                   if (AOP_TYPE (left) == AOP_ACC)
6280                     {
6281                       emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
6282                                                        FALSE, FALSE, FALSE));
6283                     }
6284                   else
6285                     {
6286                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6287                         
6288                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6289                       {
6290                           emitcode("mov", "b,a");
6291                           rOp = "b";
6292                       }
6293                         
6294                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6295                       emitcode ("orl", "a,%s", rOp);
6296                     }
6297                 }
6298               aopPut (AOP (result), "a", offset);
6299             }
6300             _endLazyDPSEvaluation();
6301         }
6302     }
6303
6304 release:
6305   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6306   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6307   freeAsmop (result, NULL, ic, TRUE);
6308 }
6309
6310 /*-----------------------------------------------------------------*/
6311 /* genXor - code for xclusive or                                   */
6312 /*-----------------------------------------------------------------*/
6313 static void
6314 genXor (iCode * ic, iCode * ifx)
6315 {
6316   operand *left, *right, *result;
6317   int size, offset = 0;
6318   unsigned long lit = 0L;
6319   bool pushResult;
6320
6321   D (emitcode (";", "genXor "););
6322
6323   AOP_OP_3_NOFATAL (ic, pushResult);
6324   AOP_SET_LOCALS (ic);
6325
6326   if (pushResult)
6327   {
6328       genFarFarLogicOp(ic, "xrl");
6329       return;
6330   }  
6331
6332 #ifdef DEBUG_TYPE
6333   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6334             AOP_TYPE (result),
6335             AOP_TYPE (left), AOP_TYPE (right));
6336   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6337             AOP_SIZE (result),
6338             AOP_SIZE (left), AOP_SIZE (right));
6339 #endif
6340
6341   /* if left is a literal & right is not ||
6342      if left needs acc & right does not */
6343   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) 
6344 #ifdef LOGIC_OPS_BROKEN      
6345       || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6346 #endif
6347      )
6348     {
6349       operand *tmp = right;
6350       right = left;
6351       left = tmp;
6352     }
6353
6354   /* if result = right then exchange them */
6355   if (sameRegs (AOP (result), AOP (right)))
6356     {
6357       operand *tmp = right;
6358       right = left;
6359       left = tmp;
6360     }
6361
6362   /* if right is bit then exchange them */
6363   if (AOP_TYPE (right) == AOP_CRY &&
6364       AOP_TYPE (left) != AOP_CRY)
6365     {
6366       operand *tmp = right;
6367       right = left;
6368       left = tmp;
6369     }
6370   if (AOP_TYPE (right) == AOP_LIT)
6371     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6372
6373   size = AOP_SIZE (result);
6374
6375   // if(bit ^ yy)
6376   // xx = bit ^ yy;
6377   if (AOP_TYPE (left) == AOP_CRY)
6378     {
6379       if (AOP_TYPE (right) == AOP_LIT)
6380         {
6381           // c = bit & literal;
6382           if (lit >> 1)
6383             {
6384               // lit>>1  != 0 => result = 1
6385               if (AOP_TYPE (result) == AOP_CRY)
6386                 {
6387                   if (size)
6388                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6389                   else if (ifx)
6390                     continueIfTrue (ifx);
6391                   goto release;
6392                 }
6393               emitcode ("setb", "c");
6394             }
6395           else
6396             {
6397               // lit == (0 or 1)
6398               if (lit == 0)
6399                 {
6400                   // lit == 0, result = left
6401                   if (size && sameRegs (AOP (result), AOP (left)))
6402                     goto release;
6403                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6404                 }
6405               else
6406                 {
6407                   // lit == 1, result = not(left)
6408                   if (size && sameRegs (AOP (result), AOP (left)))
6409                     {
6410                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6411                       goto release;
6412                     }
6413                   else
6414                     {
6415                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6416                       emitcode ("cpl", "c");
6417                     }
6418                 }
6419             }
6420
6421         }
6422       else
6423         {
6424           // right != literal
6425           symbol *tlbl = newiTempLabel (NULL);
6426           if (AOP_TYPE (right) == AOP_CRY)
6427             {
6428               // c = bit ^ bit;
6429               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6430             }
6431           else
6432             {
6433               int sizer = AOP_SIZE (right);
6434               // c = bit ^ val
6435               // if val>>1 != 0, result = 1
6436               emitcode ("setb", "c");
6437               while (sizer)
6438                 {
6439                   MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
6440                   if (sizer == 1)
6441                     // test the msb of the lsb
6442                     emitcode ("anl", "a,#0xfe");
6443                   emitcode ("jnz", "%05d$", tlbl->key + 100);
6444                   sizer--;
6445                 }
6446               // val = (0,1)
6447               emitcode ("rrc", "a");
6448             }
6449           emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6450           emitcode ("cpl", "c");
6451           emitcode ("", "%05d$:", (tlbl->key + 100));
6452         }
6453       // bit = c
6454       // val = c
6455       if (size)
6456         outBitC (result);
6457       // if(bit | ...)
6458       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6459         genIfxJump (ifx, "c");
6460       goto release;
6461     }
6462
6463   if (sameRegs (AOP (result), AOP (left)))
6464     {
6465       /* if left is same as result */
6466       for (; size--; offset++)
6467         {
6468           if (AOP_TYPE (right) == AOP_LIT)
6469             {
6470               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6471                 continue;
6472               else if (IS_AOP_PREG (left))
6473                 {
6474                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6475                   emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6476                   aopPut (AOP (result), "a", offset);
6477                 }
6478               else
6479                 emitcode ("xrl", "%s,%s",
6480                           aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6481                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6482             }
6483           else
6484             {
6485               if (AOP_TYPE (left) == AOP_ACC)
6486                 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6487               else
6488                 {
6489                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6490                   if (IS_AOP_PREG (left))
6491                     {
6492                       emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6493                       aopPut (AOP (result), "a", offset);
6494                     }
6495                   else
6496                     emitcode ("xrl", "%s,a",
6497                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6498                 }
6499             }
6500         }
6501     }
6502   else
6503     {
6504       // left & result in different registers
6505       if (AOP_TYPE (result) == AOP_CRY)
6506         {
6507           // result = bit
6508           // if(size), result in bit
6509           // if(!size && ifx), conditional oper: if(left ^ right)
6510           symbol *tlbl = newiTempLabel (NULL);
6511           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6512           if (size)
6513             emitcode ("setb", "c");
6514           while (sizer--)
6515             {
6516               if ((AOP_TYPE (right) == AOP_LIT) &&
6517                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6518                 {
6519                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6520                 }
6521               else
6522                 {
6523                   if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6524                     emitcode ("xrl", "a,%s",
6525                               aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6526                   } else {
6527                     MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6528                     emitcode ("xrl", "a,%s",
6529                               aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6530                   }
6531                 }
6532               emitcode ("jnz", "%05d$", tlbl->key + 100);
6533               offset++;
6534             }
6535           if (size)
6536             {
6537               CLRC;
6538               emitcode ("", "%05d$:", tlbl->key + 100);
6539               outBitC (result);
6540             }
6541           else if (ifx)
6542             jmpTrueOrFalse (ifx, tlbl);
6543         }
6544       else
6545         for (; (size--); offset++)
6546           {
6547             // normal case
6548             // result = left & right
6549             if (AOP_TYPE (right) == AOP_LIT)
6550               {
6551                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6552                   {
6553                     aopPut (AOP (result),
6554                             aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6555                             offset);
6556                     continue;
6557                   }
6558                 D (emitcode (";", "better literal XOR.");
6559                   );
6560                 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6561                 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
6562                                                   FALSE, FALSE, FALSE));
6563               }
6564             else
6565               {
6566                 // faster than result <- left, anl result,right
6567                 // and better if result is SFR
6568                 if (AOP_TYPE (left) == AOP_ACC)
6569                   {
6570                     emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
6571                                                      FALSE, FALSE, FALSE));
6572                   }
6573                 else
6574                   {
6575                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6576                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6577                       {
6578                           emitcode("mov", "b,a");
6579                           rOp = "b";
6580                       }
6581                         
6582                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6583                       emitcode ("xrl", "a,%s", rOp);
6584                   }
6585               }
6586             aopPut (AOP (result), "a", offset);
6587           }
6588     }
6589
6590 release:
6591   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6592   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6593   freeAsmop (result, NULL, ic, TRUE);
6594 }
6595
6596 /*-----------------------------------------------------------------*/
6597 /* genInline - write the inline code out                           */
6598 /*-----------------------------------------------------------------*/
6599 static void
6600 genInline (iCode * ic)
6601 {
6602   char *buffer, *bp, *bp1;
6603
6604   D (emitcode (";", "genInline ");
6605     );
6606
6607   _G.inLine += (!options.asmpeep);
6608
6609   buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6610   strcpy (buffer, IC_INLINE (ic));
6611
6612   /* emit each line as a code */
6613   while (*bp)
6614     {
6615       if (*bp == '\n')
6616         {
6617           *bp++ = '\0';
6618           emitcode (bp1, "");
6619           bp1 = bp;
6620         }
6621       else
6622         {
6623           if (*bp == ':')
6624             {
6625               bp++;
6626               *bp = '\0';
6627               bp++;
6628               emitcode (bp1, "");
6629               bp1 = bp;
6630             }
6631           else
6632             bp++;
6633         }
6634     }
6635   if (bp1 != bp)
6636     emitcode (bp1, "");
6637   /*     emitcode("",buffer); */
6638   _G.inLine -= (!options.asmpeep);
6639 }
6640
6641 /*-----------------------------------------------------------------*/
6642 /* genRRC - rotate right with carry                                */
6643 /*-----------------------------------------------------------------*/
6644 static void
6645 genRRC (iCode * ic)
6646 {
6647   operand *left, *result;
6648   int size, offset = 0;
6649   char *l;
6650
6651   D (emitcode (";", "genRRC ");
6652     );
6653
6654   /* rotate right with carry */
6655   left = IC_LEFT (ic);
6656   result = IC_RESULT (ic);
6657   aopOp (left, ic, FALSE, FALSE);
6658   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6659
6660   /* move it to the result */
6661   size = AOP_SIZE (result);
6662   offset = size - 1;
6663   CLRC;
6664
6665   _startLazyDPSEvaluation ();
6666   while (size--)
6667     {
6668       l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6669       MOVA (l);
6670       emitcode ("rrc", "a");
6671       if (AOP_SIZE (result) > 1)
6672         aopPut (AOP (result), "a", offset--);
6673     }
6674   _endLazyDPSEvaluation ();
6675
6676   /* now we need to put the carry into the
6677      highest order byte of the result */
6678   if (AOP_SIZE (result) > 1)
6679     {
6680       l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
6681       MOVA (l);
6682     }
6683   emitcode ("mov", "acc.7,c");
6684   aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
6685   freeAsmop (left, NULL, ic, TRUE);
6686   freeAsmop (result, NULL, ic, TRUE);
6687 }
6688
6689 /*-----------------------------------------------------------------*/
6690 /* genRLC - generate code for rotate left with carry               */
6691 /*-----------------------------------------------------------------*/
6692 static void
6693 genRLC (iCode * ic)
6694 {
6695   operand *left, *result;
6696   int size, offset = 0;
6697   char *l;
6698
6699   D (emitcode (";", "genRLC ");
6700     );
6701
6702   /* rotate right with carry */
6703   left = IC_LEFT (ic);
6704   result = IC_RESULT (ic);
6705   aopOp (left, ic, FALSE, FALSE);
6706   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6707
6708   /* move it to the result */
6709   size = AOP_SIZE (result);
6710   offset = 0;
6711   if (size--)
6712     {
6713       l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6714       MOVA (l);
6715       emitcode ("add", "a,acc");
6716       if (AOP_SIZE (result) > 1)
6717         {
6718           aopPut (AOP (result), "a", offset++);
6719         }
6720
6721       _startLazyDPSEvaluation ();
6722       while (size--)
6723         {
6724           l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6725           MOVA (l);
6726           emitcode ("rlc", "a");
6727           if (AOP_SIZE (result) > 1)
6728             aopPut (AOP (result), "a", offset++);
6729         }
6730       _endLazyDPSEvaluation ();
6731     }
6732   /* now we need to put the carry into the
6733      highest order byte of the result */
6734   if (AOP_SIZE (result) > 1)
6735     {
6736       l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
6737       MOVA (l);
6738     }
6739   emitcode ("mov", "acc.0,c");
6740   aopPut (AOP (result), "a", 0);
6741   freeAsmop (left, NULL, ic, TRUE);
6742   freeAsmop (result, NULL, ic, TRUE);
6743 }
6744
6745 /*-----------------------------------------------------------------*/
6746 /* genGetHbit - generates code get highest order bit               */
6747 /*-----------------------------------------------------------------*/
6748 static void
6749 genGetHbit (iCode * ic)
6750 {
6751   operand *left, *result;
6752   left = IC_LEFT (ic);
6753   result = IC_RESULT (ic);
6754   aopOp (left, ic, FALSE, FALSE);
6755   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6756
6757   D (emitcode (";", "genGetHbit ");
6758     );
6759
6760   /* get the highest order byte into a */
6761   MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
6762   if (AOP_TYPE (result) == AOP_CRY)
6763     {
6764       emitcode ("rlc", "a");
6765       outBitC (result);
6766     }
6767   else
6768     {
6769       emitcode ("rl", "a");
6770       emitcode ("anl", "a,#0x01");
6771       outAcc (result);
6772     }
6773
6774
6775   freeAsmop (left, NULL, ic, TRUE);
6776   freeAsmop (result, NULL, ic, TRUE);
6777 }
6778
6779 /*-----------------------------------------------------------------*/
6780 /* AccRol - rotate left accumulator by known count                 */
6781 /*-----------------------------------------------------------------*/
6782 static void
6783 AccRol (int shCount)
6784 {
6785   shCount &= 0x0007;            // shCount : 0..7
6786
6787   switch (shCount)
6788     {
6789     case 0:
6790       break;
6791     case 1:
6792       emitcode ("rl", "a");
6793       break;
6794     case 2:
6795       emitcode ("rl", "a");
6796       emitcode ("rl", "a");
6797       break;
6798     case 3:
6799       emitcode ("swap", "a");
6800       emitcode ("rr", "a");
6801       break;
6802     case 4:
6803       emitcode ("swap", "a");
6804       break;
6805     case 5:
6806       emitcode ("swap", "a");
6807       emitcode ("rl", "a");
6808       break;
6809     case 6:
6810       emitcode ("rr", "a");
6811       emitcode ("rr", "a");
6812       break;
6813     case 7:
6814       emitcode ("rr", "a");
6815       break;
6816     }
6817 }
6818
6819 /*-----------------------------------------------------------------*/
6820 /* AccLsh - left shift accumulator by known count                  */
6821 /*-----------------------------------------------------------------*/
6822 static void
6823 AccLsh (int shCount)
6824 {
6825   if (shCount != 0)
6826     {
6827       if (shCount == 1)
6828         emitcode ("add", "a,acc");
6829       else if (shCount == 2)
6830         {
6831           emitcode ("add", "a,acc");
6832           emitcode ("add", "a,acc");
6833         }
6834       else
6835         {
6836           /* rotate left accumulator */
6837           AccRol (shCount);
6838           /* and kill the lower order bits */
6839           emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6840         }
6841     }
6842 }
6843
6844 /*-----------------------------------------------------------------*/
6845 /* AccRsh - right shift accumulator by known count                 */
6846 /*-----------------------------------------------------------------*/
6847 static void
6848 AccRsh (int shCount)
6849 {
6850   if (shCount != 0)
6851     {
6852       if (shCount == 1)
6853         {
6854           CLRC;
6855           emitcode ("rrc", "a");
6856         }
6857       else
6858         {
6859           /* rotate right accumulator */
6860           AccRol (8 - shCount);
6861           /* and kill the higher order bits */
6862           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6863         }
6864     }
6865 }
6866
6867 #ifdef BETTER_LITERAL_SHIFT
6868 /*-----------------------------------------------------------------*/
6869 /* AccSRsh - signed right shift accumulator by known count                 */
6870 /*-----------------------------------------------------------------*/
6871 static void
6872 AccSRsh (int shCount)
6873 {
6874   symbol *tlbl;
6875   if (shCount != 0)
6876     {
6877       if (shCount == 1)
6878         {
6879           emitcode ("mov", "c,acc.7");
6880           emitcode ("rrc", "a");
6881         }
6882       else if (shCount == 2)
6883         {
6884           emitcode ("mov", "c,acc.7");
6885           emitcode ("rrc", "a");
6886           emitcode ("mov", "c,acc.7");
6887           emitcode ("rrc", "a");
6888         }
6889       else
6890         {
6891           tlbl = newiTempLabel (NULL);
6892           /* rotate right accumulator */
6893           AccRol (8 - shCount);
6894           /* and kill the higher order bits */
6895           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6896           emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6897           emitcode ("orl", "a,#0x%02x",
6898                     (unsigned char) ~SRMask[shCount]);
6899           emitcode ("", "%05d$:", tlbl->key + 100);
6900         }
6901     }
6902 }
6903 #endif
6904
6905 #ifdef BETTER_LITERAL_SHIFT
6906 /*-----------------------------------------------------------------*/
6907 /* shiftR1Left2Result - shift right one byte from left to result   */
6908 /*-----------------------------------------------------------------*/
6909 static void
6910 shiftR1Left2Result (operand * left, int offl,
6911                     operand * result, int offr,
6912                     int shCount, int sign)
6913 {
6914   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6915   /* shift right accumulator */
6916   if (sign)
6917     AccSRsh (shCount);
6918   else
6919     AccRsh (shCount);
6920   aopPut (AOP (result), "a", offr);
6921 }
6922 #endif
6923
6924 #ifdef BETTER_LITERAL_SHIFT
6925 /*-----------------------------------------------------------------*/
6926 /* shiftL1Left2Result - shift left one byte from left to result    */
6927 /*-----------------------------------------------------------------*/
6928 static void
6929 shiftL1Left2Result (operand * left, int offl,
6930                     operand * result, int offr, int shCount)
6931 {
6932   MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6933   /* shift left accumulator */
6934   AccLsh (shCount);
6935   aopPut (AOP (result), "a", offr);
6936 }
6937 #endif
6938
6939 #ifdef BETTER_LITERAL_SHIFT
6940 /*-----------------------------------------------------------------*/
6941 /* movLeft2Result - move byte from left to result                  */
6942 /*-----------------------------------------------------------------*/
6943 static void
6944 movLeft2Result (operand * left, int offl,
6945                 operand * result, int offr, int sign)
6946 {
6947   char *l;
6948   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6949   {
6950       l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
6951
6952       if (*l == '@' && (IS_AOP_PREG (result)))
6953       {
6954           emitcode ("mov", "a,%s", l);
6955           aopPut (AOP (result), "a", offr);
6956       }
6957       else
6958       {
6959           if (!sign)
6960           {
6961             aopPut (AOP (result), l, offr);
6962           }
6963           else
6964             {
6965               /* MSB sign in acc.7 ! */
6966               if (getDataSize (left) == offl + 1)
6967                 {
6968                   emitcode ("mov", "a,%s", l);
6969                   aopPut (AOP (result), "a", offr);
6970                 }
6971             }
6972       }
6973   }
6974 }
6975 #endif
6976
6977 #ifdef BETTER_LITERAL_SHIFT
6978 /*-----------------------------------------------------------------*/
6979 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
6980 /*-----------------------------------------------------------------*/
6981 static void
6982 AccAXRrl1 (char *x)
6983 {
6984   emitcode ("rrc", "a");
6985   emitcode ("xch", "a,%s", x);
6986   emitcode ("rrc", "a");
6987   emitcode ("xch", "a,%s", x);
6988 }
6989 #endif
6990
6991 #ifdef BETTER_LITERAL_SHIFT
6992 //REMOVE ME!!!
6993 /*-----------------------------------------------------------------*/
6994 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
6995 /*-----------------------------------------------------------------*/
6996 static void
6997 AccAXLrl1 (char *x)
6998 {
6999   emitcode ("xch", "a,%s", x);
7000   emitcode ("rlc", "a");
7001   emitcode ("xch", "a,%s", x);
7002   emitcode ("rlc", "a");
7003 }
7004 #endif
7005
7006 #ifdef BETTER_LITERAL_SHIFT
7007 /*-----------------------------------------------------------------*/
7008 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
7009 /*-----------------------------------------------------------------*/
7010 static void
7011 AccAXLsh1 (char *x)
7012 {
7013   emitcode ("xch", "a,%s", x);
7014   emitcode ("add", "a,acc");
7015   emitcode ("xch", "a,%s", x);
7016   emitcode ("rlc", "a");
7017 }
7018 #endif
7019
7020 #ifdef BETTER_LITERAL_SHIFT
7021 /*-----------------------------------------------------------------*/
7022 /* AccAXLsh - left shift a:x by known count (0..7)                 */
7023 /*-----------------------------------------------------------------*/
7024 static void
7025 AccAXLsh (char *x, int shCount)
7026 {
7027   switch (shCount)
7028     {
7029     case 0:
7030       break;
7031     case 1:
7032       AccAXLsh1 (x);
7033       break;
7034     case 2:
7035       AccAXLsh1 (x);
7036       AccAXLsh1 (x);
7037       break;
7038     case 3:
7039     case 4:
7040     case 5:                     // AAAAABBB:CCCCCDDD
7041
7042       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
7043
7044       emitcode ("anl", "a,#0x%02x",
7045                 SLMask[shCount]);       // BBB00000:CCCCCDDD
7046
7047       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
7048
7049       AccRol (shCount);         // DDDCCCCC:BBB00000
7050
7051       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
7052
7053       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
7054
7055       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
7056
7057       emitcode ("anl", "a,#0x%02x",
7058                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
7059
7060       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
7061
7062       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
7063
7064       break;
7065     case 6:                     // AAAAAABB:CCCCCCDD
7066       emitcode ("anl", "a,#0x%02x",
7067                 SRMask[shCount]);       // 000000BB:CCCCCCDD
7068       emitcode ("mov", "c,acc.0");      // c = B
7069       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
7070 #if 0
7071       AccAXRrl1 (x);            // BCCCCCCD:D000000B
7072       AccAXRrl1 (x);            // BBCCCCCC:DD000000
7073 #else
7074       emitcode("rrc","a"); 
7075       emitcode("xch","a,%s", x); 
7076       emitcode("rrc","a"); 
7077       emitcode("mov","c,acc.0"); //<< get correct bit 
7078       emitcode("xch","a,%s", x); 
7079
7080       emitcode("rrc","a"); 
7081       emitcode("xch","a,%s", x); 
7082       emitcode("rrc","a"); 
7083       emitcode("xch","a,%s", x); 
7084 #endif
7085       break;
7086     case 7:                     // a:x <<= 7
7087
7088       emitcode ("anl", "a,#0x%02x",
7089                 SRMask[shCount]);       // 0000000B:CCCCCCCD
7090
7091       emitcode ("mov", "c,acc.0");      // c = B
7092
7093       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
7094
7095       AccAXRrl1 (x);            // BCCCCCCC:D0000000
7096
7097       break;
7098     default:
7099       break;
7100     }
7101 }
7102 #endif
7103
7104 #ifdef BETTER_LITERAL_SHIFT
7105 //REMOVE ME!!!
7106 /*-----------------------------------------------------------------*/
7107 /* AccAXRsh - right shift a:x known count (0..7)                   */
7108 /*-----------------------------------------------------------------*/
7109 static void
7110 AccAXRsh (char *x, int shCount)
7111 {
7112   switch (shCount)
7113     {
7114     case 0:
7115       break;
7116     case 1:
7117       CLRC;
7118       AccAXRrl1 (x);            // 0->a:x
7119
7120       break;
7121     case 2:
7122       CLRC;
7123       AccAXRrl1 (x);            // 0->a:x
7124
7125       CLRC;
7126       AccAXRrl1 (x);            // 0->a:x
7127
7128       break;
7129     case 3:
7130     case 4:
7131     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7132
7133       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
7134
7135       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7136
7137       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7138
7139       emitcode ("anl", "a,#0x%02x",
7140                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7141
7142       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7143
7144       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7145
7146       emitcode ("anl", "a,#0x%02x",
7147                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7148
7149       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7150
7151       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7152
7153       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
7154
7155       break;
7156     case 6:                     // AABBBBBB:CCDDDDDD
7157
7158       emitcode ("mov", "c,acc.7");
7159       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7160
7161       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7162
7163       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7164
7165       emitcode ("anl", "a,#0x%02x",
7166                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7167
7168       break;
7169     case 7:                     // ABBBBBBB:CDDDDDDD
7170
7171       emitcode ("mov", "c,acc.7");      // c = A
7172
7173       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7174
7175       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7176
7177       emitcode ("anl", "a,#0x%02x",
7178                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7179
7180       break;
7181     default:
7182       break;
7183     }
7184 }
7185 #endif
7186
7187 #ifdef BETTER_LITERAL_SHIFT
7188 /*-----------------------------------------------------------------*/
7189 /* AccAXRshS - right shift signed a:x known count (0..7)           */
7190 /*-----------------------------------------------------------------*/
7191 static void
7192 AccAXRshS (char *x, int shCount)
7193 {
7194   symbol *tlbl;
7195   switch (shCount)
7196     {
7197     case 0:
7198       break;
7199     case 1:
7200       emitcode ("mov", "c,acc.7");
7201       AccAXRrl1 (x);            // s->a:x
7202
7203       break;
7204     case 2:
7205       emitcode ("mov", "c,acc.7");
7206       AccAXRrl1 (x);            // s->a:x
7207
7208       emitcode ("mov", "c,acc.7");
7209       AccAXRrl1 (x);            // s->a:x
7210
7211       break;
7212     case 3:
7213     case 4:
7214     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7215
7216       tlbl = newiTempLabel (NULL);
7217       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
7218
7219       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7220
7221       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7222
7223       emitcode ("anl", "a,#0x%02x",
7224                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7225
7226       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7227
7228       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7229
7230       emitcode ("anl", "a,#0x%02x",
7231                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7232
7233       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7234
7235       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7236
7237       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
7238
7239       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7240       emitcode ("orl", "a,#0x%02x",
7241                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
7242
7243       emitcode ("", "%05d$:", tlbl->key + 100);
7244       break;                    // SSSSAAAA:BBBCCCCC
7245
7246     case 6:                     // AABBBBBB:CCDDDDDD
7247
7248       tlbl = newiTempLabel (NULL);
7249       emitcode ("mov", "c,acc.7");
7250       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7251
7252       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7253
7254       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7255
7256       emitcode ("anl", "a,#0x%02x",
7257                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7258
7259       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7260       emitcode ("orl", "a,#0x%02x",
7261                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
7262
7263       emitcode ("", "%05d$:", tlbl->key + 100);
7264       break;
7265     case 7:                     // ABBBBBBB:CDDDDDDD
7266
7267       tlbl = newiTempLabel (NULL);
7268       emitcode ("mov", "c,acc.7");      // c = A
7269
7270       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7271
7272       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7273
7274       emitcode ("anl", "a,#0x%02x",
7275                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7276
7277       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7278       emitcode ("orl", "a,#0x%02x",
7279                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
7280
7281       emitcode ("", "%05d$:", tlbl->key + 100);
7282       break;
7283     default:
7284       break;
7285     }
7286 }
7287 #endif
7288
7289 #ifdef BETTER_LITERAL_SHIFT
7290 static void
7291 _loadLeftIntoAx(char    **lsb, 
7292                 operand *left, 
7293                 operand *result,
7294                 int     offl,
7295                 int     offr)
7296 {
7297   // Get the initial value from left into a pair of registers.
7298   // MSB must be in A, LSB can be any register.
7299   //
7300   // If the result is held in registers, it is an optimization
7301   // if the LSB can be held in the register which will hold the,
7302   // result LSB since this saves us from having to copy it into
7303   // the result following AccAXLsh.
7304   //
7305   // If the result is addressed indirectly, this is not a gain.
7306   if (AOP_NEEDSACC(result))
7307   {
7308        char *leftByte;
7309        
7310        _startLazyDPSEvaluation();
7311       if (AOP_TYPE(left) == AOP_DPTR2)
7312        {
7313            // Get MSB in A.
7314            MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
7315            // get LSB in DP2_RESULT_REG.
7316            leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
7317            assert(!strcmp(leftByte, DP2_RESULT_REG));
7318        }
7319        else
7320        {
7321            // get LSB into DP2_RESULT_REG
7322            leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
7323            if (strcmp(leftByte, DP2_RESULT_REG))
7324            {
7325                TR_AP("#7");
7326                emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7327            }
7328            // And MSB in A.
7329            leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
7330            assert(strcmp(leftByte, DP2_RESULT_REG));
7331            MOVA(leftByte);
7332        }
7333        _endLazyDPSEvaluation();
7334        *lsb = DP2_RESULT_REG;
7335   }
7336   else
7337   {
7338       if (sameRegs (AOP (result), AOP (left)) &&
7339         ((offl + MSB16) == offr))
7340       {
7341           /* don't crash result[offr] */
7342           MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
7343           emitcode ("xch", "a,%s", 
7344                     aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
7345       }
7346       else
7347       {
7348           movLeft2Result (left, offl, result, offr, 0);
7349           MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
7350       }
7351       *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
7352       assert(strcmp(*lsb,"a"));      
7353   }
7354 }
7355
7356 static void
7357 _storeAxResults(char    *lsb,
7358                 operand *result,
7359                 int     offr)
7360 {
7361   _startLazyDPSEvaluation();
7362   if (AOP_NEEDSACC(result))
7363   {
7364       /* We have to explicitly update the result LSB.
7365        */
7366       emitcode("xch","a,%s", lsb);
7367       aopPut(AOP(result), "a", offr);
7368       emitcode("mov","a,%s", lsb);
7369   }
7370   if (getDataSize (result) > 1)
7371   {
7372       aopPut (AOP (result), "a", offr + MSB16);
7373   }
7374   _endLazyDPSEvaluation();
7375 }
7376
7377 /*-----------------------------------------------------------------*/
7378 /* shiftL2Left2Result - shift left two bytes from left to result   */
7379 /*-----------------------------------------------------------------*/
7380 static void
7381 shiftL2Left2Result (operand * left, int offl,
7382                     operand * result, int offr, int shCount)
7383 {
7384   char *lsb;
7385
7386   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7387   
7388   AccAXLsh (lsb, shCount);
7389   
7390   _storeAxResults(lsb, result, offr);
7391 }
7392 #endif
7393
7394 #ifdef BETTER_LITERAL_SHIFT
7395 /*-----------------------------------------------------------------*/
7396 /* shiftR2Left2Result - shift right two bytes from left to result  */
7397 /*-----------------------------------------------------------------*/
7398 static void
7399 shiftR2Left2Result (operand * left, int offl,
7400                     operand * result, int offr,
7401                     int shCount, int sign)
7402 {
7403   char *lsb;
7404   
7405   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7406   
7407   /* a:x >> shCount (x = lsb(result)) */
7408   if (sign)
7409   {
7410      AccAXRshS(lsb, shCount);
7411   }
7412   else
7413   {
7414     AccAXRsh(lsb, shCount);
7415   }
7416   
7417   _storeAxResults(lsb, result, offr);
7418 }
7419 #endif
7420
7421 #if 0
7422 //REMOVE ME!!!
7423 /*-----------------------------------------------------------------*/
7424 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7425 /*-----------------------------------------------------------------*/
7426 static void
7427 shiftLLeftOrResult (operand * left, int offl,
7428                     operand * result, int offr, int shCount)
7429 {
7430   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7431   /* shift left accumulator */
7432   AccLsh (shCount);
7433   /* or with result */
7434   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7435   /* back to result */
7436   aopPut (AOP (result), "a", offr);
7437 }
7438 #endif
7439
7440 #if 0
7441 //REMOVE ME!!!
7442 /*-----------------------------------------------------------------*/
7443 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7444 /*-----------------------------------------------------------------*/
7445 static void
7446 shiftRLeftOrResult (operand * left, int offl,
7447                     operand * result, int offr, int shCount)
7448 {
7449   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7450   /* shift right accumulator */
7451   AccRsh (shCount);
7452   /* or with result */
7453   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7454   /* back to result */
7455   aopPut (AOP (result), "a", offr);
7456 }
7457 #endif
7458
7459 #ifdef BETTER_LITERAL_SHIFT
7460 /*-----------------------------------------------------------------*/
7461 /* genlshOne - left shift a one byte quantity by known count       */
7462 /*-----------------------------------------------------------------*/
7463 static void
7464 genlshOne (operand * result, operand * left, int shCount)
7465 {
7466   D (emitcode (";", "genlshOne "););
7467   shiftL1Left2Result (left, LSB, result, LSB, shCount);
7468 }
7469 #endif
7470
7471 #ifdef BETTER_LITERAL_SHIFT
7472 /*-----------------------------------------------------------------*/
7473 /* genlshTwo - left shift two bytes by known amount != 0           */
7474 /*-----------------------------------------------------------------*/
7475 static void
7476 genlshTwo (operand * result, operand * left, int shCount)
7477 {
7478   int size;
7479
7480   D (emitcode (";", "genlshTwo "););
7481
7482   size = getDataSize (result);
7483
7484   /* if shCount >= 8 */
7485   if (shCount >= 8)
7486   {
7487       shCount -= 8;
7488
7489       _startLazyDPSEvaluation();
7490
7491       if (size > 1)
7492         {
7493           if (shCount)
7494           {
7495             _endLazyDPSEvaluation();
7496             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7497             aopPut (AOP (result), zero, LSB);       
7498           }
7499           else
7500           {
7501             movLeft2Result (left, LSB, result, MSB16, 0);
7502             aopPut (AOP (result), zero, LSB);
7503             _endLazyDPSEvaluation();
7504           }
7505         }
7506         else
7507         {
7508           aopPut (AOP (result), zero, LSB);
7509           _endLazyDPSEvaluation();
7510         }
7511   }
7512
7513   /*  1 <= shCount <= 7 */
7514   else
7515     {
7516       if (size == 1)
7517       {
7518         shiftL1Left2Result (left, LSB, result, LSB, shCount);
7519       }
7520       else
7521       {
7522         shiftL2Left2Result (left, LSB, result, LSB, shCount);
7523       }
7524     }
7525 }
7526 #endif
7527
7528 #if 0
7529 //REMOVE ME!!!
7530 /*-----------------------------------------------------------------*/
7531 /* shiftLLong - shift left one long from left to result            */
7532 /* offl = LSB or MSB16                                             */
7533 /*-----------------------------------------------------------------*/
7534 static void
7535 shiftLLong (operand * left, operand * result, int offr)
7536 {
7537   char *l;
7538   int size = AOP_SIZE (result);
7539
7540   if (size >= LSB + offr)
7541     {
7542       l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
7543       MOVA (l);
7544       emitcode ("add", "a,acc");
7545       if (sameRegs (AOP (left), AOP (result)) &&
7546           size >= MSB16 + offr && offr != LSB)
7547         emitcode ("xch", "a,%s",
7548                   aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
7549       else
7550         aopPut (AOP (result), "a", LSB + offr);
7551     }
7552
7553   if (size >= MSB16 + offr)
7554     {
7555       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7556         {
7557           l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
7558           MOVA (l);
7559         }
7560       emitcode ("rlc", "a");
7561       if (sameRegs (AOP (left), AOP (result)) &&
7562           size >= MSB24 + offr && offr != LSB)
7563         emitcode ("xch", "a,%s",
7564                   aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
7565       else
7566         aopPut (AOP (result), "a", MSB16 + offr);
7567     }
7568
7569   if (size >= MSB24 + offr)
7570     {
7571       if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7572         {
7573           l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
7574           MOVA (l);
7575         }
7576       emitcode ("rlc", "a");
7577       if (sameRegs (AOP (left), AOP (result)) &&
7578           size >= MSB32 + offr && offr != LSB)
7579         emitcode ("xch", "a,%s",
7580                   aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
7581       else
7582         aopPut (AOP (result), "a", MSB24 + offr);
7583     }
7584
7585   if (size > MSB32 + offr)
7586     {
7587       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7588         {
7589           l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
7590           MOVA (l);
7591         }
7592       emitcode ("rlc", "a");
7593       aopPut (AOP (result), "a", MSB32 + offr);
7594     }
7595   if (offr != LSB)
7596     aopPut (AOP (result), zero, LSB);
7597 }
7598 #endif
7599
7600 #if 0
7601 //REMOVE ME!!!
7602 /*-----------------------------------------------------------------*/
7603 /* genlshFour - shift four byte by a known amount != 0             */
7604 /*-----------------------------------------------------------------*/
7605 static void
7606 genlshFour (operand * result, operand * left, int shCount)
7607 {
7608   int size;
7609
7610   D (emitcode (";", "genlshFour ");
7611     );
7612
7613   size = AOP_SIZE (result);
7614
7615   /* if shifting more that 3 bytes */
7616   if (shCount >= 24)
7617     {
7618       shCount -= 24;
7619       if (shCount)
7620         /* lowest order of left goes to the highest
7621            order of the destination */
7622         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7623       else
7624         movLeft2Result (left, LSB, result, MSB32, 0);
7625       aopPut (AOP (result), zero, LSB);
7626       aopPut (AOP (result), zero, MSB16);
7627       aopPut (AOP (result), zero, MSB24);
7628       return;
7629     }
7630
7631   /* more than two bytes */
7632   else if (shCount >= 16)
7633     {
7634       /* lower order two bytes goes to higher order two bytes */
7635       shCount -= 16;
7636       /* if some more remaining */
7637       if (shCount)
7638         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7639       else
7640         {
7641           movLeft2Result (left, MSB16, result, MSB32, 0);
7642           movLeft2Result (left, LSB, result, MSB24, 0);
7643         }
7644       aopPut (AOP (result), zero, MSB16);
7645       aopPut (AOP (result), zero, LSB);
7646       return;
7647     }
7648
7649   /* if more than 1 byte */
7650   else if (shCount >= 8)
7651     {
7652       /* lower order three bytes goes to higher order  three bytes */
7653       shCount -= 8;
7654       if (size == 2)
7655         {
7656           if (shCount)
7657             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7658           else
7659             movLeft2Result (left, LSB, result, MSB16, 0);
7660         }
7661       else
7662         {                       /* size = 4 */
7663           if (shCount == 0)
7664             {
7665               movLeft2Result (left, MSB24, result, MSB32, 0);
7666               movLeft2Result (left, MSB16, result, MSB24, 0);
7667               movLeft2Result (left, LSB, result, MSB16, 0);
7668               aopPut (AOP (result), zero, LSB);
7669             }
7670           else if (shCount == 1)
7671             shiftLLong (left, result, MSB16);
7672           else
7673             {
7674               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7675               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7676               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7677               aopPut (AOP (result), zero, LSB);
7678             }
7679         }
7680     }
7681
7682   /* 1 <= shCount <= 7 */
7683   else if (shCount <= 2)
7684     {
7685       shiftLLong (left, result, LSB);
7686       if (shCount == 2)
7687         shiftLLong (result, result, LSB);
7688     }
7689   /* 3 <= shCount <= 7, optimize */
7690   else
7691     {
7692       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7693       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7694       shiftL2Left2Result (left, LSB, result, LSB, shCount);
7695     }
7696 }
7697 #endif
7698
7699 #ifdef BETTER_LITERAL_SHIFT
7700 /*-----------------------------------------------------------------*/
7701 /* genLeftShiftLiteral - left shifting by known count              */
7702 /*-----------------------------------------------------------------*/
7703 static bool
7704 genLeftShiftLiteral (operand * left,
7705                      operand * right,
7706                      operand * result,
7707                      iCode * ic)
7708 {
7709   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7710   int size;
7711
7712   size = getSize (operandType (result));
7713
7714   D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
7715
7716   /* We only handle certain easy cases so far. */
7717   if ((shCount != 0)
7718    && (shCount < (size * 8))
7719    && (size != 1)
7720    && (size != 2))
7721   {
7722       D(emitcode (";", "genLeftShiftLiteral wimping out"););    
7723       return FALSE;
7724   }
7725
7726   freeAsmop (right, NULL, ic, TRUE);
7727
7728   aopOp(left, ic, FALSE, FALSE);
7729   aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
7730
7731 #if 1 // debug spew
7732   if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
7733   {
7734         emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
7735         if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
7736         {
7737            emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
7738         }
7739   }
7740   if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
7741   {
7742         emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
7743         if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
7744         {
7745            emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
7746         }       
7747   }  
7748 #endif
7749   
7750 #if VIEW_SIZE
7751   emitcode ("; shift left ", "result %d, left %d", size,
7752             AOP_SIZE (left));
7753 #endif
7754
7755   /* I suppose that the left size >= result size */
7756   if (shCount == 0)
7757   {
7758         _startLazyDPSEvaluation();
7759         while (size--)
7760         {
7761           movLeft2Result (left, size, result, size, 0);
7762         }
7763         _endLazyDPSEvaluation();
7764   }
7765   else if (shCount >= (size * 8))
7766   {
7767     _startLazyDPSEvaluation();
7768     while (size--)
7769     {
7770       aopPut (AOP (result), zero, size);
7771     }
7772     _endLazyDPSEvaluation();
7773   }
7774   else
7775   {
7776       switch (size)
7777         {
7778         case 1:
7779           genlshOne (result, left, shCount);
7780           break;
7781
7782         case 2:
7783           genlshTwo (result, left, shCount);
7784           break;
7785 #if 0
7786         case 4:
7787           genlshFour (result, left, shCount);
7788           break;
7789 #endif
7790         default:
7791           fprintf(stderr, "*** ack! mystery literal shift!\n");   
7792           break;
7793         }
7794     }
7795   freeAsmop (left, NULL, ic, TRUE);
7796   freeAsmop (result, NULL, ic, TRUE);
7797   return TRUE;
7798 }
7799 #endif
7800
7801 /*-----------------------------------------------------------------*/
7802 /* genLeftShift - generates code for left shifting                 */
7803 /*-----------------------------------------------------------------*/
7804 static void
7805 genLeftShift (iCode * ic)
7806 {
7807   operand *left, *right, *result;
7808   int size, offset;
7809   char *l;
7810   symbol *tlbl, *tlbl1;
7811
7812   D (emitcode (";", "genLeftShift "););
7813
7814   right = IC_RIGHT (ic);
7815   left = IC_LEFT (ic);
7816   result = IC_RESULT (ic);
7817
7818   aopOp (right, ic, FALSE, FALSE);
7819
7820
7821 #ifdef BETTER_LITERAL_SHIFT
7822   /* if the shift count is known then do it
7823      as efficiently as possible */
7824   if (AOP_TYPE (right) == AOP_LIT)
7825     {
7826       if (genLeftShiftLiteral (left, right, result, ic))
7827       {
7828         return;
7829       }
7830     }
7831 #endif
7832
7833   /* shift count is unknown then we have to form
7834      a loop get the loop count in B : Note: we take
7835      only the lower order byte since shifting
7836      more that 32 bits make no sense anyway, ( the
7837      largest size of an object can be only 32 bits ) */
7838
7839   if (AOP_TYPE (right) == AOP_LIT)
7840   {
7841       /* Really should be handled by genLeftShiftLiteral,
7842        * but since I'm too lazy to fix that today, at least we can make
7843        * some small improvement.
7844        */
7845        emitcode("mov", "b,#0x%02x",
7846                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7847   }
7848   else
7849   {
7850         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7851         emitcode ("inc", "b");
7852   }
7853   freeAsmop (right, NULL, ic, TRUE);
7854   aopOp (left, ic, FALSE, FALSE);
7855   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7856
7857   /* now move the left to the result if they are not the
7858      same */
7859   if (!sameRegs (AOP (left), AOP (result)) &&
7860       AOP_SIZE (result) > 1)
7861     {
7862
7863       size = AOP_SIZE (result);
7864       offset = 0;
7865       _startLazyDPSEvaluation ();
7866       while (size--)
7867         {
7868           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7869           if (*l == '@' && (IS_AOP_PREG (result)))
7870             {
7871
7872               emitcode ("mov", "a,%s", l);
7873               aopPut (AOP (result), "a", offset);
7874             }
7875           else
7876             aopPut (AOP (result), l, offset);
7877           offset++;
7878         }
7879       _endLazyDPSEvaluation ();
7880     }
7881
7882   tlbl = newiTempLabel (NULL);
7883   size = AOP_SIZE (result);
7884   offset = 0;
7885   tlbl1 = newiTempLabel (NULL);
7886
7887   /* if it is only one byte then */
7888   if (size == 1)
7889     {
7890       symbol *tlbl1 = newiTempLabel (NULL);
7891
7892       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7893       MOVA (l);
7894       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7895       emitcode ("", "%05d$:", tlbl->key + 100);
7896       emitcode ("add", "a,acc");
7897       emitcode ("", "%05d$:", tlbl1->key + 100);
7898       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7899       aopPut (AOP (result), "a", 0);
7900       goto release;
7901     }
7902
7903   reAdjustPreg (AOP (result));
7904
7905   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7906   emitcode ("", "%05d$:", tlbl->key + 100);
7907   l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7908   MOVA (l);
7909   emitcode ("add", "a,acc");
7910   aopPut (AOP (result), "a", offset++);
7911   _startLazyDPSEvaluation ();
7912   while (--size)
7913     {
7914       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7915       MOVA (l);
7916       emitcode ("rlc", "a");
7917       aopPut (AOP (result), "a", offset++);
7918     }
7919   _endLazyDPSEvaluation ();
7920   reAdjustPreg (AOP (result));
7921
7922   emitcode ("", "%05d$:", tlbl1->key + 100);
7923   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7924 release:
7925   freeAsmop (left, NULL, ic, TRUE);
7926   freeAsmop (result, NULL, ic, TRUE);
7927 }
7928
7929 #ifdef BETTER_LITERAL_SHIFT
7930 /*-----------------------------------------------------------------*/
7931 /* genrshOne - right shift a one byte quantity by known count      */
7932 /*-----------------------------------------------------------------*/
7933 static void
7934 genrshOne (operand * result, operand * left,
7935            int shCount, int sign)
7936 {
7937   D (emitcode (";", "genrshOne"););
7938   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7939 }
7940 #endif
7941
7942 #ifdef BETTER_LITERAL_SHIFT
7943 /*-----------------------------------------------------------------*/
7944 /* genrshTwo - right shift two bytes by known amount != 0          */
7945 /*-----------------------------------------------------------------*/
7946 static void
7947 genrshTwo (operand * result, operand * left,
7948            int shCount, int sign)
7949 {
7950   D (emitcode (";", "genrshTwo"););
7951
7952   /* if shCount >= 8 */
7953   if (shCount >= 8)
7954     {
7955       shCount -= 8;
7956       _startLazyDPSEvaluation();
7957       if (shCount)
7958       {
7959         shiftR1Left2Result (left, MSB16, result, LSB,
7960                             shCount, sign);
7961       }                     
7962       else
7963       {
7964         movLeft2Result (left, MSB16, result, LSB, sign);
7965       }
7966       addSign (result, MSB16, sign);
7967       _endLazyDPSEvaluation();
7968     }
7969
7970   /*  1 <= shCount <= 7 */
7971   else
7972   {
7973     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7974   }
7975 }
7976 #endif
7977
7978 #if 0
7979 //REMOVE ME!!!
7980 /*-----------------------------------------------------------------*/
7981 /* shiftRLong - shift right one long from left to result           */
7982 /* offl = LSB or MSB16                                             */
7983 /*-----------------------------------------------------------------*/
7984 static void
7985 shiftRLong (operand * left, int offl,
7986             operand * result, int sign)
7987 {
7988   int isSameRegs=sameRegs(AOP(left),AOP(result));
7989
7990   if (isSameRegs && offl>1) {
7991     // we are in big trouble, but this shouldn't happen
7992     werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
7993   }
7994
7995   MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7996   
7997   if (offl==MSB16) {
7998     // shift is > 8
7999     if (sign) {
8000       emitcode ("rlc", "a");
8001       emitcode ("subb", "a,acc");
8002       emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
8003     } else {
8004       aopPut (AOP(result), zero, MSB32);
8005     }
8006   }
8007
8008   if (!sign) {
8009     emitcode ("clr", "c");
8010   } else {
8011     emitcode ("mov", "c,acc.7");
8012   }
8013
8014   emitcode ("rrc", "a");
8015
8016   if (isSameRegs && offl==MSB16) {
8017     emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
8018   } else {
8019     aopPut (AOP (result), "a", MSB32);
8020     MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
8021   }
8022
8023   emitcode ("rrc", "a");
8024   if (isSameRegs && offl==1) {
8025     emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
8026   } else {
8027     aopPut (AOP (result), "a", MSB24);
8028     MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
8029   }
8030   emitcode ("rrc", "a");
8031   aopPut (AOP (result), "a", MSB16 - offl);
8032
8033   if (offl == LSB)
8034     {
8035       MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
8036       emitcode ("rrc", "a");
8037       aopPut (AOP (result), "a", LSB);
8038     }
8039 }
8040 #endif
8041
8042 #if 0
8043 //REMOVE ME!!!
8044 /*-----------------------------------------------------------------*/
8045 /* genrshFour - shift four byte by a known amount != 0             */
8046 /*-----------------------------------------------------------------*/
8047 static void
8048 genrshFour (operand * result, operand * left,
8049             int shCount, int sign)
8050 {
8051   D (emitcode (";", "genrshFour");
8052     );
8053
8054   /* if shifting more that 3 bytes */
8055   if (shCount >= 24)
8056     {
8057       shCount -= 24;
8058       if (shCount)
8059         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8060       else
8061         movLeft2Result (left, MSB32, result, LSB, sign);
8062       addSign (result, MSB16, sign);
8063     }
8064   else if (shCount >= 16)
8065     {
8066       shCount -= 16;
8067       if (shCount)
8068         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8069       else
8070         {
8071           movLeft2Result (left, MSB24, result, LSB, 0);
8072           movLeft2Result (left, MSB32, result, MSB16, sign);
8073         }
8074       addSign (result, MSB24, sign);
8075     }
8076   else if (shCount >= 8)
8077     {
8078       shCount -= 8;
8079       if (shCount == 1)
8080         shiftRLong (left, MSB16, result, sign);
8081       else if (shCount == 0)
8082         {
8083           movLeft2Result (left, MSB16, result, LSB, 0);
8084           movLeft2Result (left, MSB24, result, MSB16, 0);
8085           movLeft2Result (left, MSB32, result, MSB24, sign);
8086           addSign (result, MSB32, sign);
8087         }
8088       else
8089         {
8090           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8091           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8092           /* the last shift is signed */
8093           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8094           addSign (result, MSB32, sign);
8095         }
8096     }
8097   else
8098     {                           /* 1 <= shCount <= 7 */
8099       if (shCount <= 2)
8100         {
8101           shiftRLong (left, LSB, result, sign);
8102           if (shCount == 2)
8103             shiftRLong (result, LSB, result, sign);
8104         }
8105       else
8106         {
8107           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8108           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8109           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8110         }
8111     }
8112 }
8113 #endif
8114
8115 #ifdef BETTER_LITERAL_SHIFT
8116 /*-----------------------------------------------------------------*/
8117 /* genRightShiftLiteral - right shifting by known count            */
8118 /*-----------------------------------------------------------------*/
8119 static bool
8120 genRightShiftLiteral (operand * left,
8121                       operand * right,
8122                       operand * result,
8123                       iCode * ic,
8124                       int sign)
8125 {
8126   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8127   int size;
8128
8129   size = getSize (operandType (result));
8130
8131   D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8132
8133   /* We only handle certain easy cases so far. */
8134   if ((shCount != 0)
8135    && (shCount < (size * 8))
8136    && (size != 1)
8137    && (size != 2))
8138   {
8139       D(emitcode (";", "genRightShiftLiteral wimping out"););   
8140       return FALSE;
8141   }
8142
8143   freeAsmop (right, NULL, ic, TRUE);
8144
8145   aopOp (left, ic, FALSE, FALSE);
8146   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8147
8148 #if VIEW_SIZE
8149   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8150             AOP_SIZE (left));
8151 #endif
8152
8153   /* test the LEFT size !!! */
8154
8155   /* I suppose that the left size >= result size */
8156   if (shCount == 0)
8157   {
8158       size = getDataSize (result);
8159       _startLazyDPSEvaluation();
8160       while (size--)
8161       {
8162         movLeft2Result (left, size, result, size, 0);
8163       }
8164       _endLazyDPSEvaluation();
8165   }
8166   else if (shCount >= (size * 8))
8167     {
8168       if (sign)
8169       {
8170         /* get sign in acc.7 */
8171         MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
8172       }
8173       addSign (result, LSB, sign);
8174     }
8175   else
8176     {
8177       switch (size)
8178         {
8179         case 1:
8180           genrshOne (result, left, shCount, sign);
8181           break;
8182
8183         case 2:
8184           genrshTwo (result, left, shCount, sign);
8185           break;
8186 #if 0
8187         case 4:
8188           genrshFour (result, left, shCount, sign);
8189           break;
8190 #endif    
8191         default:
8192           break;
8193         }
8194
8195       freeAsmop (left, NULL, ic, TRUE);
8196       freeAsmop (result, NULL, ic, TRUE);
8197     }
8198     return TRUE;
8199 }
8200 #endif
8201
8202 /*-----------------------------------------------------------------*/
8203 /* genSignedRightShift - right shift of signed number              */
8204 /*-----------------------------------------------------------------*/
8205 static void
8206 genSignedRightShift (iCode * ic)
8207 {
8208   operand *right, *left, *result;
8209   int size, offset;
8210   char *l;
8211   symbol *tlbl, *tlbl1;
8212
8213   D (emitcode (";", "genSignedRightShift "););
8214
8215   /* we do it the hard way put the shift count in b
8216      and loop thru preserving the sign */
8217
8218   right = IC_RIGHT (ic);
8219   left = IC_LEFT (ic);
8220   result = IC_RESULT (ic);
8221
8222   aopOp (right, ic, FALSE, FALSE);
8223
8224 #ifdef BETTER_LITERAL_SHIFT
8225   if (AOP_TYPE (right) == AOP_LIT)
8226     {
8227       if (genRightShiftLiteral (left, right, result, ic, 1))
8228       {
8229         return;
8230       }
8231     }
8232 #endif
8233   /* shift count is unknown then we have to form
8234      a loop get the loop count in B : Note: we take
8235      only the lower order byte since shifting
8236      more that 32 bits make no sense anyway, ( the
8237      largest size of an object can be only 32 bits ) */
8238
8239   if (AOP_TYPE (right) == AOP_LIT)
8240   {
8241       /* Really should be handled by genRightShiftLiteral,
8242        * but since I'm too lazy to fix that today, at least we can make
8243        * some small improvement.
8244        */
8245        emitcode("mov", "b,#0x%02x",
8246                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8247   }
8248   else
8249   {
8250         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8251         emitcode ("inc", "b");
8252   }
8253   freeAsmop (right, NULL, ic, TRUE);
8254   aopOp (left, ic, FALSE, FALSE);
8255   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8256
8257   /* now move the left to the result if they are not the
8258      same */
8259   if (!sameRegs (AOP (left), AOP (result)) &&
8260       AOP_SIZE (result) > 1)
8261     {
8262
8263       size = AOP_SIZE (result);
8264       offset = 0;
8265       _startLazyDPSEvaluation ();
8266       while (size--)
8267         {
8268           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8269           if (*l == '@' && IS_AOP_PREG (result))
8270             {
8271
8272               emitcode ("mov", "a,%s", l);
8273               aopPut (AOP (result), "a", offset);
8274             }
8275           else
8276             aopPut (AOP (result), l, offset);
8277           offset++;
8278         }
8279       _endLazyDPSEvaluation ();
8280     }
8281
8282   /* mov the highest order bit to OVR */
8283   tlbl = newiTempLabel (NULL);
8284   tlbl1 = newiTempLabel (NULL);
8285
8286   size = AOP_SIZE (result);
8287   offset = size - 1;
8288   emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
8289   emitcode ("rlc", "a");
8290   emitcode ("mov", "ov,c");
8291   /* if it is only one byte then */
8292   if (size == 1)
8293     {
8294       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8295       MOVA (l);
8296       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8297       emitcode ("", "%05d$:", tlbl->key + 100);
8298       emitcode ("mov", "c,ov");
8299       emitcode ("rrc", "a");
8300       emitcode ("", "%05d$:", tlbl1->key + 100);
8301       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8302       aopPut (AOP (result), "a", 0);
8303       goto release;
8304     }
8305
8306   reAdjustPreg (AOP (result));
8307   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8308   emitcode ("", "%05d$:", tlbl->key + 100);
8309   emitcode ("mov", "c,ov");
8310   _startLazyDPSEvaluation ();
8311   while (size--)
8312     {
8313       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8314       MOVA (l);
8315       emitcode ("rrc", "a");
8316       aopPut (AOP (result), "a", offset--);
8317     }
8318   _endLazyDPSEvaluation ();
8319   reAdjustPreg (AOP (result));
8320   emitcode ("", "%05d$:", tlbl1->key + 100);
8321   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8322
8323 release:
8324   freeAsmop (left, NULL, ic, TRUE);
8325   freeAsmop (result, NULL, ic, TRUE);
8326 }
8327
8328 /*-----------------------------------------------------------------*/
8329 /* genRightShift - generate code for right shifting                */
8330 /*-----------------------------------------------------------------*/
8331 static void
8332 genRightShift (iCode * ic)
8333 {
8334   operand *right, *left, *result;
8335   sym_link *retype;
8336   int size, offset;
8337   char *l;
8338   symbol *tlbl, *tlbl1;
8339
8340   D (emitcode (";", "genRightShift "););
8341
8342   /* if signed then we do it the hard way preserve the
8343      sign bit moving it inwards */
8344   retype = getSpec (operandType (IC_RESULT (ic)));
8345
8346   if (!SPEC_USIGN (retype))
8347     {
8348       genSignedRightShift (ic);
8349       return;
8350     }
8351
8352   /* signed & unsigned types are treated the same : i.e. the
8353      signed is NOT propagated inwards : quoting from the
8354      ANSI - standard : "for E1 >> E2, is equivalent to division
8355      by 2**E2 if unsigned or if it has a non-negative value,
8356      otherwise the result is implementation defined ", MY definition
8357      is that the sign does not get propagated */
8358
8359   right = IC_RIGHT (ic);
8360   left = IC_LEFT (ic);
8361   result = IC_RESULT (ic);
8362
8363   aopOp (right, ic, FALSE, FALSE);
8364
8365 #ifdef BETTER_LITERAL_SHIFT
8366   /* if the shift count is known then do it
8367      as efficiently as possible */
8368   if (AOP_TYPE (right) == AOP_LIT)
8369     {
8370       if (genRightShiftLiteral (left, right, result, ic, 0))
8371       {
8372         return;
8373       }
8374     }
8375 #endif
8376
8377   /* shift count is unknown then we have to form
8378      a loop get the loop count in B : Note: we take
8379      only the lower order byte since shifting
8380      more that 32 bits make no sense anyway, ( the
8381      largest size of an object can be only 32 bits ) */
8382   
8383   if (AOP_TYPE (right) == AOP_LIT)
8384   {
8385       /* Really should be handled by genRightShiftLiteral,
8386        * but since I'm too lazy to fix that today, at least we can make
8387        * some small improvement.
8388        */
8389        emitcode("mov", "b,#0x%02x",
8390                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8391   }
8392   else
8393   {
8394         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8395         emitcode ("inc", "b");
8396   }
8397   freeAsmop (right, NULL, ic, TRUE);
8398   aopOp (left, ic, FALSE, FALSE);
8399   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8400
8401   /* now move the left to the result if they are not the
8402      same */
8403   if (!sameRegs (AOP (left), AOP (result)) &&
8404       AOP_SIZE (result) > 1)
8405     {
8406
8407       size = AOP_SIZE (result);
8408       offset = 0;
8409       _startLazyDPSEvaluation ();
8410       while (size--)
8411         {
8412           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8413           if (*l == '@' && IS_AOP_PREG (result))
8414             {
8415
8416               emitcode ("mov", "a,%s", l);
8417               aopPut (AOP (result), "a", offset);
8418             }
8419           else
8420             aopPut (AOP (result), l, offset);
8421           offset++;
8422         }
8423       _endLazyDPSEvaluation ();
8424     }
8425
8426   tlbl = newiTempLabel (NULL);
8427   tlbl1 = newiTempLabel (NULL);
8428   size = AOP_SIZE (result);
8429   offset = size - 1;
8430
8431   /* if it is only one byte then */
8432   if (size == 1)
8433     {
8434       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8435       MOVA (l);
8436       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8437       emitcode ("", "%05d$:", tlbl->key + 100);
8438       CLRC;
8439       emitcode ("rrc", "a");
8440       emitcode ("", "%05d$:", tlbl1->key + 100);
8441       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8442       aopPut (AOP (result), "a", 0);
8443       goto release;
8444     }
8445
8446   reAdjustPreg (AOP (result));
8447   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8448   emitcode ("", "%05d$:", tlbl->key + 100);
8449   CLRC;
8450   _startLazyDPSEvaluation ();
8451   while (size--)
8452     {
8453       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8454       MOVA (l);
8455       emitcode ("rrc", "a");
8456       aopPut (AOP (result), "a", offset--);
8457     }
8458   _endLazyDPSEvaluation ();
8459   reAdjustPreg (AOP (result));
8460
8461   emitcode ("", "%05d$:", tlbl1->key + 100);
8462   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8463
8464 release:
8465   freeAsmop (left, NULL, ic, TRUE);
8466   freeAsmop (result, NULL, ic, TRUE);
8467 }
8468
8469 /*-----------------------------------------------------------------*/
8470 /* genUnpackBits - generates code for unpacking bits               */
8471 /*-----------------------------------------------------------------*/
8472 static void
8473 genUnpackBits (operand * result, char *rname, int ptype)
8474 {
8475   int shCnt;
8476   int rlen = 0;
8477   sym_link *etype;
8478   int offset = 0;
8479
8480   D (emitcode (";", "genUnpackBits ");
8481     );
8482
8483   etype = getSpec (operandType (result));
8484
8485   /* read the first byte  */
8486   switch (ptype)
8487     {
8488
8489     case POINTER:
8490     case IPOINTER:
8491       emitcode ("mov", "a,@%s", rname);
8492       break;
8493
8494     case PPOINTER:
8495       emitcode ("movx", "a,@%s", rname);
8496       break;
8497
8498     case FPOINTER:
8499       emitcode ("movx", "a,@dptr");
8500       break;
8501
8502     case CPOINTER:
8503       emitcode ("clr", "a");
8504       emitcode ("movc", "a,@a+dptr");
8505       break;
8506
8507     case GPOINTER:
8508       emitcode ("lcall", "__gptrget");
8509       break;
8510     }
8511
8512   /* if we have bitdisplacement then it fits   */
8513   /* into this byte completely or if length is */
8514   /* less than a byte                          */
8515   if ((shCnt = SPEC_BSTR (etype)) ||
8516       (SPEC_BLEN (etype) <= 8))
8517     {
8518
8519       /* shift right acc */
8520       AccRsh (shCnt);
8521
8522       emitcode ("anl", "a,#0x%02x",
8523                 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
8524       aopPut (AOP (result), "a", offset);
8525       return;
8526     }
8527
8528   /* bit field did not fit in a byte  */
8529   rlen = SPEC_BLEN (etype) - 8;
8530   aopPut (AOP (result), "a", offset++);
8531
8532   while (1)
8533     {
8534
8535       switch (ptype)
8536         {
8537         case POINTER:
8538         case IPOINTER:
8539           emitcode ("inc", "%s", rname);
8540           emitcode ("mov", "a,@%s", rname);
8541           break;
8542
8543         case PPOINTER:
8544           emitcode ("inc", "%s", rname);
8545           emitcode ("movx", "a,@%s", rname);
8546           break;
8547
8548         case FPOINTER:
8549           emitcode ("inc", "dptr");
8550           emitcode ("movx", "a,@dptr");
8551           break;
8552
8553         case CPOINTER:
8554           emitcode ("clr", "a");
8555           emitcode ("inc", "dptr");
8556           emitcode ("movc", "a,@a+dptr");
8557           break;
8558
8559         case GPOINTER:
8560           emitcode ("inc", "dptr");
8561           emitcode ("lcall", "__gptrget");
8562           break;
8563         }
8564
8565       rlen -= 8;
8566       /* if we are done */
8567       if (rlen < 8)
8568         break;
8569
8570       aopPut (AOP (result), "a", offset++);
8571
8572     }
8573
8574   if (rlen)
8575     {
8576       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
8577       aopPut (AOP (result), "a", offset);
8578     }
8579
8580   return;
8581 }
8582
8583
8584 /*-----------------------------------------------------------------*/
8585 /* genDataPointerGet - generates code when ptr offset is known     */
8586 /*-----------------------------------------------------------------*/
8587 static void
8588 genDataPointerGet (operand * left,
8589                    operand * result,
8590                    iCode * ic)
8591 {
8592   char *l;
8593   char buffer[256];
8594   int size, offset = 0;
8595   aopOp (result, ic, TRUE, FALSE);
8596
8597   /* get the string representation of the name */
8598   l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
8599   size = AOP_SIZE (result);
8600   _startLazyDPSEvaluation ();
8601   while (size--)
8602     {
8603       if (offset)
8604         sprintf (buffer, "(%s + %d)", l + 1, offset);
8605       else
8606         sprintf (buffer, "%s", l + 1);
8607       aopPut (AOP (result), buffer, offset++);
8608     }
8609   _endLazyDPSEvaluation ();
8610
8611   freeAsmop (left, NULL, ic, TRUE);
8612   freeAsmop (result, NULL, ic, TRUE);
8613 }
8614
8615 /*-----------------------------------------------------------------*/
8616 /* genNearPointerGet - emitcode for near pointer fetch             */
8617 /*-----------------------------------------------------------------*/
8618 static void
8619 genNearPointerGet (operand * left,
8620                    operand * result,
8621                    iCode * ic,
8622                    iCode *pi)
8623 {
8624   asmop *aop = NULL;
8625   regs *preg = NULL;
8626   char *rname;
8627   sym_link *rtype, *retype, *letype;
8628   sym_link *ltype = operandType (left);
8629   char buffer[80];
8630
8631   rtype = operandType (result);
8632   retype = getSpec (rtype);
8633   letype = getSpec (ltype);
8634
8635   aopOp (left, ic, FALSE, FALSE);
8636
8637   /* if left is rematerialisable and
8638      result is not bit variable type and
8639      the left is pointer to data space i.e
8640      lower 128 bytes of space */
8641   if (AOP_TYPE (left) == AOP_IMMD &&
8642       !IS_BITVAR (retype) &&
8643       !IS_BITVAR (letype) &&
8644       DCL_TYPE (ltype) == POINTER)
8645     {
8646       genDataPointerGet (left, result, ic);
8647       return;
8648     }
8649
8650   /* if the value is already in a pointer register
8651      then don't need anything more */
8652   if (!AOP_INPREG (AOP (left)))
8653     {
8654       /* otherwise get a free pointer register */
8655       aop = newAsmop (0);
8656       preg = getFreePtr (ic, &aop, FALSE);
8657       emitcode ("mov", "%s,%s",
8658                 preg->name,
8659                 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8660       rname = preg->name;
8661     }
8662   else
8663     rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8664
8665   freeAsmop (left, NULL, ic, TRUE);
8666   aopOp (result, ic, FALSE, FALSE);
8667
8668   /* if bitfield then unpack the bits */
8669   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8670     genUnpackBits (result, rname, POINTER);
8671   else
8672     {
8673       /* we have can just get the values */
8674       int size = AOP_SIZE (result);
8675       int offset = 0;
8676
8677       while (size--)
8678         {
8679           if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8680             {
8681
8682               emitcode ("mov", "a,@%s", rname);
8683               aopPut (AOP (result), "a", offset);
8684             }
8685           else
8686             {
8687               sprintf (buffer, "@%s", rname);
8688               aopPut (AOP (result), buffer, offset);
8689             }
8690           offset++;
8691           if (size || pi)
8692             emitcode ("inc", "%s", rname);
8693         }
8694     }
8695
8696   /* now some housekeeping stuff */
8697   if (aop)
8698     {
8699       /* we had to allocate for this iCode */
8700       if (pi) { /* post increment present */
8701         aopPut(AOP ( left ),rname,0);
8702       }
8703       freeAsmop (NULL, aop, ic, TRUE);
8704     }
8705   else
8706     {
8707       /* we did not allocate which means left
8708          already in a pointer register, then
8709          if size > 0 && this could be used again
8710          we have to point it back to where it
8711          belongs */
8712       if (AOP_SIZE (result) > 1 &&
8713           !OP_SYMBOL (left)->remat &&
8714           (OP_SYMBOL (left)->liveTo > ic->seq ||
8715            ic->depth) &&
8716           !pi)
8717         {
8718           int size = AOP_SIZE (result) - 1;
8719           while (size--)
8720             emitcode ("dec", "%s", rname);
8721         }
8722     }
8723
8724   /* done */
8725   freeAsmop (result, NULL, ic, TRUE);
8726   if (pi) pi->generated = 1;
8727 }
8728
8729 /*-----------------------------------------------------------------*/
8730 /* genPagedPointerGet - emitcode for paged pointer fetch           */
8731 /*-----------------------------------------------------------------*/
8732 static void
8733 genPagedPointerGet (operand * left,
8734                     operand * result,
8735                     iCode * ic,
8736                     iCode * pi)
8737 {
8738   asmop *aop = NULL;
8739   regs *preg = NULL;
8740   char *rname;
8741   sym_link *rtype, *retype, *letype;
8742
8743   rtype = operandType (result);
8744   retype = getSpec (rtype);
8745   letype = getSpec (operandType (left));
8746   aopOp (left, ic, FALSE, FALSE);
8747
8748   /* if the value is already in a pointer register
8749      then don't need anything more */
8750   if (!AOP_INPREG (AOP (left)))
8751     {
8752       /* otherwise get a free pointer register */
8753       aop = newAsmop (0);
8754       preg = getFreePtr (ic, &aop, FALSE);
8755       emitcode ("mov", "%s,%s",
8756                 preg->name,
8757                 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8758       rname = preg->name;
8759     }
8760   else
8761     rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8762
8763   freeAsmop (left, NULL, ic, TRUE);
8764   aopOp (result, ic, FALSE, FALSE);
8765
8766   /* if bitfield then unpack the bits */
8767   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8768     genUnpackBits (result, rname, PPOINTER);
8769   else
8770     {
8771       /* we have can just get the values */
8772       int size = AOP_SIZE (result);
8773       int offset = 0;
8774
8775       while (size--)
8776         {
8777
8778           emitcode ("movx", "a,@%s", rname);
8779           aopPut (AOP (result), "a", offset);
8780
8781           offset++;
8782
8783           if (size || pi)
8784             emitcode ("inc", "%s", rname);
8785         }
8786     }
8787
8788   /* now some housekeeping stuff */
8789   if (aop)
8790     {
8791       /* we had to allocate for this iCode */
8792       if (pi) aopPut ( AOP (left), rname, 0);
8793       freeAsmop (NULL, aop, ic, TRUE);
8794     }
8795   else
8796     {
8797       /* we did not allocate which means left
8798          already in a pointer register, then
8799          if size > 0 && this could be used again
8800          we have to point it back to where it
8801          belongs */
8802       if (AOP_SIZE (result) > 1 &&
8803           !OP_SYMBOL (left)->remat &&
8804           (OP_SYMBOL (left)->liveTo > ic->seq ||
8805            ic->depth) &&
8806           !pi)
8807         {
8808           int size = AOP_SIZE (result) - 1;
8809           while (size--)
8810             emitcode ("dec", "%s", rname);
8811         }
8812     }
8813
8814   /* done */
8815   freeAsmop (result, NULL, ic, TRUE);
8816   if (pi) pi->generated = 1;
8817 }
8818
8819 /*-----------------------------------------------------------------*/
8820 /* genFarPointerGet - gget value from far space                    */
8821 /*-----------------------------------------------------------------*/
8822 static void
8823 genFarPointerGet (operand * left,
8824                   operand * result, iCode * ic, iCode *pi)
8825 {
8826   int size, offset;
8827   sym_link *retype = getSpec (operandType (result));
8828   sym_link *letype = getSpec (operandType (left));
8829   D (emitcode (";", "genFarPointerGet");
8830     );
8831
8832   aopOp (left, ic, FALSE, FALSE);
8833
8834   /* if the operand is already in dptr
8835      then we do nothing else we move the value to dptr */
8836   if (AOP_TYPE (left) != AOP_STR)
8837     {
8838       /* if this is remateriazable */
8839       if (AOP_TYPE (left) == AOP_IMMD)
8840         {
8841           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8842         }
8843       else
8844         {
8845           /* we need to get it byte by byte */
8846           _startLazyDPSEvaluation ();
8847           if (AOP_TYPE (left) != AOP_DPTR)
8848             {
8849               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8850               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8851               if (options.model == MODEL_FLAT24)
8852                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8853             }
8854           else
8855             {
8856               /* We need to generate a load to DPTR indirect through DPTR. */
8857               D (emitcode (";", "genFarPointerGet -- indirection special case.");
8858                 );
8859               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8860               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8861               if (options.model == MODEL_FLAT24)
8862                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8863               emitcode ("pop", "dph");
8864               emitcode ("pop", "dpl");
8865             }
8866           _endLazyDPSEvaluation ();
8867         }
8868     }
8869   /* so dptr know contains the address */
8870   aopOp (result, ic, FALSE, TRUE);
8871
8872   /* if bit then unpack */
8873   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8874     genUnpackBits (result, "dptr", FPOINTER);
8875   else
8876     {
8877       size = AOP_SIZE (result);
8878       offset = 0;
8879
8880       _startLazyDPSEvaluation ();
8881       while (size--)
8882         {
8883
8884           genSetDPTR (0);
8885           _flushLazyDPS ();
8886
8887           emitcode ("movx", "a,@dptr");
8888           if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
8889             emitcode ("inc", "dptr");
8890
8891           aopPut (AOP (result), "a", offset++);
8892         }
8893       _endLazyDPSEvaluation ();
8894     }
8895   if (pi && AOP_TYPE (left) != AOP_IMMD) {
8896     aopPut ( AOP (left), "dpl", 0);
8897     aopPut ( AOP (left), "dph", 1);
8898     if (options.model == MODEL_FLAT24)
8899             aopPut ( AOP (left), "dpx", 2);
8900     pi->generated = 1;
8901   } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
8902              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
8903       
8904       size = AOP_SIZE (result) - 1;
8905       while (size--) emitcode ("lcall","__decdptr");
8906   }
8907
8908   freeAsmop (left, NULL, ic, TRUE);
8909   freeAsmop (result, NULL, ic, TRUE);
8910 }
8911
8912 /*-----------------------------------------------------------------*/
8913 /* emitcodePointerGet - gget value from code space                  */
8914 /*-----------------------------------------------------------------*/
8915 static void
8916 emitcodePointerGet (operand * left,
8917                     operand * result, iCode * ic, iCode *pi)
8918 {
8919   int size, offset;
8920   sym_link *retype = getSpec (operandType (result));
8921
8922   aopOp (left, ic, FALSE, FALSE);
8923
8924   /* if the operand is already in dptr
8925      then we do nothing else we move the value to dptr */
8926   if (AOP_TYPE (left) != AOP_STR)
8927     {
8928       /* if this is remateriazable */
8929       if (AOP_TYPE (left) == AOP_IMMD)
8930         {
8931           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8932         }
8933       else
8934         {                       /* we need to get it byte by byte */
8935           _startLazyDPSEvaluation ();
8936           if (AOP_TYPE (left) != AOP_DPTR)
8937             {
8938               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8939               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8940               if (options.model == MODEL_FLAT24)
8941                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8942             }
8943           else
8944             {
8945               /* We need to generate a load to DPTR indirect through DPTR. */
8946               D (emitcode (";", "gencodePointerGet -- indirection special case.");
8947                 );
8948               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8949               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8950               if (options.model == MODEL_FLAT24)
8951                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8952               emitcode ("pop", "dph");
8953               emitcode ("pop", "dpl");
8954             }
8955           _endLazyDPSEvaluation ();
8956         }
8957     }
8958   /* so dptr know contains the address */
8959   aopOp (result, ic, FALSE, TRUE);
8960
8961   /* if bit then unpack */
8962   if (IS_BITVAR (retype))
8963     genUnpackBits (result, "dptr", CPOINTER);
8964   else
8965     {
8966       size = AOP_SIZE (result);
8967       offset = 0;
8968
8969       _startLazyDPSEvaluation ();
8970       while (size--)
8971         {
8972           genSetDPTR (0);
8973           _flushLazyDPS ();
8974
8975           emitcode ("clr", "a");
8976           emitcode ("movc", "a,@a+dptr");
8977           if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
8978             emitcode ("inc", "dptr");
8979           aopPut (AOP (result), "a", offset++);
8980         }
8981       _endLazyDPSEvaluation ();
8982     }
8983   if (pi && AOP_TYPE (left) != AOP_IMMD) {
8984       aopPut ( AOP (left), "dpl", 0);
8985       aopPut ( AOP (left), "dph", 1);
8986       if (options.model == MODEL_FLAT24)
8987           aopPut ( AOP (left), "dpx", 2);
8988       pi->generated = 1;
8989   } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
8990              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
8991       
8992       size = AOP_SIZE (result) - 1;
8993       while (size--) emitcode ("lcall","__decdptr");
8994   }
8995   
8996   freeAsmop (left, NULL, ic, TRUE);
8997   freeAsmop (result, NULL, ic, TRUE);
8998 }
8999
9000 /*-----------------------------------------------------------------*/
9001 /* genGenPointerGet - gget value from generic pointer space        */
9002 /*-----------------------------------------------------------------*/
9003 static void
9004 genGenPointerGet (operand * left,
9005                   operand * result, iCode * ic, iCode * pi)
9006 {
9007   int size, offset;
9008   sym_link *retype = getSpec (operandType (result));
9009   sym_link *letype = getSpec (operandType (left));
9010
9011   D (emitcode (";", "genGenPointerGet "); );
9012
9013   aopOp (left, ic, FALSE, (OP_SYMBOL(left)->ruonly ? FALSE : TRUE));
9014
9015   /* if the operand is already in dptr
9016      then we do nothing else we move the value to dptr */
9017   if (AOP_TYPE (left) != AOP_STR)
9018     {
9019       /* if this is remateriazable */
9020       if (AOP_TYPE (left) == AOP_IMMD)
9021         {
9022           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9023           if (AOP(left)->aopu.aop_immd.from_cast_remat) 
9024                   emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, FALSE));
9025           else
9026                   emitcode ("mov", "b,#%d", pointerCode (retype));
9027         }
9028       else
9029         {                       /* we need to get it byte by byte */
9030           _startLazyDPSEvaluation ();
9031           if (AOP(left)->type==AOP_DPTR2) {
9032             char *l;
9033             l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
9034             genSetDPTR(0);
9035             _flushLazyDPS();
9036             emitcode ("mov", "dpl,%s", l);
9037             l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
9038             genSetDPTR(0);
9039             _flushLazyDPS();
9040             emitcode ("mov", "dph,%s", l);
9041             if (options.model == MODEL_FLAT24) {
9042               l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
9043               genSetDPTR(0);
9044               _flushLazyDPS();
9045               emitcode ("mov", "dpx,%s", l);
9046               emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
9047             } else {
9048               emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9049             }
9050           } else {
9051             emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
9052             emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
9053             if (options.model == MODEL_FLAT24) {
9054               emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9055               emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
9056             } else {
9057               emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9058             }
9059           }
9060           _endLazyDPSEvaluation ();
9061         }
9062     }
9063   /* so dptr know contains the address */
9064   aopOp (result, ic, FALSE, TRUE);
9065
9066   /* if bit then unpack */
9067   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9068     genUnpackBits (result, "dptr", GPOINTER);
9069   else
9070     {
9071       size = AOP_SIZE (result);
9072       offset = 0;
9073
9074       while (size--)
9075         {
9076           emitcode ("lcall", "__gptrget");
9077           aopPut (AOP (result), "a", offset++);
9078           if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9079             emitcode ("inc", "dptr");
9080         }
9081     }
9082
9083   if (pi && AOP_TYPE (left) != AOP_IMMD) {
9084     aopPut ( AOP (left), "dpl", 0);
9085     aopPut ( AOP (left), "dph", 1);
9086     if (options.model == MODEL_FLAT24) {
9087         aopPut ( AOP (left), "dpx", 2);
9088         aopPut ( AOP (left), "b", 3);   
9089     } else  aopPut ( AOP (left), "b", 2);       
9090     pi->generated = 1;
9091   } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9092              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9093       
9094       size = AOP_SIZE (result) - 1;
9095       while (size--) emitcode ("lcall","__decdptr");
9096   }
9097
9098   freeAsmop (left, NULL, ic, TRUE);
9099   freeAsmop (result, NULL, ic, TRUE);
9100 }
9101
9102 /*-----------------------------------------------------------------*/
9103 /* genPointerGet - generate code for pointer get                   */
9104 /*-----------------------------------------------------------------*/
9105 static void
9106 genPointerGet (iCode * ic, iCode *pi)
9107 {
9108   operand *left, *result;
9109   sym_link *type, *etype;
9110   int p_type;
9111
9112   D (emitcode (";", "genPointerGet ");
9113     );
9114
9115   left = IC_LEFT (ic);
9116   result = IC_RESULT (ic);
9117
9118   /* depending on the type of pointer we need to
9119      move it to the correct pointer register */
9120   type = operandType (left);
9121   etype = getSpec (type);
9122   /* if left is of type of pointer then it is simple */
9123   if (IS_PTR (type) && !IS_FUNC (type->next))
9124     p_type = DCL_TYPE (type);
9125   else
9126     {
9127       /* we have to go by the storage class */
9128       p_type = PTR_TYPE (SPEC_OCLS (etype));
9129     }
9130   /* special case when cast remat */
9131   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9132       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9133           left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9134           type =   type = operandType (left);
9135           p_type = DCL_TYPE (type);
9136   }
9137   /* now that we have the pointer type we assign
9138      the pointer values */
9139   switch (p_type)
9140     {
9141
9142     case POINTER:
9143     case IPOINTER:
9144       genNearPointerGet (left, result, ic, pi);
9145       break;
9146
9147     case PPOINTER:
9148       genPagedPointerGet (left, result, ic, pi);
9149       break;
9150
9151     case FPOINTER:
9152       genFarPointerGet (left, result, ic, pi);
9153       break;
9154
9155     case CPOINTER:
9156       emitcodePointerGet (left, result, ic, pi);
9157       break;
9158
9159     case GPOINTER:
9160       genGenPointerGet (left, result, ic, pi);
9161       break;
9162     }
9163
9164 }
9165
9166 /*-----------------------------------------------------------------*/
9167 /* genPackBits - generates code for packed bit storage             */
9168 /*-----------------------------------------------------------------*/
9169 static void
9170 genPackBits (sym_link * etype,
9171              operand * right,
9172              char *rname, int p_type)
9173 {
9174   int shCount = 0;
9175   int offset = 0;
9176   int rLen = 0;
9177   int blen, bstr;
9178   char *l;
9179
9180   blen = SPEC_BLEN (etype);
9181   bstr = SPEC_BSTR (etype);
9182
9183   l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9184   MOVA (l);
9185
9186   /* if the bit lenth is less than or    */
9187   /* it exactly fits a byte then         */
9188   if (SPEC_BLEN (etype) <= 8)
9189     {
9190       shCount = SPEC_BSTR (etype);
9191
9192       /* shift left acc */
9193       AccLsh (shCount);
9194
9195       if (SPEC_BLEN (etype) < 8)
9196         {                       /* if smaller than a byte */
9197
9198
9199           switch (p_type)
9200             {
9201             case POINTER:
9202               emitcode ("mov", "b,a");
9203               emitcode ("mov", "a,@%s", rname);
9204               break;
9205
9206             case FPOINTER:
9207               emitcode ("mov", "b,a");
9208               emitcode ("movx", "a,@dptr");
9209               break;
9210
9211             case GPOINTER:
9212               emitcode ("push", "b");
9213               emitcode ("push", "acc");
9214               emitcode ("lcall", "__gptrget");
9215               emitcode ("pop", "b");
9216               break;
9217             }
9218
9219           emitcode ("anl", "a,#0x%02x", (unsigned char)
9220                     ((unsigned char) (0xFF << (blen + bstr)) |
9221                      (unsigned char) (0xFF >> (8 - bstr))));
9222           emitcode ("orl", "a,b");
9223           if (p_type == GPOINTER)
9224             emitcode ("pop", "b");
9225         }
9226     }
9227
9228   switch (p_type)
9229     {
9230     case POINTER:
9231       emitcode ("mov", "@%s,a", rname);
9232       break;
9233
9234     case FPOINTER:
9235       emitcode ("movx", "@dptr,a");
9236       break;
9237
9238     case GPOINTER:
9239       emitcode ("lcall", "__gptrput");
9240       break;
9241     }
9242
9243   /* if we r done */
9244   if (SPEC_BLEN (etype) <= 8)
9245     return;
9246
9247   emitcode ("inc", "%s", rname);
9248   rLen = SPEC_BLEN (etype);
9249
9250   /* now generate for lengths greater than one byte */
9251   while (1)
9252     {
9253
9254       l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
9255
9256       rLen -= 8;
9257       if (rLen < 8)
9258         break;
9259
9260       switch (p_type)
9261         {
9262         case POINTER:
9263           if (*l == '@')
9264             {
9265               MOVA (l);
9266               emitcode ("mov", "@%s,a", rname);
9267             }
9268           else
9269             emitcode ("mov", "@%s,%s", rname, l);
9270           break;
9271
9272         case FPOINTER:
9273           MOVA (l);
9274           emitcode ("movx", "@dptr,a");
9275           break;
9276
9277         case GPOINTER:
9278           MOVA (l);
9279           emitcode ("lcall", "__gptrput");
9280           break;
9281         }
9282       emitcode ("inc", "%s", rname);
9283     }
9284
9285   MOVA (l);
9286
9287   /* last last was not complete */
9288   if (rLen)
9289     {
9290       /* save the byte & read byte */
9291       switch (p_type)
9292         {
9293         case POINTER:
9294           emitcode ("mov", "b,a");
9295           emitcode ("mov", "a,@%s", rname);
9296           break;
9297
9298         case FPOINTER:
9299           emitcode ("mov", "b,a");
9300           emitcode ("movx", "a,@dptr");
9301           break;
9302
9303         case GPOINTER:
9304           emitcode ("push", "b");
9305           emitcode ("push", "acc");
9306           emitcode ("lcall", "__gptrget");
9307           emitcode ("pop", "b");
9308           break;
9309         }
9310
9311       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
9312       emitcode ("orl", "a,b");
9313     }
9314
9315   if (p_type == GPOINTER)
9316     emitcode ("pop", "b");
9317
9318   switch (p_type)
9319     {
9320
9321     case POINTER:
9322       emitcode ("mov", "@%s,a", rname);
9323       break;
9324
9325     case FPOINTER:
9326       emitcode ("movx", "@dptr,a");
9327       break;
9328
9329     case GPOINTER:
9330       emitcode ("lcall", "__gptrput");
9331       break;
9332     }
9333 }
9334 /*-----------------------------------------------------------------*/
9335 /* genDataPointerSet - remat pointer to data space                 */
9336 /*-----------------------------------------------------------------*/
9337 static void
9338 genDataPointerSet (operand * right,
9339                    operand * result,
9340                    iCode * ic)
9341 {
9342   int size, offset = 0;
9343   char *l, buffer[256];
9344
9345   aopOp (right, ic, FALSE, FALSE);
9346
9347   l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
9348   size = AOP_SIZE (right);
9349   while (size--)
9350     {
9351       if (offset)
9352         sprintf (buffer, "(%s + %d)", l + 1, offset);
9353       else
9354         sprintf (buffer, "%s", l + 1);
9355       emitcode ("mov", "%s,%s", buffer,
9356                 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
9357     }
9358
9359   freeAsmop (right, NULL, ic, TRUE);
9360   freeAsmop (result, NULL, ic, TRUE);
9361 }
9362
9363 /*-----------------------------------------------------------------*/
9364 /* genNearPointerSet - emitcode for near pointer put                */
9365 /*-----------------------------------------------------------------*/
9366 static void
9367 genNearPointerSet (operand * right,
9368                    operand * result,
9369                    iCode * ic,
9370                    iCode * pi)
9371 {
9372   asmop *aop = NULL;
9373   regs *preg = NULL;
9374   char *rname, *l;
9375   sym_link *retype, *letype;
9376   sym_link *ptype = operandType (result);
9377
9378   retype = getSpec (operandType (right));
9379   letype = getSpec (ptype);
9380
9381   aopOp (result, ic, FALSE, FALSE);
9382
9383   /* if the result is rematerializable &
9384      in data space & not a bit variable */
9385   if (AOP_TYPE (result) == AOP_IMMD &&
9386       DCL_TYPE (ptype) == POINTER &&
9387       !IS_BITVAR (retype) &&
9388       !IS_BITVAR (letype))
9389     {
9390       genDataPointerSet (right, result, ic);
9391       return;
9392     }
9393
9394   /* if the value is already in a pointer register
9395      then don't need anything more */
9396   if (!AOP_INPREG (AOP (result)))
9397     {
9398       /* otherwise get a free pointer register */
9399       aop = newAsmop (0);
9400       preg = getFreePtr (ic, &aop, FALSE);
9401       emitcode ("mov", "%s,%s",
9402                 preg->name,
9403                 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9404       rname = preg->name;
9405     }
9406   else
9407     rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9408
9409   aopOp (right, ic, FALSE, FALSE);
9410
9411   /* if bitfield then unpack the bits */
9412   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9413     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
9414   else
9415     {
9416       /* we have can just get the values */
9417       int size = AOP_SIZE (right);
9418       int offset = 0;
9419
9420       while (size--)
9421         {
9422           l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
9423           if (*l == '@')
9424             {
9425               MOVA (l);
9426               emitcode ("mov", "@%s,a", rname);
9427             }
9428           else
9429             emitcode ("mov", "@%s,%s", rname, l);
9430           if (size || pi)
9431             emitcode ("inc", "%s", rname);
9432           offset++;
9433         }
9434     }
9435
9436   /* now some housekeeping stuff */
9437   if (aop)
9438     {
9439       /* we had to allocate for this iCode */
9440       if (pi) aopPut (AOP (result),rname,0);
9441       freeAsmop (NULL, aop, ic, TRUE);
9442     }
9443   else
9444     {
9445       /* we did not allocate which means left
9446          already in a pointer register, then
9447          if size > 0 && this could be used again
9448          we have to point it back to where it
9449          belongs */
9450       if (AOP_SIZE (right) > 1 &&
9451           !OP_SYMBOL (result)->remat &&
9452           (OP_SYMBOL (result)->liveTo > ic->seq ||
9453            ic->depth) &&
9454           !pi)
9455         {
9456           int size = AOP_SIZE (right) - 1;
9457           while (size--)
9458             emitcode ("dec", "%s", rname);
9459         }
9460     }
9461
9462   /* done */
9463   if (pi) pi->generated = 1;
9464   freeAsmop (result, NULL, ic, TRUE);
9465   freeAsmop (right, NULL, ic, TRUE);
9466
9467
9468 }
9469
9470 /*-----------------------------------------------------------------*/
9471 /* genPagedPointerSet - emitcode for Paged pointer put             */
9472 /*-----------------------------------------------------------------*/
9473 static void
9474 genPagedPointerSet (operand * right,
9475                     operand * result,
9476                     iCode * ic,
9477                     iCode *pi)
9478 {
9479   asmop *aop = NULL;
9480   regs *preg = NULL;
9481   char *rname, *l;
9482   sym_link *retype, *letype;
9483
9484   retype = getSpec (operandType (right));
9485   letype = getSpec (operandType (result));
9486
9487   aopOp (result, ic, FALSE, FALSE);
9488
9489   /* if the value is already in a pointer register
9490      then don't need anything more */
9491   if (!AOP_INPREG (AOP (result)))
9492     {
9493       /* otherwise get a free pointer register */
9494       aop = newAsmop (0);
9495       preg = getFreePtr (ic, &aop, FALSE);
9496       emitcode ("mov", "%s,%s",
9497                 preg->name,
9498                 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9499       rname = preg->name;
9500     }
9501   else
9502     rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9503
9504   aopOp (right, ic, FALSE, FALSE);
9505
9506   /* if bitfield then unpack the bits */
9507   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9508     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
9509   else
9510     {
9511       /* we have can just get the values */
9512       int size = AOP_SIZE (right);
9513       int offset = 0;
9514
9515       while (size--)
9516         {
9517           l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
9518
9519           MOVA (l);
9520           emitcode ("movx", "@%s,a", rname);
9521
9522           if (size || pi)
9523             emitcode ("inc", "%s", rname);
9524
9525           offset++;
9526         }
9527     }
9528
9529   /* now some housekeeping stuff */
9530   if (aop)
9531     {
9532       if (pi) aopPut (AOP (result),rname,0);
9533       /* we had to allocate for this iCode */
9534       freeAsmop (NULL, aop, ic, TRUE);
9535     }
9536   else
9537     {
9538       /* we did not allocate which means left
9539          already in a pointer register, then
9540          if size > 0 && this could be used again
9541          we have to point it back to where it
9542          belongs */
9543       if (AOP_SIZE (right) > 1 &&
9544           !OP_SYMBOL (result)->remat &&
9545           (OP_SYMBOL (result)->liveTo > ic->seq ||
9546            ic->depth) &&
9547           !pi)
9548         {
9549           int size = AOP_SIZE (right) - 1;
9550           while (size--)
9551             emitcode ("dec", "%s", rname);
9552         }
9553     }
9554
9555   /* done */
9556   if (pi) pi->generated = 1;
9557   freeAsmop (result, NULL, ic, TRUE);
9558   freeAsmop (right, NULL, ic, TRUE);
9559
9560
9561 }
9562
9563 /*-----------------------------------------------------------------*/
9564 /* genFarPointerSet - set value from far space                     */
9565 /*-----------------------------------------------------------------*/
9566 static void
9567 genFarPointerSet (operand * right,
9568                   operand * result, iCode * ic, iCode *pi)
9569 {
9570   int size, offset;
9571   sym_link *retype = getSpec (operandType (right));
9572   sym_link *letype = getSpec (operandType (result));
9573
9574   aopOp (result, ic, FALSE, FALSE);
9575
9576   /* if the operand is already in dptr
9577      then we do nothing else we move the value to dptr */
9578   if (AOP_TYPE (result) != AOP_STR)
9579     {
9580       /* if this is remateriazable */
9581       if (AOP_TYPE (result) == AOP_IMMD)
9582         emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9583       else
9584         {
9585           /* we need to get it byte by byte */
9586           _startLazyDPSEvaluation ();
9587           if (AOP_TYPE (result) != AOP_DPTR)
9588             {
9589               emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9590               emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9591               if (options.model == MODEL_FLAT24)
9592                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9593             }
9594           else
9595             {
9596               /* We need to generate a load to DPTR indirect through DPTR. */
9597               D (emitcode (";", "genFarPointerSet -- indirection special case.");
9598                 );
9599               emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
9600               emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
9601               if (options.model == MODEL_FLAT24)
9602                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9603               emitcode ("pop", "dph");
9604               emitcode ("pop", "dpl");
9605             }
9606           _endLazyDPSEvaluation ();
9607         }
9608     }
9609   /* so dptr know contains the address */
9610   aopOp (right, ic, FALSE, TRUE);
9611
9612   /* if bit then unpack */
9613   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9614     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
9615   else
9616     {
9617       size = AOP_SIZE (right);
9618       offset = 0;
9619
9620       _startLazyDPSEvaluation ();
9621       while (size--)
9622         {
9623           char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9624           MOVA (l);
9625
9626           genSetDPTR (0);
9627           _flushLazyDPS ();
9628
9629           emitcode ("movx", "@dptr,a");
9630           if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
9631             emitcode ("inc", "dptr");
9632         }
9633       _endLazyDPSEvaluation ();
9634     }
9635
9636   if (pi && AOP_TYPE (result) != AOP_IMMD) {
9637       aopPut (AOP(result),"dpl",0);
9638       aopPut (AOP(result),"dph",1);
9639       if (options.model == MODEL_FLAT24)
9640           aopPut (AOP(result),"dpx",2);
9641       pi->generated=1;
9642   } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
9643              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
9644       
9645       size = AOP_SIZE (right) - 1;
9646       while (size--) emitcode ("lcall","__decdptr");
9647   }
9648   freeAsmop (result, NULL, ic, TRUE);
9649   freeAsmop (right, NULL, ic, TRUE);
9650 }
9651
9652 /*-----------------------------------------------------------------*/
9653 /* genGenPointerSet - set value from generic pointer space         */
9654 /*-----------------------------------------------------------------*/
9655 static void
9656 genGenPointerSet (operand * right,
9657                   operand * result, iCode * ic, iCode *pi)
9658 {
9659   int size, offset;
9660   sym_link *retype = getSpec (operandType (right));
9661   sym_link *letype = getSpec (operandType (result));
9662
9663   aopOp (result, ic, FALSE, OP_SYMBOL(result)->ruonly ? FALSE : TRUE);
9664
9665   /* if the operand is already in dptr
9666      then we do nothing else we move the value to dptr */
9667   if (AOP_TYPE (result) != AOP_STR)
9668     {
9669       _startLazyDPSEvaluation ();
9670       /* if this is remateriazable */
9671       if (AOP_TYPE (result) == AOP_IMMD)
9672         {
9673           emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9674           if (AOP(result)->aopu.aop_immd.from_cast_remat) 
9675                   emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, FALSE));
9676           else
9677                   emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9678         }
9679       else
9680         {                       /* we need to get it byte by byte */
9681           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9682           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9683           if (options.model == MODEL_FLAT24) {
9684             emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9685             emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
9686           } else {
9687             emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9688           }
9689         }
9690       _endLazyDPSEvaluation ();
9691     }
9692   /* so dptr know contains the address */
9693   aopOp (right, ic, FALSE, TRUE);
9694
9695   /* if bit then unpack */
9696   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9697     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
9698   else
9699     {
9700       size = AOP_SIZE (right);
9701       offset = 0;
9702
9703       _startLazyDPSEvaluation ();
9704       while (size--)
9705         {
9706           char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9707           MOVA (l);
9708
9709           genSetDPTR (0);
9710           _flushLazyDPS ();
9711
9712           emitcode ("lcall", "__gptrput");
9713           if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
9714             emitcode ("inc", "dptr");
9715         }
9716       _endLazyDPSEvaluation ();
9717     }
9718
9719   if (pi && AOP_TYPE (result) != AOP_IMMD) {
9720       aopPut (AOP(result),"dpl",0);
9721       aopPut (AOP(result),"dph",1);
9722       if (options.model == MODEL_FLAT24) {
9723           aopPut (AOP(result),"dpx",2);
9724           aopPut (AOP(result),"b",3);
9725       } else {
9726           aopPut (AOP(result),"b",2);
9727       }
9728       pi->generated=1;
9729   } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
9730              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
9731       
9732       size = AOP_SIZE (right) - 1;
9733       while (size--) emitcode ("lcall","__decdptr");
9734   }
9735   freeAsmop (result, NULL, ic, TRUE);
9736   freeAsmop (right, NULL, ic, TRUE);
9737 }
9738
9739 /*-----------------------------------------------------------------*/
9740 /* genPointerSet - stores the value into a pointer location        */
9741 /*-----------------------------------------------------------------*/
9742 static void
9743 genPointerSet (iCode * ic, iCode *pi)
9744 {
9745   operand *right, *result;
9746   sym_link *type, *etype;
9747   int p_type;
9748
9749   D (emitcode (";", "genPointerSet ");
9750     );
9751
9752   right = IC_RIGHT (ic);
9753   result = IC_RESULT (ic);
9754
9755   /* depending on the type of pointer we need to
9756      move it to the correct pointer register */
9757   type = operandType (result);
9758   etype = getSpec (type);
9759   /* if left is of type of pointer then it is simple */
9760   if (IS_PTR (type) && !IS_FUNC (type->next))
9761     {
9762       p_type = DCL_TYPE (type);
9763     }
9764   else
9765     {
9766       /* we have to go by the storage class */
9767       p_type = PTR_TYPE (SPEC_OCLS (etype));
9768     }
9769   /* special case when cast remat */
9770   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
9771       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
9772           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
9773           type =   type = operandType (result);
9774           p_type = DCL_TYPE (type);
9775   }
9776
9777   /* now that we have the pointer type we assign
9778      the pointer values */
9779   switch (p_type)
9780     {
9781
9782     case POINTER:
9783     case IPOINTER:
9784       genNearPointerSet (right, result, ic, pi);
9785       break;
9786
9787     case PPOINTER:
9788       genPagedPointerSet (right, result, ic, pi);
9789       break;
9790
9791     case FPOINTER:
9792       genFarPointerSet (right, result, ic, pi);
9793       break;
9794
9795     case GPOINTER:
9796       genGenPointerSet (right, result, ic, pi);
9797       break;
9798     }
9799
9800 }
9801
9802 /*-----------------------------------------------------------------*/
9803 /* genIfx - generate code for Ifx statement                        */
9804 /*-----------------------------------------------------------------*/
9805 static void
9806 genIfx (iCode * ic, iCode * popIc)
9807 {
9808   operand *cond = IC_COND (ic);
9809   int isbit = 0;
9810
9811   D (emitcode (";", "genIfx "););
9812
9813   aopOp (cond, ic, FALSE, FALSE);
9814
9815   /* get the value into acc */
9816   if (AOP_TYPE (cond) != AOP_CRY)
9817     toBoolean (cond);
9818   else
9819     isbit = 1;
9820   /* the result is now in the accumulator */
9821   freeAsmop (cond, NULL, ic, TRUE);
9822
9823   /* if there was something to be popped then do it */
9824   if (popIc)
9825     genIpop (popIc);
9826
9827   /* if the condition is  a bit variable */
9828   if (isbit && IS_ITEMP (cond) &&
9829       SPIL_LOC (cond))
9830     genIfxJump (ic, SPIL_LOC (cond)->rname);
9831   else if (isbit && !IS_ITEMP (cond))
9832     genIfxJump (ic, OP_SYMBOL (cond)->rname);
9833   else
9834     genIfxJump (ic, "a");
9835
9836   ic->generated = 1;
9837 }
9838
9839 /*-----------------------------------------------------------------*/
9840 /* genAddrOf - generates code for address of                       */
9841 /*-----------------------------------------------------------------*/
9842 static void
9843 genAddrOf (iCode * ic)
9844 {
9845   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
9846   int size, offset;
9847
9848   D (emitcode (";", "genAddrOf ");
9849     );
9850
9851   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9852
9853   /* if the operand is on the stack then we
9854      need to get the stack offset of this
9855      variable */
9856   if (sym->onStack) {
9857       
9858       /* if 10 bit stack */
9859       if (options.stack10bit) {
9860           /* if it has an offset then we need to compute it */
9861           if (sym->stack) {
9862               emitcode ("mov", "a,_bpx");
9863               emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
9864               emitcode ("mov", "b,a");
9865               emitcode ("mov", "a,_bpx+1");
9866               emitcode ("addc","a,#0x%02x", (((short) sym->stack) >> 8) & 0xff);
9867               aopPut (AOP (IC_RESULT (ic)), "b", 0);
9868               aopPut (AOP (IC_RESULT (ic)), "a", 1);
9869               aopPut (AOP (IC_RESULT (ic)), "#0x40", 2);
9870           } else {
9871               /* we can just move _bp */
9872               aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
9873               aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
9874               aopPut (AOP (IC_RESULT (ic)), "#0x40", 2);
9875           }       
9876       } else {
9877           /* if it has an offset then we need to compute it */
9878           if (sym->stack) {
9879               emitcode ("mov", "a,_bp");
9880               emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
9881               aopPut (AOP (IC_RESULT (ic)), "a", 0);
9882           } else {
9883               /* we can just move _bp */
9884               aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
9885           }
9886           /* fill the result with zero */
9887           size = AOP_SIZE (IC_RESULT (ic)) - 1;
9888           
9889           
9890           if (options.stack10bit && size < (FPTRSIZE - 1)) {
9891               fprintf (stderr,
9892                        "*** warning: pointer to stack var truncated.\n");
9893           }
9894
9895           offset = 1;
9896           while (size--) {
9897               aopPut (AOP (IC_RESULT (ic)), zero, offset++);
9898           }      
9899       }
9900       goto release;
9901   }
9902
9903   /* object not on stack then we need the name */
9904   size = AOP_SIZE (IC_RESULT (ic));
9905   offset = 0;
9906
9907   while (size--)
9908     {
9909       char s[SDCC_NAME_MAX];
9910       if (offset)
9911         sprintf (s, "#(%s >> %d)",
9912                  sym->rname,
9913                  offset * 8);
9914       else
9915         sprintf (s, "#%s", sym->rname);
9916       aopPut (AOP (IC_RESULT (ic)), s, offset++);
9917     }
9918
9919 release:
9920   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9921
9922 }
9923
9924 /*-----------------------------------------------------------------*/
9925 /* genArrayInit - generates code for address of                       */
9926 /*-----------------------------------------------------------------*/
9927 static void
9928 genArrayInit (iCode * ic)
9929 {
9930     literalList *iLoop;
9931     int         ix, count;
9932     int         elementSize = 0, eIndex;
9933     unsigned    val, lastVal;
9934     sym_link    *type;
9935     operand     *left=IC_LEFT(ic);
9936     
9937     D (emitcode (";", "genArrayInit "););
9938
9939     aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
9940     
9941     if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
9942     {
9943         // Load immediate value into DPTR.
9944         emitcode("mov", "dptr, %s",
9945              aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, TRUE));
9946     }
9947     else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
9948     {
9949 #if 0
9950       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9951               "Unexpected operand to genArrayInit.\n");
9952       exit(1);
9953 #else
9954       // a regression because of SDCCcse.c:1.52
9955       emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9956       emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9957       if (options.model == MODEL_FLAT24)
9958         emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9959 #endif
9960     }
9961     
9962     type = operandType(IC_LEFT(ic));
9963     
9964     if (type && type->next)
9965     {
9966         elementSize = getSize(type->next);
9967     }
9968     else
9969     {
9970         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9971                                 "can't determine element size in genArrayInit.\n");
9972         exit(1);
9973     }
9974     
9975     iLoop = IC_ARRAYILIST(ic);
9976     lastVal = 0xffff;
9977     
9978     while (iLoop)
9979     {
9980         bool firstpass = TRUE;
9981         
9982         emitcode(";", "store %d x 0x%x to DPTR (element size %d)", 
9983                  iLoop->count, (int)iLoop->literalValue, elementSize);
9984         
9985         ix = iLoop->count;
9986         
9987         while (ix)
9988         {
9989             symbol *tlbl = NULL;
9990             
9991             count = ix > 256 ? 256 : ix;
9992             
9993             if (count > 1)
9994             {
9995                 tlbl = newiTempLabel (NULL);
9996                 if (firstpass || (count & 0xff))
9997                 {
9998                     emitcode("mov", "b, #0x%x", count & 0xff);
9999                 }
10000                 
10001                 emitcode ("", "%05d$:", tlbl->key + 100);
10002             }
10003             
10004             firstpass = FALSE;
10005                 
10006             for (eIndex = 0; eIndex < elementSize; eIndex++)
10007             {
10008                 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10009                 if (val != lastVal)
10010                 {
10011                     emitcode("mov", "a, #0x%x", val);
10012                     lastVal = val;
10013                 }
10014                 
10015                 emitcode("movx", "@dptr, a");
10016                 emitcode("inc", "dptr");
10017             }
10018             
10019             if (count > 1)
10020             {
10021                 emitcode("djnz", "b, %05d$", tlbl->key + 100);
10022             }
10023             
10024             ix -= count;
10025         }
10026         
10027         iLoop = iLoop->next;
10028     }
10029     
10030     freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10031 }
10032
10033 /*-----------------------------------------------------------------*/
10034 /* genFarFarAssign - assignment when both are in far space         */
10035 /*-----------------------------------------------------------------*/
10036 static void
10037 genFarFarAssign (operand * result, operand * right, iCode * ic)
10038 {
10039   int size = AOP_SIZE (right);
10040   int offset = 0;
10041   symbol *rSym = NULL;
10042
10043   if (size == 1)
10044   {
10045       /* quick & easy case. */
10046       D(emitcode(";","genFarFarAssign (1 byte case)"););      
10047       MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
10048       freeAsmop (right, NULL, ic, FALSE);
10049       /* now assign DPTR to result */
10050       _G.accInUse++;
10051       aopOp(result, ic, FALSE, FALSE);
10052       _G.accInUse--;
10053       aopPut(AOP(result), "a", 0);
10054       freeAsmop(result, NULL, ic, FALSE);
10055       return;
10056   }
10057   
10058   /* See if we've got an underlying symbol to abuse. */
10059   if (IS_SYMOP(result) && OP_SYMBOL(result))
10060   {
10061       if (IS_TRUE_SYMOP(result))
10062       {
10063           rSym = OP_SYMBOL(result);
10064       }
10065       else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10066       {
10067           rSym = OP_SYMBOL(result)->usl.spillLoc;
10068       }
10069   }
10070              
10071   if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10072   {
10073       /* We can use the '390 auto-toggle feature to good effect here. */
10074       
10075       D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10076       emitcode("mov", "dps, #0x21");    /* Select DPTR2 & auto-toggle. */
10077       emitcode ("mov", "dptr,#%s", rSym->rname); 
10078       /* DP2 = result, DP1 = right, DP1 is current. */
10079       while (size)
10080       {
10081           emitcode("movx", "a,@dptr");
10082           emitcode("movx", "@dptr,a");
10083           if (--size)
10084           {
10085                emitcode("inc", "dptr");
10086                emitcode("inc", "dptr");
10087           }
10088       }
10089       emitcode("mov", "dps, #0");
10090       freeAsmop (right, NULL, ic, FALSE);
10091 #if 0
10092 some alternative code for processors without auto-toggle
10093 no time to test now, so later well put in...kpb
10094         D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10095         emitcode("mov", "dps, #0x01");  /* Select DPTR2. */
10096         emitcode ("mov", "dptr,#%s", rSym->rname); 
10097         /* DP2 = result, DP1 = right, DP1 is current. */
10098         while (size)
10099         {
10100           --size;
10101           emitcode("movx", "a,@dptr");
10102           if (size)
10103             emitcode("inc", "dptr");
10104           emitcode("inc", "dps");
10105           emitcode("movx", "@dptr,a");
10106           if (size)
10107             emitcode("inc", "dptr");
10108           emitcode("inc", "dps");
10109         }
10110         emitcode("mov", "dps, #0");
10111         freeAsmop (right, NULL, ic, FALSE);
10112 #endif
10113   }
10114   else
10115   {
10116       D (emitcode (";", "genFarFarAssign"););
10117       aopOp (result, ic, TRUE, TRUE);
10118
10119       _startLazyDPSEvaluation ();
10120       
10121       while (size--)
10122         {
10123           aopPut (AOP (result),
10124                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
10125           offset++;
10126         }
10127       _endLazyDPSEvaluation ();
10128       freeAsmop (result, NULL, ic, FALSE);
10129       freeAsmop (right, NULL, ic, FALSE);
10130   }
10131 }
10132
10133 /*-----------------------------------------------------------------*/
10134 /* genAssign - generate code for assignment                        */
10135 /*-----------------------------------------------------------------*/
10136 static void
10137 genAssign (iCode * ic)
10138 {
10139   operand *result, *right;
10140   int size, offset;
10141   unsigned long lit = 0L;
10142
10143   D (emitcode (";", "genAssign ");
10144     );
10145
10146   result = IC_RESULT (ic);
10147   right = IC_RIGHT (ic);
10148
10149   /* if they are the same */
10150   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10151     return;
10152
10153   aopOp (right, ic, FALSE, FALSE);
10154
10155   emitcode (";", "genAssign: resultIsFar = %s",
10156             isOperandInFarSpace (result) ?
10157             "TRUE" : "FALSE");
10158
10159   /* special case both in far space */
10160   if ((AOP_TYPE (right) == AOP_DPTR ||
10161        AOP_TYPE (right) == AOP_DPTR2) &&
10162   /* IS_TRUE_SYMOP(result)       && */
10163       isOperandInFarSpace (result))
10164     {
10165       genFarFarAssign (result, right, ic);
10166       return;
10167     }
10168
10169   aopOp (result, ic, TRUE, FALSE);
10170
10171   /* if they are the same registers */
10172   if (sameRegs (AOP (right), AOP (result)))
10173     goto release;
10174
10175   /* if the result is a bit */
10176   if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10177     {
10178       /* if the right size is a literal then
10179          we know what the value is */
10180       if (AOP_TYPE (right) == AOP_LIT)
10181         {
10182           if (((int) operandLitValue (right)))
10183             aopPut (AOP (result), one, 0);
10184           else
10185             aopPut (AOP (result), zero, 0);
10186           goto release;
10187         }
10188
10189       /* the right is also a bit variable */
10190       if (AOP_TYPE (right) == AOP_CRY)
10191         {
10192           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10193           aopPut (AOP (result), "c", 0);
10194           goto release;
10195         }
10196
10197       /* we need to or */
10198       toBoolean (right);
10199       aopPut (AOP (result), "a", 0);
10200       goto release;
10201     }
10202
10203   /* bit variables done */
10204   /* general case */
10205   size = AOP_SIZE (result);
10206   offset = 0;
10207   if (AOP_TYPE (right) == AOP_LIT)
10208     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10209
10210   if ((size > 1) &&
10211       (AOP_TYPE (result) != AOP_REG) &&
10212       (AOP_TYPE (right) == AOP_LIT) &&
10213       !IS_FLOAT (operandType (right)))
10214     {
10215       _startLazyDPSEvaluation ();
10216       while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10217         {
10218           aopPut (AOP (result),
10219                   aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
10220                   offset);
10221           offset++;
10222           size--;
10223         }
10224       /* And now fill the rest with zeros. */
10225       if (size)
10226         {
10227           emitcode ("clr", "a");
10228         }
10229       while (size--)
10230         {
10231           aopPut (AOP (result), "a", offset++);
10232         }
10233       _endLazyDPSEvaluation ();
10234     }
10235   else
10236     {
10237       _startLazyDPSEvaluation ();
10238       while (size--)
10239         {
10240           aopPut (AOP (result),
10241                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10242                   offset);
10243           offset++;
10244         }
10245       _endLazyDPSEvaluation ();
10246     }
10247
10248 release:
10249   freeAsmop (right, NULL, ic, FALSE);
10250   freeAsmop (result, NULL, ic, TRUE);
10251 }
10252
10253 /*-----------------------------------------------------------------*/
10254 /* genJumpTab - generates code for jump table                      */
10255 /*-----------------------------------------------------------------*/
10256 static void
10257 genJumpTab (iCode * ic)
10258 {
10259   symbol *jtab;
10260   char *l;
10261
10262   D (emitcode (";", "genJumpTab ");
10263     );
10264
10265   aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10266   /* get the condition into accumulator */
10267   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
10268   MOVA (l);
10269   /* multiply by four! */
10270   emitcode ("add", "a,acc");
10271   emitcode ("add", "a,acc");
10272   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10273
10274   jtab = newiTempLabel (NULL);
10275   emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
10276   emitcode ("jmp", "@a+dptr");
10277   emitcode ("", "%05d$:", jtab->key + 100);
10278   /* now generate the jump labels */
10279   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10280        jtab = setNextItem (IC_JTLABELS (ic)))
10281     emitcode ("ljmp", "%05d$", jtab->key + 100);
10282
10283 }
10284
10285 /*-----------------------------------------------------------------*/
10286 /* genCast - gen code for casting                                  */
10287 /*-----------------------------------------------------------------*/
10288 static void
10289 genCast (iCode * ic)
10290 {
10291   operand *result = IC_RESULT (ic);
10292   sym_link *ctype = operandType (IC_LEFT (ic));
10293   sym_link *rtype = operandType (IC_RIGHT (ic));
10294   operand *right = IC_RIGHT (ic);
10295   int size, offset;
10296
10297   D (emitcode (";", "genCast ");
10298     );
10299
10300   /* if they are equivalent then do nothing */
10301   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10302     return;
10303
10304   aopOp (right, ic, FALSE, FALSE);
10305   aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
10306
10307   /* if the result is a bit */
10308   // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10309   if (IS_BITVAR(OP_SYMBOL(result)->type))
10310     {
10311       /* if the right size is a literal then
10312          we know what the value is */
10313       if (AOP_TYPE (right) == AOP_LIT)
10314         {
10315           if (((int) operandLitValue (right)))
10316             aopPut (AOP (result), one, 0);
10317           else
10318             aopPut (AOP (result), zero, 0);
10319
10320           goto release;
10321         }
10322
10323       /* the right is also a bit variable */
10324       if (AOP_TYPE (right) == AOP_CRY)
10325         {
10326           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10327           aopPut (AOP (result), "c", 0);
10328           goto release;
10329         }
10330
10331       /* we need to or */
10332       toBoolean (right);
10333       aopPut (AOP (result), "a", 0);
10334       goto release;
10335     }
10336
10337   /* if they are the same size : or less */
10338   if (AOP_SIZE (result) <= AOP_SIZE (right))
10339     {
10340
10341       /* if they are in the same place */
10342       if (sameRegs (AOP (right), AOP (result)))
10343         goto release;
10344
10345       /* if they in different places then copy */
10346       size = AOP_SIZE (result);
10347       offset = 0;
10348       _startLazyDPSEvaluation ();
10349       while (size--)
10350         {
10351           aopPut (AOP (result),
10352                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10353                   offset);
10354           offset++;
10355         }
10356       _endLazyDPSEvaluation ();
10357       goto release;
10358     }
10359
10360
10361   /* if the result is of type pointer */
10362   if (IS_PTR (ctype))
10363     {
10364
10365       int p_type;
10366       sym_link *type = operandType (right);
10367
10368       /* pointer to generic pointer */
10369       if (IS_GENPTR (ctype))
10370         {
10371           char *l = zero;
10372
10373           if (IS_PTR (type))
10374             {
10375               p_type = DCL_TYPE (type);
10376             }
10377           else
10378             {
10379 #if OLD_CAST_BEHAVIOR
10380               /* KV: we are converting a non-pointer type to
10381                * a generic pointer. This (ifdef'd out) code
10382                * says that the resulting generic pointer
10383                * should have the same class as the storage
10384                * location of the non-pointer variable.
10385                *
10386                * For example, converting an int (which happens
10387                * to be stored in DATA space) to a pointer results
10388                * in a DATA generic pointer; if the original int
10389                * in XDATA space, so will be the resulting pointer.
10390                *
10391                * I don't like that behavior, and thus this change:
10392                * all such conversions will be forced to XDATA and
10393                * throw a warning. If you want some non-XDATA
10394                * type, or you want to suppress the warning, you
10395                * must go through an intermediate cast, like so:
10396                *
10397                * char _generic *gp = (char _xdata *)(intVar);
10398                */
10399               sym_link *etype = getSpec (type);
10400
10401               /* we have to go by the storage class */
10402               if (SPEC_OCLS (etype) != generic)
10403                 {
10404                   p_type = PTR_TYPE (SPEC_OCLS (etype));
10405                 }
10406               else
10407 #endif
10408                 {
10409                   /* Converting unknown class (i.e. register variable)
10410                    * to generic pointer. This is not good, but
10411                    * we'll make a guess (and throw a warning).
10412                    */
10413                   p_type = FPOINTER;
10414                   werror (W_INT_TO_GEN_PTR_CAST);
10415                 }
10416             }
10417
10418           /* the first two bytes are known */
10419           size = GPTRSIZE - 1;
10420           offset = 0;
10421           _startLazyDPSEvaluation ();
10422           while (size--)
10423             {
10424               aopPut (AOP (result),
10425                       aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10426                       offset);
10427               offset++;
10428             }
10429           _endLazyDPSEvaluation ();
10430
10431           /* the last byte depending on type */
10432           switch (p_type)
10433             {
10434             case IPOINTER:
10435             case POINTER:
10436               l = zero;
10437               break;
10438             case FPOINTER:
10439               l = one;
10440               break;
10441             case CPOINTER:
10442               l = "#0x02";
10443               break;
10444             case PPOINTER:
10445               l = "#0x03";
10446               break;
10447
10448             default:
10449               /* this should never happen */
10450               werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10451                       "got unknown pointer type");
10452               exit (1);
10453             }
10454           aopPut (AOP (result), l, GPTRSIZE - 1);
10455           goto release;
10456         }
10457
10458       /* just copy the pointers */
10459       size = AOP_SIZE (result);
10460       offset = 0;
10461       _startLazyDPSEvaluation ();
10462       while (size--)
10463         {
10464           aopPut (AOP (result),
10465                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10466                   offset);
10467           offset++;
10468         }
10469       _endLazyDPSEvaluation ();
10470       goto release;
10471     }
10472
10473   /* so we now know that the size of destination is greater
10474      than the size of the source */
10475   /* we move to result for the size of source */
10476   size = AOP_SIZE (right);
10477   offset = 0;
10478   _startLazyDPSEvaluation ();
10479   while (size--)
10480     {
10481       aopPut (AOP (result),
10482               aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10483               offset);
10484       offset++;
10485     }
10486   _endLazyDPSEvaluation ();
10487
10488   /* now depending on the sign of the source && destination */
10489   size = AOP_SIZE (result) - AOP_SIZE (right);
10490   /* if unsigned or not an integral type */
10491   /* also, if the source is a bit, we don't need to sign extend, because
10492    * it can't possibly have set the sign bit.
10493    */
10494   if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
10495     {
10496       while (size--)
10497         {
10498           aopPut (AOP (result), zero, offset++);
10499         }
10500     }
10501   else
10502     {
10503       /* we need to extend the sign :{ */
10504       char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
10505                         FALSE, FALSE, TRUE);
10506       MOVA (l);
10507       emitcode ("rlc", "a");
10508       emitcode ("subb", "a,acc");
10509       while (size--)
10510         aopPut (AOP (result), "a", offset++);
10511     }
10512
10513   /* we are done hurray !!!! */
10514
10515 release:
10516   freeAsmop (right, NULL, ic, TRUE);
10517   freeAsmop (result, NULL, ic, TRUE);
10518
10519 }
10520
10521 /*-----------------------------------------------------------------*/
10522 /* genDjnz - generate decrement & jump if not zero instrucion      */
10523 /*-----------------------------------------------------------------*/
10524 static int
10525 genDjnz (iCode * ic, iCode * ifx)
10526 {
10527   symbol *lbl, *lbl1;
10528   if (!ifx)
10529     return 0;
10530
10531   /* if the if condition has a false label
10532      then we cannot save */
10533   if (IC_FALSE (ifx))
10534     return 0;
10535
10536   /* if the minus is not of the form
10537      a = a - 1 */
10538   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
10539       !IS_OP_LITERAL (IC_RIGHT (ic)))
10540     return 0;
10541
10542   if (operandLitValue (IC_RIGHT (ic)) != 1)
10543     return 0;
10544
10545   /* if the size of this greater than one then no
10546      saving */
10547   if (getSize (operandType (IC_RESULT (ic))) > 1)
10548     return 0;
10549
10550   /* otherwise we can save BIG */
10551   D(emitcode(";", "genDjnz"););
10552
10553   lbl = newiTempLabel (NULL);
10554   lbl1 = newiTempLabel (NULL);
10555
10556   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10557
10558   if (AOP_NEEDSACC(IC_RESULT(ic)))
10559   {
10560       /* If the result is accessed indirectly via
10561        * the accumulator, we must explicitly write
10562        * it back after the decrement.
10563        */
10564       char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
10565       
10566       if (strcmp(rByte, "a"))
10567       {
10568            /* Something is hopelessly wrong */
10569            fprintf(stderr, "*** warning: internal error at %s:%d\n",
10570                    __FILE__, __LINE__);
10571            /* We can just give up; the generated code will be inefficient,
10572             * but what the hey.
10573             */
10574            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10575            return 0;
10576       }
10577       emitcode ("dec", "%s", rByte);
10578       aopPut(AOP(IC_RESULT(ic)), rByte, 0);
10579       emitcode ("jnz", "%05d$", lbl->key + 100);
10580   }
10581   else if (IS_AOP_PREG (IC_RESULT (ic)))
10582     {
10583       emitcode ("dec", "%s",
10584                 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10585       emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10586       emitcode ("jnz", "%05d$", lbl->key + 100);
10587     }
10588   else
10589     {
10590       emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
10591                 lbl->key + 100);
10592     }
10593   emitcode ("sjmp", "%05d$", lbl1->key + 100);
10594   emitcode ("", "%05d$:", lbl->key + 100);
10595   emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
10596   emitcode ("", "%05d$:", lbl1->key + 100);
10597
10598   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10599   ifx->generated = 1;
10600   return 1;
10601 }
10602
10603 /*-----------------------------------------------------------------*/
10604 /* genReceive - generate code for a receive iCode                  */
10605 /*-----------------------------------------------------------------*/
10606 static void
10607 genReceive (iCode * ic)
10608 {
10609
10610   D (emitcode (";", "genReceive ");
10611     );
10612
10613   if (isOperandInFarSpace (IC_RESULT (ic)) &&
10614       (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
10615        IS_TRUE_SYMOP (IC_RESULT (ic))))
10616     {
10617       int size = getSize (operandType (IC_RESULT (ic)));
10618       int offset = fReturnSizeDS390 - size;
10619       while (size--)
10620         {
10621           emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
10622                             fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
10623           offset++;
10624         }
10625       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10626       size = AOP_SIZE (IC_RESULT (ic));
10627       offset = 0;
10628       while (size--)
10629         {
10630           emitcode ("pop", "acc");
10631           aopPut (AOP (IC_RESULT (ic)), "a", offset++);
10632         }
10633
10634     }
10635   else
10636     {
10637       _G.accInUse++;
10638       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10639       _G.accInUse--;
10640       assignResultValue (IC_RESULT (ic));
10641     }
10642
10643   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10644 }
10645
10646 /*-----------------------------------------------------------------*/
10647 /* gen390Code - generate code for Dallas 390 based controllers     */
10648 /*-----------------------------------------------------------------*/
10649 void
10650 gen390Code (iCode * lic)
10651 {
10652   iCode *ic;
10653   int cln = 0;
10654
10655   lineHead = lineCurr = NULL;
10656
10657   if (options.model == MODEL_FLAT24) {
10658     fReturnSizeDS390 = 5;
10659     fReturn = fReturn24;
10660   } else {
10661     fReturnSizeDS390 = 4;
10662     fReturn = fReturn16;
10663     options.stack10bit=0;
10664   }
10665 #if 0
10666   //REMOVE ME!!!
10667   /* print the allocation information */
10668   if (allocInfo)
10669     printAllocInfo (currFunc, codeOutFile);
10670 #endif
10671   /* if debug information required */
10672   if (options.debug && currFunc)
10673     {
10674       cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
10675       _G.debugLine = 1;
10676       if (IS_STATIC (currFunc->etype))
10677         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
10678       else
10679         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
10680       _G.debugLine = 0;
10681     }
10682   /* stack pointer name */
10683   if (options.useXstack)
10684     spname = "_spx";
10685   else
10686     spname = "sp";
10687
10688
10689   for (ic = lic; ic; ic = ic->next)
10690     {
10691
10692       if (cln != ic->lineno)
10693         {
10694           if (options.debug)
10695             {
10696               _G.debugLine = 1;
10697               emitcode ("", "C$%s$%d$%d$%d ==.",
10698                         FileBaseName (ic->filename), ic->lineno,
10699                         ic->level, ic->block);
10700               _G.debugLine = 0;
10701             }
10702           emitcode (";", "%s %d", ic->filename, ic->lineno);
10703           cln = ic->lineno;
10704         }
10705       /* if the result is marked as
10706          spilt and rematerializable or code for
10707          this has already been generated then
10708          do nothing */
10709       if (resultRemat (ic) || ic->generated)
10710         continue;
10711
10712       /* depending on the operation */
10713       switch (ic->op)
10714         {
10715         case '!':
10716           genNot (ic);
10717           break;
10718
10719         case '~':
10720           genCpl (ic);
10721           break;
10722
10723         case UNARYMINUS:
10724           genUminus (ic);
10725           break;
10726
10727         case IPUSH:
10728           genIpush (ic);
10729           break;
10730
10731         case IPOP:
10732           /* IPOP happens only when trying to restore a
10733              spilt live range, if there is an ifx statement
10734              following this pop then the if statement might
10735              be using some of the registers being popped which
10736              would destory the contents of the register so
10737              we need to check for this condition and handle it */
10738           if (ic->next &&
10739               ic->next->op == IFX &&
10740               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
10741             genIfx (ic->next, ic);
10742           else
10743             genIpop (ic);
10744           break;
10745
10746         case CALL:
10747           genCall (ic);
10748           break;
10749
10750         case PCALL:
10751           genPcall (ic);
10752           break;
10753
10754         case FUNCTION:
10755           genFunction (ic);
10756           break;
10757
10758         case ENDFUNCTION:
10759           genEndFunction (ic);
10760           break;
10761
10762         case RETURN:
10763           genRet (ic);
10764           break;
10765
10766         case LABEL:
10767           genLabel (ic);
10768           break;
10769
10770         case GOTO:
10771           genGoto (ic);
10772           break;
10773
10774         case '+':
10775           genPlus (ic);
10776           break;
10777
10778         case '-':
10779           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
10780             genMinus (ic);
10781           break;
10782
10783         case '*':
10784           genMult (ic);
10785           break;
10786
10787         case '/':
10788           genDiv (ic);
10789           break;
10790
10791         case '%':
10792           genMod (ic);
10793           break;
10794
10795         case '>':
10796           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
10797           break;
10798
10799         case '<':
10800           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
10801           break;
10802
10803         case LE_OP:
10804         case GE_OP:
10805         case NE_OP:
10806
10807           /* note these two are xlated by algebraic equivalence
10808              during parsing SDCC.y */
10809           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10810                   "got '>=' or '<=' shouldn't have come here");
10811           break;
10812
10813         case EQ_OP:
10814           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
10815           break;
10816
10817         case AND_OP:
10818           genAndOp (ic);
10819           break;
10820
10821         case OR_OP:
10822           genOrOp (ic);
10823           break;
10824
10825         case '^':
10826           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
10827           break;
10828
10829         case '|':
10830           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
10831           break;
10832
10833         case BITWISEAND:
10834           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
10835           break;
10836
10837         case INLINEASM:
10838           genInline (ic);
10839           break;
10840
10841         case RRC:
10842           genRRC (ic);
10843           break;
10844
10845         case RLC:
10846           genRLC (ic);
10847           break;
10848
10849         case GETHBIT:
10850           genGetHbit (ic);
10851           break;
10852
10853         case LEFT_OP:
10854           genLeftShift (ic);
10855           break;
10856
10857         case RIGHT_OP:
10858           genRightShift (ic);
10859           break;
10860
10861         case GET_VALUE_AT_ADDRESS:
10862           genPointerGet (ic,hasInc(IC_LEFT(ic),ic));
10863           break;
10864
10865         case '=':
10866           if (POINTER_SET (ic))
10867             genPointerSet (ic,hasInc(IC_RESULT(ic),ic));
10868           else
10869             genAssign (ic);
10870           break;
10871
10872         case IFX:
10873           genIfx (ic, NULL);
10874           break;
10875
10876         case ADDRESS_OF:
10877           genAddrOf (ic);
10878           break;
10879
10880         case JUMPTABLE:
10881           genJumpTab (ic);
10882           break;
10883
10884         case CAST:
10885           genCast (ic);
10886           break;
10887
10888         case RECEIVE:
10889           genReceive (ic);
10890           break;
10891
10892         case SEND:
10893           addSet (&_G.sendSet, ic);
10894           break;
10895
10896         case ARRAYINIT:
10897             genArrayInit(ic);
10898             break;
10899             
10900         default:
10901           ic = ic;
10902         }
10903     }
10904
10905
10906   /* now we are ready to call the
10907      peep hole optimizer */
10908   if (!options.nopeep)
10909     peepHole (&lineHead);
10910
10911   /* now do the actual printing */
10912   printLine (lineHead, codeOutFile);
10913   return;
10914 }