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