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