Fix broken genXor in bug-460444
[fw/sdcc] / src / ds390 / gen.c
1 /*-------------------------------------------------------------------------
2   gen.c - source file for code generation for DS80C390
3
4   Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
5          and -  Jean-Louis VERN.jlvern@writeme.com (1999)
6   Bug Fixes  -  Wojciech Stryjewski  wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7   DS390 adaptation by Kevin Vigor <kevin@vigor.nu>
8
9   This program is free software; you can redistribute it and/or modify it
10   under the terms of the GNU General Public License as published by the
11   Free Software Foundation; either version 2, or (at your option) any
12   later version.
13
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License for more details.
18
19   You should have received a copy of the GNU General Public License
20   along with this program; if not, write to the Free Software
21   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22
23   In other words, you are welcome to use, share and improve this program.
24   You are forbidden to forbid anyone else to use, share and improve
25   what you give them.   Help stamp out software-hoarding!
26 -------------------------------------------------------------------------*/
27
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <ctype.h>
32
33 #include <common.h>
34 #include "ralloc.h"
35 #include "gen.h"
36 #include "SDCCglobl.h"
37 #include "newalloc.h"
38
39 #ifdef HAVE_SYS_ISA_DEFS_H
40 #include <sys/isa_defs.h>
41 #else
42 #ifdef HAVE_MACHINE_ENDIAN_H
43 #include <machine/endian.h>
44 #else
45 #ifdef HAVE_ENDIAN_H
46 #include <endian.h>
47 #else
48 #if !defined(__BORLANDC__) && !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__CYGWIN__)
49 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
50 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
51 #endif
52 #endif
53 #endif
54 #endif
55
56 #define BETTER_LITERAL_SHIFT
57
58 char *aopLiteral (value * val, int offset);
59
60 /* this is the down and dirty file with all kinds of
61    kludgy & hacky stuff. This is what it is all about
62    CODE GENERATION for a specific MCU . some of the
63    routines may be reusable, will have to see */
64
65 static char *zero = "#0x00";
66 static char *one = "#0x01";
67 static char *spname;
68
69 #define D(x) x
70
71 #define TR_DPTR(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_DPTR1 %s ", s); }
72 #define TR_AP(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_AP %s ", s); }
73
74 unsigned fReturnSizeDS390 = 5;  /* shared with ralloc.c */
75 static char *fReturn24[] =
76 {"dpl", "dph", "dpx", "b", "a"};
77 static char *fReturn16[] =
78 {"dpl", "dph", "b", "a"};
79 static char **fReturn = fReturn24;
80 static char *accUse[] =
81 {"a", "b"};
82
83 static short rbank = -1;
84
85 static struct
86   {
87     short r0Pushed;
88     short r1Pushed;
89     short accInUse;
90     short inLine;
91     short debugLine;
92     short nRegsSaved;
93     set *sendSet;
94   }
95 _G;
96
97 static void saveRBank (int, iCode *, bool);
98
99 #define RESULTONSTACK(x) \
100                          (IC_RESULT(x) && IC_RESULT(x)->aop && \
101                          IC_RESULT(x)->aop->type == AOP_STK )
102
103 /* #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x); */
104 #define MOVA(x) { char *_mova_tmp = strdup(x); \
105                  if (strcmp(_mova_tmp,"a") && strcmp(_mova_tmp,"acc")) \
106                  { \
107                     emitcode("mov","a,%s",_mova_tmp); \
108                  } \
109                  free(_mova_tmp); \
110                 }
111 #define CLRC    emitcode("clr","c")
112 #define SETC    emitcode("setb","c")
113
114 // A scratch register which will be used to hold
115 // result bytes from operands in far space via DPTR2.
116 #define DP2_RESULT_REG  "ap"
117
118 static lineNode *lineHead = NULL;
119 static lineNode *lineCurr = NULL;
120
121 static unsigned char SLMask[] =
122 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
123  0xE0, 0xC0, 0x80, 0x00};
124 static unsigned char SRMask[] =
125 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
126  0x07, 0x03, 0x01, 0x00};
127
128 #define LSB     0
129 #define MSB16   1
130 #define MSB24   2
131 #define MSB32   3
132
133 /*-----------------------------------------------------------------*/
134 /* emitcode - writes the code into a file : for now it is simple    */
135 /*-----------------------------------------------------------------*/
136 static void
137 emitcode (char *inst, char *fmt,...)
138 {
139   va_list ap;
140   char lb[INITIAL_INLINEASM];
141   char *lbp = lb;
142
143   va_start (ap, fmt);
144
145   if (inst && *inst)
146     {
147       if (fmt && *fmt)
148         sprintf (lb, "%s\t", inst);
149       else
150         sprintf (lb, "%s", inst);
151       vsprintf (lb + (strlen (lb)), fmt, ap);
152     }
153   else
154     vsprintf (lb, fmt, ap);
155
156   while (isspace (*lbp))
157     lbp++;
158
159   if (lbp && *lbp)
160     lineCurr = (lineCurr ?
161                 connectLine (lineCurr, newLineNode (lb)) :
162                 (lineHead = newLineNode (lb)));
163   lineCurr->isInline = _G.inLine;
164   lineCurr->isDebug = _G.debugLine;
165   va_end (ap);
166 }
167
168 /*-----------------------------------------------------------------*/
169 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
170 /*-----------------------------------------------------------------*/
171 static regs *
172 getFreePtr (iCode * ic, asmop ** aopp, bool result)
173 {
174   bool r0iu = FALSE, r1iu = FALSE;
175   bool r0ou = FALSE, r1ou = FALSE;
176
177   /* the logic: if r0 & r1 used in the instruction
178      then we are in trouble otherwise */
179
180   /* first check if r0 & r1 are used by this
181      instruction, in which case we are in trouble */
182   r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
183   r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
184   if (r0iu && r1iu) {
185       goto endOfWorld;
186     }
187
188   r0ou = bitVectBitValue (ic->rMask, R0_IDX);
189   r1ou = bitVectBitValue (ic->rMask, R1_IDX);
190
191   /* if no usage of r0 then return it */
192   if (!r0iu && !r0ou)
193     {
194       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
195       (*aopp)->type = AOP_R0;
196
197       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
198     }
199
200   /* if no usage of r1 then return it */
201   if (!r1iu && !r1ou)
202     {
203       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
204       (*aopp)->type = AOP_R1;
205
206       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R1_IDX);
207     }
208
209   /* now we know they both have usage */
210   /* if r0 not used in this instruction */
211   if (!r0iu)
212     {
213       /* push it if not already pushed */
214       if (!_G.r0Pushed)
215         {
216           emitcode ("push", "%s",
217                     ds390_regWithIdx (R0_IDX)->dname);
218           _G.r0Pushed++;
219         }
220
221       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
222       (*aopp)->type = AOP_R0;
223
224       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
225     }
226
227   /* if r1 not used then */
228
229   if (!r1iu)
230     {
231       /* push it if not already pushed */
232       if (!_G.r1Pushed)
233         {
234           emitcode ("push", "%s",
235                     ds390_regWithIdx (R1_IDX)->dname);
236           _G.r1Pushed++;
237         }
238
239       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
240       (*aopp)->type = AOP_R1;
241       return ds390_regWithIdx (R1_IDX);
242     }
243
244 endOfWorld:
245   /* I said end of world but not quite end of world yet */
246   /* if this is a result then we can push it on the stack */
247   if (result)
248     {
249       (*aopp)->type = AOP_STK;
250       return NULL;
251     }
252
253   /* other wise this is true end of the world */
254   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
255           "getFreePtr should never reach here");
256   exit (1);
257 }
258
259 /*-----------------------------------------------------------------*/
260 /* newAsmop - creates a new asmOp                                  */
261 /*-----------------------------------------------------------------*/
262 static asmop *
263 newAsmop (short type)
264 {
265   asmop *aop;
266
267   aop = Safe_calloc (1, sizeof (asmop));
268   aop->type = type;
269   return aop;
270 }
271
272 static int _currentDPS;         /* Current processor DPS. */
273 static int _desiredDPS;         /* DPS value compiler thinks we should be using. */
274 static int _lazyDPS = 0;        /* if non-zero, we are doing lazy evaluation of DPS changes. */
275
276 /*-----------------------------------------------------------------*/
277 /* genSetDPTR: generate code to select which DPTR is in use (zero  */
278 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390     */
279 /* alternate DPTR (DPL1/DPH1/DPX1).          */
280 /*-----------------------------------------------------------------*/
281 static void
282 genSetDPTR (int n)
283 {
284
285   /* If we are doing lazy evaluation, simply note the desired
286    * change, but don't emit any code yet.
287    */
288   if (_lazyDPS)
289     {
290       _desiredDPS = n;
291       return;
292     }
293
294   if (!n)
295     {
296       emitcode ("mov", "dps, #0x00");
297     }
298   else
299     {
300       TR_DPTR("#1");
301       emitcode ("mov", "dps, #0x01");
302     }
303 }
304
305 /*-----------------------------------------------------------------*/
306 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
307 /*                   */
308 /* Any code that operates on DPTR (NB: not on the individual     */
309 /* components, like DPH) *must* call _flushLazyDPS() before using  */
310 /* DPTR within a lazy DPS evaluation block.        */
311 /*                   */
312 /* Note that aopPut and aopGet already contain the proper calls to */
313 /* _flushLazyDPS, so it is safe to use these calls within a lazy   */
314 /* DPS evaluation block.             */
315 /*                   */
316 /* Also, _flushLazyDPS must be called before any flow control      */
317 /* operations that could potentially branch out of the block.    */
318 /*                         */
319 /* Lazy DPS evaluation is simply an optimization (though an      */
320 /* important one), so if in doubt, leave it out.       */
321 /*-----------------------------------------------------------------*/
322 static void
323 _startLazyDPSEvaluation (void)
324 {
325   _currentDPS = 0;
326   _desiredDPS = 0;
327 #ifdef BETTER_LITERAL_SHIFT  
328   _lazyDPS++;
329 #else
330   _lazyDPS = 1;
331 #endif  
332 }
333
334 /*-----------------------------------------------------------------*/
335 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
336 /* desired one. Call before using DPTR within a lazy DPS evaluation */
337 /* block.                */
338 /*-----------------------------------------------------------------*/
339 static void
340 _flushLazyDPS (void)
341 {
342   if (!_lazyDPS)
343     {
344       /* nothing to do. */
345       return;
346     }
347
348   if (_desiredDPS != _currentDPS)
349     {
350       if (_desiredDPS)
351         {
352           emitcode ("inc", "dps");
353         }
354       else
355         {
356           emitcode ("dec", "dps");
357         }
358       _currentDPS = _desiredDPS;
359     }
360 }
361
362 /*-----------------------------------------------------------------*/
363 /* _endLazyDPSEvaluation: end lazy DPS evaluation block.     */
364 /*                   */
365 /* Forces us back to the safe state (standard DPTR selected).    */
366 /*-----------------------------------------------------------------*/
367 static void
368 _endLazyDPSEvaluation (void)
369 {
370 #ifdef BETTER_LITERAL_SHIFT  
371   _lazyDPS--;
372 #else
373   _lazyDPS = 0;
374 #endif    
375   if (!_lazyDPS)
376   {
377     if (_currentDPS)
378     {
379       genSetDPTR (0);
380       _flushLazyDPS ();
381     }
382     _currentDPS = 0;
383     _desiredDPS = 0;
384   }
385 }
386
387
388
389 /*-----------------------------------------------------------------*/
390 /* pointerCode - returns the code for a pointer type               */
391 /*-----------------------------------------------------------------*/
392 static int
393 pointerCode (sym_link * etype)
394 {
395
396   return PTR_TYPE (SPEC_OCLS (etype));
397
398 }
399
400 /*-----------------------------------------------------------------*/
401 /* aopForSym - for a true symbol                                   */
402 /*-----------------------------------------------------------------*/
403 static asmop *
404 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
405 {
406   asmop *aop;
407   memmap *space = SPEC_OCLS (sym->etype);
408
409   /* if already has one */
410   if (sym->aop)
411     return sym->aop;
412
413   /* assign depending on the storage class */
414   /* if it is on the stack or indirectly addressable */
415   /* space we need to assign either r0 or r1 to it   */
416   if ((sym->onStack && !options.stack10bit) || sym->iaccess)
417     {
418       sym->aop = aop = newAsmop (0);
419       aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
420       aop->size = getSize (sym->type);
421
422       /* now assign the address of the variable to
423          the pointer register */
424       if (aop->type != AOP_STK)
425         {
426
427           if (sym->onStack)
428             {
429               if (_G.accInUse)
430                 emitcode ("push", "acc");
431
432               emitcode ("mov", "a,_bp");
433               emitcode ("add", "a,#0x%02x",
434                         ((sym->stack < 0) ?
435                          ((char) (sym->stack - _G.nRegsSaved)) :
436                          ((char) sym->stack)) & 0xff);
437               emitcode ("mov", "%s,a",
438                         aop->aopu.aop_ptr->name);
439
440               if (_G.accInUse)
441                 emitcode ("pop", "acc");
442             }
443           else
444             emitcode ("mov", "%s,#%s",
445                       aop->aopu.aop_ptr->name,
446                       sym->rname);
447           aop->paged = space->paged;
448         }
449       else
450         aop->aopu.aop_stk = sym->stack;
451       return aop;
452     }
453
454   if (sym->onStack && options.stack10bit)
455     {
456       /* It's on the 10 bit stack, which is located in
457        * far data space.
458        */
459
460       if (_G.accInUse)
461         emitcode ("push", "acc");
462
463       emitcode ("mov", "a,_bpx");
464       emitcode ("clr","c");
465       emitcode ("subb", "a,#0x%02x",
466                 -((sym->stack < 0) ?
467                   ((short) (sym->stack - _G.nRegsSaved)) :
468                   ((short) sym->stack)) & 0xff);
469       emitcode ("mov","b,a");
470       emitcode ("mov","a,#0x%02x",(-((sym->stack < 0) ?
471                                      ((short) (sym->stack - _G.nRegsSaved)) :
472                                      ((short) sym->stack)) >> 8) & 0xff);
473       emitcode ("subb","a,_bpx+1");
474       if (useDP2) {
475           if (options.model == MODEL_FLAT24)
476               emitcode ("mov", "dpx1,#0x40");
477           TR_DPTR("#2");
478           emitcode ("mov", "dph1,a");
479           emitcode ("mov", "dpl1,b");
480       } else {
481           if (options.model == MODEL_FLAT24)
482               emitcode ("mov", "dpx,#0x40");
483           emitcode ("mov", "dph,a");
484           emitcode ("mov", "dpl,b");
485       }
486
487       if (_G.accInUse)
488         emitcode ("pop", "acc");
489
490       sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
491       aop->size = getSize (sym->type);
492       return aop;
493     }
494
495   /* if in bit space */
496   if (IN_BITSPACE (space))
497     {
498       sym->aop = aop = newAsmop (AOP_CRY);
499       aop->aopu.aop_dir = sym->rname;
500       aop->size = getSize (sym->type);
501       return aop;
502     }
503   /* if it is in direct space */
504   if (IN_DIRSPACE (space))
505     {
506       sym->aop = aop = newAsmop (AOP_DIR);
507       aop->aopu.aop_dir = sym->rname;
508       aop->size = getSize (sym->type);
509       return aop;
510     }
511
512   /* special case for a function */
513   if (IS_FUNC (sym->type))
514     {
515       sym->aop = aop = newAsmop (AOP_IMMD);
516       aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
517       strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
518       aop->size = FPTRSIZE;
519       return aop;
520     }
521
522   /* only remaining is far space */
523   /* in which case DPTR gets the address */
524   sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
525   if (useDP2)
526     {
527       genSetDPTR (1);
528       _flushLazyDPS ();
529       emitcode ("mov", "dptr,#%s", sym->rname);
530       genSetDPTR (0);
531     }
532   else
533     {
534       emitcode ("mov", "dptr,#%s", sym->rname);
535     }
536   aop->size = getSize (sym->type);
537
538   /* if it is in code space */
539   if (IN_CODESPACE (space))
540     aop->code = 1;
541
542   return aop;
543 }
544
545 /*-----------------------------------------------------------------*/
546 /* aopForRemat - rematerialzes an object                           */
547 /*-----------------------------------------------------------------*/
548 static asmop *
549 aopForRemat (symbol * sym)
550 {
551   iCode *ic = sym->rematiCode;
552   asmop *aop = newAsmop (AOP_IMMD);
553   int ptr_type =0;
554   int val = 0;
555
556   for (;;)
557     {
558       if (ic->op == '+')
559         val += (int) operandLitValue (IC_RIGHT (ic));
560       else if (ic->op == '-')
561         val -= (int) operandLitValue (IC_RIGHT (ic));
562       else if (IS_CAST_ICODE(ic)) {
563               sym_link *from_type = operandType(IC_RIGHT(ic));
564               aop->aopu.aop_immd.from_cast_remat = 1;
565               ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
566               ptr_type = DCL_TYPE(from_type);
567               if (ptr_type == IPOINTER) {
568                 // bug #481053
569                 ptr_type = POINTER;
570               }
571               continue ;
572       } else break;
573       
574       ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
575     }
576
577   if (val)
578     sprintf (buffer, "(%s %c 0x%04x)",
579              OP_SYMBOL (IC_LEFT (ic))->rname,
580              val >= 0 ? '+' : '-',
581              abs (val) & 0xffff);
582   else
583     strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
584
585   aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
586   strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
587   /* set immd2 field if required */
588   if (aop->aopu.aop_immd.from_cast_remat) {
589           sprintf(buffer,"#0x%02x",ptr_type);
590           aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
591           strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
592   }
593
594   return aop;
595 }
596
597 /*-----------------------------------------------------------------*/
598 /* regsInCommon - two operands have some registers in common       */
599 /*-----------------------------------------------------------------*/
600 static bool
601 regsInCommon (operand * op1, operand * op2)
602 {
603   symbol *sym1, *sym2;
604   int i;
605
606   /* if they have registers in common */
607   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
608     return FALSE;
609
610   sym1 = OP_SYMBOL (op1);
611   sym2 = OP_SYMBOL (op2);
612
613   if (sym1->nRegs == 0 || sym2->nRegs == 0)
614     return FALSE;
615
616   for (i = 0; i < sym1->nRegs; i++)
617     {
618       int j;
619       if (!sym1->regs[i])
620         continue;
621
622       for (j = 0; j < sym2->nRegs; j++)
623         {
624           if (!sym2->regs[j])
625             continue;
626
627           if (sym2->regs[j] == sym1->regs[i])
628             return TRUE;
629         }
630     }
631
632   return FALSE;
633 }
634
635 /*-----------------------------------------------------------------*/
636 /* operandsEqu - equivalent                                        */
637 /*-----------------------------------------------------------------*/
638 static bool
639 operandsEqu (operand * op1, operand * op2)
640 {
641   symbol *sym1, *sym2;
642
643   /* if they not symbols */
644   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
645     return FALSE;
646
647   sym1 = OP_SYMBOL (op1);
648   sym2 = OP_SYMBOL (op2);
649
650   /* if both are itemps & one is spilt
651      and the other is not then false */
652   if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
653       sym1->isspilt != sym2->isspilt)
654     return FALSE;
655
656   /* if they are the same */
657   if (sym1 == sym2)
658     return TRUE;
659
660   if (strcmp (sym1->rname, sym2->rname) == 0)
661     return TRUE;
662
663
664   /* if left is a tmp & right is not */
665   if (IS_ITEMP (op1) &&
666       !IS_ITEMP (op2) &&
667       sym1->isspilt &&
668       (sym1->usl.spillLoc == sym2))
669     return TRUE;
670
671   if (IS_ITEMP (op2) &&
672       !IS_ITEMP (op1) &&
673       sym2->isspilt &&
674       sym1->level > 0 &&
675       (sym2->usl.spillLoc == sym1))
676     return TRUE;
677
678   return FALSE;
679 }
680
681 /*-----------------------------------------------------------------*/
682 /* sameRegs - two asmops have the same registers                   */
683 /*-----------------------------------------------------------------*/
684 static bool
685 sameRegs (asmop * aop1, asmop * aop2)
686 {
687   int i;
688
689   if (aop1 == aop2)
690     {
691       if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
692         {
693           return FALSE;
694         }
695       return TRUE;
696     }
697
698   if (aop1->type != AOP_REG ||
699       aop2->type != AOP_REG)
700     return FALSE;
701
702   if (aop1->size != aop2->size)
703     return FALSE;
704
705   for (i = 0; i < aop1->size; i++)
706     if (aop1->aopu.aop_reg[i] !=
707         aop2->aopu.aop_reg[i])
708       return FALSE;
709
710   return TRUE;
711 }
712
713 /*-----------------------------------------------------------------*/
714 /* aopOp - allocates an asmop for an operand  :                    */
715 /*-----------------------------------------------------------------*/
716 static void
717 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
718 {
719   asmop *aop;
720   symbol *sym;
721   int i;
722
723   if (!op)
724     return;
725
726   /* if this a literal */
727   if (IS_OP_LITERAL (op))
728     {
729       op->aop = aop = newAsmop (AOP_LIT);
730       aop->aopu.aop_lit = op->operand.valOperand;
731       aop->size = getSize (operandType (op));
732       return;
733     }
734
735   /* if already has a asmop then continue */
736   if (op->aop)
737     return;
738
739   /* if the underlying symbol has a aop */
740   if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
741     {
742       op->aop = OP_SYMBOL (op)->aop;
743       return;
744     }
745
746   /* if this is a true symbol */
747   if (IS_TRUE_SYMOP (op))
748     {
749       op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
750       return;
751     }
752
753   /* this is a temporary : this has
754      only four choices :
755      a) register
756      b) spillocation
757      c) rematerialize
758      d) conditional
759      e) can be a return use only */
760
761   sym = OP_SYMBOL (op);
762
763
764   /* if the type is a conditional */
765   if (sym->regType == REG_CND)
766     {
767       aop = op->aop = sym->aop = newAsmop (AOP_CRY);
768       aop->size = 0;
769       return;
770     }
771
772   /* if it is spilt then two situations
773      a) is rematerialize
774      b) has a spill location */
775   if (sym->isspilt || sym->nRegs == 0)
776     {
777
778       /* rematerialize it NOW */
779       if (sym->remat)
780         {
781           sym->aop = op->aop = aop =
782             aopForRemat (sym);
783           aop->size = getSize (sym->type);
784           return;
785         }
786
787       if (sym->accuse)
788         {
789           int i;
790           aop = op->aop = sym->aop = newAsmop (AOP_ACC);
791           aop->size = getSize (sym->type);
792           for (i = 0; i < 2; i++)
793             aop->aopu.aop_str[i] = accUse[i];
794           return;
795         }
796
797       if (sym->ruonly)
798         {
799           int i;
800
801           if (useDP2)
802             {
803               /* a AOP_STR uses DPTR, but DPTR is already in use;
804                * we're just hosed.
805                */
806               fprintf (stderr, "*** Internal error: AOP_STR with DPTR in use! for operand %s\n",sym->name);
807             }
808
809           aop = op->aop = sym->aop = newAsmop (AOP_STR);
810           aop->size = getSize (sym->type);
811           for (i = 0; i < (int) fReturnSizeDS390; i++)
812             aop->aopu.aop_str[i] = fReturn[i];
813           return;
814         }
815
816       /* else spill location  */
817       sym->aop = op->aop = aop =
818         aopForSym (ic, sym->usl.spillLoc, result, useDP2);
819       aop->size = getSize (sym->type);
820       return;
821     }
822
823   /* must be in a register */
824   sym->aop = op->aop = aop = newAsmop (AOP_REG);
825   aop->size = sym->nRegs;
826   for (i = 0; i < sym->nRegs; i++)
827     aop->aopu.aop_reg[i] = sym->regs[i];
828 }
829
830 /*-----------------------------------------------------------------*/
831 /* freeAsmop - free up the asmop given to an operand               */
832 /*----------------------------------------------------------------*/
833 static void
834 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
835 {
836   asmop *aop;
837
838   if (!op)
839     aop = aaop;
840   else
841     aop = op->aop;
842
843   if (!aop)
844     return;
845
846   if (aop->freed)
847     goto dealloc;
848
849   aop->freed = 1;
850
851   /* depending on the asmop type only three cases need work AOP_RO
852      , AOP_R1 && AOP_STK */
853   switch (aop->type)
854     {
855     case AOP_R0:
856       if (_G.r0Pushed)
857         {
858           if (pop)
859             {
860               emitcode ("pop", "ar0");
861               _G.r0Pushed--;
862             }
863         }
864       bitVectUnSetBit (ic->rUsed, R0_IDX);
865       break;
866
867     case AOP_R1:
868       if (_G.r1Pushed)
869         {
870           if (pop)
871             {
872               emitcode ("pop", "ar1");
873               _G.r1Pushed--;
874             }
875         }
876       bitVectUnSetBit (ic->rUsed, R1_IDX);
877       break;
878
879     case AOP_STK:
880       {
881         int sz = aop->size;
882         int stk = aop->aopu.aop_stk + aop->size;
883         bitVectUnSetBit (ic->rUsed, R0_IDX);
884         bitVectUnSetBit (ic->rUsed, R1_IDX);
885
886         getFreePtr (ic, &aop, FALSE);
887
888         if (options.stack10bit)
889           {
890             /* I'm not sure what to do here yet... */
891             /* #STUB */
892             fprintf (stderr,
893                      "*** Warning: probably generating bad code for "
894                      "10 bit stack mode.\n");
895           }
896
897         if (stk)
898           {
899             emitcode ("mov", "a,_bp");
900             emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
901             emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
902           }
903         else
904           {
905             emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
906           }
907
908         while (sz--)
909           {
910             emitcode ("pop", "acc");
911             emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
912             if (!sz)
913               break;
914             emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
915           }
916         op->aop = aop;
917         freeAsmop (op, NULL, ic, TRUE);
918         if (_G.r0Pushed)
919           {
920             emitcode ("pop", "ar0");
921             _G.r0Pushed--;
922           }
923
924         if (_G.r1Pushed)
925           {
926             emitcode ("pop", "ar1");
927             _G.r1Pushed--;
928           }
929       }
930     }
931
932 dealloc:
933   /* all other cases just dealloc */
934   if (op)
935     {
936       op->aop = NULL;
937       if (IS_SYMOP (op))
938         {
939           OP_SYMBOL (op)->aop = NULL;
940           /* if the symbol has a spill */
941           if (SPIL_LOC (op))
942             SPIL_LOC (op)->aop = NULL;
943         }
944     }
945 }
946
947 /*------------------------------------------------------------------*/
948 /* aopGet - for fetching value of the aop                           */
949 /*                    */
950 /* Set canClobberACC if you are sure it is OK to clobber the value  */
951 /* in the accumulator. Set it FALSE otherwise; FALSE is always safe, */
952 /* just less efficient.               */
953 /*------------------------------------------------------------------*/
954
955 static char *
956 aopGet (asmop * aop,
957         int offset,
958         bool bit16,
959         bool dname,
960         bool canClobberACC)
961 {
962   char *s = buffer;
963   char *rs;
964
965   /* offset is greater than
966      size then zero */
967   if (offset > (aop->size - 1) &&
968       aop->type != AOP_LIT)
969     return zero;
970
971   /* depending on type */
972   switch (aop->type)
973     {
974
975     case AOP_R0:
976     case AOP_R1:
977       /* if we need to increment it */
978       while (offset > aop->coff)
979         {
980           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
981           aop->coff++;
982         }
983
984       while (offset < aop->coff)
985         {
986           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
987           aop->coff--;
988         }
989
990       aop->coff = offset;
991       if (aop->paged)
992         {
993           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
994           return (dname ? "acc" : "a");
995         }
996       sprintf (s, "@%s", aop->aopu.aop_ptr->name);
997       rs = Safe_calloc (1, strlen (s) + 1);
998       strcpy (rs, s);
999       return rs;
1000
1001     case AOP_DPTR:
1002     case AOP_DPTR2:
1003
1004       if (aop->type == AOP_DPTR2)
1005         {
1006           genSetDPTR (1);
1007           if (!canClobberACC)
1008             {
1009                     TR_AP("#1");
1010                     emitcode ("xch", "a, %s", DP2_RESULT_REG);
1011             }
1012         }
1013
1014       _flushLazyDPS ();
1015
1016       while (offset > aop->coff)
1017         {
1018           emitcode ("inc", "dptr");
1019           aop->coff++;
1020         }
1021
1022       while (offset < aop->coff)
1023         {
1024           emitcode ("lcall", "__decdptr");
1025           aop->coff--;
1026         }
1027
1028       aop->coff = offset;
1029       if (aop->code)
1030         {
1031           emitcode ("clr", "a");
1032           emitcode ("movc", "a,@a+dptr");
1033         }
1034       else
1035         {
1036           emitcode ("movx", "a,@dptr");
1037         }
1038
1039       if (aop->type == AOP_DPTR2)
1040         {
1041           genSetDPTR (0);
1042           if (!canClobberACC)
1043             {
1044        TR_AP("#2");
1045               emitcode ("xch", "a, %s", DP2_RESULT_REG);
1046               return DP2_RESULT_REG;
1047             }
1048         }
1049       return (dname ? "acc" : "a");
1050
1051     case AOP_IMMD:
1052       if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
1053               sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
1054       } else if (bit16)
1055         sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
1056       else if (offset)
1057         sprintf (s, "#(%s >> %d)",
1058                  aop->aopu.aop_immd.aop_immd1,
1059                  offset * 8);
1060       else
1061         sprintf (s, "#%s",
1062                  aop->aopu.aop_immd.aop_immd1);
1063       rs = Safe_calloc (1, strlen (s) + 1);
1064       strcpy (rs, s);
1065       return rs;
1066
1067     case AOP_DIR:
1068       if (offset)
1069         sprintf (s, "(%s + %d)",
1070                  aop->aopu.aop_dir,
1071                  offset);
1072       else
1073         sprintf (s, "%s", aop->aopu.aop_dir);
1074       rs = Safe_calloc (1, strlen (s) + 1);
1075       strcpy (rs, s);
1076       return rs;
1077
1078     case AOP_REG:
1079       if (dname)
1080         return aop->aopu.aop_reg[offset]->dname;
1081       else
1082         return aop->aopu.aop_reg[offset]->name;
1083
1084     case AOP_CRY:
1085       emitcode ("clr", "a");
1086       emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1087       emitcode ("rlc", "a");
1088       return (dname ? "acc" : "a");
1089
1090     case AOP_ACC:
1091       if (!offset && dname)
1092         return "acc";
1093       return aop->aopu.aop_str[offset];
1094
1095     case AOP_LIT:
1096       return aopLiteral (aop->aopu.aop_lit, offset);
1097
1098     case AOP_STR:
1099       aop->coff = offset;
1100       if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1101           dname)
1102         return "acc";
1103
1104       return aop->aopu.aop_str[offset];
1105
1106     }
1107
1108   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1109           "aopget got unsupported aop->type");
1110   exit (1);
1111 }
1112 /*-----------------------------------------------------------------*/
1113 /* aopPut - puts a string for a aop                                */
1114 /*-----------------------------------------------------------------*/
1115 static void
1116 aopPut (asmop * aop, char *s, int offset)
1117 {
1118   char *d = buffer;
1119
1120   if (aop->size && offset > (aop->size - 1))
1121     {
1122       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1123               "aopPut got offset > aop->size");
1124       exit (1);
1125     }
1126
1127   /* will assign value to value */
1128   /* depending on where it is ofcourse */
1129   switch (aop->type)
1130     {
1131     case AOP_DIR:
1132       if (offset)
1133         sprintf (d, "(%s + %d)",
1134                  aop->aopu.aop_dir, offset);
1135       else
1136         sprintf (d, "%s", aop->aopu.aop_dir);
1137
1138       if (strcmp (d, s))
1139         emitcode ("mov", "%s,%s", d, s);
1140
1141       break;
1142
1143     case AOP_REG:
1144       if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1145           strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1146         {
1147           if (*s == '@' ||
1148               strcmp (s, "r0") == 0 ||
1149               strcmp (s, "r1") == 0 ||
1150               strcmp (s, "r2") == 0 ||
1151               strcmp (s, "r3") == 0 ||
1152               strcmp (s, "r4") == 0 ||
1153               strcmp (s, "r5") == 0 ||
1154               strcmp (s, "r6") == 0 ||
1155               strcmp (s, "r7") == 0)
1156             emitcode ("mov", "%s,%s",
1157                       aop->aopu.aop_reg[offset]->dname, s);
1158           else
1159             emitcode ("mov", "%s,%s",
1160                       aop->aopu.aop_reg[offset]->name, s);
1161         }
1162       break;
1163
1164     case AOP_DPTR:
1165     case AOP_DPTR2:
1166
1167       if (aop->type == AOP_DPTR2)
1168         {
1169           genSetDPTR (1);
1170         }
1171       _flushLazyDPS ();
1172
1173       if (aop->code)
1174         {
1175           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1176                   "aopPut writting to code space");
1177           exit (1);
1178         }
1179
1180       while (offset > aop->coff)
1181         {
1182           aop->coff++;
1183           emitcode ("inc", "dptr");
1184         }
1185
1186       while (offset < aop->coff)
1187         {
1188           aop->coff--;
1189           emitcode ("lcall", "__decdptr");
1190         }
1191
1192       aop->coff = offset;
1193
1194       /* if not in accumulater */
1195       MOVA (s);
1196
1197       emitcode ("movx", "@dptr,a");
1198
1199       if (aop->type == AOP_DPTR2)
1200         {
1201           genSetDPTR (0);
1202         }
1203       break;
1204
1205     case AOP_R0:
1206     case AOP_R1:
1207       while (offset > aop->coff)
1208         {
1209           aop->coff++;
1210           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1211         }
1212       while (offset < aop->coff)
1213         {
1214           aop->coff--;
1215           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1216         }
1217       aop->coff = offset;
1218
1219       if (aop->paged)
1220         {
1221           MOVA (s);
1222           emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1223
1224         }
1225       else if (*s == '@')
1226         {
1227           MOVA (s);
1228           emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1229         }
1230       else if (strcmp (s, "r0") == 0 ||
1231                strcmp (s, "r1") == 0 ||
1232                strcmp (s, "r2") == 0 ||
1233                strcmp (s, "r3") == 0 ||
1234                strcmp (s, "r4") == 0 ||
1235                strcmp (s, "r5") == 0 ||
1236                strcmp (s, "r6") == 0 ||
1237                strcmp (s, "r7") == 0)
1238         {
1239           char buffer[10];
1240           sprintf (buffer, "a%s", s);
1241           emitcode ("mov", "@%s,%s",
1242                     aop->aopu.aop_ptr->name, buffer);
1243         }
1244       else
1245         emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1246
1247       break;
1248
1249     case AOP_STK:
1250       if (strcmp (s, "a") == 0)
1251         emitcode ("push", "acc");
1252       else
1253         if (*s=='@') {
1254           MOVA(s);
1255           emitcode ("push", "acc");
1256         } else {
1257           emitcode ("push", s);
1258         }
1259
1260       break;
1261
1262     case AOP_CRY:
1263       /* if bit variable */
1264       if (!aop->aopu.aop_dir)
1265         {
1266           emitcode ("clr", "a");
1267           emitcode ("rlc", "a");
1268         }
1269       else
1270         {
1271           if (s == zero)
1272             emitcode ("clr", "%s", aop->aopu.aop_dir);
1273           else if (s == one)
1274             emitcode ("setb", "%s", aop->aopu.aop_dir);
1275           else if (!strcmp (s, "c"))
1276             emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1277           else
1278             {
1279               if (strcmp (s, "a"))
1280                 {
1281                   MOVA (s);
1282                 }
1283               {
1284                 symbol *lbl = newiTempLabel (NULL);
1285                 emitcode ("clr", "c");
1286                 emitcode ("jz", "%05d$", lbl->key + 100);
1287                 emitcode ("cpl", "c");
1288                 emitcode ("", "%05d$:", lbl->key + 100);
1289                 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1290               }
1291             }
1292         }
1293       break;
1294
1295     case AOP_STR:
1296       aop->coff = offset;
1297       if (strcmp (aop->aopu.aop_str[offset], s))
1298         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1299       break;
1300
1301     case AOP_ACC:
1302       aop->coff = offset;
1303       if (!offset && (strcmp (s, "acc") == 0))
1304         break;
1305
1306       if (strcmp (aop->aopu.aop_str[offset], s))
1307         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1308       break;
1309
1310     default:
1311       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1312               "aopPut got unsupported aop->type");
1313       exit (1);
1314     }
1315
1316 }
1317
1318
1319 /*--------------------------------------------------------------------*/
1320 /* reAdjustPreg - points a register back to where it should (coff==0) */
1321 /*--------------------------------------------------------------------*/
1322 static void
1323 reAdjustPreg (asmop * aop)
1324 {
1325   if ((aop->coff==0) || (aop->size <= 1)) {
1326     return;
1327   }
1328
1329   switch (aop->type)
1330     {
1331     case AOP_R0:
1332     case AOP_R1:
1333       while (aop->coff--)
1334         emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1335       break;
1336     case AOP_DPTR:
1337     case AOP_DPTR2:
1338       if (aop->type == AOP_DPTR2)
1339         {
1340           genSetDPTR (1);
1341           _flushLazyDPS ();
1342         }
1343       while (aop->coff--)
1344         {
1345           emitcode ("lcall", "__decdptr");
1346         }
1347
1348       if (aop->type == AOP_DPTR2)
1349         {
1350           genSetDPTR (0);
1351         }
1352       break;
1353
1354     }
1355   aop->coff=0;
1356 }
1357
1358 #define AOP(op) op->aop
1359 #define AOP_TYPE(op) AOP(op)->type
1360 #define AOP_SIZE(op) AOP(op)->size
1361 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1362                        AOP_TYPE(x) == AOP_R0))
1363
1364 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
1365                         AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1366                          AOP(x)->paged))
1367
1368 #define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
1369                       (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1370                       x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1371
1372 /* Workaround for DS80C390 bug: div ab may return bogus results
1373  * if A is accessed in instruction immediately before the div.
1374  *
1375  * Will be fixed in B4 rev of processor, Dallas claims.
1376  */
1377
1378 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L)       \
1379     if (!AOP_NEEDSACC(RIGHT))         \
1380     {               \
1381       /* We can load A first, then B, since     \
1382        * B (the RIGHT operand) won't clobber A,   \
1383        * thus avoiding touching A right before the div. \
1384        */             \
1385       D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1386       L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE);     \
1387       MOVA(L);            \
1388       emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1389     }               \
1390     else              \
1391     {               \
1392       /* Just stuff in a nop after loading A. */    \
1393       emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1394       L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE);   \
1395       MOVA(L);            \
1396       emitcode("nop", "; workaround for DS80C390 div bug.");  \
1397     }
1398
1399 /*-----------------------------------------------------------------*/
1400 /* genNotFloat - generates not for float operations              */
1401 /*-----------------------------------------------------------------*/
1402 static void
1403 genNotFloat (operand * op, operand * res)
1404 {
1405   int size, offset;
1406   char *l;
1407   symbol *tlbl;
1408
1409   D (emitcode (";", "genNotFloat ");
1410     );
1411
1412   /* we will put 127 in the first byte of
1413      the result */
1414   aopPut (AOP (res), "#127", 0);
1415   size = AOP_SIZE (op) - 1;
1416   offset = 1;
1417
1418   _startLazyDPSEvaluation ();
1419   l = aopGet (op->aop, offset++, FALSE, FALSE, TRUE);
1420   MOVA (l);
1421
1422   while (size--)
1423     {
1424       emitcode ("orl", "a,%s",
1425                 aopGet (op->aop,
1426                         offset++, FALSE, FALSE, FALSE));
1427     }
1428   _endLazyDPSEvaluation ();
1429
1430   tlbl = newiTempLabel (NULL);
1431   aopPut (res->aop, one, 1);
1432   emitcode ("jz", "%05d$", (tlbl->key + 100));
1433   aopPut (res->aop, zero, 1);
1434   emitcode ("", "%05d$:", (tlbl->key + 100));
1435
1436   size = res->aop->size - 2;
1437   offset = 2;
1438   /* put zeros in the rest */
1439   while (size--)
1440     aopPut (res->aop, zero, offset++);
1441 }
1442
1443 /*-----------------------------------------------------------------*/
1444 /* opIsGptr: returns non-zero if the passed operand is       */
1445 /* a generic pointer type.             */
1446 /*-----------------------------------------------------------------*/
1447 static int
1448 opIsGptr (operand * op)
1449 {
1450   sym_link *type = operandType (op);
1451
1452   if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1453     {
1454       return 1;
1455     }
1456   return 0;
1457 }
1458
1459 /*-----------------------------------------------------------------*/
1460 /* getDataSize - get the operand data size                         */
1461 /*-----------------------------------------------------------------*/
1462 static int
1463 getDataSize (operand * op)
1464 {
1465   int size;
1466   size = AOP_SIZE (op);
1467   if (size == GPTRSIZE)
1468     {
1469       sym_link *type = operandType (op);
1470       if (IS_GENPTR (type))
1471         {
1472           /* generic pointer; arithmetic operations
1473            * should ignore the high byte (pointer type).
1474            */
1475           size--;
1476         }
1477     }
1478   return size;
1479 }
1480
1481 /*-----------------------------------------------------------------*/
1482 /* outAcc - output Acc                                             */
1483 /*-----------------------------------------------------------------*/
1484 static void
1485 outAcc (operand * result)
1486 {
1487   int size, offset;
1488   size = getDataSize (result);
1489   if (size)
1490     {
1491       aopPut (AOP (result), "a", 0);
1492       size--;
1493       offset = 1;
1494       /* unsigned or positive */
1495       while (size--)
1496         {
1497           aopPut (AOP (result), zero, offset++);
1498         }
1499     }
1500 }
1501
1502 /*-----------------------------------------------------------------*/
1503 /* outBitC - output a bit C                                        */
1504 /*-----------------------------------------------------------------*/
1505 static void
1506 outBitC (operand * result)
1507 {
1508   /* if the result is bit */
1509   if (AOP_TYPE (result) == AOP_CRY)
1510     {
1511       aopPut (AOP (result), "c", 0);
1512     }
1513   else
1514     {
1515       emitcode ("clr", "a");
1516       emitcode ("rlc", "a");
1517       outAcc (result);
1518     }
1519 }
1520
1521 /*-----------------------------------------------------------------*/
1522 /* toBoolean - emit code for orl a,operator(sizeop)                */
1523 /*-----------------------------------------------------------------*/
1524 static void
1525 toBoolean (operand * oper)
1526 {
1527   int   size = AOP_SIZE (oper) - 1;
1528   int   offset = 1;
1529   bool usedB = FALSE;
1530
1531   /* The generic part of a generic pointer should
1532    * not participate in it's truth value.
1533    *
1534    * i.e. 0x10000000 is zero.
1535    */
1536   if (opIsGptr (oper))
1537     {
1538       D (emitcode (";", "toBoolean: generic ptr special case.");
1539         );
1540       size--;
1541     }
1542
1543   _startLazyDPSEvaluation ();
1544   if (AOP_NEEDSACC (oper) && size)
1545     {
1546       usedB = TRUE;
1547       emitcode ("push", "b");
1548       emitcode ("mov", "b, %s", aopGet (AOP (oper), 0, FALSE, FALSE, FALSE));
1549     }
1550   else
1551     {
1552       MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, TRUE));
1553     }
1554   while (size--)
1555     {
1556       if (usedB)
1557         {
1558           emitcode ("orl", "b,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1559         }
1560       else
1561         {
1562           emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1563         }
1564     }
1565   _endLazyDPSEvaluation ();
1566
1567   if (usedB)
1568     {
1569       emitcode ("mov", "a,b");
1570       emitcode ("pop", "b");
1571     }
1572 }
1573
1574
1575 /*-----------------------------------------------------------------*/
1576 /* genNot - generate code for ! operation                          */
1577 /*-----------------------------------------------------------------*/
1578 static void
1579 genNot (iCode * ic)
1580 {
1581   symbol *tlbl;
1582   sym_link *optype = operandType (IC_LEFT (ic));
1583
1584   D (emitcode (";", "genNot ");
1585     );
1586
1587   /* assign asmOps to operand & result */
1588   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1589   aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1590
1591   /* if in bit space then a special case */
1592   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1593     {
1594       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1595       emitcode ("cpl", "c");
1596       outBitC (IC_RESULT (ic));
1597       goto release;
1598     }
1599
1600   /* if type float then do float */
1601   if (IS_FLOAT (optype))
1602     {
1603       genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1604       goto release;
1605     }
1606
1607   toBoolean (IC_LEFT (ic));
1608
1609   tlbl = newiTempLabel (NULL);
1610   emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1611   emitcode ("", "%05d$:", tlbl->key + 100);
1612   outBitC (IC_RESULT (ic));
1613
1614 release:
1615   /* release the aops */
1616   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1617   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1618 }
1619
1620
1621 /*-----------------------------------------------------------------*/
1622 /* genCpl - generate code for complement                           */
1623 /*-----------------------------------------------------------------*/
1624 static void
1625 genCpl (iCode * ic)
1626 {
1627   int offset = 0;
1628   int size;
1629
1630   D (emitcode (";", "genCpl ");
1631     );
1632
1633
1634   /* assign asmOps to operand & result */
1635   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1636   aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1637
1638   /* if both are in bit space then
1639      a special case */
1640   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1641       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1642     {
1643
1644       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1645       emitcode ("cpl", "c");
1646       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1647       goto release;
1648     }
1649
1650   size = AOP_SIZE (IC_RESULT (ic));
1651   _startLazyDPSEvaluation ();
1652   while (size--)
1653     {
1654       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1655       MOVA (l);
1656       emitcode ("cpl", "a");
1657       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1658     }
1659   _endLazyDPSEvaluation ();
1660
1661
1662 release:
1663   /* release the aops */
1664   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1665   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1666 }
1667
1668 /*-----------------------------------------------------------------*/
1669 /* genUminusFloat - unary minus for floating points                */
1670 /*-----------------------------------------------------------------*/
1671 static void
1672 genUminusFloat (operand * op, operand * result)
1673 {
1674   int size, offset = 0;
1675   char *l;
1676   /* for this we just need to flip the
1677      first it then copy the rest in place */
1678   D (emitcode (";", "genUminusFloat");
1679     );
1680
1681   _startLazyDPSEvaluation ();
1682   size = AOP_SIZE (op) - 1;
1683   l = aopGet (AOP (op), 3, FALSE, FALSE, TRUE);
1684   MOVA (l);
1685
1686   emitcode ("cpl", "acc.7");
1687   aopPut (AOP (result), "a", 3);
1688
1689   while (size--)
1690     {
1691       aopPut (AOP (result),
1692               aopGet (AOP (op), offset, FALSE, FALSE, FALSE),
1693               offset);
1694       offset++;
1695     }
1696   _endLazyDPSEvaluation ();
1697 }
1698
1699 /*-----------------------------------------------------------------*/
1700 /* genUminus - unary minus code generation                         */
1701 /*-----------------------------------------------------------------*/
1702 static void
1703 genUminus (iCode * ic)
1704 {
1705   int offset, size;
1706   sym_link *optype, *rtype;
1707
1708   D (emitcode (";", "genUminus ");
1709     );
1710
1711
1712   /* assign asmops */
1713   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1714   aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1715
1716   /* if both in bit space then special
1717      case */
1718   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1719       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1720     {
1721
1722       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1723       emitcode ("cpl", "c");
1724       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1725       goto release;
1726     }
1727
1728   optype = operandType (IC_LEFT (ic));
1729   rtype = operandType (IC_RESULT (ic));
1730
1731   /* if float then do float stuff */
1732   if (IS_FLOAT (optype))
1733     {
1734       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1735       goto release;
1736     }
1737
1738   /* otherwise subtract from zero */
1739   size = AOP_SIZE (IC_LEFT (ic));
1740   offset = 0;
1741   _startLazyDPSEvaluation ();
1742   while (size--)
1743     {
1744       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1745       if (!strcmp (l, "a"))
1746         {
1747           if (offset == 0)
1748             SETC;
1749           emitcode ("cpl", "a");
1750           emitcode ("addc", "a,#0");
1751         }
1752       else
1753         {
1754           if (offset == 0)
1755             CLRC;
1756           emitcode ("clr", "a");
1757           emitcode ("subb", "a,%s", l);
1758         }
1759       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1760     }
1761   _endLazyDPSEvaluation ();
1762
1763   /* if any remaining bytes in the result */
1764   /* we just need to propagate the sign   */
1765   if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1766     {
1767       emitcode ("rlc", "a");
1768       emitcode ("subb", "a,acc");
1769       while (size--)
1770         aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1771     }
1772
1773 release:
1774   /* release the aops */
1775   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1776   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1777 }
1778
1779 /*-----------------------------------------------------------------*/
1780 /* saveRegisters - will look for a call and save the registers     */
1781 /*-----------------------------------------------------------------*/
1782 static void
1783 saveRegisters (iCode * lic)
1784 {
1785   int i;
1786   iCode *ic;
1787   bitVect *rsave;
1788   sym_link *detype;
1789
1790   /* look for call */
1791   for (ic = lic; ic; ic = ic->next)
1792     if (ic->op == CALL || ic->op == PCALL)
1793       break;
1794
1795   if (!ic)
1796     {
1797       fprintf (stderr, "found parameter push with no function call\n");
1798       return;
1799     }
1800
1801   /* if the registers have been saved already then
1802      do nothing */
1803   if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type) ||
1804       IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic))))
1805     return;
1806
1807   /* find the registers in use at this time
1808      and push them away to safety */
1809   rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1810                          ic->rUsed);
1811
1812   ic->regsSaved = 1;
1813   if (options.useXstack)
1814     {
1815       if (bitVectBitValue (rsave, R0_IDX))
1816         emitcode ("mov", "b,r0");
1817       emitcode ("mov", "r0,%s", spname);
1818       for (i = 0; i < ds390_nRegs; i++)
1819         {
1820           if (bitVectBitValue (rsave, i))
1821             {
1822               if (i == R0_IDX)
1823                 emitcode ("mov", "a,b");
1824               else
1825                 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
1826               emitcode ("movx", "@r0,a");
1827               emitcode ("inc", "r0");
1828             }
1829         }
1830       emitcode ("mov", "%s,r0", spname);
1831       if (bitVectBitValue (rsave, R0_IDX))
1832         emitcode ("mov", "r0,b");
1833     }
1834   else
1835     for (i = 0; i < ds390_nRegs; i++)
1836       {
1837         if (bitVectBitValue (rsave, i))
1838           emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
1839       }
1840
1841   detype = getSpec (operandType (IC_LEFT (ic)));
1842 }
1843
1844 /*-----------------------------------------------------------------*/
1845 /* unsaveRegisters - pop the pushed registers                      */
1846 /*-----------------------------------------------------------------*/
1847 static void
1848 unsaveRegisters (iCode * ic)
1849 {
1850   int i;
1851   bitVect *rsave;
1852   /* find the registers in use at this time
1853      and push them away to safety */
1854   rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1855                          ic->rUsed);
1856
1857   if (options.useXstack)
1858     {
1859       emitcode ("mov", "r0,%s", spname);
1860       for (i = ds390_nRegs; i >= 0; i--)
1861         {
1862           if (bitVectBitValue (rsave, i))
1863             {
1864               emitcode ("dec", "r0");
1865               emitcode ("movx", "a,@r0");
1866               if (i == R0_IDX)
1867                 emitcode ("mov", "b,a");
1868               else
1869                 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
1870             }
1871
1872         }
1873       emitcode ("mov", "%s,r0", spname);
1874       if (bitVectBitValue (rsave, R0_IDX))
1875         emitcode ("mov", "r0,b");
1876     }
1877   else
1878     for (i = ds390_nRegs; i >= 0; i--)
1879       {
1880         if (bitVectBitValue (rsave, i))
1881           emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
1882       }
1883
1884 }
1885
1886
1887 /*-----------------------------------------------------------------*/
1888 /* pushSide -                */
1889 /*-----------------------------------------------------------------*/
1890 static void
1891 pushSide (operand * oper, int size)
1892 {
1893   int offset = 0;
1894   _startLazyDPSEvaluation ();
1895   while (size--)
1896     {
1897       char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, FALSE);
1898       if (AOP_TYPE (oper) != AOP_REG &&
1899           AOP_TYPE (oper) != AOP_DIR &&
1900           strcmp (l, "a"))
1901         {
1902           emitcode ("mov", "a,%s", l);
1903           emitcode ("push", "acc");
1904         }
1905       else
1906         emitcode ("push", "%s", l);
1907     }
1908   _endLazyDPSEvaluation ();
1909 }
1910
1911 /*-----------------------------------------------------------------*/
1912 /* assignResultValue -               */
1913 /*-----------------------------------------------------------------*/
1914 static void
1915 assignResultValue (operand * oper)
1916 {
1917   int offset = 0;
1918   int size = AOP_SIZE (oper);
1919
1920   _startLazyDPSEvaluation ();
1921   while (size--)
1922     {
1923       aopPut (AOP (oper), fReturn[offset], offset);
1924       offset++;
1925     }
1926   _endLazyDPSEvaluation ();
1927 }
1928
1929
1930 /*-----------------------------------------------------------------*/
1931 /* genXpush - pushes onto the external stack                       */
1932 /*-----------------------------------------------------------------*/
1933 static void
1934 genXpush (iCode * ic)
1935 {
1936   asmop *aop = newAsmop (0);
1937   regs *r;
1938   int size, offset = 0;
1939
1940   D (emitcode (";", "genXpush ");
1941     );
1942
1943   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1944   r = getFreePtr (ic, &aop, FALSE);
1945
1946
1947   emitcode ("mov", "%s,_spx", r->name);
1948
1949   size = AOP_SIZE (IC_LEFT (ic));
1950   _startLazyDPSEvaluation ();
1951   while (size--)
1952     {
1953
1954       char *l = aopGet (AOP (IC_LEFT (ic)),
1955                         offset++, FALSE, FALSE, TRUE);
1956       MOVA (l);
1957       emitcode ("movx", "@%s,a", r->name);
1958       emitcode ("inc", "%s", r->name);
1959
1960     }
1961   _endLazyDPSEvaluation ();
1962
1963
1964   emitcode ("mov", "_spx,%s", r->name);
1965
1966   freeAsmop (NULL, aop, ic, TRUE);
1967   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1968 }
1969
1970 /*-----------------------------------------------------------------*/
1971 /* genIpush - genrate code for pushing this gets a little complex  */
1972 /*-----------------------------------------------------------------*/
1973 static void
1974 genIpush (iCode * ic)
1975 {
1976   int size, offset = 0;
1977   char *l;
1978
1979   D (emitcode (";", "genIpush ");
1980     );
1981
1982   /* if this is not a parm push : ie. it is spill push
1983      and spill push is always done on the local stack */
1984   if (!ic->parmPush)
1985     {
1986
1987       /* and the item is spilt then do nothing */
1988       if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1989         return;
1990
1991       aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1992       size = AOP_SIZE (IC_LEFT (ic));
1993       /* push it on the stack */
1994       _startLazyDPSEvaluation ();
1995       while (size--)
1996         {
1997           l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, TRUE);
1998           if (*l == '#')
1999             {
2000               MOVA (l);
2001               l = "acc";
2002             }
2003           emitcode ("push", "%s", l);
2004         }
2005       _endLazyDPSEvaluation ();
2006       return;
2007     }
2008
2009   /* this is a paramter push: in this case we call
2010      the routine to find the call and save those
2011      registers that need to be saved */
2012   saveRegisters (ic);
2013
2014   /* if use external stack then call the external
2015      stack pushing routine */
2016   if (options.useXstack)
2017     {
2018       genXpush (ic);
2019       return;
2020     }
2021
2022   /* then do the push */
2023   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2024
2025   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2026   size = AOP_SIZE (IC_LEFT (ic));
2027
2028   _startLazyDPSEvaluation ();
2029   while (size--)
2030     {
2031       l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, FALSE);
2032       if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2033           AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2034           strcmp (l, "a"))
2035         {
2036           emitcode ("mov", "a,%s", l);
2037           emitcode ("push", "acc");
2038         }
2039       else
2040         emitcode ("push", "%s", l);
2041     }
2042   _endLazyDPSEvaluation ();
2043
2044   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2045 }
2046
2047 /*-----------------------------------------------------------------*/
2048 /* genIpop - recover the registers: can happen only for spilling   */
2049 /*-----------------------------------------------------------------*/
2050 static void
2051 genIpop (iCode * ic)
2052 {
2053   int size, offset;
2054
2055   D (emitcode (";", "genIpop ");
2056     );
2057
2058
2059   /* if the temp was not pushed then */
2060   if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2061     return;
2062
2063   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2064   size = AOP_SIZE (IC_LEFT (ic));
2065   offset = (size - 1);
2066   _startLazyDPSEvaluation ();
2067   while (size--)
2068     {
2069       emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2070                                      FALSE, TRUE, TRUE));
2071     }
2072   _endLazyDPSEvaluation ();
2073
2074   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2075 }
2076
2077 /*-----------------------------------------------------------------*/
2078 /* unsaveRBank - restores the resgister bank from stack            */
2079 /*-----------------------------------------------------------------*/
2080 static void
2081 unsaveRBank (int bank, iCode * ic, bool popPsw)
2082 {
2083   int i;
2084   asmop *aop = NULL;
2085   regs *r = NULL;
2086
2087   if (options.useXstack)
2088   {
2089       if (!ic)
2090       {
2091           /* Assume r0 is available for use. */
2092           r = ds390_regWithIdx (R0_IDX);;          
2093       } 
2094       else
2095       {
2096           aop = newAsmop (0);
2097           r = getFreePtr (ic, &aop, FALSE);
2098       }
2099       emitcode ("mov", "%s,_spx", r->name);      
2100   }
2101   
2102   if (popPsw)
2103     {
2104       if (options.useXstack)
2105       {
2106           emitcode ("movx", "a,@%s", r->name);
2107           emitcode ("mov", "psw,a");
2108           emitcode ("dec", "%s", r->name);
2109         }
2110       else
2111       {
2112         emitcode ("pop", "psw");
2113       }
2114     }
2115
2116   for (i = (ds390_nRegs - 1); i >= 0; i--)
2117     {
2118       if (options.useXstack)
2119         {
2120           emitcode ("movx", "a,@%s", r->name);
2121           emitcode ("mov", "(%s+%d),a",
2122                     regs390[i].base, 8 * bank + regs390[i].offset);
2123           emitcode ("dec", "%s", r->name);
2124
2125         }
2126       else
2127         emitcode ("pop", "(%s+%d)",
2128                   regs390[i].base, 8 * bank + regs390[i].offset);
2129     }
2130
2131   if (options.useXstack)
2132     {
2133       emitcode ("mov", "_spx,%s", r->name);
2134     }
2135     
2136   if (aop)
2137   {
2138       freeAsmop (NULL, aop, ic, TRUE);  
2139   }    
2140 }
2141
2142 /*-----------------------------------------------------------------*/
2143 /* saveRBank - saves an entire register bank on the stack          */
2144 /*-----------------------------------------------------------------*/
2145 static void
2146 saveRBank (int bank, iCode * ic, bool pushPsw)
2147 {
2148   int i;
2149   asmop *aop = NULL;
2150   regs *r = NULL;
2151
2152   if (options.useXstack)
2153     {
2154         if (!ic)
2155         {
2156           /* Assume r0 is available for use. */
2157                   r = ds390_regWithIdx (R0_IDX);;
2158         }
2159         else
2160         {
2161           aop = newAsmop (0);
2162           r = getFreePtr (ic, &aop, FALSE);
2163         }
2164         emitcode ("mov", "%s,_spx", r->name);    
2165     }
2166
2167   for (i = 0; i < ds390_nRegs; i++)
2168     {
2169       if (options.useXstack)
2170         {
2171           emitcode ("inc", "%s", r->name);
2172           emitcode ("mov", "a,(%s+%d)",
2173                     regs390[i].base, 8 * bank + regs390[i].offset);
2174           emitcode ("movx", "@%s,a", r->name);
2175         }
2176       else
2177         emitcode ("push", "(%s+%d)",
2178                   regs390[i].base, 8 * bank + regs390[i].offset);
2179     }
2180
2181   if (pushPsw)
2182     {
2183       if (options.useXstack)
2184         {
2185           emitcode ("mov", "a,psw");
2186           emitcode ("movx", "@%s,a", r->name);
2187           emitcode ("inc", "%s", r->name);
2188           emitcode ("mov", "_spx,%s", r->name);
2189         }
2190       else
2191       {
2192         emitcode ("push", "psw");
2193       }
2194
2195       emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2196     }
2197   
2198   if (aop)
2199   {
2200        freeAsmop (NULL, aop, ic, TRUE);
2201   }    
2202     
2203   if (ic)
2204   {  
2205       ic->bankSaved = 1;
2206   }
2207 }
2208
2209 /*-----------------------------------------------------------------*/
2210 /* genCall - generates a call statement                            */
2211 /*-----------------------------------------------------------------*/
2212 static void
2213 genCall (iCode * ic)
2214 {
2215   sym_link *dtype;
2216   bool restoreBank = FALSE;
2217   bool swapBanks = FALSE;
2218
2219   D (emitcode (";", "genCall "););
2220
2221   /* if we are calling a not _naked function that is not using
2222      the same register bank then we need to save the
2223      destination registers on the stack */
2224   dtype = operandType (IC_LEFT (ic));
2225   if (dtype && !IFFUNC_ISNAKED(dtype) &&
2226       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2227       IFFUNC_ISISR (currFunc->type))
2228   {
2229       if (!ic->bankSaved) 
2230       {
2231            /* This is unexpected; the bank should have been saved in
2232             * genFunction.
2233             */
2234            saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2235            restoreBank = TRUE;
2236       }
2237       swapBanks = TRUE;
2238   }
2239   
2240     /* if caller saves & we have not saved then */
2241     if (!ic->regsSaved)
2242       saveRegisters (ic);
2243   
2244   /* if send set is not empty the assign */
2245   /* We've saved all the registers we care about;
2246   * therefore, we may clobber any register not used
2247   * in the calling convention (i.e. anything not in
2248   * fReturn.
2249   */
2250   if (_G.sendSet)
2251     {
2252       iCode *sic;
2253
2254       for (sic = setFirstItem (_G.sendSet); sic;
2255            sic = setNextItem (_G.sendSet))
2256         {
2257           int size, offset = 0;
2258
2259           aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2260           size = AOP_SIZE (IC_LEFT (sic));
2261
2262           _startLazyDPSEvaluation ();
2263           while (size--)
2264             {
2265               char *l = aopGet (AOP(IC_LEFT(sic)), offset,
2266                                 FALSE, FALSE, TRUE);
2267                 if ((AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR) && size)
2268                 {
2269                     emitcode("mov", "%s,%s", regs390[offset].name, l);
2270                 }
2271                 else if (strcmp (l, fReturn[offset]))
2272                 {
2273                     emitcode ("mov", "%s,%s",
2274                               fReturn[offset],
2275                               l);
2276                 }
2277               offset++;
2278             }
2279           _endLazyDPSEvaluation ();
2280           if (AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR)
2281           {
2282               size = AOP_SIZE (IC_LEFT (sic));
2283               if (size)
2284               {
2285                  size--;
2286               }
2287               while (size)
2288               {
2289                    size--;
2290                    emitcode("mov", "%s,%s",
2291                                     fReturn[size], regs390[size].name);
2292               }
2293           }
2294           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2295         }
2296       _G.sendSet = NULL;
2297     }  
2298     
2299   if (swapBanks)
2300   {
2301         emitcode ("mov", "psw,#0x%02x", 
2302            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2303   }
2304
2305   /* make the call */
2306   emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2307                             OP_SYMBOL (IC_LEFT (ic))->rname :
2308                             OP_SYMBOL (IC_LEFT (ic))->name));
2309
2310   if (swapBanks)
2311   {
2312        emitcode ("mov", "psw,#0x%02x", 
2313           ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2314   }
2315
2316   /* if we need assign a result value */
2317   if ((IS_ITEMP (IC_RESULT (ic)) &&
2318        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2319         OP_SYMBOL (IC_RESULT (ic))->accuse ||
2320         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2321       IS_TRUE_SYMOP (IC_RESULT (ic)))
2322     {
2323       if (isOperandInFarSpace (IC_RESULT (ic))
2324           && getSize (operandType (IC_RESULT (ic))) <= 2)
2325         {
2326           int size = getSize (operandType (IC_RESULT (ic)));
2327
2328           /* Special case for 1 or 2 byte return in far space. */
2329           MOVA (fReturn[0]);
2330           if (size > 1)
2331             {
2332               emitcode ("mov", "b,%s", fReturn[1]);
2333             }
2334
2335           aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2336           aopPut (AOP (IC_RESULT (ic)), "a", 0);
2337
2338           if (size > 1)
2339             {
2340               aopPut (AOP (IC_RESULT (ic)), "b", 1);
2341             }
2342           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2343         }
2344       else
2345         {
2346           _G.accInUse++;
2347           aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2348           _G.accInUse--;
2349
2350           assignResultValue (IC_RESULT (ic));
2351
2352           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2353         }
2354     }
2355
2356   /* adjust the stack for parameters if
2357      required */
2358   if (ic->parmBytes) {
2359       if (options.stack10bit) {
2360           emitcode ("clr","c");
2361           emitcode ("mov","a,sp");
2362           emitcode ("subb","a,#0x%02x",ic->parmBytes & 0xff);
2363           emitcode ("mov","sp,a");
2364           emitcode ("mov","a,#0x%02x",(ic->parmBytes >> 8) & 0xff);
2365           emitcode ("subb","a,_ESP");
2366           emitcode ("mov","_ESP,a");      
2367       } else {
2368           int i;
2369           if (ic->parmBytes > 3) {
2370               emitcode ("mov", "a,%s", spname);
2371               emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2372               emitcode ("mov", "%s,a", spname);
2373           } else
2374               for (i = 0; i < ic->parmBytes; i++)
2375                   emitcode ("dec", "%s", spname);
2376       }
2377   }
2378
2379   /* if we hade saved some registers then unsave them */
2380   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2381     unsaveRegisters (ic);
2382
2383   /* if register bank was saved then pop them */
2384   if (restoreBank)
2385     unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2386 }
2387
2388 /*-----------------------------------------------------------------*/
2389 /* genPcall - generates a call by pointer statement                */
2390 /*-----------------------------------------------------------------*/
2391 static void
2392 genPcall (iCode * ic)
2393 {
2394   sym_link *dtype;
2395   symbol *rlbl = newiTempLabel (NULL);
2396   bool restoreBank=FALSE;
2397
2398   D (emitcode (";", "genPcall ");
2399     );
2400
2401
2402   /* if caller saves & we have not saved then */
2403   if (!ic->regsSaved)
2404     saveRegisters (ic);
2405
2406   /* if we are calling a function that is not using
2407      the same register bank then we need to save the
2408      destination registers on the stack */
2409   dtype = operandType (IC_LEFT (ic));
2410   if (dtype && !IFFUNC_ISNAKED(dtype) &&
2411       IFFUNC_ISISR (currFunc->type) &&
2412       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2413     saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2414     restoreBank=TRUE;
2415   }
2416
2417   /* push the return address on to the stack */
2418   emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2419   emitcode ("push", "acc");
2420   emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2421   emitcode ("push", "acc");
2422
2423   if (options.model == MODEL_FLAT24)
2424     {
2425       emitcode ("mov", "a,#(%05d$ >> 16)", (rlbl->key + 100));
2426       emitcode ("push", "acc");
2427     }
2428
2429   /* now push the calling address */
2430   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2431
2432   pushSide (IC_LEFT (ic), FPTRSIZE);
2433
2434   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2435
2436   /* if send set is not empty the assign */
2437   if (_G.sendSet)
2438     {
2439       iCode *sic;
2440
2441       for (sic = setFirstItem (_G.sendSet); sic;
2442            sic = setNextItem (_G.sendSet))
2443         {
2444           int size, offset = 0;
2445
2446           aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2447           size = AOP_SIZE (IC_LEFT (sic));
2448           _startLazyDPSEvaluation ();
2449           while (size--)
2450             {
2451               char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2452                                 FALSE, FALSE, TRUE);
2453               if (strcmp (l, fReturn[offset]))
2454                 {
2455                   emitcode ("mov", "%s,%s",
2456                             fReturn[offset],
2457                             l);
2458                 }
2459               offset++;
2460             }
2461           _endLazyDPSEvaluation ();
2462           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2463         }
2464       _G.sendSet = NULL;
2465     }
2466
2467   emitcode ("ret", "");
2468   emitcode ("", "%05d$:", (rlbl->key + 100));
2469
2470
2471   /* if we need assign a result value */
2472   if ((IS_ITEMP (IC_RESULT (ic)) &&
2473        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2474         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2475       IS_TRUE_SYMOP (IC_RESULT (ic)))
2476     {
2477
2478       _G.accInUse++;
2479       aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2480       _G.accInUse--;
2481
2482       assignResultValue (IC_RESULT (ic));
2483
2484       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2485     }
2486
2487   /* adjust the stack for parameters if
2488      required */
2489   if (ic->parmBytes)
2490     {
2491       int i;
2492       if (ic->parmBytes > 3)
2493         {
2494           emitcode ("mov", "a,%s", spname);
2495           emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2496           emitcode ("mov", "%s,a", spname);
2497         }
2498       else
2499         for (i = 0; i < ic->parmBytes; i++)
2500           emitcode ("dec", "%s", spname);
2501
2502     }
2503
2504   /* if register bank was saved then unsave them */
2505   if (restoreBank)
2506     unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2507   
2508   /* if we hade saved some registers then
2509      unsave them */
2510   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2511     unsaveRegisters (ic);
2512
2513 }
2514
2515 /*-----------------------------------------------------------------*/
2516 /* resultRemat - result  is rematerializable                       */
2517 /*-----------------------------------------------------------------*/
2518 static int
2519 resultRemat (iCode * ic)
2520 {
2521   if (SKIP_IC (ic) || ic->op == IFX)
2522     return 0;
2523
2524   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2525     {
2526       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2527       if (sym->remat && !POINTER_SET (ic))
2528         return 1;
2529     }
2530
2531   return 0;
2532 }
2533
2534 #if defined(__BORLANDC__) || defined(_MSC_VER)
2535 #define STRCASECMP stricmp
2536 #else
2537 #define STRCASECMP strcasecmp
2538 #endif
2539
2540 /*-----------------------------------------------------------------*/
2541 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2542 /*-----------------------------------------------------------------*/
2543 static bool
2544 inExcludeList (char *s)
2545 {
2546   int i = 0;
2547
2548   if (options.excludeRegs[i] &&
2549       STRCASECMP (options.excludeRegs[i], "none") == 0)
2550     return FALSE;
2551
2552   for (i = 0; options.excludeRegs[i]; i++)
2553     {
2554       if (options.excludeRegs[i] &&
2555           STRCASECMP (s, options.excludeRegs[i]) == 0)
2556         return TRUE;
2557     }
2558   return FALSE;
2559 }
2560
2561 /*-----------------------------------------------------------------*/
2562 /* genFunction - generated code for function entry                 */
2563 /*-----------------------------------------------------------------*/
2564 static void
2565 genFunction (iCode * ic)
2566 {
2567   symbol *sym;
2568   sym_link *ftype;
2569   bool   switchedPSW = FALSE;
2570
2571   D (emitcode (";", "genFunction "););
2572
2573   _G.nRegsSaved = 0;
2574   /* create the function header */
2575   emitcode (";", "-----------------------------------------");
2576   emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2577   emitcode (";", "-----------------------------------------");
2578
2579   emitcode ("", "%s:", sym->rname);
2580   ftype = operandType (IC_LEFT (ic));
2581
2582   if (IFFUNC_ISNAKED(ftype))
2583   {
2584       emitcode(";", "naked function: no prologue.");
2585       return;
2586   }
2587
2588   /* if critical function then turn interrupts off */
2589   if (IFFUNC_ISCRITICAL (ftype))
2590     emitcode ("clr", "ea");
2591
2592   /* here we need to generate the equates for the
2593      register bank if required */
2594   if (FUNC_REGBANK (ftype) != rbank)
2595     {
2596       int i;
2597
2598       rbank = FUNC_REGBANK (ftype);
2599       for (i = 0; i < ds390_nRegs; i++)
2600         {
2601           if (regs390[i].print) {
2602               if (strcmp (regs390[i].base, "0") == 0)
2603                   emitcode ("", "%s = 0x%02x",
2604                             regs390[i].dname,
2605                             8 * rbank + regs390[i].offset);
2606               else
2607                   emitcode ("", "%s = %s + 0x%02x",
2608                             regs390[i].dname,
2609                             regs390[i].base,
2610                             8 * rbank + regs390[i].offset);
2611           }
2612         }
2613     }
2614
2615   /* if this is an interrupt service routine then
2616      save acc, b, dpl, dph  */
2617   if (IFFUNC_ISISR (sym->type))
2618     {
2619
2620       if (!inExcludeList ("acc"))
2621         emitcode ("push", "acc");
2622       if (!inExcludeList ("b"))
2623         emitcode ("push", "b");
2624       if (!inExcludeList ("dpl"))
2625         emitcode ("push", "dpl");
2626       if (!inExcludeList ("dph"))
2627         emitcode ("push", "dph");
2628       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2629         {
2630           emitcode ("push", "dpx");
2631           /* Make sure we're using standard DPTR */
2632           emitcode ("push", "dps");
2633           emitcode ("mov", "dps, #0x00");
2634           if (options.stack10bit)
2635             {
2636               /* This ISR could conceivably use DPTR2. Better save it. */
2637               emitcode ("push", "dpl1");
2638               emitcode ("push", "dph1");
2639               emitcode ("push", "dpx1");
2640               emitcode ("push",  DP2_RESULT_REG);
2641             }
2642         }
2643       /* if this isr has no bank i.e. is going to
2644          run with bank 0 , then we need to save more
2645          registers :-) */
2646       if (!FUNC_REGBANK (sym->type))
2647         {
2648
2649           /* if this function does not call any other
2650              function then we can be economical and
2651              save only those registers that are used */
2652           if (!IFFUNC_HASFCALL(sym->type))
2653             {
2654               int i;
2655
2656               /* if any registers used */
2657               if (sym->regsUsed)
2658                 {
2659                   /* save the registers used */
2660                   for (i = 0; i < sym->regsUsed->size; i++)
2661                     {
2662                       if (bitVectBitValue (sym->regsUsed, i) ||
2663                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2664                         emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2665                     }
2666                 }
2667
2668             }
2669           else
2670             {
2671               /* this function has  a function call cannot
2672                  determines register usage so we will have to push the
2673                  entire bank */
2674               saveRBank (0, ic, FALSE);
2675             }
2676         }
2677         else
2678         {
2679             /* This ISR uses a non-zero bank.
2680              *
2681              * We assume that the bank is available for our
2682              * exclusive use.
2683              *
2684              * However, if this ISR calls a function which uses some
2685              * other bank, we must save that bank entirely.
2686              */
2687             unsigned long banksToSave = 0;
2688             
2689             if (IFFUNC_HASFCALL(sym->type))
2690             {
2691
2692 #define MAX_REGISTER_BANKS 4
2693
2694                 iCode *i;
2695                 int ix;
2696
2697                 for (i = ic; i; i = i->next)
2698                 {
2699                     if (i->op == ENDFUNCTION)
2700                     {
2701                         /* we got to the end OK. */
2702                         break;
2703                     }
2704                     
2705                     if (i->op == CALL)
2706                     {
2707                         sym_link *dtype;
2708                         
2709                         dtype = operandType (IC_LEFT(i));
2710                         if (dtype 
2711                          && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2712                         {
2713                              /* Mark this bank for saving. */
2714                              if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2715                              {
2716                                  werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2717                              }
2718                              else
2719                              {
2720                                  banksToSave |= (1 << FUNC_REGBANK(dtype));
2721                              }
2722                              
2723                              /* And note that we don't need to do it in 
2724                               * genCall.
2725                               */
2726                              i->bankSaved = 1;
2727                         }
2728                     }
2729                     if (i->op == PCALL)
2730                     {
2731                         /* This is a mess; we have no idea what
2732                          * register bank the called function might
2733                          * use.
2734                          *
2735                          * The only thing I can think of to do is
2736                          * throw a warning and hope.
2737                          */
2738                         werror(W_FUNCPTR_IN_USING_ISR);   
2739                     }
2740                 }
2741
2742                 if (banksToSave && options.useXstack)
2743                 {
2744                     /* Since we aren't passing it an ic, 
2745                      * saveRBank will assume r0 is available to abuse.
2746                      *
2747                      * So switch to our (trashable) bank now, so
2748                      * the caller's R0 isn't trashed.
2749                      */
2750                     emitcode ("push", "psw");
2751                     emitcode ("mov", "psw,#0x%02x", 
2752                               (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2753                     switchedPSW = TRUE;
2754                 }
2755                 
2756                 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2757                 {
2758                      if (banksToSave & (1 << ix))
2759                      {
2760                          saveRBank(ix, NULL, FALSE);
2761                      }
2762                 }
2763             }
2764             // jwk: this needs a closer look
2765             SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2766         }
2767     }
2768   else
2769     {
2770       /* if callee-save to be used for this function
2771          then save the registers being used in this function */
2772       if (IFFUNC_CALLEESAVES(sym->type))
2773         {
2774           int i;
2775
2776           /* if any registers used */
2777           if (sym->regsUsed)
2778             {
2779               /* save the registers used */
2780               for (i = 0; i < sym->regsUsed->size; i++)
2781                 {
2782                   if (bitVectBitValue (sym->regsUsed, i) ||
2783                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2784                     {
2785                       emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2786                       _G.nRegsSaved++;
2787                     }
2788                 }
2789             }
2790         }
2791     }
2792
2793   /* set the register bank to the desired value */
2794   if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
2795    && !switchedPSW)
2796     {
2797       emitcode ("push", "psw");
2798       emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2799     }
2800
2801   if (IFFUNC_ISREENT (sym->type) || options.stackAuto) {
2802       if (options.stack10bit) {
2803           emitcode ("push","_bpx");
2804           emitcode ("push","_bpx+1");
2805           emitcode ("mov","_bpx,%s",spname);
2806           emitcode ("mov","_bpx+1,_ESP");
2807           emitcode ("anl","_bpx+1,#3");
2808       } else {
2809           if (options.useXstack) {
2810               emitcode ("mov", "r0,%s", spname);
2811               emitcode ("mov", "a,_bp");
2812               emitcode ("movx", "@r0,a");
2813               emitcode ("inc", "%s", spname);
2814           } else {
2815               /* set up the stack */
2816               emitcode ("push", "_bp"); /* save the callers stack  */
2817           }
2818           emitcode ("mov", "_bp,%s", spname);
2819       }
2820   }
2821
2822   /* adjust the stack for the function */
2823   if (sym->stack) {
2824       int i = sym->stack;
2825       if (options.stack10bit) {
2826           if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);
2827           assert (sym->recvSize <= 4);
2828           emitcode ("mov","a,sp");
2829           emitcode ("add","a,#0x%02x", ((short) sym->stack & 0xff));
2830           emitcode ("mov","sp,a");
2831           emitcode ("mov","a,_ESP");
2832           emitcode ("addc","a,0x%02x", (((short) sym->stack) >> 8) & 0xff);
2833           emitcode ("mov","_ESP,a");
2834       } else {
2835           if (i > 256)
2836               werror (W_STACK_OVERFLOW, sym->name);
2837           
2838           if (i > 3 && sym->recvSize < 4) {
2839               
2840               emitcode ("mov", "a,sp");
2841               emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2842               emitcode ("mov", "sp,a");
2843               
2844           } else
2845               while (i--)
2846                   emitcode ("inc", "sp");
2847       }
2848   }
2849
2850   if (sym->xstack)
2851     {
2852
2853       emitcode ("mov", "a,_spx");
2854       emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2855       emitcode ("mov", "_spx,a");
2856     }
2857
2858 }
2859
2860 /*-----------------------------------------------------------------*/
2861 /* genEndFunction - generates epilogue for functions               */
2862 /*-----------------------------------------------------------------*/
2863 static void
2864 genEndFunction (iCode * ic)
2865 {
2866   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2867
2868   D (emitcode (";", "genEndFunction "););
2869
2870   if (IFFUNC_ISNAKED(sym->type))
2871   {
2872       emitcode(";", "naked function: no epilogue.");
2873       return;
2874   }
2875
2876   if (IFFUNC_ISREENT (sym->type) || options.stackAuto) {
2877       if (options.stack10bit) {
2878           emitcode ("mov", "sp,_bpx", spname);
2879           emitcode ("mov", "_ESP,_bpx+1", spname);
2880       } else {
2881           emitcode ("mov", "%s,_bp", spname);
2882       }
2883   }
2884
2885   /* if use external stack but some variables were
2886      added to the local stack then decrement the
2887      local stack */
2888   if (options.useXstack && sym->stack) {
2889       emitcode ("mov", "a,sp");
2890       emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2891       emitcode ("mov", "sp,a");
2892   }
2893
2894
2895   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto)) {
2896       if (options.useXstack) {
2897           emitcode ("mov", "r0,%s", spname);
2898           emitcode ("movx", "a,@r0");
2899           emitcode ("mov", "_bp,a");
2900           emitcode ("dec", "%s", spname);
2901       } else {
2902           if (options.stack10bit) {
2903               emitcode ("pop", "_bpx+1");
2904               emitcode ("pop", "_bpx");
2905           } else {
2906               emitcode ("pop", "_bp");
2907           }
2908       }
2909   }
2910
2911   /* restore the register bank  */
2912   if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
2913   {
2914     if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
2915      || !options.useXstack)
2916     {
2917         /* Special case of ISR using non-zero bank with useXstack
2918          * is handled below.
2919          */
2920         emitcode ("pop", "psw");
2921     }
2922   }
2923
2924   if (IFFUNC_ISISR (sym->type))
2925     {
2926
2927       /* now we need to restore the registers */
2928       /* if this isr has no bank i.e. is going to
2929          run with bank 0 , then we need to save more
2930          registers :-) */
2931       if (!FUNC_REGBANK (sym->type))
2932         {
2933           /* if this function does not call any other
2934              function then we can be economical and
2935              save only those registers that are used */
2936           if (!IFFUNC_HASFCALL(sym->type))
2937             {
2938               int i;
2939
2940               /* if any registers used */
2941               if (sym->regsUsed)
2942                 {
2943                   /* save the registers used */
2944                   for (i = sym->regsUsed->size; i >= 0; i--)
2945                     {
2946                       if (bitVectBitValue (sym->regsUsed, i) ||
2947                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2948                         emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2949                     }
2950                 }
2951
2952             }
2953           else
2954             {
2955               /* this function has  a function call cannot
2956                  determines register usage so we will have to pop the
2957                  entire bank */
2958               unsaveRBank (0, ic, FALSE);
2959             }
2960         }
2961         else
2962         {
2963             /* This ISR uses a non-zero bank.
2964              *
2965              * Restore any register banks saved by genFunction
2966              * in reverse order.
2967              */
2968           // jwk: this needs a closer look
2969             unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2970             int ix;
2971           
2972             for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2973             {
2974                 if (savedBanks & (1 << ix))
2975                 {
2976                     unsaveRBank(ix, NULL, FALSE);
2977                 }
2978             }
2979             
2980             if (options.useXstack)
2981             {
2982                 /* Restore bank AFTER calling unsaveRBank,
2983                  * since it can trash r0.
2984                  */
2985                 emitcode ("pop", "psw");
2986             }
2987         }
2988
2989       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2990         {
2991           if (options.stack10bit)
2992             {
2993               emitcode ("pop", DP2_RESULT_REG);
2994               emitcode ("pop", "dpx1");
2995               emitcode ("pop", "dph1");
2996               emitcode ("pop", "dpl1");
2997             }
2998           emitcode ("pop", "dps");
2999           emitcode ("pop", "dpx");
3000         }
3001       if (!inExcludeList ("dph"))
3002         emitcode ("pop", "dph");
3003       if (!inExcludeList ("dpl"))
3004         emitcode ("pop", "dpl");
3005       if (!inExcludeList ("b"))
3006         emitcode ("pop", "b");
3007       if (!inExcludeList ("acc"))
3008         emitcode ("pop", "acc");
3009
3010       if (IFFUNC_ISCRITICAL (sym->type))
3011         emitcode ("setb", "ea");
3012
3013       /* if debug then send end of function */
3014       if (options.debug && currFunc) {
3015           _G.debugLine = 1;
3016           emitcode ("", "C$%s$%d$%d$%d ==.",
3017                     FileBaseName (ic->filename), currFunc->lastLine,
3018                     ic->level, ic->block);
3019           if (IS_STATIC (currFunc->etype))
3020             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3021           else
3022             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3023           _G.debugLine = 0;
3024         }
3025
3026       emitcode ("reti", "");
3027     }
3028   else
3029     {
3030       if (IFFUNC_ISCRITICAL (sym->type))
3031         emitcode ("setb", "ea");
3032
3033       if (IFFUNC_CALLEESAVES(sym->type))
3034         {
3035           int i;
3036
3037           /* if any registers used */
3038           if (sym->regsUsed)
3039             {
3040               /* save the registers used */
3041               for (i = sym->regsUsed->size; i >= 0; i--)
3042                 {
3043                   if (bitVectBitValue (sym->regsUsed, i) ||
3044                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3045                     emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3046                 }
3047             }
3048
3049         }
3050
3051       /* if debug then send end of function */
3052       if (options.debug && currFunc)
3053         {
3054           _G.debugLine = 1;
3055           emitcode ("", "C$%s$%d$%d$%d ==.",
3056                     FileBaseName (ic->filename), currFunc->lastLine,
3057                     ic->level, ic->block);
3058           if (IS_STATIC (currFunc->etype))
3059             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3060           else
3061             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3062           _G.debugLine = 0;
3063         }
3064
3065       emitcode ("ret", "");
3066     }
3067
3068 }
3069
3070 /*-----------------------------------------------------------------*/
3071 /* genRet - generate code for return statement                     */
3072 /*-----------------------------------------------------------------*/
3073 static void
3074 genRet (iCode * ic)
3075 {
3076   int size, offset = 0, pushed = 0;
3077
3078   D (emitcode (";", "genRet ");
3079     );
3080
3081   /* if we have no return value then
3082      just generate the "ret" */
3083   if (!IC_LEFT (ic))
3084     goto jumpret;
3085
3086   /* we have something to return then
3087      move the return value into place */
3088   aopOp (IC_LEFT (ic), ic, FALSE, 
3089          (IS_SYMOP(IC_LEFT(ic)) && OP_SYMBOL(IC_LEFT(ic))->ruonly ? FALSE :TRUE));
3090   size = AOP_SIZE (IC_LEFT (ic));
3091
3092   _startLazyDPSEvaluation ();
3093   while (size--)
3094     {
3095       char *l;
3096       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3097         {
3098           l = aopGet (AOP (IC_LEFT (ic)), offset++,
3099                       FALSE, TRUE, FALSE);
3100           emitcode ("push", "%s", l);
3101           pushed++;
3102         }
3103       else
3104         {
3105           /* Since A is the last element of fReturn,
3106            * is is OK to clobber it in the aopGet.
3107            */
3108           l = aopGet (AOP (IC_LEFT (ic)), offset,
3109                       FALSE, FALSE, TRUE);
3110           if (strcmp (fReturn[offset], l))
3111             emitcode ("mov", "%s,%s", fReturn[offset++], l);
3112         }
3113     }
3114   _endLazyDPSEvaluation ();
3115
3116   if (pushed)
3117     {
3118       while (pushed)
3119         {
3120           pushed--;
3121           if (strcmp (fReturn[pushed], "a"))
3122             emitcode ("pop", fReturn[pushed]);
3123           else
3124             emitcode ("pop", "acc");
3125         }
3126     }
3127   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3128
3129 jumpret:
3130   /* generate a jump to the return label
3131      if the next is not the return statement */
3132   if (!(ic->next && ic->next->op == LABEL &&
3133         IC_LABEL (ic->next) == returnLabel))
3134
3135     emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3136
3137 }
3138
3139 /*-----------------------------------------------------------------*/
3140 /* genLabel - generates a label                                    */
3141 /*-----------------------------------------------------------------*/
3142 static void
3143 genLabel (iCode * ic)
3144 {
3145   /* special case never generate */
3146   if (IC_LABEL (ic) == entryLabel)
3147     return;
3148
3149   D (emitcode (";", "genLabel ");
3150     );
3151
3152   emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3153 }
3154
3155 /*-----------------------------------------------------------------*/
3156 /* genGoto - generates a ljmp                                      */
3157 /*-----------------------------------------------------------------*/
3158 static void
3159 genGoto (iCode * ic)
3160 {
3161   D (emitcode (";", "genGoto ");
3162     );
3163   emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
3164 }
3165
3166 /*-----------------------------------------------------------------*/
3167 /* findLabelBackwards: walks back through the iCode chain looking  */
3168 /* for the given label. Returns number of iCode instructions     */
3169 /* between that label and given ic.          */
3170 /* Returns zero if label not found.          */
3171 /*-----------------------------------------------------------------*/
3172 static int
3173 findLabelBackwards (iCode * ic, int key)
3174 {
3175   int count = 0;
3176
3177   while (ic->prev)
3178     {
3179       ic = ic->prev;
3180       count++;
3181
3182       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3183         {
3184           /* printf("findLabelBackwards = %d\n", count); */
3185           return count;
3186         }
3187     }
3188
3189   return 0;
3190 }
3191
3192 /*-----------------------------------------------------------------*/
3193 /* genPlusIncr :- does addition with increment if possible         */
3194 /*-----------------------------------------------------------------*/
3195 static bool
3196 genPlusIncr (iCode * ic)
3197 {
3198   unsigned int icount;
3199   unsigned int size = getDataSize (IC_RESULT (ic));
3200
3201   /* will try to generate an increment */
3202   /* if the right side is not a literal
3203      we cannot */
3204   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3205     return FALSE;
3206
3207   /* if the literal value of the right hand side
3208      is greater than 4 then it is not worth it */
3209   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3210     return FALSE;
3211
3212   /* if increment 16 bits in register */
3213   if (
3214        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3215        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3216        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3217        (size > 1) &&
3218        (icount == 1))
3219     {
3220       symbol *tlbl;
3221       int emitTlbl;
3222       int labelRange;
3223
3224       /* If the next instruction is a goto and the goto target
3225        * is <= 5 instructions previous to this, we can generate
3226        * jumps straight to that target.
3227        */
3228       if (ic->next && ic->next->op == GOTO
3229           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3230           && labelRange <= 5)
3231         {
3232           emitcode (";", "tail increment optimized (range %d)", labelRange);
3233           tlbl = IC_LABEL (ic->next);
3234           emitTlbl = 0;
3235         }
3236       else
3237         {
3238           tlbl = newiTempLabel (NULL);
3239           emitTlbl = 1;
3240         }
3241       emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3242       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3243           IS_AOP_PREG (IC_RESULT (ic)))
3244         emitcode ("cjne", "%s,#0x00,%05d$"
3245                   ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3246                   ,tlbl->key + 100);
3247       else
3248         {
3249           emitcode ("clr", "a");
3250           emitcode ("cjne", "a,%s,%05d$"
3251                     ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3252                     ,tlbl->key + 100);
3253         }
3254
3255       emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3256       if (size > 2)
3257         {
3258           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3259               IS_AOP_PREG (IC_RESULT (ic)))
3260             emitcode ("cjne", "%s,#0x00,%05d$"
3261                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3262                       ,tlbl->key + 100);
3263           else
3264             emitcode ("cjne", "a,%s,%05d$"
3265                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3266                       ,tlbl->key + 100);
3267
3268           emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3269         }
3270       if (size > 3)
3271         {
3272           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3273               IS_AOP_PREG (IC_RESULT (ic)))
3274             emitcode ("cjne", "%s,#0x00,%05d$"
3275                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3276                       ,tlbl->key + 100);
3277           else
3278             {
3279               emitcode ("cjne", "a,%s,%05d$"
3280                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3281                         ,tlbl->key + 100);
3282             }
3283           emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3284         }
3285
3286       if (emitTlbl)
3287         {
3288           emitcode ("", "%05d$:", tlbl->key + 100);
3289         }
3290       return TRUE;
3291     }
3292
3293   /* if the sizes are greater than 1 then we cannot */
3294   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3295       AOP_SIZE (IC_LEFT (ic)) > 1)
3296     return FALSE;
3297
3298   /* we can if the aops of the left & result match or
3299      if they are in registers and the registers are the
3300      same */
3301   if (
3302        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3303        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3304        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3305     {
3306
3307       if (icount > 3)
3308         {
3309           MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3310           emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3311           aopPut (AOP (IC_RESULT (ic)), "a", 0);
3312         }
3313       else
3314         {
3315
3316           _startLazyDPSEvaluation ();
3317           while (icount--)
3318             {
3319               emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3320             }
3321           _endLazyDPSEvaluation ();
3322         }
3323
3324       return TRUE;
3325     }
3326
3327   return FALSE;
3328 }
3329
3330 /*-----------------------------------------------------------------*/
3331 /* outBitAcc - output a bit in acc                                 */
3332 /*-----------------------------------------------------------------*/
3333 static void
3334 outBitAcc (operand * result)
3335 {
3336   symbol *tlbl = newiTempLabel (NULL);
3337   /* if the result is a bit */
3338   if (AOP_TYPE (result) == AOP_CRY)
3339     {
3340       aopPut (AOP (result), "a", 0);
3341     }
3342   else
3343     {
3344       emitcode ("jz", "%05d$", tlbl->key + 100);
3345       emitcode ("mov", "a,%s", one);
3346       emitcode ("", "%05d$:", tlbl->key + 100);
3347       outAcc (result);
3348     }
3349 }
3350
3351 /*-----------------------------------------------------------------*/
3352 /* genPlusBits - generates code for addition of two bits           */
3353 /*-----------------------------------------------------------------*/
3354 static void
3355 genPlusBits (iCode * ic)
3356 {
3357   D (emitcode (";", "genPlusBits ");
3358     );
3359   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3360     {
3361       symbol *lbl = newiTempLabel (NULL);
3362       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3363       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3364       emitcode ("cpl", "c");
3365       emitcode ("", "%05d$:", (lbl->key + 100));
3366       outBitC (IC_RESULT (ic));
3367     }
3368   else
3369     {
3370       emitcode ("clr", "a");
3371       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3372       emitcode ("rlc", "a");
3373       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3374       emitcode ("addc", "a,#0x00");
3375       outAcc (IC_RESULT (ic));
3376     }
3377 }
3378
3379 static void
3380 adjustArithmeticResult (iCode * ic)
3381 {
3382   if (opIsGptr (IC_RESULT (ic)) &&
3383       opIsGptr (IC_LEFT (ic)) &&
3384       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3385     {
3386       aopPut (AOP (IC_RESULT (ic)),
3387               aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3388               GPTRSIZE - 1);
3389     }
3390
3391   if (opIsGptr (IC_RESULT (ic)) &&
3392       opIsGptr (IC_RIGHT (ic)) &&
3393       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3394     {
3395       aopPut (AOP (IC_RESULT (ic)),
3396             aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3397               GPTRSIZE - 1);
3398     }
3399
3400   if (opIsGptr (IC_RESULT (ic)) &&
3401       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3402       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3403       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3404       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3405     {
3406       char buffer[5];
3407       sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3408       aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3409     }
3410 }
3411
3412 #if 0 // AOP_OP_3 is deprecated; nobody likes Ack errors.
3413       // Please don't bring it back without a really good reason.
3414 // Macro to aopOp all three operands of an ic. Will fatal if this cannot be done
3415 // (because all three operands are in far space).
3416 #define AOP_OP_3(ic) \
3417     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3418     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3419     aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3420               (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3421     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3422         AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3423     { \
3424         /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3425         fprintf(stderr,                                  \
3426                "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno);   \
3427     }
3428 #endif
3429
3430 // Macro to aopOp all three operands of an ic. If this cannot be done, 
3431 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3432 // will be set TRUE. The caller must then handle the case specially, noting
3433 // that the IC_RESULT operand is not aopOp'd.
3434 #define AOP_OP_3_NOFATAL(ic, rc) \
3435     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3436     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR) || \
3437                                   (OP_SYMBOL(IC_RESULT(ic))->ruonly)); \
3438     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3439         (isOperandInFarSpace(IC_RESULT(ic)) || OP_SYMBOL(IC_RESULT(ic))->ruonly )) \
3440     { \
3441        /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3442        rc = TRUE; \
3443     }  \
3444     else \
3445     { \
3446        aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3447                                      (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3448        rc = FALSE; \
3449        if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3450            AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3451        { \
3452             /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3453             fprintf(stderr,                                  \
3454                     "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno);   \
3455        } \
3456     }
3457
3458 // aopOp the left & right operands of an ic.
3459 #define AOP_OP_2(ic) \
3460     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3461     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3462
3463 // convienience macro.
3464 #define AOP_SET_LOCALS(ic) \
3465     left = IC_LEFT(ic); \
3466     right = IC_RIGHT(ic); \
3467     result = IC_RESULT(ic);
3468
3469
3470 // Given an integer value of pushedSize bytes on the stack,
3471 // adjust it to be resultSize bytes, either by discarding
3472 // the most significant bytes or by zero-padding.
3473 //
3474 // On exit from this macro, pushedSize will have been adjusted to
3475 // equal resultSize, and ACC may be trashed.
3476 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize)            \
3477       /* If the pushed data is bigger than the result,          \
3478        * simply discard unused bytes. Icky, but works.          \
3479        */                                                       \
3480       while (pushedSize > resultSize)                           \
3481       {                                                         \
3482           D (emitcode (";", "discarding unused result byte."););\
3483           emitcode ("pop", "acc");                              \
3484           pushedSize--;                                         \
3485       }                                                         \
3486       if (pushedSize < resultSize)                              \
3487       {                                                         \
3488           emitcode ("clr", "a");                                \
3489           /* Conversly, we haven't pushed enough here.          \
3490            * just zero-pad, and all is well.                    \
3491            */                                                   \
3492           while (pushedSize < resultSize)                       \
3493           {                                                     \
3494               emitcode("push", "acc");                          \
3495               pushedSize++;                                     \
3496           }                                                     \
3497       }                                                         \
3498       assert(pushedSize == resultSize);
3499
3500 /*-----------------------------------------------------------------*/
3501 /* genPlus - generates code for addition                           */
3502 /*-----------------------------------------------------------------*/
3503 static void
3504 genPlus (iCode * ic)
3505 {
3506   int size, offset = 0;
3507   bool pushResult = FALSE;
3508   int rSize;
3509
3510   D (emitcode (";", "genPlus "););
3511
3512   /* special cases :- */
3513   if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)) &&
3514       isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
3515       aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
3516       size = floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
3517       while (size--) emitcode ("inc","dptr");
3518       freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
3519       return ;
3520   }
3521   if ( IS_SYMOP(IC_LEFT(ic)) && 
3522        OP_SYMBOL(IC_LEFT(ic))->remat &&
3523        isOperandInFarSpace(IC_RIGHT(ic))) {
3524       operand *op = IC_RIGHT(ic);
3525       IC_RIGHT(ic) = IC_LEFT(ic);
3526       IC_LEFT(ic) = op;
3527   }
3528                 
3529   AOP_OP_3_NOFATAL (ic, pushResult);
3530   if (pushResult)
3531     {
3532       D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3533     }
3534
3535   if (!pushResult)
3536     {
3537       /* if literal, literal on the right or
3538          if left requires ACC or right is already
3539          in ACC */
3540       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3541        || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3542           || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3543         {
3544           operand *t = IC_RIGHT (ic);
3545           IC_RIGHT (ic) = IC_LEFT (ic);
3546           IC_LEFT (ic) = t;
3547           emitcode (";", "Swapped plus args.");
3548         }
3549
3550       /* if both left & right are in bit
3551          space */
3552       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3553           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3554         {
3555           genPlusBits (ic);
3556           goto release;
3557         }
3558
3559       /* if left in bit space & right literal */
3560       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3561           AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3562         {
3563           emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3564           /* if result in bit space */
3565           if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3566             {
3567               if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3568                 emitcode ("cpl", "c");
3569               outBitC (IC_RESULT (ic));
3570             }
3571           else
3572             {
3573               size = getDataSize (IC_RESULT (ic));
3574               _startLazyDPSEvaluation ();
3575               while (size--)
3576                 {
3577                   MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3578                   emitcode ("addc", "a,#00");
3579                   aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3580                 }
3581               _endLazyDPSEvaluation ();
3582             }
3583           goto release;
3584         }
3585
3586       /* if I can do an increment instead
3587          of add then GOOD for ME */
3588       if (genPlusIncr (ic) == TRUE)
3589         {
3590           emitcode (";", "did genPlusIncr");
3591           goto release;
3592         }
3593
3594     }
3595   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3596
3597   _startLazyDPSEvaluation ();
3598   while (size--)
3599     {
3600       if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
3601         {
3602           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3603           if (offset == 0)
3604             emitcode ("add", "a,%s",
3605                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3606           else
3607             emitcode ("addc", "a,%s",
3608                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3609         }
3610       else
3611         {
3612           if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
3613           {
3614               /* right is going to use ACC or we would have taken the
3615                * above branch.
3616                */
3617               assert(AOP_NEEDSACC(IC_RIGHT(ic)));
3618        TR_AP("#3");
3619               D(emitcode(";", "+ AOP_ACC special case."););
3620               emitcode("xch", "a, %s", DP2_RESULT_REG);
3621           }
3622           MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3623           if (offset == 0)
3624           {
3625             if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
3626             {
3627          TR_AP("#4");
3628                 emitcode("add", "a, %s", DP2_RESULT_REG); 
3629             }
3630             else
3631             {
3632                 emitcode ("add", "a,%s",
3633                         aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE, FALSE));
3634             }
3635           }
3636           else
3637           {
3638             emitcode ("addc", "a,%s",
3639                   aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3640           }
3641         }
3642       if (!pushResult)
3643         {
3644           aopPut (AOP (IC_RESULT (ic)), "a", offset);
3645         }
3646       else
3647         {
3648           emitcode ("push", "acc");
3649         }
3650       offset++;
3651     }
3652   _endLazyDPSEvaluation ();
3653
3654   if (pushResult)
3655     {
3656       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3657
3658       size = getDataSize (IC_LEFT (ic));
3659       rSize = getDataSize (IC_RESULT (ic));
3660
3661       ADJUST_PUSHED_RESULT(size, rSize);
3662
3663       _startLazyDPSEvaluation ();
3664       while (size--)
3665         {
3666           emitcode ("pop", "acc");
3667           aopPut (AOP (IC_RESULT (ic)), "a", size);
3668         }
3669       _endLazyDPSEvaluation ();
3670     }
3671
3672   adjustArithmeticResult (ic);
3673
3674 release:
3675   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3676   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3677   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3678 }
3679
3680 /*-----------------------------------------------------------------*/
3681 /* genMinusDec :- does subtraction with deccrement if possible     */
3682 /*-----------------------------------------------------------------*/
3683 static bool
3684 genMinusDec (iCode * ic)
3685 {
3686   unsigned int icount;
3687   unsigned int size = getDataSize (IC_RESULT (ic));
3688
3689   /* will try to generate an increment */
3690   /* if the right side is not a literal
3691      we cannot */
3692   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3693     return FALSE;
3694
3695   /* if the literal value of the right hand side
3696      is greater than 4 then it is not worth it */
3697   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3698     return FALSE;
3699
3700   /* if decrement 16 bits in register */
3701   if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3702       AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3703       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3704       (size > 1) &&
3705       (icount == 1))
3706     {
3707       symbol *tlbl;
3708       int emitTlbl;
3709       int labelRange;
3710
3711       /* If the next instruction is a goto and the goto target
3712          * is <= 5 instructions previous to this, we can generate
3713          * jumps straight to that target.
3714        */
3715       if (ic->next && ic->next->op == GOTO
3716           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3717           && labelRange <= 5)
3718         {
3719           emitcode (";", "tail decrement optimized (range %d)", labelRange);
3720           tlbl = IC_LABEL (ic->next);
3721           emitTlbl = 0;
3722         }
3723       else
3724         {
3725           tlbl = newiTempLabel (NULL);
3726           emitTlbl = 1;
3727         }
3728
3729       emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3730       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3731           AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3732           IS_AOP_PREG (IC_RESULT (ic)))
3733         emitcode ("cjne", "%s,#0xff,%05d$"
3734                   ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3735                   ,tlbl->key + 100);
3736       else
3737         {
3738           emitcode ("mov", "a,#0xff");
3739           emitcode ("cjne", "a,%s,%05d$"
3740                     ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3741                     ,tlbl->key + 100);
3742         }
3743       emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3744       if (size > 2)
3745         {
3746           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3747               AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3748               IS_AOP_PREG (IC_RESULT (ic)))
3749             emitcode ("cjne", "%s,#0xff,%05d$"
3750                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3751                       ,tlbl->key + 100);
3752           else
3753             {
3754               emitcode ("cjne", "a,%s,%05d$"
3755                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3756                         ,tlbl->key + 100);
3757             }
3758           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3759         }
3760       if (size > 3)
3761         {
3762           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3763               AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3764               IS_AOP_PREG (IC_RESULT (ic)))
3765             emitcode ("cjne", "%s,#0xff,%05d$"
3766                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3767                       ,tlbl->key + 100);
3768           else
3769             {
3770               emitcode ("cjne", "a,%s,%05d$"
3771                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3772                         ,tlbl->key + 100);
3773             }
3774           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3775         }
3776       if (emitTlbl)
3777         {
3778           emitcode ("", "%05d$:", tlbl->key + 100);
3779         }
3780       return TRUE;
3781     }
3782
3783   /* if the sizes are greater than 1 then we cannot */
3784   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3785       AOP_SIZE (IC_LEFT (ic)) > 1)
3786     return FALSE;
3787
3788   /* we can if the aops of the left & result match or
3789      if they are in registers and the registers are the
3790      same */
3791   if (
3792        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3793        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3794        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3795     {
3796
3797       _startLazyDPSEvaluation ();
3798       while (icount--)
3799         {
3800           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
3801         }
3802       _endLazyDPSEvaluation ();
3803
3804       return TRUE;
3805     }
3806
3807   return FALSE;
3808 }
3809
3810 /*-----------------------------------------------------------------*/
3811 /* addSign - complete with sign                                    */
3812 /*-----------------------------------------------------------------*/
3813 static void
3814 addSign (operand * result, int offset, int sign)
3815 {
3816   int size = (getDataSize (result) - offset);
3817   if (size > 0)
3818     {
3819       _startLazyDPSEvaluation();
3820       if (sign)
3821         {
3822           emitcode ("rlc", "a");
3823           emitcode ("subb", "a,acc");
3824           while (size--)
3825           {
3826             aopPut (AOP (result), "a", offset++);
3827           }
3828         }
3829       else
3830       {
3831         while (size--)
3832         {
3833           aopPut (AOP (result), zero, offset++);
3834         }
3835       }
3836       _endLazyDPSEvaluation();
3837     }
3838 }
3839
3840 /*-----------------------------------------------------------------*/
3841 /* genMinusBits - generates code for subtraction  of two bits      */
3842 /*-----------------------------------------------------------------*/
3843 static void
3844 genMinusBits (iCode * ic)
3845 {
3846   symbol *lbl = newiTempLabel (NULL);
3847
3848   D (emitcode (";", "genMinusBits "););
3849
3850   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3851     {
3852       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3853       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3854       emitcode ("cpl", "c");
3855       emitcode ("", "%05d$:", (lbl->key + 100));
3856       outBitC (IC_RESULT (ic));
3857     }
3858   else
3859     {
3860       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3861       emitcode ("subb", "a,acc");
3862       emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3863       emitcode ("inc", "a");
3864       emitcode ("", "%05d$:", (lbl->key + 100));
3865       aopPut (AOP (IC_RESULT (ic)), "a", 0);
3866       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3867     }
3868 }
3869
3870 /*-----------------------------------------------------------------*/
3871 /* genMinus - generates code for subtraction                       */
3872 /*-----------------------------------------------------------------*/
3873 static void
3874 genMinus (iCode * ic)
3875 {
3876   int size, offset = 0;
3877   int rSize;
3878   unsigned long lit = 0L;
3879   bool pushResult = FALSE;
3880
3881   D (emitcode (";", "genMinus "););
3882
3883   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3884   aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
3885   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
3886       (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
3887     {
3888       pushResult = TRUE;
3889     }
3890   else
3891     {
3892       aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
3893
3894       /* special cases :- */
3895       /* if both left & right are in bit space */
3896       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3897           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3898         {
3899           genMinusBits (ic);
3900           goto release;
3901         }
3902
3903       /* if I can do an decrement instead
3904          of subtract then GOOD for ME */
3905       if (genMinusDec (ic) == TRUE)
3906         goto release;
3907
3908     }
3909
3910   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3911
3912   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3913     {
3914       CLRC;
3915     }
3916   else
3917     {
3918       lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3919       lit = -(long) lit;
3920     }
3921
3922
3923   /* if literal, add a,#-lit, else normal subb */
3924   _startLazyDPSEvaluation ();
3925   while (size--)
3926     {
3927       MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3928       if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3929         emitcode ("subb", "a,%s",
3930                   aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3931       else
3932         {
3933           /* first add without previous c */
3934           if (!offset) {
3935             if (!size && lit==-1) {
3936               emitcode ("dec", "a");
3937             } else {
3938               emitcode ("add", "a,#0x%02x",
3939                         (unsigned int) (lit & 0x0FFL));
3940             }
3941           } else {
3942             emitcode ("addc", "a,#0x%02x",
3943                       (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3944           }
3945         }
3946
3947       if (pushResult)
3948         {
3949           emitcode ("push", "acc");
3950         }
3951       else
3952         {
3953           aopPut (AOP (IC_RESULT (ic)), "a", offset);
3954         }
3955       offset++;
3956     }
3957   _endLazyDPSEvaluation ();
3958
3959   if (pushResult)
3960     {
3961       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3962
3963       size = getDataSize (IC_LEFT (ic));
3964       rSize = getDataSize (IC_RESULT (ic));
3965
3966       ADJUST_PUSHED_RESULT(size, rSize);
3967
3968       _startLazyDPSEvaluation ();
3969       while (size--)
3970         {
3971           emitcode ("pop", "acc");
3972           aopPut (AOP (IC_RESULT (ic)), "a", size);
3973         }
3974       _endLazyDPSEvaluation ();
3975     }
3976
3977   adjustArithmeticResult (ic);
3978
3979 release:
3980   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3981   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3982   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3983 }
3984
3985
3986 /*-----------------------------------------------------------------*/
3987 /* genMultbits :- multiplication of bits                           */
3988 /*-----------------------------------------------------------------*/
3989 static void
3990 genMultbits (operand * left,
3991              operand * right,
3992              operand * result,
3993              iCode   * ic)
3994 {
3995   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3996   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3997   aopOp(result, ic, TRUE, FALSE);
3998   outBitC (result);
3999 }
4000
4001
4002 /*-----------------------------------------------------------------*/
4003 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
4004 /*-----------------------------------------------------------------*/
4005 static void
4006 genMultOneByte (operand * left,
4007                 operand * right,
4008                 operand * result,
4009                 iCode   * ic)
4010 {
4011   sym_link *opetype = operandType (result);
4012   symbol *lbl;
4013
4014
4015   /* (if two literals: the value is computed before) */
4016   /* if one literal, literal on the right */
4017   if (AOP_TYPE (left) == AOP_LIT)
4018     {
4019       operand *t = right;
4020       right = left;
4021       left = t;
4022       emitcode (";", "swapped left and right");
4023     }
4024
4025   if (SPEC_USIGN(opetype)
4026       // ignore the sign of left and right, what else can we do?
4027       || (SPEC_USIGN(operandType(left)) && 
4028           SPEC_USIGN(operandType(right)))) {
4029     // just an unsigned 8*8=8/16 multiply
4030     //emitcode (";","unsigned");
4031     emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4032     MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4033     emitcode ("mul", "ab");
4034    
4035     _G.accInUse++;
4036     aopOp(result, ic, TRUE, FALSE);
4037       
4038       if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4039       {
4040           // this should never happen
4041           fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4042                    AOP_SIZE(result), __FILE__, lineno);
4043           exit (1);
4044       }      
4045       
4046     aopPut (AOP (result), "a", 0);
4047     _G.accInUse--;
4048     if (AOP_SIZE(result)==2) 
4049     {
4050       aopPut (AOP (result), "b", 1);
4051     }
4052     return;
4053   }
4054
4055   // we have to do a signed multiply
4056
4057   emitcode (";", "signed");
4058   emitcode ("clr", "F0"); // reset sign flag
4059   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4060
4061   lbl=newiTempLabel(NULL);
4062   emitcode ("jnb", "acc.7,%05d$",  lbl->key+100);
4063   // left side is negative, 8-bit two's complement, this fails for -128
4064   emitcode ("setb", "F0"); // set sign flag
4065   emitcode ("cpl", "a");
4066   emitcode ("inc", "a");
4067
4068   emitcode ("", "%05d$:", lbl->key+100);
4069
4070   /* if literal */
4071   if (AOP_TYPE(right)==AOP_LIT) {
4072     signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
4073     /* AND literal negative */
4074     if ((int) val < 0) {
4075       emitcode ("cpl", "F0"); // complement sign flag
4076       emitcode ("mov", "b,#0x%02x", -val);
4077     } else {
4078       emitcode ("mov", "b,#0x%02x", val);
4079     }
4080   } else {
4081     lbl=newiTempLabel(NULL);
4082     emitcode ("mov", "b,a");
4083     emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4084     emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
4085     // right side is negative, 8-bit two's complement
4086     emitcode ("cpl", "F0"); // complement sign flag
4087     emitcode ("cpl", "a");
4088     emitcode ("inc", "a");
4089     emitcode ("", "%05d$:", lbl->key+100);
4090   }
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   lbl=newiTempLabel(NULL);
4105   emitcode ("jnb", "F0,%05d$", lbl->key+100);
4106   // only ONE op was negative, we have to do a 8/16-bit two's complement
4107   emitcode ("cpl", "a"); // lsb
4108   if (AOP_SIZE(result)==1) {
4109     emitcode ("inc", "a");
4110   } else {
4111     emitcode ("add", "a,#1");
4112     emitcode ("xch", "a,b");
4113     emitcode ("cpl", "a"); // msb
4114     emitcode ("addc", "a,#0");
4115     emitcode ("xch", "a,b");
4116   }
4117
4118   emitcode ("", "%05d$:", lbl->key+100);
4119   aopPut (AOP (result), "a", 0);
4120   _G.accInUse--;
4121   if (AOP_SIZE(result)==2) {
4122     aopPut (AOP (result), "b", 1);
4123   }
4124 }
4125
4126 /*-----------------------------------------------------------------*/
4127 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply    */
4128 /*-----------------------------------------------------------------*/
4129 static void genMultTwoByte (operand *left, operand *right, 
4130                             operand *result, iCode *ic)
4131 {
4132         sym_link *retype = getSpec(operandType(right));
4133         sym_link *letype = getSpec(operandType(left));
4134         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4135         symbol *lbl;
4136
4137         if (AOP_TYPE (left) == AOP_LIT) {
4138                 operand *t = right;
4139                 right = left;
4140                 left = t;
4141         }
4142         /* save EA bit in F1 */
4143         lbl = newiTempLabel(NULL);
4144         emitcode ("setb","F1");
4145         emitcode ("jbc","EA,%05d$",lbl->key+100);
4146         emitcode ("clr","F1");
4147         emitcode("","%05d$:",lbl->key+100);
4148
4149         /* load up MB with right */
4150         if (!umult) {
4151                 emitcode("clr","F0");
4152                 if (AOP_TYPE(right) == AOP_LIT) {
4153                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
4154                         if (val < 0) {
4155                                 emitcode("setb","F0");
4156                                 val = -val;
4157                         }
4158                         emitcode ("mov","mb,#0x%02x",val & 0xff);
4159                         emitcode ("mov","mb,#0x%02x",(val >> 8) & 0xff);                    
4160                 } else {
4161                         lbl = newiTempLabel(NULL);
4162                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4163                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4164                         emitcode ("jnb","acc.7,%05d$",lbl->key+100);            
4165                         emitcode ("xch", "a,b");
4166                         emitcode ("cpl","a");
4167                         emitcode ("add", "a,#1");
4168                         emitcode ("xch", "a,b");
4169                         emitcode ("cpl", "a"); // msb
4170                         emitcode ("addc", "a,#0");
4171                         emitcode ("setb","F0");
4172                         emitcode ("","%05d$:",lbl->key+100);
4173                         emitcode ("mov","mb,b");
4174                         emitcode ("mov","mb,a");
4175                 }
4176         } else {
4177                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4178                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4179         }
4180         /* load up MA with left */
4181         if (!umult) {
4182                 lbl = newiTempLabel(NULL);
4183                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4184                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4185                 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4186                 emitcode ("xch", "a,b");
4187                 emitcode ("cpl","a");
4188                 emitcode ("add", "a,#1");
4189                 emitcode ("xch", "a,b");
4190                 emitcode ("cpl", "a"); // msb
4191                 emitcode ("addc","a,#0");
4192                 emitcode ("jbc","F0,%05d$",lbl->key+100);
4193                 emitcode ("setb","F0");
4194                 emitcode ("","%05d$:",lbl->key+100);
4195                 emitcode ("mov","ma,b");
4196                 emitcode ("mov","ma,a");
4197         } else {
4198                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4199                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4200         }
4201         /* wait for multiplication to finish */
4202         lbl = newiTempLabel(NULL);
4203         emitcode("","%05d$:", lbl->key+100);
4204         emitcode("mov","a,mcnt1");
4205         emitcode("anl","a,#0x80");
4206         emitcode("jnz","%05d$",lbl->key+100);
4207         
4208         freeAsmop (left, NULL, ic, TRUE);
4209         freeAsmop (right, NULL, ic,TRUE);
4210         aopOp(result, ic, TRUE, FALSE);
4211
4212         /* if unsigned then simple */   
4213         if (umult) {
4214                 emitcode ("mov","a,ma");
4215                 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4216                 emitcode ("mov","a,ma");
4217                 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4218                 aopPut(AOP(result),"ma",1);
4219                 aopPut(AOP(result),"ma",0);
4220         } else {
4221                 emitcode("push","ma");
4222                 emitcode("push","ma");
4223                 emitcode("push","ma");
4224                 MOVA("ma");
4225                 /* negate result if needed */
4226                 lbl = newiTempLabel(NULL);      
4227                 emitcode("jnb","F0,%05d$",lbl->key+100);
4228                 emitcode("cpl","a");
4229                 emitcode("add","a,#1");
4230                 emitcode("","%05d$:", lbl->key+100);
4231                 if (AOP_TYPE(result) == AOP_ACC)
4232                 {
4233                     D(emitcode(";", "ACC special case."););
4234                     /* We know result is the only live aop, and 
4235                      * it's obviously not a DPTR2, so AP is available.
4236                      */
4237                     emitcode("mov", "%s,acc", DP2_RESULT_REG);
4238                 }
4239                 else
4240                 {
4241                     aopPut(AOP(result),"a",0);
4242                 }
4243             
4244                 emitcode("pop","acc");
4245                 lbl = newiTempLabel(NULL);      
4246                 emitcode("jnb","F0,%05d$",lbl->key+100);
4247                 emitcode("cpl","a");
4248                 emitcode("addc","a,#0");
4249                 emitcode("","%05d$:", lbl->key+100);
4250                 aopPut(AOP(result),"a",1);
4251                 emitcode("pop","acc");
4252                 if (AOP_SIZE(result) >= 3) {
4253                         lbl = newiTempLabel(NULL);      
4254                         emitcode("jnb","F0,%05d$",lbl->key+100);
4255                         emitcode("cpl","a");
4256                         emitcode("addc","a,#0");                        
4257                         emitcode("","%05d$:", lbl->key+100);
4258                         aopPut(AOP(result),"a",2);
4259                 }
4260                 emitcode("pop","acc");
4261                 if (AOP_SIZE(result) >= 4) {
4262                         lbl = newiTempLabel(NULL);      
4263                         emitcode("jnb","F0,%05d$",lbl->key+100);
4264                         emitcode("cpl","a");
4265                         emitcode("addc","a,#0");                        
4266                         emitcode("","%05d$:", lbl->key+100);
4267                         aopPut(AOP(result),"a",3);
4268                 }
4269                 if (AOP_TYPE(result) == AOP_ACC)
4270                 {
4271                     /* We stashed the result away above. */
4272                     emitcode("mov", "acc,%s", DP2_RESULT_REG);
4273                 }           
4274                 
4275         }
4276         freeAsmop (result, NULL, ic, TRUE);
4277
4278         /* restore EA bit in F1 */
4279         lbl = newiTempLabel(NULL);
4280         emitcode ("jnb","F1,%05d$",lbl->key+100);
4281         emitcode ("setb","EA");
4282         emitcode("","%05d$:",lbl->key+100);
4283         return ;
4284 }
4285
4286 /*-----------------------------------------------------------------*/
4287 /* genMult - generates code for multiplication                     */
4288 /*-----------------------------------------------------------------*/
4289 static void
4290 genMult (iCode * ic)
4291 {
4292   operand *left = IC_LEFT (ic);
4293   operand *right = IC_RIGHT (ic);
4294   operand *result = IC_RESULT (ic);
4295
4296   D (emitcode (";", "genMult "););
4297
4298   /* assign the amsops */
4299   AOP_OP_2 (ic);
4300
4301   /* special cases first */
4302   /* both are bits */
4303   if (AOP_TYPE (left) == AOP_CRY &&
4304       AOP_TYPE (right) == AOP_CRY)
4305     {
4306       genMultbits (left, right, result, ic);
4307       goto release;
4308     }
4309
4310   /* if both are of size == 1 */
4311   if (AOP_SIZE (left) == 1 &&
4312       AOP_SIZE (right) == 1)
4313     {
4314       genMultOneByte (left, right, result, ic);
4315       goto release;
4316     }
4317
4318   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4319           /* use the ds390 ARITHMETIC accel UNIT */
4320           genMultTwoByte (left, right, result, ic);
4321           return ;
4322   }
4323   /* should have been converted to function call */
4324   assert (0);
4325
4326 release:
4327   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4328   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4329   freeAsmop (result, NULL, ic, TRUE);
4330 }
4331
4332 /*-----------------------------------------------------------------*/
4333 /* genDivbits :- division of bits                                  */
4334 /*-----------------------------------------------------------------*/
4335 static void
4336 genDivbits (operand * left,
4337             operand * right,
4338             operand * result,
4339             iCode   * ic)
4340 {
4341
4342   char *l;
4343
4344   /* the result must be bit */
4345   LOAD_AB_FOR_DIV (left, right, l);
4346   emitcode ("div", "ab");
4347   emitcode ("rrc", "a");
4348   aopOp(result, ic, TRUE, FALSE);
4349     
4350   aopPut (AOP (result), "c", 0);
4351 }
4352
4353 /*-----------------------------------------------------------------*/
4354 /* genDivOneByte : 8 bit division                                  */
4355 /*-----------------------------------------------------------------*/
4356 static void
4357 genDivOneByte (operand * left,
4358                operand * right,
4359                operand * result,
4360                iCode   * ic)
4361 {
4362   sym_link *opetype = operandType (result);
4363   char *l;
4364   symbol *lbl;
4365   int size, offset;
4366
4367   offset = 1;
4368   /* signed or unsigned */
4369   if (SPEC_USIGN (opetype))
4370     {
4371         /* unsigned is easy */
4372         LOAD_AB_FOR_DIV (left, right, l);
4373         emitcode ("div", "ab");
4374
4375         _G.accInUse++;
4376         aopOp(result, ic, TRUE, FALSE);
4377         aopPut (AOP (result), "a", 0);
4378         _G.accInUse--;
4379
4380         size = AOP_SIZE (result) - 1;
4381         
4382         while (size--)
4383         {
4384             aopPut (AOP (result), zero, offset++);
4385         }
4386       return;
4387     }
4388
4389   /* signed is a little bit more difficult */
4390
4391   /* save the signs of the operands */
4392   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4393   MOVA (l);
4394   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4395   emitcode ("push", "acc");     /* save it on the stack */
4396
4397   /* now sign adjust for both left & right */
4398   l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4399   MOVA (l);
4400   lbl = newiTempLabel (NULL);
4401   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4402   emitcode ("cpl", "a");
4403   emitcode ("inc", "a");
4404   emitcode ("", "%05d$:", (lbl->key + 100));
4405   emitcode ("mov", "b,a");
4406
4407   /* sign adjust left side */
4408   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4409   MOVA (l);
4410
4411   lbl = newiTempLabel (NULL);
4412   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4413   emitcode ("cpl", "a");
4414   emitcode ("inc", "a");
4415   emitcode ("", "%05d$:", (lbl->key + 100));
4416
4417   /* now the division */
4418   emitcode ("nop", "; workaround for DS80C390 div bug.");
4419   emitcode ("div", "ab");
4420   /* we are interested in the lower order
4421      only */
4422   emitcode ("mov", "b,a");
4423   lbl = newiTempLabel (NULL);
4424   emitcode ("pop", "acc");
4425   /* if there was an over flow we don't
4426      adjust the sign of the result */
4427   emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4428   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4429   CLRC;
4430   emitcode ("clr", "a");
4431   emitcode ("subb", "a,b");
4432   emitcode ("mov", "b,a");
4433   emitcode ("", "%05d$:", (lbl->key + 100));
4434
4435   /* now we are done */
4436     _G.accInUse++;
4437     aopOp(result, ic, TRUE, FALSE);
4438     
4439     aopPut (AOP (result), "b", 0);
4440     
4441     size = AOP_SIZE (result) - 1;
4442     
4443     if (size > 0)
4444     {
4445       emitcode ("mov", "c,b.7");
4446       emitcode ("subb", "a,acc");
4447     }
4448     while (size--)
4449     {
4450         aopPut (AOP (result), "a", offset++);
4451     }
4452     _G.accInUse--;
4453
4454 }
4455
4456 /*-----------------------------------------------------------------*/
4457 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide       */
4458 /*-----------------------------------------------------------------*/
4459 static void genDivTwoByte (operand *left, operand *right, 
4460                             operand *result, iCode *ic)
4461 {
4462         sym_link *retype = getSpec(operandType(right));
4463         sym_link *letype = getSpec(operandType(left));
4464         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4465         symbol *lbl;
4466
4467         /* save EA bit in F1 */
4468         lbl = newiTempLabel(NULL);
4469         emitcode ("setb","F1");
4470         emitcode ("jbc","EA,%05d$",lbl->key+100);
4471         emitcode ("clr","F1");
4472         emitcode("","%05d$:",lbl->key+100);
4473
4474         /* load up MA with left */
4475         if (!umult) {
4476                 emitcode("clr","F0");
4477                 lbl = newiTempLabel(NULL);
4478                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4479                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4480                 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4481                 emitcode ("xch", "a,b");
4482                 emitcode ("cpl","a");
4483                 emitcode ("add", "a,#1");
4484                 emitcode ("xch", "a,b");
4485                 emitcode ("cpl", "a"); // msb
4486                 emitcode ("addc","a,#0");
4487                 emitcode ("setb","F0");
4488                 emitcode ("","%05d$:",lbl->key+100);
4489                 emitcode ("mov","ma,b");
4490                 emitcode ("mov","ma,a");
4491         } else {
4492                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4493                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4494         }
4495
4496         /* load up MB with right */
4497         if (!umult) {
4498                 if (AOP_TYPE(right) == AOP_LIT) {
4499                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
4500                         if (val < 0) {
4501                                 lbl = newiTempLabel(NULL);
4502                                 emitcode ("jbc","F0,%05d$",lbl->key+100);
4503                                 emitcode("setb","F0");
4504                                 emitcode ("","%05d$:",lbl->key+100);
4505                                 val = -val;
4506                         } 
4507                         emitcode ("mov","mb,#0x%02x",val & 0xff);                   
4508                         emitcode ("mov","mb,#0x%02x",(val >> 8) & 0xff);
4509                 } else {
4510                         lbl = newiTempLabel(NULL);
4511                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4512                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4513                         emitcode ("jnb","acc.7,%05d$",lbl->key+100);            
4514                         emitcode ("xch", "a,b");
4515                         emitcode ("cpl","a");
4516                         emitcode ("add", "a,#1");
4517                         emitcode ("xch", "a,b");
4518                         emitcode ("cpl", "a"); // msb
4519                         emitcode ("addc", "a,#0");
4520                         emitcode ("jbc","F0,%05d$",lbl->key+100);
4521                         emitcode ("setb","F0");
4522                         emitcode ("","%05d$:",lbl->key+100);
4523                         emitcode ("mov","mb,b");
4524                         emitcode ("mov","mb,a");
4525                 }
4526         } else {
4527                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4528                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4529         }
4530
4531         /* wait for multiplication to finish */
4532         lbl = newiTempLabel(NULL);
4533         emitcode("","%05d$:", lbl->key+100);
4534         emitcode("mov","a,mcnt1");
4535         emitcode("anl","a,#0x80");
4536         emitcode("jnz","%05d$",lbl->key+100);
4537         
4538         freeAsmop (left, NULL, ic, TRUE);
4539         freeAsmop (right, NULL, ic,TRUE);
4540         aopOp(result, ic, TRUE, FALSE);
4541
4542         /* if unsigned then simple */   
4543         if (umult) {
4544                 aopPut(AOP(result),"ma",1);
4545                 aopPut(AOP(result),"ma",0);
4546         } else {
4547                 emitcode("push","ma");
4548                 MOVA("ma");
4549                 /* negate result if needed */
4550                 lbl = newiTempLabel(NULL);      
4551                 emitcode("jnb","F0,%05d$",lbl->key+100);
4552                 emitcode("cpl","a");
4553                 emitcode("add","a,#1");
4554                 emitcode("","%05d$:", lbl->key+100);
4555                 aopPut(AOP(result),"a",0);
4556                 emitcode("pop","acc");
4557                 lbl = newiTempLabel(NULL);      
4558                 emitcode("jnb","F0,%05d$",lbl->key+100);
4559                 emitcode("cpl","a");
4560                 emitcode("addc","a,#0");
4561                 emitcode("","%05d$:", lbl->key+100);
4562                 aopPut(AOP(result),"a",1);
4563         }
4564         freeAsmop (result, NULL, ic, TRUE);
4565         /* restore EA bit in F1 */
4566         lbl = newiTempLabel(NULL);
4567         emitcode ("jnb","F1,%05d$",lbl->key+100);
4568         emitcode ("setb","EA");
4569         emitcode("","%05d$:",lbl->key+100);
4570         return ;
4571 }
4572
4573 /*-----------------------------------------------------------------*/
4574 /* genDiv - generates code for division                            */
4575 /*-----------------------------------------------------------------*/
4576 static void
4577 genDiv (iCode * ic)
4578 {
4579   operand *left = IC_LEFT (ic);
4580   operand *right = IC_RIGHT (ic);
4581   operand *result = IC_RESULT (ic);
4582
4583   D (emitcode (";", "genDiv "););
4584
4585   /* assign the amsops */
4586   AOP_OP_2 (ic);
4587
4588   /* special cases first */
4589   /* both are bits */
4590   if (AOP_TYPE (left) == AOP_CRY &&
4591       AOP_TYPE (right) == AOP_CRY)
4592     {
4593       genDivbits (left, right, result, ic);
4594       goto release;
4595     }
4596
4597   /* if both are of size == 1 */
4598   if (AOP_SIZE (left) == 1 &&
4599       AOP_SIZE (right) == 1)
4600     {
4601       genDivOneByte (left, right, result, ic);
4602       goto release;
4603     }
4604
4605   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4606           /* use the ds390 ARITHMETIC accel UNIT */
4607           genDivTwoByte (left, right, result, ic);
4608           return ;
4609   }
4610   /* should have been converted to function call */
4611   assert (0);
4612 release:
4613   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4614   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4615   freeAsmop (result, NULL, ic, TRUE);
4616 }
4617
4618 /*-----------------------------------------------------------------*/
4619 /* genModbits :- modulus of bits                                   */
4620 /*-----------------------------------------------------------------*/
4621 static void
4622 genModbits (operand * left,
4623             operand * right,
4624             operand * result,
4625             iCode   * ic)
4626 {
4627
4628   char *l;
4629
4630   /* the result must be bit */
4631   LOAD_AB_FOR_DIV (left, right, l);
4632   emitcode ("div", "ab");
4633   emitcode ("mov", "a,b");
4634   emitcode ("rrc", "a");
4635   aopOp(result, ic, TRUE, FALSE);
4636   aopPut (AOP (result), "c", 0);
4637 }
4638
4639 /*-----------------------------------------------------------------*/
4640 /* genModOneByte : 8 bit modulus                                   */
4641 /*-----------------------------------------------------------------*/
4642 static void
4643 genModOneByte (operand * left,
4644                operand * right,
4645                operand * result,
4646                iCode   * ic)
4647 {
4648   sym_link *opetype = operandType (result);
4649   char *l;
4650   symbol *lbl;
4651
4652   /* signed or unsigned */
4653   if (SPEC_USIGN (opetype))
4654     {
4655       /* unsigned is easy */
4656       LOAD_AB_FOR_DIV (left, right, l);
4657       emitcode ("div", "ab");
4658       aopOp(result, ic, TRUE, FALSE);   
4659       aopPut (AOP (result), "b", 0);
4660       return;
4661     }
4662
4663   /* signed is a little bit more difficult */
4664
4665   /* save the signs of the operands */
4666   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4667   MOVA (l);
4668
4669   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4670   emitcode ("push", "acc");     /* save it on the stack */
4671
4672   /* now sign adjust for both left & right */
4673   l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4674   MOVA (l);
4675
4676   lbl = newiTempLabel (NULL);
4677   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4678   emitcode ("cpl", "a");
4679   emitcode ("inc", "a");
4680   emitcode ("", "%05d$:", (lbl->key + 100));
4681   emitcode ("mov", "b,a");
4682
4683   /* sign adjust left side */
4684   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4685   MOVA (l);
4686
4687   lbl = newiTempLabel (NULL);
4688   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4689   emitcode ("cpl", "a");
4690   emitcode ("inc", "a");
4691   emitcode ("", "%05d$:", (lbl->key + 100));
4692
4693   /* now the multiplication */
4694   emitcode ("nop", "; workaround for DS80C390 div bug.");
4695   emitcode ("div", "ab");
4696   /* we are interested in the lower order
4697      only */
4698   lbl = newiTempLabel (NULL);
4699   emitcode ("pop", "acc");
4700   /* if there was an over flow we don't
4701      adjust the sign of the result */
4702   emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4703   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4704   CLRC;
4705   emitcode ("clr", "a");
4706   emitcode ("subb", "a,b");
4707   emitcode ("mov", "b,a");
4708   emitcode ("", "%05d$:", (lbl->key + 100));
4709
4710   /* now we are done */
4711   aopOp(result, ic, TRUE, FALSE);    
4712   aopPut (AOP (result), "b", 0);
4713
4714 }
4715
4716 /*-----------------------------------------------------------------*/
4717 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus      */
4718 /*-----------------------------------------------------------------*/
4719 static void genModTwoByte (operand *left, operand *right, 
4720                             operand *result, iCode *ic)
4721 {
4722         sym_link *retype = getSpec(operandType(right));
4723         sym_link *letype = getSpec(operandType(left));
4724         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4725         symbol *lbl;
4726
4727         /* load up MA with left */
4728         /* save EA bit in F1 */
4729         lbl = newiTempLabel(NULL);
4730         emitcode ("setb","F1");
4731         emitcode ("jbc","EA,%05d$",lbl->key+100);
4732         emitcode ("clr","F1");
4733         emitcode("","%05d$:",lbl->key+100);
4734
4735         if (!umult) {
4736                 lbl = newiTempLabel(NULL);
4737                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4738                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4739                 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4740                 emitcode ("xch", "a,b");
4741                 emitcode ("cpl","a");
4742                 emitcode ("add", "a,#1");
4743                 emitcode ("xch", "a,b");
4744                 emitcode ("cpl", "a"); // msb
4745                 emitcode ("addc","a,#0");
4746                 emitcode ("","%05d$:",lbl->key+100);
4747                 emitcode ("mov","ma,b");
4748                 emitcode ("mov","ma,a");
4749         } else {
4750                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4751                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4752         }
4753
4754         /* load up MB with right */
4755         if (!umult) {
4756                 if (AOP_TYPE(right) == AOP_LIT) {
4757                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
4758                         if (val < 0) {
4759                                 val = -val;
4760                         } 
4761                         emitcode ("mov","mb,#0x%02x",val & 0xff);
4762                         emitcode ("mov","mb,#0x%02x",(val >> 8) & 0xff);                    
4763                 } else {
4764                         lbl = newiTempLabel(NULL);
4765                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4766                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4767                         emitcode ("jnb","acc.7,%05d$",lbl->key+100);            
4768                         emitcode ("xch", "a,b");
4769                         emitcode ("cpl","a");
4770                         emitcode ("add", "a,#1");
4771                         emitcode ("xch", "a,b");
4772                         emitcode ("cpl", "a"); // msb
4773                         emitcode ("addc", "a,#0");
4774                         emitcode ("","%05d$:",lbl->key+100);
4775                         emitcode ("mov","mb,b");
4776                         emitcode ("mov","mb,a");
4777                 }
4778         } else {
4779                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4780                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4781         }
4782
4783         /* wait for multiplication to finish */
4784         lbl = newiTempLabel(NULL);
4785         emitcode("","%05d$:", lbl->key+100);
4786         emitcode("mov","a,mcnt1");
4787         emitcode("anl","a,#0x80");
4788         emitcode("jnz","%05d$",lbl->key+100);
4789         
4790         freeAsmop (left, NULL, ic, TRUE);
4791         freeAsmop (right, NULL, ic,TRUE);
4792         aopOp(result, ic, TRUE, FALSE);
4793
4794         aopPut(AOP(result),"mb",1);
4795         aopPut(AOP(result),"mb",0);
4796         freeAsmop (result, NULL, ic, TRUE);
4797
4798         /* restore EA bit in F1 */
4799         lbl = newiTempLabel(NULL);
4800         emitcode ("jnb","F1,%05d$",lbl->key+100);
4801         emitcode ("setb","EA");
4802         emitcode("","%05d$:",lbl->key+100);
4803         return ;
4804 }
4805
4806 /*-----------------------------------------------------------------*/
4807 /* genMod - generates code for division                            */
4808 /*-----------------------------------------------------------------*/
4809 static void
4810 genMod (iCode * ic)
4811 {
4812   operand *left = IC_LEFT (ic);
4813   operand *right = IC_RIGHT (ic);
4814   operand *result = IC_RESULT (ic);
4815
4816   D (emitcode (";", "genMod "); );
4817
4818   /* assign the amsops */
4819   AOP_OP_2 (ic);
4820
4821   /* special cases first */
4822   /* both are bits */
4823   if (AOP_TYPE (left) == AOP_CRY &&
4824       AOP_TYPE (right) == AOP_CRY)
4825     {
4826       genModbits (left, right, result, ic);
4827       goto release;
4828     }
4829
4830   /* if both are of size == 1 */
4831   if (AOP_SIZE (left) == 1 &&
4832       AOP_SIZE (right) == 1)
4833     {
4834       genModOneByte (left, right, result, ic);
4835       goto release;
4836     }
4837
4838   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4839           /* use the ds390 ARITHMETIC accel UNIT */
4840           genModTwoByte (left, right, result, ic);
4841           return ;
4842   }
4843
4844   /* should have been converted to function call */
4845   assert (0);
4846
4847 release:
4848   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4849   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4850   freeAsmop (result, NULL, ic, TRUE);
4851 }
4852
4853 /*-----------------------------------------------------------------*/
4854 /* genIfxJump :- will create a jump depending on the ifx           */
4855 /*-----------------------------------------------------------------*/
4856 static void
4857 genIfxJump (iCode * ic, char *jval)
4858 {
4859   symbol *jlbl;
4860   symbol *tlbl = newiTempLabel (NULL);
4861   char *inst;
4862
4863   D (emitcode (";", "genIfxJump ");
4864     );
4865
4866   /* if true label then we jump if condition
4867      supplied is true */
4868   if (IC_TRUE (ic))
4869     {
4870       jlbl = IC_TRUE (ic);
4871       inst = ((strcmp (jval, "a") == 0 ? "jz" :
4872                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4873     }
4874   else
4875     {
4876       /* false label is present */
4877       jlbl = IC_FALSE (ic);
4878       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4879                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4880     }
4881   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4882     emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4883   else
4884     emitcode (inst, "%05d$", tlbl->key + 100);
4885   emitcode ("ljmp", "%05d$", jlbl->key + 100);
4886   emitcode ("", "%05d$:", tlbl->key + 100);
4887
4888   /* mark the icode as generated */
4889   ic->generated = 1;
4890 }
4891
4892 /*-----------------------------------------------------------------*/
4893 /* genCmp :- greater or less than comparison                       */
4894 /*-----------------------------------------------------------------*/
4895 static void
4896 genCmp (operand * left, operand * right,
4897         iCode * ic, iCode * ifx, int sign)
4898 {
4899   int size, offset = 0;
4900   unsigned long lit = 0L;
4901   operand *result;
4902
4903   D (emitcode (";", "genCmp");
4904     );
4905
4906   result = IC_RESULT (ic);
4907
4908   /* if left & right are bit variables */
4909   if (AOP_TYPE (left) == AOP_CRY &&
4910       AOP_TYPE (right) == AOP_CRY)
4911     {
4912       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4913       emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
4914     }
4915   else
4916     {
4917       /* subtract right from left if at the
4918          end the carry flag is set then we know that
4919          left is greater than right */
4920       size = max (AOP_SIZE (left), AOP_SIZE (right));
4921
4922       /* if unsigned char cmp with lit, do cjne left,#right,zz */
4923       if ((size == 1) && !sign &&
4924           (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4925         {
4926           symbol *lbl = newiTempLabel (NULL);
4927           emitcode ("cjne", "%s,%s,%05d$",
4928                     aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
4929                     aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4930                     lbl->key + 100);
4931           emitcode ("", "%05d$:", lbl->key + 100);
4932         }
4933       else
4934         {
4935           if (AOP_TYPE (right) == AOP_LIT)
4936             {
4937               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4938               /* optimize if(x < 0) or if(x >= 0) */
4939               if (lit == 0L)
4940                 {
4941                   if (!sign)
4942                     {
4943                       CLRC;
4944                     }
4945                   else
4946                     {
4947                       MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
4948
4949                       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4950                       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4951
4952                       aopOp (result, ic, FALSE, FALSE);
4953
4954                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4955                         {
4956                           freeAsmop (result, NULL, ic, TRUE);
4957                           genIfxJump (ifx, "acc.7");
4958                           return;
4959                         }
4960                       else
4961                         {
4962                           emitcode ("rlc", "a");
4963                         }
4964                       goto release_freedLR;
4965                     }
4966                   goto release;
4967                 }
4968             }
4969           CLRC;
4970           while (size--)
4971             {
4972               emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
4973               MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4974               emitcode (";", "genCmp #2");
4975               if (sign && (size == 0))
4976                 {
4977                   emitcode (";", "genCmp #3");
4978                   emitcode ("xrl", "a,#0x80");
4979                   if (AOP_TYPE (right) == AOP_LIT)
4980                     {
4981                       unsigned long lit = (unsigned long)
4982                       floatFromVal (AOP (right)->aopu.aop_lit);
4983                       emitcode (";", "genCmp #3.1");
4984                       emitcode ("subb", "a,#0x%02x",
4985                                 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4986                     }
4987                   else
4988                     {
4989                       emitcode (";", "genCmp #3.2");
4990                       if (AOP_NEEDSACC (right))
4991                         {
4992                           emitcode ("push", "acc");
4993                         }
4994                       emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
4995                                                        FALSE, FALSE, FALSE));
4996                       emitcode ("xrl", "b,#0x80");
4997                       if (AOP_NEEDSACC (right))
4998                         {
4999                           emitcode ("pop", "acc");
5000                         }
5001                       emitcode ("subb", "a,b");
5002                     }
5003                 }
5004               else
5005                 {
5006                   const char *s;
5007
5008                   emitcode (";", "genCmp #4");
5009                   if (AOP_NEEDSACC (right))
5010                     {
5011                       /* Yuck!! */
5012                       emitcode (";", "genCmp #4.1");
5013                       emitcode ("xch", "a, b");
5014                       MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
5015                       emitcode ("xch", "a, b");
5016                       s = "b";
5017                     }
5018                   else
5019                     {
5020                       emitcode (";", "genCmp #4.2");
5021                       s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
5022                     }
5023
5024                   emitcode ("subb", "a,%s", s);
5025                 }
5026             }
5027         }
5028     }
5029
5030 release:
5031 /* Don't need the left & right operands any more; do need the result. */
5032   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5033   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5034
5035   aopOp (result, ic, FALSE, FALSE);
5036
5037 release_freedLR:
5038
5039   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5040     {
5041       outBitC (result);
5042     }
5043   else
5044     {
5045       /* if the result is used in the next
5046          ifx conditional branch then generate
5047          code a little differently */
5048       if (ifx)
5049         {
5050           genIfxJump (ifx, "c");
5051         }
5052       else
5053         {
5054           outBitC (result);
5055         }
5056       /* leave the result in acc */
5057     }
5058   freeAsmop (result, NULL, ic, TRUE);
5059 }
5060
5061 /*-----------------------------------------------------------------*/
5062 /* genCmpGt :- greater than comparison                             */
5063 /*-----------------------------------------------------------------*/
5064 static void
5065 genCmpGt (iCode * ic, iCode * ifx)
5066 {
5067   operand *left, *right;
5068   sym_link *letype, *retype;
5069   int sign;
5070
5071   D (emitcode (";", "genCmpGt ");
5072     );
5073
5074   left = IC_LEFT (ic);
5075   right = IC_RIGHT (ic);
5076
5077   letype = getSpec (operandType (left));
5078   retype = getSpec (operandType (right));
5079   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5080
5081   /* assign the left & right amsops */
5082   AOP_OP_2 (ic);
5083
5084   genCmp (right, left, ic, ifx, sign);
5085 }
5086
5087 /*-----------------------------------------------------------------*/
5088 /* genCmpLt - less than comparisons                                */
5089 /*-----------------------------------------------------------------*/
5090 static void
5091 genCmpLt (iCode * ic, iCode * ifx)
5092 {
5093   operand *left, *right;
5094   sym_link *letype, *retype;
5095   int sign;
5096
5097   D (emitcode (";", "genCmpLt "););
5098
5099   left = IC_LEFT (ic);
5100   right = IC_RIGHT (ic);
5101
5102   letype = getSpec (operandType (left));
5103   retype = getSpec (operandType (right));
5104   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5105
5106   /* assign the left & right amsops */
5107   AOP_OP_2 (ic);
5108
5109   genCmp (left, right, ic, ifx, sign);
5110 }
5111
5112 /*-----------------------------------------------------------------*/
5113 /* gencjneshort - compare and jump if not equal                    */
5114 /*-----------------------------------------------------------------*/
5115 static void
5116 gencjneshort (operand * left, operand * right, symbol * lbl)
5117 {
5118   int size = max (AOP_SIZE (left), AOP_SIZE (right));
5119   int offset = 0;
5120   unsigned long lit = 0L;
5121
5122   D (emitcode (";", "gencjneshort");
5123     );
5124
5125   /* if the left side is a literal or
5126      if the right is in a pointer register and left
5127      is not */
5128   if ((AOP_TYPE (left) == AOP_LIT) ||
5129       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5130     {
5131       operand *t = right;
5132       right = left;
5133       left = t;
5134     }
5135
5136   if (AOP_TYPE (right) == AOP_LIT)
5137     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5138
5139   if (opIsGptr (left) || opIsGptr (right))
5140     {
5141       /* We are comparing a generic pointer to something.
5142        * Exclude the generic type byte from the comparison.
5143        */
5144       size--;
5145       D (emitcode (";", "cjneshort: generic ptr special case.");
5146         )
5147     }
5148
5149
5150   /* if the right side is a literal then anything goes */
5151   if (AOP_TYPE (right) == AOP_LIT &&
5152       AOP_TYPE (left) != AOP_DIR)
5153     {
5154       while (size--)
5155         {
5156           char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5157           MOVA (l);
5158           emitcode ("cjne", "a,%s,%05d$",
5159                     aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
5160                     lbl->key + 100);
5161           offset++;
5162         }
5163     }
5164
5165   /* if the right side is in a register or in direct space or
5166      if the left is a pointer register & right is not */
5167   else if (AOP_TYPE (right) == AOP_REG ||
5168            AOP_TYPE (right) == AOP_DIR ||
5169            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5170            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5171     {
5172       while (size--)
5173         {
5174           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5175           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5176               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5177             emitcode ("jnz", "%05d$", lbl->key + 100);
5178           else
5179             emitcode ("cjne", "a,%s,%05d$",
5180                       aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
5181                       lbl->key + 100);
5182           offset++;
5183         }
5184     }
5185   else
5186     {
5187       /* right is a pointer reg need both a & b */
5188       while (size--)
5189         {
5190           char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5191           if (strcmp (l, "b"))
5192             emitcode ("mov", "b,%s", l);
5193           MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5194           emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
5195           offset++;
5196         }
5197     }
5198 }
5199
5200 /*-----------------------------------------------------------------*/
5201 /* gencjne - compare and jump if not equal                         */
5202 /*-----------------------------------------------------------------*/
5203 static void
5204 gencjne (operand * left, operand * right, symbol * lbl)
5205 {
5206   symbol *tlbl = newiTempLabel (NULL);
5207
5208   D (emitcode (";", "gencjne");
5209     );
5210
5211   gencjneshort (left, right, lbl);
5212
5213   emitcode ("mov", "a,%s", one);
5214   emitcode ("sjmp", "%05d$", tlbl->key + 100);
5215   emitcode ("", "%05d$:", lbl->key + 100);
5216   emitcode ("clr", "a");
5217   emitcode ("", "%05d$:", tlbl->key + 100);
5218 }
5219
5220 /*-----------------------------------------------------------------*/
5221 /* genCmpEq - generates code for equal to                          */
5222 /*-----------------------------------------------------------------*/
5223 static void
5224 genCmpEq (iCode * ic, iCode * ifx)
5225 {
5226   operand *left, *right, *result;
5227
5228   D (emitcode (";", "genCmpEq ");
5229     );
5230
5231   AOP_OP_2 (ic);
5232   AOP_SET_LOCALS (ic);
5233
5234   /* if literal, literal on the right or
5235      if the right is in a pointer register and left
5236      is not */
5237   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5238       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5239     {
5240       operand *t = IC_RIGHT (ic);
5241       IC_RIGHT (ic) = IC_LEFT (ic);
5242       IC_LEFT (ic) = t;
5243     }
5244
5245   if (ifx &&                    /* !AOP_SIZE(result) */
5246       OP_SYMBOL (result) &&
5247       OP_SYMBOL (result)->regType == REG_CND)
5248     {
5249       symbol *tlbl;
5250       /* if they are both bit variables */
5251       if (AOP_TYPE (left) == AOP_CRY &&
5252           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5253         {
5254           if (AOP_TYPE (right) == AOP_LIT)
5255             {
5256               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5257               if (lit == 0L)
5258                 {
5259                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5260                   emitcode ("cpl", "c");
5261                 }
5262               else if (lit == 1L)
5263                 {
5264                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5265                 }
5266               else
5267                 {
5268                   emitcode ("clr", "c");
5269                 }
5270               /* AOP_TYPE(right) == AOP_CRY */
5271             }
5272           else
5273             {
5274               symbol *lbl = newiTempLabel (NULL);
5275               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5276               emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5277               emitcode ("cpl", "c");
5278               emitcode ("", "%05d$:", (lbl->key + 100));
5279             }
5280           /* if true label then we jump if condition
5281              supplied is true */
5282           tlbl = newiTempLabel (NULL);
5283           if (IC_TRUE (ifx))
5284             {
5285               emitcode ("jnc", "%05d$", tlbl->key + 100);
5286               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5287             }
5288           else
5289             {
5290               emitcode ("jc", "%05d$", tlbl->key + 100);
5291               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5292             }
5293           emitcode ("", "%05d$:", tlbl->key + 100);
5294         }
5295       else
5296         {
5297           tlbl = newiTempLabel (NULL);
5298           gencjneshort (left, right, tlbl);
5299           if (IC_TRUE (ifx))
5300             {
5301               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5302               emitcode ("", "%05d$:", tlbl->key + 100);
5303             }
5304           else
5305             {
5306               symbol *lbl = newiTempLabel (NULL);
5307               emitcode ("sjmp", "%05d$", lbl->key + 100);
5308               emitcode ("", "%05d$:", tlbl->key + 100);
5309               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5310               emitcode ("", "%05d$:", lbl->key + 100);
5311             }
5312         }
5313       /* mark the icode as generated */
5314       ifx->generated = 1;
5315
5316       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5317       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5318       return;
5319     }
5320
5321   /* if they are both bit variables */
5322   if (AOP_TYPE (left) == AOP_CRY &&
5323       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5324     {
5325       if (AOP_TYPE (right) == AOP_LIT)
5326         {
5327           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5328           if (lit == 0L)
5329             {
5330               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5331               emitcode ("cpl", "c");
5332             }
5333           else if (lit == 1L)
5334             {
5335               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5336             }
5337           else
5338             {
5339               emitcode ("clr", "c");
5340             }
5341           /* AOP_TYPE(right) == AOP_CRY */
5342         }
5343       else
5344         {
5345           symbol *lbl = newiTempLabel (NULL);
5346           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5347           emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5348           emitcode ("cpl", "c");
5349           emitcode ("", "%05d$:", (lbl->key + 100));
5350         }
5351
5352       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5353       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5354
5355       aopOp (result, ic, TRUE, FALSE);
5356
5357       /* c = 1 if egal */
5358       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5359         {
5360           outBitC (result);
5361           goto release;
5362         }
5363       if (ifx)
5364         {
5365           genIfxJump (ifx, "c");
5366           goto release;
5367         }
5368       /* if the result is used in an arithmetic operation
5369          then put the result in place */
5370       outBitC (result);
5371     }
5372   else
5373     {
5374       gencjne (left, right, newiTempLabel (NULL));
5375
5376       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5377       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5378
5379       aopOp (result, ic, TRUE, FALSE);
5380
5381       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5382         {
5383           aopPut (AOP (result), "a", 0);
5384           goto release;
5385         }
5386       if (ifx)
5387         {
5388           genIfxJump (ifx, "a");
5389           goto release;
5390         }
5391       /* if the result is used in an arithmetic operation
5392          then put the result in place */
5393       if (AOP_TYPE (result) != AOP_CRY)
5394         outAcc (result);
5395       /* leave the result in acc */
5396     }
5397
5398 release:
5399   freeAsmop (result, NULL, ic, TRUE);
5400 }
5401
5402 /*-----------------------------------------------------------------*/
5403 /* ifxForOp - returns the icode containing the ifx for operand     */
5404 /*-----------------------------------------------------------------*/
5405 static iCode *
5406 ifxForOp (operand * op, iCode * ic)
5407 {
5408   /* if true symbol then needs to be assigned */
5409   if (IS_TRUE_SYMOP (op))
5410     return NULL;
5411
5412   /* if this has register type condition and
5413      the next instruction is ifx with the same operand
5414      and live to of the operand is upto the ifx only then */
5415   if (ic->next &&
5416       ic->next->op == IFX &&
5417       IC_COND (ic->next)->key == op->key &&
5418       OP_SYMBOL (op)->liveTo <= ic->next->seq)
5419     return ic->next;
5420
5421   return NULL;
5422 }
5423 /*-----------------------------------------------------------------*/
5424 /* hasInc - operand is incremented before any other use            */
5425 /*-----------------------------------------------------------------*/
5426 static iCode *
5427 hasInc (operand *op, iCode *ic)
5428 {
5429   sym_link *type = operandType(op);
5430   sym_link *retype = getSpec (type);
5431   iCode *lic = ic->next;
5432   int isize ;
5433   
5434   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5435   if (!IS_SYMOP(op)) return NULL;
5436
5437   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5438   isize = getSize(type->next);
5439   while (lic) {
5440       /* if operand of the form op = op + <sizeof *op> */
5441       if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5442           isOperandEqual(IC_RESULT(lic),op) && 
5443           isOperandLiteral(IC_RIGHT(lic)) &&
5444           operandLitValue(IC_RIGHT(lic)) == isize) {
5445           return lic;
5446       }
5447       /* if the operand used or deffed */
5448       if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5449           return NULL;
5450       }
5451       /* if GOTO or IFX */
5452       if (lic->op == IFX || lic->op == GOTO) break;
5453       lic = lic->next;
5454   }
5455   return NULL;
5456 }
5457
5458 /*-----------------------------------------------------------------*/
5459 /* genAndOp - for && operation                                     */
5460 /*-----------------------------------------------------------------*/
5461 static void
5462 genAndOp (iCode * ic)
5463 {
5464   operand *left, *right, *result;
5465   symbol *tlbl;
5466
5467   D (emitcode (";", "genAndOp "););
5468
5469   /* note here that && operations that are in an
5470      if statement are taken away by backPatchLabels
5471      only those used in arthmetic operations remain */
5472   AOP_OP_2 (ic);
5473   AOP_SET_LOCALS (ic);
5474
5475   /* if both are bit variables */
5476   if (AOP_TYPE (left) == AOP_CRY &&
5477       AOP_TYPE (right) == AOP_CRY)
5478     {
5479       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5480       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5481       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5482       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5483   
5484       aopOp (result,ic,FALSE, FALSE);
5485       outBitC (result);
5486     }
5487   else
5488     {
5489       tlbl = newiTempLabel (NULL);
5490       toBoolean (left);
5491       emitcode ("jz", "%05d$", tlbl->key + 100);
5492       toBoolean (right);
5493       emitcode ("", "%05d$:", tlbl->key + 100);
5494       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5495       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5496   
5497       aopOp (result,ic,FALSE, FALSE);
5498       outBitAcc (result);
5499     }
5500     freeAsmop (result, NULL, ic, TRUE);
5501 }
5502
5503
5504 /*-----------------------------------------------------------------*/
5505 /* genOrOp - for || operation                                      */
5506 /*-----------------------------------------------------------------*/
5507 static void
5508 genOrOp (iCode * ic)
5509 {
5510   operand *left, *right, *result;
5511   symbol *tlbl;
5512
5513   D (emitcode (";", "genOrOp "););
5514
5515   /* note here that || operations that are in an
5516      if statement are taken away by backPatchLabels
5517      only those used in arthmetic operations remain */
5518   AOP_OP_2 (ic);
5519   AOP_SET_LOCALS (ic);
5520
5521   /* if both are bit variables */
5522   if (AOP_TYPE (left) == AOP_CRY &&
5523       AOP_TYPE (right) == AOP_CRY)
5524     {
5525       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5526       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5527       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5528       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5529   
5530       aopOp (result,ic,FALSE, FALSE);
5531       
5532       outBitC (result);
5533     }
5534   else
5535     {
5536       tlbl = newiTempLabel (NULL);
5537       toBoolean (left);
5538       emitcode ("jnz", "%05d$", tlbl->key + 100);
5539       toBoolean (right);
5540       emitcode ("", "%05d$:", tlbl->key + 100);
5541       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5542       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5543   
5544       aopOp (result,ic,FALSE, FALSE);
5545       
5546       outBitAcc (result);
5547     }
5548
5549   freeAsmop (result, NULL, ic, TRUE);
5550 }
5551
5552 /*-----------------------------------------------------------------*/
5553 /* isLiteralBit - test if lit == 2^n                               */
5554 /*-----------------------------------------------------------------*/
5555 static int
5556 isLiteralBit (unsigned long lit)
5557 {
5558   unsigned long pw[32] =
5559   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5560    0x100L, 0x200L, 0x400L, 0x800L,
5561    0x1000L, 0x2000L, 0x4000L, 0x8000L,
5562    0x10000L, 0x20000L, 0x40000L, 0x80000L,
5563    0x100000L, 0x200000L, 0x400000L, 0x800000L,
5564    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5565    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5566   int idx;
5567
5568   for (idx = 0; idx < 32; idx++)
5569     if (lit == pw[idx])
5570       return idx + 1;
5571   return 0;
5572 }
5573
5574 /*-----------------------------------------------------------------*/
5575 /* continueIfTrue -                                                */
5576 /*-----------------------------------------------------------------*/
5577 static void
5578 continueIfTrue (iCode * ic)
5579 {
5580   if (IC_TRUE (ic))
5581     emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5582   ic->generated = 1;
5583 }
5584
5585 /*-----------------------------------------------------------------*/
5586 /* jmpIfTrue -                                                     */
5587 /*-----------------------------------------------------------------*/
5588 static void
5589 jumpIfTrue (iCode * ic)
5590 {
5591   if (!IC_TRUE (ic))
5592     emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5593   ic->generated = 1;
5594 }
5595
5596 /*-----------------------------------------------------------------*/
5597 /* jmpTrueOrFalse -                                                */
5598 /*-----------------------------------------------------------------*/
5599 static void
5600 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
5601 {
5602   // ugly but optimized by peephole
5603   if (IC_TRUE (ic))
5604     {
5605       symbol *nlbl = newiTempLabel (NULL);
5606       emitcode ("sjmp", "%05d$", nlbl->key + 100);
5607       emitcode ("", "%05d$:", tlbl->key + 100);
5608       emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5609       emitcode ("", "%05d$:", nlbl->key + 100);
5610     }
5611   else
5612     {
5613       emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5614       emitcode ("", "%05d$:", tlbl->key + 100);
5615     }
5616   ic->generated = 1;
5617 }
5618
5619 // Generate code to perform a bit-wise logic operation
5620 // on two operands in far space (assumed to already have been 
5621 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
5622 // in far space. This requires pushing the result on the stack
5623 // then popping it into the result.
5624 static void
5625 genFarFarLogicOp(iCode *ic, char *logicOp)
5626 {
5627       int size, resultSize, compSize;
5628       int offset = 0;
5629       
5630       TR_AP("#5");
5631       D(emitcode(";", "%s special case for 3 far operands.", logicOp););
5632       compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ? 
5633                   AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
5634       
5635       _startLazyDPSEvaluation();
5636       for (size = compSize; (size--); offset++)
5637       {
5638           MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
5639           emitcode ("mov", "%s, acc", DP2_RESULT_REG);
5640           MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
5641           
5642           emitcode (logicOp, "a,%s", DP2_RESULT_REG);
5643           emitcode ("push", "acc");
5644       }
5645       _endLazyDPSEvaluation();
5646      
5647       freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5648       freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5649       aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
5650      
5651       resultSize = AOP_SIZE(IC_RESULT(ic));
5652
5653       ADJUST_PUSHED_RESULT(compSize, resultSize);
5654
5655       _startLazyDPSEvaluation();
5656       while (compSize--)
5657       {
5658           emitcode ("pop", "acc");
5659           aopPut (AOP (IC_RESULT (ic)), "a", compSize);
5660       }
5661       _endLazyDPSEvaluation();
5662       freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
5663 }
5664
5665
5666 /*-----------------------------------------------------------------*/
5667 /* genAnd  - code for and                                          */
5668 /*-----------------------------------------------------------------*/
5669 static void
5670 genAnd (iCode * ic, iCode * ifx)
5671 {
5672   operand *left, *right, *result;
5673   int size, offset = 0;
5674   unsigned long lit = 0L;
5675   int bytelit = 0;
5676   char buffer[10];
5677   bool pushResult;
5678
5679   D (emitcode (";", "genAnd "););
5680
5681   AOP_OP_3_NOFATAL (ic, pushResult);
5682   AOP_SET_LOCALS (ic);
5683
5684   if (pushResult)
5685   {
5686       genFarFarLogicOp(ic, "anl");
5687       return;
5688   }  
5689
5690 #ifdef DEBUG_TYPE
5691   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5692             AOP_TYPE (result),
5693             AOP_TYPE (left), AOP_TYPE (right));
5694   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5695             AOP_SIZE (result),
5696             AOP_SIZE (left), AOP_SIZE (right));
5697 #endif
5698
5699   /* if left is a literal & right is not then exchange them */
5700   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5701 #ifdef LOGIC_OPS_BROKEN      
5702     ||  AOP_NEEDSACC (left)
5703 #endif
5704     )
5705     {
5706       operand *tmp = right;
5707       right = left;
5708       left = tmp;
5709     }
5710
5711   /* if result = right then exchange them */
5712   if (sameRegs (AOP (result), AOP (right)))
5713     {
5714       operand *tmp = right;
5715       right = left;
5716       left = tmp;
5717     }
5718
5719   /* if right is bit then exchange them */
5720   if (AOP_TYPE (right) == AOP_CRY &&
5721       AOP_TYPE (left) != AOP_CRY)
5722     {
5723       operand *tmp = right;
5724       right = left;
5725       left = tmp;
5726     }
5727   if (AOP_TYPE (right) == AOP_LIT)
5728     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5729
5730   size = AOP_SIZE (result);
5731
5732   // if(bit & yy)
5733   // result = bit & yy;
5734   if (AOP_TYPE (left) == AOP_CRY)
5735     {
5736       // c = bit & literal;
5737       if (AOP_TYPE (right) == AOP_LIT)
5738         {
5739           if (lit & 1)
5740             {
5741               if (size && sameRegs (AOP (result), AOP (left)))
5742                 // no change
5743                 goto release;
5744               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5745             }
5746           else
5747             {
5748               // bit(result) = 0;
5749               if (size && (AOP_TYPE (result) == AOP_CRY))
5750                 {
5751                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5752                   goto release;
5753                 }
5754               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5755                 {
5756                   jumpIfTrue (ifx);
5757                   goto release;
5758                 }
5759               emitcode ("clr", "c");
5760             }
5761         }
5762       else
5763         {
5764           if (AOP_TYPE (right) == AOP_CRY)
5765             {
5766               // c = bit & bit;
5767               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5768               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5769             }
5770           else
5771             {
5772               // c = bit & val;
5773               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
5774               // c = lsb
5775               emitcode ("rrc", "a");
5776               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5777             }
5778         }
5779       // bit = c
5780       // val = c
5781       if (size)
5782         outBitC (result);
5783       // if(bit & ...)
5784       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5785         genIfxJump (ifx, "c");
5786       goto release;
5787     }
5788
5789   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5790   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5791   if ((AOP_TYPE (right) == AOP_LIT) &&
5792       (AOP_TYPE (result) == AOP_CRY) &&
5793       (AOP_TYPE (left) != AOP_CRY))
5794     {
5795       int posbit = isLiteralBit (lit);
5796       /* left &  2^n */
5797       if (posbit)
5798         {
5799           posbit--;
5800           MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
5801           // bit = left & 2^n
5802           if (size)
5803             emitcode ("mov", "c,acc.%d", posbit & 0x07);
5804           // if(left &  2^n)
5805           else
5806             {
5807               if (ifx)
5808                 {
5809                   sprintf (buffer, "acc.%d", posbit & 0x07);
5810                   genIfxJump (ifx, buffer);
5811                 }
5812               goto release;
5813             }
5814         }
5815       else
5816         {
5817           symbol *tlbl = newiTempLabel (NULL);
5818           int sizel = AOP_SIZE (left);
5819           if (size)
5820             emitcode ("setb", "c");
5821           while (sizel--)
5822             {
5823               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5824                 {
5825                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5826                   // byte ==  2^n ?
5827                   if ((posbit = isLiteralBit (bytelit)) != 0)
5828                     emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5829                   else
5830                     {
5831                       if (bytelit != 0x0FFL)
5832                         emitcode ("anl", "a,%s",
5833                           aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
5834                       emitcode ("jnz", "%05d$", tlbl->key + 100);
5835                     }
5836                 }
5837               offset++;
5838             }
5839           // bit = left & literal
5840           if (size)
5841             {
5842               emitcode ("clr", "c");
5843               emitcode ("", "%05d$:", tlbl->key + 100);
5844             }
5845           // if(left & literal)
5846           else
5847             {
5848               if (ifx)
5849                 jmpTrueOrFalse (ifx, tlbl);
5850               goto release;
5851             }
5852         }
5853       outBitC (result);
5854       goto release;
5855     }
5856
5857   /* if left is same as result */
5858   if (sameRegs (AOP (result), AOP (left)))
5859     {
5860       for (; size--; offset++)
5861         {
5862           if (AOP_TYPE (right) == AOP_LIT)
5863             {
5864               if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5865                 continue;
5866               else if (bytelit == 0)
5867                 aopPut (AOP (result), zero, offset);
5868               else if (IS_AOP_PREG (result))
5869                 {
5870                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5871                   emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5872                   aopPut (AOP (result), "a", offset);
5873                 }
5874               else
5875                 emitcode ("anl", "%s,%s",
5876                           aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5877                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5878             }
5879           else
5880             {
5881               if (AOP_TYPE (left) == AOP_ACC)
5882                 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5883               else
5884                 {
5885                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5886                   if (IS_AOP_PREG (result))
5887                     {
5888                       emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5889                       aopPut (AOP (result), "a", offset);
5890
5891                     }
5892                   else
5893                     emitcode ("anl", "%s,a",
5894                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5895                 }
5896             }
5897         }
5898     }
5899   else
5900     {
5901       // left & result in different registers
5902       if (AOP_TYPE (result) == AOP_CRY)
5903         {
5904           // result = bit
5905           // if(size), result in bit
5906           // if(!size && ifx), conditional oper: if(left & right)
5907           symbol *tlbl = newiTempLabel (NULL);
5908           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5909           if (size)
5910             emitcode ("setb", "c");
5911           while (sizer--)
5912             {
5913               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5914                 emitcode ("anl", "a,%s",
5915                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5916               } else {
5917                 if (AOP_TYPE(left)==AOP_ACC) {
5918                   emitcode("mov", "b,a");
5919                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5920                   emitcode("anl", "a,b");
5921                 }else {
5922                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5923                   emitcode ("anl", "a,%s",
5924                             aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5925                 }
5926               }
5927               emitcode ("jnz", "%05d$", tlbl->key + 100);
5928               offset++;
5929             }
5930           if (size)
5931             {
5932               CLRC;
5933               emitcode ("", "%05d$:", tlbl->key + 100);
5934               outBitC (result);
5935             }
5936           else if (ifx)
5937             jmpTrueOrFalse (ifx, tlbl);
5938         }
5939       else
5940         {
5941           for (; (size--); offset++)
5942             {
5943               // normal case
5944               // result = left & right
5945               if (AOP_TYPE (right) == AOP_LIT)
5946                 {
5947                   if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5948                     {
5949                       aopPut (AOP (result),
5950                            aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5951                               offset);
5952                       continue;
5953                     }
5954                   else if (bytelit == 0)
5955                     {
5956                       aopPut (AOP (result), zero, offset);
5957                       continue;
5958                     }
5959                   D (emitcode (";", "better literal AND."););
5960                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5961                   emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
5962                                                     FALSE, FALSE, FALSE));
5963
5964                 }
5965               else
5966                 {
5967                   // faster than result <- left, anl result,right
5968                   // and better if result is SFR
5969                   if (AOP_TYPE (left) == AOP_ACC)
5970                     {
5971                       emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
5972                                                        FALSE, FALSE, FALSE));
5973                     }
5974                   else
5975                     {
5976                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
5977                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
5978                       {
5979                           emitcode("mov", "b,a");
5980                           rOp = "b";
5981                       }
5982                         
5983                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5984                       emitcode ("anl", "a,%s", rOp);
5985                     }                   
5986                 }
5987               aopPut (AOP (result), "a", offset);
5988             }
5989         }
5990     }
5991
5992 release:
5993   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5994   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5995   freeAsmop (result, NULL, ic, TRUE);
5996 }
5997
5998
5999 /*-----------------------------------------------------------------*/
6000 /* genOr  - code for or                                            */
6001 /*-----------------------------------------------------------------*/
6002 static void
6003 genOr (iCode * ic, iCode * ifx)
6004 {
6005   operand *left, *right, *result;
6006   int size, offset = 0;
6007   unsigned long lit = 0L;
6008   bool     pushResult;
6009
6010   D (emitcode (";", "genOr "););
6011
6012   AOP_OP_3_NOFATAL (ic, pushResult);
6013   AOP_SET_LOCALS (ic);
6014
6015   if (pushResult)
6016   {
6017       genFarFarLogicOp(ic, "orl");
6018       return;
6019   }
6020
6021
6022 #ifdef DEBUG_TYPE
6023   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6024             AOP_TYPE (result),
6025             AOP_TYPE (left), AOP_TYPE (right));
6026   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6027             AOP_SIZE (result),
6028             AOP_SIZE (left), AOP_SIZE (right));
6029 #endif
6030
6031   /* if left is a literal & right is not then exchange them */
6032   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6033 #ifdef LOGIC_OPS_BROKEN
6034    || AOP_NEEDSACC (left) // I think this is a net loss now.
6035 #endif      
6036       )
6037     {
6038       operand *tmp = right;
6039       right = left;
6040       left = tmp;
6041     }
6042
6043   /* if result = right then exchange them */
6044   if (sameRegs (AOP (result), AOP (right)))
6045     {
6046       operand *tmp = right;
6047       right = left;
6048       left = tmp;
6049     }
6050
6051   /* if right is bit then exchange them */
6052   if (AOP_TYPE (right) == AOP_CRY &&
6053       AOP_TYPE (left) != AOP_CRY)
6054     {
6055       operand *tmp = right;
6056       right = left;
6057       left = tmp;
6058     }
6059   if (AOP_TYPE (right) == AOP_LIT)
6060     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6061
6062   size = AOP_SIZE (result);
6063
6064   // if(bit | yy)
6065   // xx = bit | yy;
6066   if (AOP_TYPE (left) == AOP_CRY)
6067     {
6068       if (AOP_TYPE (right) == AOP_LIT)
6069         {
6070           // c = bit & literal;
6071           if (lit)
6072             {
6073               // lit != 0 => result = 1
6074               if (AOP_TYPE (result) == AOP_CRY)
6075                 {
6076                   if (size)
6077                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6078                   else if (ifx)
6079                     continueIfTrue (ifx);
6080                   goto release;
6081                 }
6082               emitcode ("setb", "c");
6083             }
6084           else
6085             {
6086               // lit == 0 => result = left
6087               if (size && sameRegs (AOP (result), AOP (left)))
6088                 goto release;
6089               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6090             }
6091         }
6092       else
6093         {
6094           if (AOP_TYPE (right) == AOP_CRY)
6095             {
6096               // c = bit | bit;
6097               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6098               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6099             }
6100           else
6101             {
6102               // c = bit | val;
6103               symbol *tlbl = newiTempLabel (NULL);
6104               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6105                 emitcode ("setb", "c");
6106               emitcode ("jb", "%s,%05d$",
6107                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
6108               toBoolean (right);
6109               emitcode ("jnz", "%05d$", tlbl->key + 100);
6110               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6111                 {
6112                   jmpTrueOrFalse (ifx, tlbl);
6113                   goto release;
6114                 }
6115               else
6116                 {
6117                   CLRC;
6118                   emitcode ("", "%05d$:", tlbl->key + 100);
6119                 }
6120             }
6121         }
6122       // bit = c
6123       // val = c
6124       if (size)
6125         outBitC (result);
6126       // if(bit | ...)
6127       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6128         genIfxJump (ifx, "c");
6129       goto release;
6130     }
6131
6132   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6133   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6134   if ((AOP_TYPE (right) == AOP_LIT) &&
6135       (AOP_TYPE (result) == AOP_CRY) &&
6136       (AOP_TYPE (left) != AOP_CRY))
6137     {
6138       if (lit)
6139         {
6140           // result = 1
6141           if (size)
6142             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6143           else
6144             continueIfTrue (ifx);
6145           goto release;
6146         }
6147       else
6148         {
6149           // lit = 0, result = boolean(left)
6150           if (size)
6151             emitcode ("setb", "c");
6152           toBoolean (right);
6153           if (size)
6154             {
6155               symbol *tlbl = newiTempLabel (NULL);
6156               emitcode ("jnz", "%05d$", tlbl->key + 100);
6157               CLRC;
6158               emitcode ("", "%05d$:", tlbl->key + 100);
6159             }
6160           else
6161             {
6162               genIfxJump (ifx, "a");
6163               goto release;
6164             }
6165         }
6166       outBitC (result);
6167       goto release;
6168     }
6169
6170   /* if left is same as result */
6171   if (sameRegs (AOP (result), AOP (left)))
6172     {
6173       for (; size--; offset++)
6174         {
6175           if (AOP_TYPE (right) == AOP_LIT)
6176             {
6177               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6178                 {
6179                   continue;
6180                 }
6181               else
6182                 {
6183                   if (IS_AOP_PREG (left))
6184                     {
6185                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6186                       emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6187                       aopPut (AOP (result), "a", offset);
6188                     }
6189                   else
6190                     {
6191                       emitcode ("orl", "%s,%s",
6192                             aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6193                          aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6194                     }
6195                 }
6196             }
6197           else
6198             {
6199               if (AOP_TYPE (left) == AOP_ACC)
6200                 {
6201                   emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6202                 }
6203               else
6204                 {
6205                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6206                   if (IS_AOP_PREG (left))
6207                     {
6208                       emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6209                       aopPut (AOP (result), "a", offset);
6210                     }
6211                   else
6212                     {
6213                       emitcode ("orl", "%s,a",
6214                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6215                     }
6216                 }
6217             }
6218         }
6219     }
6220   else
6221     {
6222       // left & result in different registers
6223       if (AOP_TYPE (result) == AOP_CRY)
6224         {
6225           // result = bit
6226           // if(size), result in bit
6227           // if(!size && ifx), conditional oper: if(left | right)
6228           symbol *tlbl = newiTempLabel (NULL);
6229           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6230           if (size)
6231             emitcode ("setb", "c");
6232           while (sizer--)
6233             {
6234               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6235                 emitcode ("orl", "a,%s",
6236                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6237               } else {
6238                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6239                 emitcode ("orl", "a,%s",
6240                           aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6241               }
6242               emitcode ("jnz", "%05d$", tlbl->key + 100);
6243               offset++;
6244             }
6245           if (size)
6246             {
6247               CLRC;
6248               emitcode ("", "%05d$:", tlbl->key + 100);
6249               outBitC (result);
6250             }
6251           else if (ifx)
6252             jmpTrueOrFalse (ifx, tlbl);
6253         }
6254       else
6255         {
6256             _startLazyDPSEvaluation();
6257           for (; (size--); offset++)
6258             {
6259               // normal case
6260               // result = left & right
6261               if (AOP_TYPE (right) == AOP_LIT)
6262                 {
6263                   if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6264                     {
6265                       aopPut (AOP (result),
6266                            aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6267                               offset);
6268                       continue;
6269                     }
6270                   D (emitcode (";", "better literal OR."););
6271                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6272                   emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
6273                                                     FALSE, FALSE, FALSE));
6274
6275                 }
6276               else
6277                 {
6278                   // faster than result <- left, anl result,right
6279                   // and better if result is SFR
6280                   if (AOP_TYPE (left) == AOP_ACC)
6281                     {
6282                       emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
6283                                                        FALSE, FALSE, FALSE));
6284                     }
6285                   else
6286                     {
6287                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6288                         
6289                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6290                       {
6291                           emitcode("mov", "b,a");
6292                           rOp = "b";
6293                       }
6294                         
6295                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6296                       emitcode ("orl", "a,%s", rOp);
6297                     }
6298                 }
6299               aopPut (AOP (result), "a", offset);
6300             }
6301             _endLazyDPSEvaluation();
6302         }
6303     }
6304
6305 release:
6306   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6307   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6308   freeAsmop (result, NULL, ic, TRUE);
6309 }
6310
6311 /*-----------------------------------------------------------------*/
6312 /* genXor - code for xclusive or                                   */
6313 /*-----------------------------------------------------------------*/
6314 static void
6315 genXor (iCode * ic, iCode * ifx)
6316 {
6317   operand *left, *right, *result;
6318   int size, offset = 0;
6319   unsigned long lit = 0L;
6320   bool pushResult;
6321
6322   D (emitcode (";", "genXor "););
6323
6324   AOP_OP_3_NOFATAL (ic, pushResult);
6325   AOP_SET_LOCALS (ic);
6326
6327   if (pushResult)
6328   {
6329       genFarFarLogicOp(ic, "xrl");
6330       return;
6331   }  
6332
6333 #ifdef DEBUG_TYPE
6334   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6335             AOP_TYPE (result),
6336             AOP_TYPE (left), AOP_TYPE (right));
6337   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6338             AOP_SIZE (result),
6339             AOP_SIZE (left), AOP_SIZE (right));
6340 #endif
6341
6342   /* if left is a literal & right is not ||
6343      if left needs acc & right does not */
6344   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) 
6345 #ifdef LOGIC_OPS_BROKEN      
6346       || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6347 #endif
6348      )
6349     {
6350       operand *tmp = right;
6351       right = left;
6352       left = tmp;
6353     }
6354
6355   /* if result = right then exchange them */
6356   if (sameRegs (AOP (result), AOP (right)))
6357     {
6358       operand *tmp = right;
6359       right = left;
6360       left = tmp;
6361     }
6362
6363   /* if right is bit then exchange them */
6364   if (AOP_TYPE (right) == AOP_CRY &&
6365       AOP_TYPE (left) != AOP_CRY)
6366     {
6367       operand *tmp = right;
6368       right = left;
6369       left = tmp;
6370     }
6371   if (AOP_TYPE (right) == AOP_LIT)
6372     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6373
6374   size = AOP_SIZE (result);
6375
6376   // if(bit ^ yy)
6377   // xx = bit ^ yy;
6378   if (AOP_TYPE (left) == AOP_CRY)
6379     {
6380       if (AOP_TYPE (right) == AOP_LIT)
6381         {
6382           // c = bit & literal;
6383           if (lit >> 1)
6384             {
6385               // lit>>1  != 0 => result = 1
6386               if (AOP_TYPE (result) == AOP_CRY)
6387                 {
6388                   if (size)
6389                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6390                   else if (ifx)
6391                     continueIfTrue (ifx);
6392                   goto release;
6393                 }
6394               emitcode ("setb", "c");
6395             }
6396           else
6397             {
6398               // lit == (0 or 1)
6399               if (lit == 0)
6400                 {
6401                   // lit == 0, result = left
6402                   if (size && sameRegs (AOP (result), AOP (left)))
6403                     goto release;
6404                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6405                 }
6406               else
6407                 {
6408                   // lit == 1, result = not(left)
6409                   if (size && sameRegs (AOP (result), AOP (left)))
6410                     {
6411                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6412                       goto release;
6413                     }
6414                   else
6415                     {
6416                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6417                       emitcode ("cpl", "c");
6418                     }
6419                 }
6420             }
6421
6422         }
6423       else
6424         {
6425           // right != literal
6426           symbol *tlbl = newiTempLabel (NULL);
6427           if (AOP_TYPE (right) == AOP_CRY)
6428             {
6429               // c = bit ^ bit;
6430               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6431             }
6432           else
6433             {
6434               int sizer = AOP_SIZE (right);
6435               // c = bit ^ val
6436               // if val>>1 != 0, result = 1
6437               emitcode ("setb", "c");
6438               while (sizer)
6439                 {
6440                   MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
6441                   if (sizer == 1)
6442                     // test the msb of the lsb
6443                     emitcode ("anl", "a,#0xfe");
6444                   emitcode ("jnz", "%05d$", tlbl->key + 100);
6445                   sizer--;
6446                 }
6447               // val = (0,1)
6448               emitcode ("rrc", "a");
6449             }
6450           emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6451           emitcode ("cpl", "c");
6452           emitcode ("", "%05d$:", (tlbl->key + 100));
6453         }
6454       // bit = c
6455       // val = c
6456       if (size)
6457         outBitC (result);
6458       // if(bit | ...)
6459       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6460         genIfxJump (ifx, "c");
6461       goto release;
6462     }
6463
6464   if (sameRegs (AOP (result), AOP (left)))
6465     {
6466       /* if left is same as result */
6467       for (; size--; offset++)
6468         {
6469           if (AOP_TYPE (right) == AOP_LIT)
6470             {
6471               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6472                 continue;
6473               else if (IS_AOP_PREG (left))
6474                 {
6475                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6476                   emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6477                   aopPut (AOP (result), "a", offset);
6478                 }
6479               else
6480                 emitcode ("xrl", "%s,%s",
6481                           aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6482                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6483             }
6484           else
6485             {
6486               if (AOP_TYPE (left) == AOP_ACC)
6487                 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6488               else
6489                 {
6490                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6491                   if (IS_AOP_PREG (left))
6492                     {
6493                       emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6494                       aopPut (AOP (result), "a", offset);
6495                     }
6496                   else
6497                     emitcode ("xrl", "%s,a",
6498                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6499                 }
6500             }
6501         }
6502     }
6503   else
6504     {
6505       // left & result in different registers
6506       if (AOP_TYPE (result) == AOP_CRY)
6507         {
6508           // result = bit
6509           // if(size), result in bit
6510           // if(!size && ifx), conditional oper: if(left ^ right)
6511           symbol *tlbl = newiTempLabel (NULL);
6512           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6513                   
6514           if (size)
6515             emitcode ("setb", "c");
6516           while (sizer--)
6517             {
6518               if ((AOP_TYPE (right) == AOP_LIT) &&
6519                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6520                 {
6521                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6522                 }
6523               else
6524                 {
6525                   if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6526                     emitcode ("xrl", "a,%s",
6527                               aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6528                   } else {
6529                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6530                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6531                       {
6532                           emitcode("mov", "b,a");
6533                           rOp = "b";
6534                       }
6535                         
6536                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6537                       emitcode ("xrl", "a,%s", rOp);                  
6538                   }
6539                 }
6540               emitcode ("jnz", "%05d$", tlbl->key + 100);
6541               offset++;
6542             }
6543           if (size)
6544             {
6545               CLRC;
6546               emitcode ("", "%05d$:", tlbl->key + 100);
6547               outBitC (result);
6548             }
6549           else if (ifx)
6550             jmpTrueOrFalse (ifx, tlbl);
6551         }
6552       else
6553         {
6554         for (; (size--); offset++)
6555           {
6556             // normal case
6557             // result = left & right
6558             if (AOP_TYPE (right) == AOP_LIT)
6559               {
6560                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6561                   {
6562                     aopPut (AOP (result),
6563                             aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6564                             offset);
6565                     continue;
6566                   }
6567                 D (emitcode (";", "better literal XOR."););
6568                 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6569                 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
6570                                                   FALSE, FALSE, FALSE));
6571               }
6572             else
6573               {
6574                 // faster than result <- left, anl result,right
6575                 // and better if result is SFR
6576                 if (AOP_TYPE (left) == AOP_ACC)
6577                   {
6578                     emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
6579                                                      FALSE, FALSE, FALSE));
6580                   }
6581                 else
6582                   {
6583                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6584                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6585                       {
6586                           emitcode("mov", "b,a");
6587                           rOp = "b";
6588                       }
6589                         
6590                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6591                       emitcode ("xrl", "a,%s", rOp);
6592                   }
6593               }
6594             aopPut (AOP (result), "a", offset);
6595           }
6596         }
6597         
6598     }
6599
6600 release:
6601   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6602   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6603   freeAsmop (result, NULL, ic, TRUE);
6604 }
6605
6606 /*-----------------------------------------------------------------*/
6607 /* genInline - write the inline code out                           */
6608 /*-----------------------------------------------------------------*/
6609 static void
6610 genInline (iCode * ic)
6611 {
6612   char *buffer, *bp, *bp1;
6613
6614   D (emitcode (";", "genInline ");
6615     );
6616
6617   _G.inLine += (!options.asmpeep);
6618
6619   buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6620   strcpy (buffer, IC_INLINE (ic));
6621
6622   /* emit each line as a code */
6623   while (*bp)
6624     {
6625       if (*bp == '\n')
6626         {
6627           *bp++ = '\0';
6628           emitcode (bp1, "");
6629           bp1 = bp;
6630         }
6631       else
6632         {
6633           if (*bp == ':')
6634             {
6635               bp++;
6636               *bp = '\0';
6637               bp++;
6638               emitcode (bp1, "");
6639               bp1 = bp;
6640             }
6641           else
6642             bp++;
6643         }
6644     }
6645   if (bp1 != bp)
6646     emitcode (bp1, "");
6647   /*     emitcode("",buffer); */
6648   _G.inLine -= (!options.asmpeep);
6649 }
6650
6651 /*-----------------------------------------------------------------*/
6652 /* genRRC - rotate right with carry                                */
6653 /*-----------------------------------------------------------------*/
6654 static void
6655 genRRC (iCode * ic)
6656 {
6657   operand *left, *result;
6658   int size, offset = 0;
6659   char *l;
6660
6661   D (emitcode (";", "genRRC ");
6662     );
6663
6664   /* rotate right with carry */
6665   left = IC_LEFT (ic);
6666   result = IC_RESULT (ic);
6667   aopOp (left, ic, FALSE, FALSE);
6668   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6669
6670   /* move it to the result */
6671   size = AOP_SIZE (result);
6672   offset = size - 1;
6673   CLRC;
6674
6675   _startLazyDPSEvaluation ();
6676   while (size--)
6677     {
6678       l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6679       MOVA (l);
6680       emitcode ("rrc", "a");
6681       if (AOP_SIZE (result) > 1)
6682         aopPut (AOP (result), "a", offset--);
6683     }
6684   _endLazyDPSEvaluation ();
6685
6686   /* now we need to put the carry into the
6687      highest order byte of the result */
6688   if (AOP_SIZE (result) > 1)
6689     {
6690       l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
6691       MOVA (l);
6692     }
6693   emitcode ("mov", "acc.7,c");
6694   aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
6695   freeAsmop (left, NULL, ic, TRUE);
6696   freeAsmop (result, NULL, ic, TRUE);
6697 }
6698
6699 /*-----------------------------------------------------------------*/
6700 /* genRLC - generate code for rotate left with carry               */
6701 /*-----------------------------------------------------------------*/
6702 static void
6703 genRLC (iCode * ic)
6704 {
6705   operand *left, *result;
6706   int size, offset = 0;
6707   char *l;
6708
6709   D (emitcode (";", "genRLC ");
6710     );
6711
6712   /* rotate right with carry */
6713   left = IC_LEFT (ic);
6714   result = IC_RESULT (ic);
6715   aopOp (left, ic, FALSE, FALSE);
6716   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6717
6718   /* move it to the result */
6719   size = AOP_SIZE (result);
6720   offset = 0;
6721   if (size--)
6722     {
6723       l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6724       MOVA (l);
6725       emitcode ("add", "a,acc");
6726       if (AOP_SIZE (result) > 1)
6727         {
6728           aopPut (AOP (result), "a", offset++);
6729         }
6730
6731       _startLazyDPSEvaluation ();
6732       while (size--)
6733         {
6734           l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6735           MOVA (l);
6736           emitcode ("rlc", "a");
6737           if (AOP_SIZE (result) > 1)
6738             aopPut (AOP (result), "a", offset++);
6739         }
6740       _endLazyDPSEvaluation ();
6741     }
6742   /* now we need to put the carry into the
6743      highest order byte of the result */
6744   if (AOP_SIZE (result) > 1)
6745     {
6746       l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
6747       MOVA (l);
6748     }
6749   emitcode ("mov", "acc.0,c");
6750   aopPut (AOP (result), "a", 0);
6751   freeAsmop (left, NULL, ic, TRUE);
6752   freeAsmop (result, NULL, ic, TRUE);
6753 }
6754
6755 /*-----------------------------------------------------------------*/
6756 /* genGetHbit - generates code get highest order bit               */
6757 /*-----------------------------------------------------------------*/
6758 static void
6759 genGetHbit (iCode * ic)
6760 {
6761   operand *left, *result;
6762   left = IC_LEFT (ic);
6763   result = IC_RESULT (ic);
6764   aopOp (left, ic, FALSE, FALSE);
6765   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6766
6767   D (emitcode (";", "genGetHbit ");
6768     );
6769
6770   /* get the highest order byte into a */
6771   MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
6772   if (AOP_TYPE (result) == AOP_CRY)
6773     {
6774       emitcode ("rlc", "a");
6775       outBitC (result);
6776     }
6777   else
6778     {
6779       emitcode ("rl", "a");
6780       emitcode ("anl", "a,#0x01");
6781       outAcc (result);
6782     }
6783
6784
6785   freeAsmop (left, NULL, ic, TRUE);
6786   freeAsmop (result, NULL, ic, TRUE);
6787 }
6788
6789 /*-----------------------------------------------------------------*/
6790 /* AccRol - rotate left accumulator by known count                 */
6791 /*-----------------------------------------------------------------*/
6792 static void
6793 AccRol (int shCount)
6794 {
6795   shCount &= 0x0007;            // shCount : 0..7
6796
6797   switch (shCount)
6798     {
6799     case 0:
6800       break;
6801     case 1:
6802       emitcode ("rl", "a");
6803       break;
6804     case 2:
6805       emitcode ("rl", "a");
6806       emitcode ("rl", "a");
6807       break;
6808     case 3:
6809       emitcode ("swap", "a");
6810       emitcode ("rr", "a");
6811       break;
6812     case 4:
6813       emitcode ("swap", "a");
6814       break;
6815     case 5:
6816       emitcode ("swap", "a");
6817       emitcode ("rl", "a");
6818       break;
6819     case 6:
6820       emitcode ("rr", "a");
6821       emitcode ("rr", "a");
6822       break;
6823     case 7:
6824       emitcode ("rr", "a");
6825       break;
6826     }
6827 }
6828
6829 /*-----------------------------------------------------------------*/
6830 /* AccLsh - left shift accumulator by known count                  */
6831 /*-----------------------------------------------------------------*/
6832 static void
6833 AccLsh (int shCount)
6834 {
6835   if (shCount != 0)
6836     {
6837       if (shCount == 1)
6838         emitcode ("add", "a,acc");
6839       else if (shCount == 2)
6840         {
6841           emitcode ("add", "a,acc");
6842           emitcode ("add", "a,acc");
6843         }
6844       else
6845         {
6846           /* rotate left accumulator */
6847           AccRol (shCount);
6848           /* and kill the lower order bits */
6849           emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6850         }
6851     }
6852 }
6853
6854 /*-----------------------------------------------------------------*/
6855 /* AccRsh - right shift accumulator by known count                 */
6856 /*-----------------------------------------------------------------*/
6857 static void
6858 AccRsh (int shCount)
6859 {
6860   if (shCount != 0)
6861     {
6862       if (shCount == 1)
6863         {
6864           CLRC;
6865           emitcode ("rrc", "a");
6866         }
6867       else
6868         {
6869           /* rotate right accumulator */
6870           AccRol (8 - shCount);
6871           /* and kill the higher order bits */
6872           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6873         }
6874     }
6875 }
6876
6877 #ifdef BETTER_LITERAL_SHIFT
6878 /*-----------------------------------------------------------------*/
6879 /* AccSRsh - signed right shift accumulator by known count                 */
6880 /*-----------------------------------------------------------------*/
6881 static void
6882 AccSRsh (int shCount)
6883 {
6884   symbol *tlbl;
6885   if (shCount != 0)
6886     {
6887       if (shCount == 1)
6888         {
6889           emitcode ("mov", "c,acc.7");
6890           emitcode ("rrc", "a");
6891         }
6892       else if (shCount == 2)
6893         {
6894           emitcode ("mov", "c,acc.7");
6895           emitcode ("rrc", "a");
6896           emitcode ("mov", "c,acc.7");
6897           emitcode ("rrc", "a");
6898         }
6899       else
6900         {
6901           tlbl = newiTempLabel (NULL);
6902           /* rotate right accumulator */
6903           AccRol (8 - shCount);
6904           /* and kill the higher order bits */
6905           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6906           emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6907           emitcode ("orl", "a,#0x%02x",
6908                     (unsigned char) ~SRMask[shCount]);
6909           emitcode ("", "%05d$:", tlbl->key + 100);
6910         }
6911     }
6912 }
6913 #endif
6914
6915 #ifdef BETTER_LITERAL_SHIFT
6916 /*-----------------------------------------------------------------*/
6917 /* shiftR1Left2Result - shift right one byte from left to result   */
6918 /*-----------------------------------------------------------------*/
6919 static void
6920 shiftR1Left2Result (operand * left, int offl,
6921                     operand * result, int offr,
6922                     int shCount, int sign)
6923 {
6924   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6925   /* shift right accumulator */
6926   if (sign)
6927     AccSRsh (shCount);
6928   else
6929     AccRsh (shCount);
6930   aopPut (AOP (result), "a", offr);
6931 }
6932 #endif
6933
6934 #ifdef BETTER_LITERAL_SHIFT
6935 /*-----------------------------------------------------------------*/
6936 /* shiftL1Left2Result - shift left one byte from left to result    */
6937 /*-----------------------------------------------------------------*/
6938 static void
6939 shiftL1Left2Result (operand * left, int offl,
6940                     operand * result, int offr, int shCount)
6941 {
6942   MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6943   /* shift left accumulator */
6944   AccLsh (shCount);
6945   aopPut (AOP (result), "a", offr);
6946 }
6947 #endif
6948
6949 #ifdef BETTER_LITERAL_SHIFT
6950 /*-----------------------------------------------------------------*/
6951 /* movLeft2Result - move byte from left to result                  */
6952 /*-----------------------------------------------------------------*/
6953 static void
6954 movLeft2Result (operand * left, int offl,
6955                 operand * result, int offr, int sign)
6956 {
6957   char *l;
6958   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6959   {
6960       l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
6961
6962       if (*l == '@' && (IS_AOP_PREG (result)))
6963       {
6964           emitcode ("mov", "a,%s", l);
6965           aopPut (AOP (result), "a", offr);
6966       }
6967       else
6968       {
6969           if (!sign)
6970           {
6971             aopPut (AOP (result), l, offr);
6972           }
6973           else
6974             {
6975               /* MSB sign in acc.7 ! */
6976               if (getDataSize (left) == offl + 1)
6977                 {
6978                   emitcode ("mov", "a,%s", l);
6979                   aopPut (AOP (result), "a", offr);
6980                 }
6981             }
6982       }
6983   }
6984 }
6985 #endif
6986
6987 #ifdef BETTER_LITERAL_SHIFT
6988 /*-----------------------------------------------------------------*/
6989 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
6990 /*-----------------------------------------------------------------*/
6991 static void
6992 AccAXRrl1 (char *x)
6993 {
6994   emitcode ("rrc", "a");
6995   emitcode ("xch", "a,%s", x);
6996   emitcode ("rrc", "a");
6997   emitcode ("xch", "a,%s", x);
6998 }
6999 #endif
7000
7001 #ifdef BETTER_LITERAL_SHIFT
7002 //REMOVE ME!!!
7003 /*-----------------------------------------------------------------*/
7004 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
7005 /*-----------------------------------------------------------------*/
7006 static void
7007 AccAXLrl1 (char *x)
7008 {
7009   emitcode ("xch", "a,%s", x);
7010   emitcode ("rlc", "a");
7011   emitcode ("xch", "a,%s", x);
7012   emitcode ("rlc", "a");
7013 }
7014 #endif
7015
7016 #ifdef BETTER_LITERAL_SHIFT
7017 /*-----------------------------------------------------------------*/
7018 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
7019 /*-----------------------------------------------------------------*/
7020 static void
7021 AccAXLsh1 (char *x)
7022 {
7023   emitcode ("xch", "a,%s", x);
7024   emitcode ("add", "a,acc");
7025   emitcode ("xch", "a,%s", x);
7026   emitcode ("rlc", "a");
7027 }
7028 #endif
7029
7030 #ifdef BETTER_LITERAL_SHIFT
7031 /*-----------------------------------------------------------------*/
7032 /* AccAXLsh - left shift a:x by known count (0..7)                 */
7033 /*-----------------------------------------------------------------*/
7034 static void
7035 AccAXLsh (char *x, int shCount)
7036 {
7037   switch (shCount)
7038     {
7039     case 0:
7040       break;
7041     case 1:
7042       AccAXLsh1 (x);
7043       break;
7044     case 2:
7045       AccAXLsh1 (x);
7046       AccAXLsh1 (x);
7047       break;
7048     case 3:
7049     case 4:
7050     case 5:                     // AAAAABBB:CCCCCDDD
7051
7052       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
7053
7054       emitcode ("anl", "a,#0x%02x",
7055                 SLMask[shCount]);       // BBB00000:CCCCCDDD
7056
7057       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
7058
7059       AccRol (shCount);         // DDDCCCCC:BBB00000
7060
7061       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
7062
7063       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
7064
7065       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
7066
7067       emitcode ("anl", "a,#0x%02x",
7068                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
7069
7070       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
7071
7072       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
7073
7074       break;
7075     case 6:                     // AAAAAABB:CCCCCCDD
7076       emitcode ("anl", "a,#0x%02x",
7077                 SRMask[shCount]);       // 000000BB:CCCCCCDD
7078       emitcode ("mov", "c,acc.0");      // c = B
7079       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
7080 #if 0
7081       AccAXRrl1 (x);            // BCCCCCCD:D000000B
7082       AccAXRrl1 (x);            // BBCCCCCC:DD000000
7083 #else
7084       emitcode("rrc","a"); 
7085       emitcode("xch","a,%s", x); 
7086       emitcode("rrc","a"); 
7087       emitcode("mov","c,acc.0"); //<< get correct bit 
7088       emitcode("xch","a,%s", x); 
7089
7090       emitcode("rrc","a"); 
7091       emitcode("xch","a,%s", x); 
7092       emitcode("rrc","a"); 
7093       emitcode("xch","a,%s", x); 
7094 #endif
7095       break;
7096     case 7:                     // a:x <<= 7
7097
7098       emitcode ("anl", "a,#0x%02x",
7099                 SRMask[shCount]);       // 0000000B:CCCCCCCD
7100
7101       emitcode ("mov", "c,acc.0");      // c = B
7102
7103       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
7104
7105       AccAXRrl1 (x);            // BCCCCCCC:D0000000
7106
7107       break;
7108     default:
7109       break;
7110     }
7111 }
7112 #endif
7113
7114 #ifdef BETTER_LITERAL_SHIFT
7115 //REMOVE ME!!!
7116 /*-----------------------------------------------------------------*/
7117 /* AccAXRsh - right shift a:x known count (0..7)                   */
7118 /*-----------------------------------------------------------------*/
7119 static void
7120 AccAXRsh (char *x, int shCount)
7121 {
7122   switch (shCount)
7123     {
7124     case 0:
7125       break;
7126     case 1:
7127       CLRC;
7128       AccAXRrl1 (x);            // 0->a:x
7129
7130       break;
7131     case 2:
7132       CLRC;
7133       AccAXRrl1 (x);            // 0->a:x
7134
7135       CLRC;
7136       AccAXRrl1 (x);            // 0->a:x
7137
7138       break;
7139     case 3:
7140     case 4:
7141     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7142
7143       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
7144
7145       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7146
7147       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7148
7149       emitcode ("anl", "a,#0x%02x",
7150                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7151
7152       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7153
7154       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7155
7156       emitcode ("anl", "a,#0x%02x",
7157                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7158
7159       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7160
7161       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7162
7163       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
7164
7165       break;
7166     case 6:                     // AABBBBBB:CCDDDDDD
7167
7168       emitcode ("mov", "c,acc.7");
7169       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7170
7171       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7172
7173       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7174
7175       emitcode ("anl", "a,#0x%02x",
7176                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7177
7178       break;
7179     case 7:                     // ABBBBBBB:CDDDDDDD
7180
7181       emitcode ("mov", "c,acc.7");      // c = A
7182
7183       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7184
7185       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7186
7187       emitcode ("anl", "a,#0x%02x",
7188                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7189
7190       break;
7191     default:
7192       break;
7193     }
7194 }
7195 #endif
7196
7197 #ifdef BETTER_LITERAL_SHIFT
7198 /*-----------------------------------------------------------------*/
7199 /* AccAXRshS - right shift signed a:x known count (0..7)           */
7200 /*-----------------------------------------------------------------*/
7201 static void
7202 AccAXRshS (char *x, int shCount)
7203 {
7204   symbol *tlbl;
7205   switch (shCount)
7206     {
7207     case 0:
7208       break;
7209     case 1:
7210       emitcode ("mov", "c,acc.7");
7211       AccAXRrl1 (x);            // s->a:x
7212
7213       break;
7214     case 2:
7215       emitcode ("mov", "c,acc.7");
7216       AccAXRrl1 (x);            // s->a:x
7217
7218       emitcode ("mov", "c,acc.7");
7219       AccAXRrl1 (x);            // s->a:x
7220
7221       break;
7222     case 3:
7223     case 4:
7224     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7225
7226       tlbl = newiTempLabel (NULL);
7227       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
7228
7229       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7230
7231       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7232
7233       emitcode ("anl", "a,#0x%02x",
7234                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7235
7236       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7237
7238       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7239
7240       emitcode ("anl", "a,#0x%02x",
7241                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7242
7243       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7244
7245       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7246
7247       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
7248
7249       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7250       emitcode ("orl", "a,#0x%02x",
7251                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
7252
7253       emitcode ("", "%05d$:", tlbl->key + 100);
7254       break;                    // SSSSAAAA:BBBCCCCC
7255
7256     case 6:                     // AABBBBBB:CCDDDDDD
7257
7258       tlbl = newiTempLabel (NULL);
7259       emitcode ("mov", "c,acc.7");
7260       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7261
7262       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7263
7264       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7265
7266       emitcode ("anl", "a,#0x%02x",
7267                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7268
7269       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7270       emitcode ("orl", "a,#0x%02x",
7271                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
7272
7273       emitcode ("", "%05d$:", tlbl->key + 100);
7274       break;
7275     case 7:                     // ABBBBBBB:CDDDDDDD
7276
7277       tlbl = newiTempLabel (NULL);
7278       emitcode ("mov", "c,acc.7");      // c = A
7279
7280       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7281
7282       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7283
7284       emitcode ("anl", "a,#0x%02x",
7285                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7286
7287       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7288       emitcode ("orl", "a,#0x%02x",
7289                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
7290
7291       emitcode ("", "%05d$:", tlbl->key + 100);
7292       break;
7293     default:
7294       break;
7295     }
7296 }
7297 #endif
7298
7299 #ifdef BETTER_LITERAL_SHIFT
7300 static void
7301 _loadLeftIntoAx(char    **lsb, 
7302                 operand *left, 
7303                 operand *result,
7304                 int     offl,
7305                 int     offr)
7306 {
7307   // Get the initial value from left into a pair of registers.
7308   // MSB must be in A, LSB can be any register.
7309   //
7310   // If the result is held in registers, it is an optimization
7311   // if the LSB can be held in the register which will hold the,
7312   // result LSB since this saves us from having to copy it into
7313   // the result following AccAXLsh.
7314   //
7315   // If the result is addressed indirectly, this is not a gain.
7316   if (AOP_NEEDSACC(result))
7317   {
7318        char *leftByte;
7319        
7320        _startLazyDPSEvaluation();
7321       if (AOP_TYPE(left) == AOP_DPTR2)
7322        {
7323            // Get MSB in A.
7324            MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
7325            // get LSB in DP2_RESULT_REG.
7326            leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
7327            assert(!strcmp(leftByte, DP2_RESULT_REG));
7328        }
7329        else
7330        {
7331            // get LSB into DP2_RESULT_REG
7332            leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
7333            if (strcmp(leftByte, DP2_RESULT_REG))
7334            {
7335                TR_AP("#7");
7336                emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7337            }
7338            // And MSB in A.
7339            leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
7340            assert(strcmp(leftByte, DP2_RESULT_REG));
7341            MOVA(leftByte);
7342        }
7343        _endLazyDPSEvaluation();
7344        *lsb = DP2_RESULT_REG;
7345   }
7346   else
7347   {
7348       if (sameRegs (AOP (result), AOP (left)) &&
7349         ((offl + MSB16) == offr))
7350       {
7351           /* don't crash result[offr] */
7352           MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
7353           emitcode ("xch", "a,%s", 
7354                     aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
7355       }
7356       else
7357       {
7358           movLeft2Result (left, offl, result, offr, 0);
7359           MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
7360       }
7361       *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
7362       assert(strcmp(*lsb,"a"));      
7363   }
7364 }
7365
7366 static void
7367 _storeAxResults(char    *lsb,
7368                 operand *result,
7369                 int     offr)
7370 {
7371   _startLazyDPSEvaluation();
7372   if (AOP_NEEDSACC(result))
7373   {
7374       /* We have to explicitly update the result LSB.
7375        */
7376       emitcode("xch","a,%s", lsb);
7377       aopPut(AOP(result), "a", offr);
7378       emitcode("mov","a,%s", lsb);
7379   }
7380   if (getDataSize (result) > 1)
7381   {
7382       aopPut (AOP (result), "a", offr + MSB16);
7383   }
7384   _endLazyDPSEvaluation();
7385 }
7386
7387 /*-----------------------------------------------------------------*/
7388 /* shiftL2Left2Result - shift left two bytes from left to result   */
7389 /*-----------------------------------------------------------------*/
7390 static void
7391 shiftL2Left2Result (operand * left, int offl,
7392                     operand * result, int offr, int shCount)
7393 {
7394   char *lsb;
7395
7396   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7397   
7398   AccAXLsh (lsb, shCount);
7399   
7400   _storeAxResults(lsb, result, offr);
7401 }
7402 #endif
7403
7404 #ifdef BETTER_LITERAL_SHIFT
7405 /*-----------------------------------------------------------------*/
7406 /* shiftR2Left2Result - shift right two bytes from left to result  */
7407 /*-----------------------------------------------------------------*/
7408 static void
7409 shiftR2Left2Result (operand * left, int offl,
7410                     operand * result, int offr,
7411                     int shCount, int sign)
7412 {
7413   char *lsb;
7414   
7415   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7416   
7417   /* a:x >> shCount (x = lsb(result)) */
7418   if (sign)
7419   {
7420      AccAXRshS(lsb, shCount);
7421   }
7422   else
7423   {
7424     AccAXRsh(lsb, shCount);
7425   }
7426   
7427   _storeAxResults(lsb, result, offr);
7428 }
7429 #endif
7430
7431 #if 0
7432 //REMOVE ME!!!
7433 /*-----------------------------------------------------------------*/
7434 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7435 /*-----------------------------------------------------------------*/
7436 static void
7437 shiftLLeftOrResult (operand * left, int offl,
7438                     operand * result, int offr, int shCount)
7439 {
7440   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7441   /* shift left accumulator */
7442   AccLsh (shCount);
7443   /* or with result */
7444   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7445   /* back to result */
7446   aopPut (AOP (result), "a", offr);
7447 }
7448 #endif
7449
7450 #if 0
7451 //REMOVE ME!!!
7452 /*-----------------------------------------------------------------*/
7453 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7454 /*-----------------------------------------------------------------*/
7455 static void
7456 shiftRLeftOrResult (operand * left, int offl,
7457                     operand * result, int offr, int shCount)
7458 {
7459   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7460   /* shift right accumulator */
7461   AccRsh (shCount);
7462   /* or with result */
7463   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7464   /* back to result */
7465   aopPut (AOP (result), "a", offr);
7466 }
7467 #endif
7468
7469 #ifdef BETTER_LITERAL_SHIFT
7470 /*-----------------------------------------------------------------*/
7471 /* genlshOne - left shift a one byte quantity by known count       */
7472 /*-----------------------------------------------------------------*/
7473 static void
7474 genlshOne (operand * result, operand * left, int shCount)
7475 {
7476   D (emitcode (";", "genlshOne "););
7477   shiftL1Left2Result (left, LSB, result, LSB, shCount);
7478 }
7479 #endif
7480
7481 #ifdef BETTER_LITERAL_SHIFT
7482 /*-----------------------------------------------------------------*/
7483 /* genlshTwo - left shift two bytes by known amount != 0           */
7484 /*-----------------------------------------------------------------*/
7485 static void
7486 genlshTwo (operand * result, operand * left, int shCount)
7487 {
7488   int size;
7489
7490   D (emitcode (";", "genlshTwo "););
7491
7492   size = getDataSize (result);
7493
7494   /* if shCount >= 8 */
7495   if (shCount >= 8)
7496   {
7497       shCount -= 8;
7498
7499       _startLazyDPSEvaluation();
7500
7501       if (size > 1)
7502         {
7503           if (shCount)
7504           {
7505             _endLazyDPSEvaluation();
7506             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7507             aopPut (AOP (result), zero, LSB);       
7508           }
7509           else
7510           {
7511             movLeft2Result (left, LSB, result, MSB16, 0);
7512             aopPut (AOP (result), zero, LSB);
7513             _endLazyDPSEvaluation();
7514           }
7515         }
7516         else
7517         {
7518           aopPut (AOP (result), zero, LSB);
7519           _endLazyDPSEvaluation();
7520         }
7521   }
7522
7523   /*  1 <= shCount <= 7 */
7524   else
7525     {
7526       if (size == 1)
7527       {
7528         shiftL1Left2Result (left, LSB, result, LSB, shCount);
7529       }
7530       else
7531       {
7532         shiftL2Left2Result (left, LSB, result, LSB, shCount);
7533       }
7534     }
7535 }
7536 #endif
7537
7538 #if 0
7539 //REMOVE ME!!!
7540 /*-----------------------------------------------------------------*/
7541 /* shiftLLong - shift left one long from left to result            */
7542 /* offl = LSB or MSB16                                             */
7543 /*-----------------------------------------------------------------*/
7544 static void
7545 shiftLLong (operand * left, operand * result, int offr)
7546 {
7547   char *l;
7548   int size = AOP_SIZE (result);
7549
7550   if (size >= LSB + offr)
7551     {
7552       l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
7553       MOVA (l);
7554       emitcode ("add", "a,acc");
7555       if (sameRegs (AOP (left), AOP (result)) &&
7556           size >= MSB16 + offr && offr != LSB)
7557         emitcode ("xch", "a,%s",
7558                   aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
7559       else
7560         aopPut (AOP (result), "a", LSB + offr);
7561     }
7562
7563   if (size >= MSB16 + offr)
7564     {
7565       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7566         {
7567           l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
7568           MOVA (l);
7569         }
7570       emitcode ("rlc", "a");
7571       if (sameRegs (AOP (left), AOP (result)) &&
7572           size >= MSB24 + offr && offr != LSB)
7573         emitcode ("xch", "a,%s",
7574                   aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
7575       else
7576         aopPut (AOP (result), "a", MSB16 + offr);
7577     }
7578
7579   if (size >= MSB24 + offr)
7580     {
7581       if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7582         {
7583           l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
7584           MOVA (l);
7585         }
7586       emitcode ("rlc", "a");
7587       if (sameRegs (AOP (left), AOP (result)) &&
7588           size >= MSB32 + offr && offr != LSB)
7589         emitcode ("xch", "a,%s",
7590                   aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
7591       else
7592         aopPut (AOP (result), "a", MSB24 + offr);
7593     }
7594
7595   if (size > MSB32 + offr)
7596     {
7597       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7598         {
7599           l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
7600           MOVA (l);
7601         }
7602       emitcode ("rlc", "a");
7603       aopPut (AOP (result), "a", MSB32 + offr);
7604     }
7605   if (offr != LSB)
7606     aopPut (AOP (result), zero, LSB);
7607 }
7608 #endif
7609
7610 #if 0
7611 //REMOVE ME!!!
7612 /*-----------------------------------------------------------------*/
7613 /* genlshFour - shift four byte by a known amount != 0             */
7614 /*-----------------------------------------------------------------*/
7615 static void
7616 genlshFour (operand * result, operand * left, int shCount)
7617 {
7618   int size;
7619
7620   D (emitcode (";", "genlshFour ");
7621     );
7622
7623   size = AOP_SIZE (result);
7624
7625   /* if shifting more that 3 bytes */
7626   if (shCount >= 24)
7627     {
7628       shCount -= 24;
7629       if (shCount)
7630         /* lowest order of left goes to the highest
7631            order of the destination */
7632         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7633       else
7634         movLeft2Result (left, LSB, result, MSB32, 0);
7635       aopPut (AOP (result), zero, LSB);
7636       aopPut (AOP (result), zero, MSB16);
7637       aopPut (AOP (result), zero, MSB24);
7638       return;
7639     }
7640
7641   /* more than two bytes */
7642   else if (shCount >= 16)
7643     {
7644       /* lower order two bytes goes to higher order two bytes */
7645       shCount -= 16;
7646       /* if some more remaining */
7647       if (shCount)
7648         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7649       else
7650         {
7651           movLeft2Result (left, MSB16, result, MSB32, 0);
7652           movLeft2Result (left, LSB, result, MSB24, 0);
7653         }
7654       aopPut (AOP (result), zero, MSB16);
7655       aopPut (AOP (result), zero, LSB);
7656       return;
7657     }
7658
7659   /* if more than 1 byte */
7660   else if (shCount >= 8)
7661     {
7662       /* lower order three bytes goes to higher order  three bytes */
7663       shCount -= 8;
7664       if (size == 2)
7665         {
7666           if (shCount)
7667             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7668           else
7669             movLeft2Result (left, LSB, result, MSB16, 0);
7670         }
7671       else
7672         {                       /* size = 4 */
7673           if (shCount == 0)
7674             {
7675               movLeft2Result (left, MSB24, result, MSB32, 0);
7676               movLeft2Result (left, MSB16, result, MSB24, 0);
7677               movLeft2Result (left, LSB, result, MSB16, 0);
7678               aopPut (AOP (result), zero, LSB);
7679             }
7680           else if (shCount == 1)
7681             shiftLLong (left, result, MSB16);
7682           else
7683             {
7684               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7685               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7686               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7687               aopPut (AOP (result), zero, LSB);
7688             }
7689         }
7690     }
7691
7692   /* 1 <= shCount <= 7 */
7693   else if (shCount <= 2)
7694     {
7695       shiftLLong (left, result, LSB);
7696       if (shCount == 2)
7697         shiftLLong (result, result, LSB);
7698     }
7699   /* 3 <= shCount <= 7, optimize */
7700   else
7701     {
7702       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7703       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7704       shiftL2Left2Result (left, LSB, result, LSB, shCount);
7705     }
7706 }
7707 #endif
7708
7709 #ifdef BETTER_LITERAL_SHIFT
7710 /*-----------------------------------------------------------------*/
7711 /* genLeftShiftLiteral - left shifting by known count              */
7712 /*-----------------------------------------------------------------*/
7713 static bool
7714 genLeftShiftLiteral (operand * left,
7715                      operand * right,
7716                      operand * result,
7717                      iCode * ic)
7718 {
7719   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7720   int size;
7721
7722   size = getSize (operandType (result));
7723
7724   D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
7725
7726   /* We only handle certain easy cases so far. */
7727   if ((shCount != 0)
7728    && (shCount < (size * 8))
7729    && (size != 1)
7730    && (size != 2))
7731   {
7732       D(emitcode (";", "genLeftShiftLiteral wimping out"););    
7733       return FALSE;
7734   }
7735
7736   freeAsmop (right, NULL, ic, TRUE);
7737
7738   aopOp(left, ic, FALSE, FALSE);
7739   aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
7740
7741 #if 1 // debug spew
7742   if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
7743   {
7744         emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
7745         if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
7746         {
7747            emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
7748         }
7749   }
7750   if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
7751   {
7752         emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
7753         if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
7754         {
7755            emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
7756         }       
7757   }  
7758 #endif
7759   
7760 #if VIEW_SIZE
7761   emitcode ("; shift left ", "result %d, left %d", size,
7762             AOP_SIZE (left));
7763 #endif
7764
7765   /* I suppose that the left size >= result size */
7766   if (shCount == 0)
7767   {
7768         _startLazyDPSEvaluation();
7769         while (size--)
7770         {
7771           movLeft2Result (left, size, result, size, 0);
7772         }
7773         _endLazyDPSEvaluation();
7774   }
7775   else if (shCount >= (size * 8))
7776   {
7777     _startLazyDPSEvaluation();
7778     while (size--)
7779     {
7780       aopPut (AOP (result), zero, size);
7781     }
7782     _endLazyDPSEvaluation();
7783   }
7784   else
7785   {
7786       switch (size)
7787         {
7788         case 1:
7789           genlshOne (result, left, shCount);
7790           break;
7791
7792         case 2:
7793           genlshTwo (result, left, shCount);
7794           break;
7795 #if 0
7796         case 4:
7797           genlshFour (result, left, shCount);
7798           break;
7799 #endif
7800         default:
7801           fprintf(stderr, "*** ack! mystery literal shift!\n");   
7802           break;
7803         }
7804     }
7805   freeAsmop (left, NULL, ic, TRUE);
7806   freeAsmop (result, NULL, ic, TRUE);
7807   return TRUE;
7808 }
7809 #endif
7810
7811 /*-----------------------------------------------------------------*/
7812 /* genLeftShift - generates code for left shifting                 */
7813 /*-----------------------------------------------------------------*/
7814 static void
7815 genLeftShift (iCode * ic)
7816 {
7817   operand *left, *right, *result;
7818   int size, offset;
7819   char *l;
7820   symbol *tlbl, *tlbl1;
7821
7822   D (emitcode (";", "genLeftShift "););
7823
7824   right = IC_RIGHT (ic);
7825   left = IC_LEFT (ic);
7826   result = IC_RESULT (ic);
7827
7828   aopOp (right, ic, FALSE, FALSE);
7829
7830
7831 #ifdef BETTER_LITERAL_SHIFT
7832   /* if the shift count is known then do it
7833      as efficiently as possible */
7834   if (AOP_TYPE (right) == AOP_LIT)
7835     {
7836       if (genLeftShiftLiteral (left, right, result, ic))
7837       {
7838         return;
7839       }
7840     }
7841 #endif
7842
7843   /* shift count is unknown then we have to form
7844      a loop get the loop count in B : Note: we take
7845      only the lower order byte since shifting
7846      more that 32 bits make no sense anyway, ( the
7847      largest size of an object can be only 32 bits ) */
7848
7849   if (AOP_TYPE (right) == AOP_LIT)
7850   {
7851       /* Really should be handled by genLeftShiftLiteral,
7852        * but since I'm too lazy to fix that today, at least we can make
7853        * some small improvement.
7854        */
7855        emitcode("mov", "b,#0x%02x",
7856                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7857   }
7858   else
7859   {
7860         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7861         emitcode ("inc", "b");
7862   }
7863   freeAsmop (right, NULL, ic, TRUE);
7864   aopOp (left, ic, FALSE, FALSE);
7865   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7866
7867   /* now move the left to the result if they are not the
7868      same */
7869   if (!sameRegs (AOP (left), AOP (result)) &&
7870       AOP_SIZE (result) > 1)
7871     {
7872
7873       size = AOP_SIZE (result);
7874       offset = 0;
7875       _startLazyDPSEvaluation ();
7876       while (size--)
7877         {
7878           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7879           if (*l == '@' && (IS_AOP_PREG (result)))
7880             {
7881
7882               emitcode ("mov", "a,%s", l);
7883               aopPut (AOP (result), "a", offset);
7884             }
7885           else
7886             aopPut (AOP (result), l, offset);
7887           offset++;
7888         }
7889       _endLazyDPSEvaluation ();
7890     }
7891
7892   tlbl = newiTempLabel (NULL);
7893   size = AOP_SIZE (result);
7894   offset = 0;
7895   tlbl1 = newiTempLabel (NULL);
7896
7897   /* if it is only one byte then */
7898   if (size == 1)
7899     {
7900       symbol *tlbl1 = newiTempLabel (NULL);
7901
7902       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7903       MOVA (l);
7904       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7905       emitcode ("", "%05d$:", tlbl->key + 100);
7906       emitcode ("add", "a,acc");
7907       emitcode ("", "%05d$:", tlbl1->key + 100);
7908       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7909       aopPut (AOP (result), "a", 0);
7910       goto release;
7911     }
7912
7913   reAdjustPreg (AOP (result));
7914
7915   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7916   emitcode ("", "%05d$:", tlbl->key + 100);
7917   l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7918   MOVA (l);
7919   emitcode ("add", "a,acc");
7920   aopPut (AOP (result), "a", offset++);
7921   _startLazyDPSEvaluation ();
7922   while (--size)
7923     {
7924       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7925       MOVA (l);
7926       emitcode ("rlc", "a");
7927       aopPut (AOP (result), "a", offset++);
7928     }
7929   _endLazyDPSEvaluation ();
7930   reAdjustPreg (AOP (result));
7931
7932   emitcode ("", "%05d$:", tlbl1->key + 100);
7933   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7934 release:
7935   freeAsmop (left, NULL, ic, TRUE);
7936   freeAsmop (result, NULL, ic, TRUE);
7937 }
7938
7939 #ifdef BETTER_LITERAL_SHIFT
7940 /*-----------------------------------------------------------------*/
7941 /* genrshOne - right shift a one byte quantity by known count      */
7942 /*-----------------------------------------------------------------*/
7943 static void
7944 genrshOne (operand * result, operand * left,
7945            int shCount, int sign)
7946 {
7947   D (emitcode (";", "genrshOne"););
7948   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7949 }
7950 #endif
7951
7952 #ifdef BETTER_LITERAL_SHIFT
7953 /*-----------------------------------------------------------------*/
7954 /* genrshTwo - right shift two bytes by known amount != 0          */
7955 /*-----------------------------------------------------------------*/
7956 static void
7957 genrshTwo (operand * result, operand * left,
7958            int shCount, int sign)
7959 {
7960   D (emitcode (";", "genrshTwo"););
7961
7962   /* if shCount >= 8 */
7963   if (shCount >= 8)
7964     {
7965       shCount -= 8;
7966       _startLazyDPSEvaluation();
7967       if (shCount)
7968       {
7969         shiftR1Left2Result (left, MSB16, result, LSB,
7970                             shCount, sign);
7971       }                     
7972       else
7973       {
7974         movLeft2Result (left, MSB16, result, LSB, sign);
7975       }
7976       addSign (result, MSB16, sign);
7977       _endLazyDPSEvaluation();
7978     }
7979
7980   /*  1 <= shCount <= 7 */
7981   else
7982   {
7983     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7984   }
7985 }
7986 #endif
7987
7988 #if 0
7989 //REMOVE ME!!!
7990 /*-----------------------------------------------------------------*/
7991 /* shiftRLong - shift right one long from left to result           */
7992 /* offl = LSB or MSB16                                             */
7993 /*-----------------------------------------------------------------*/
7994 static void
7995 shiftRLong (operand * left, int offl,
7996             operand * result, int sign)
7997 {
7998   int isSameRegs=sameRegs(AOP(left),AOP(result));
7999
8000   if (isSameRegs && offl>1) {
8001     // we are in big trouble, but this shouldn't happen
8002     werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8003   }
8004
8005   MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
8006   
8007   if (offl==MSB16) {
8008     // shift is > 8
8009     if (sign) {
8010       emitcode ("rlc", "a");
8011       emitcode ("subb", "a,acc");
8012       emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
8013     } else {
8014       aopPut (AOP(result), zero, MSB32);
8015     }
8016   }
8017
8018   if (!sign) {
8019     emitcode ("clr", "c");
8020   } else {
8021     emitcode ("mov", "c,acc.7");
8022   }
8023
8024   emitcode ("rrc", "a");
8025
8026   if (isSameRegs && offl==MSB16) {
8027     emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
8028   } else {
8029     aopPut (AOP (result), "a", MSB32);
8030     MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
8031   }
8032
8033   emitcode ("rrc", "a");
8034   if (isSameRegs && offl==1) {
8035     emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
8036   } else {
8037     aopPut (AOP (result), "a", MSB24);
8038     MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
8039   }
8040   emitcode ("rrc", "a");
8041   aopPut (AOP (result), "a", MSB16 - offl);
8042
8043   if (offl == LSB)
8044     {
8045       MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
8046       emitcode ("rrc", "a");
8047       aopPut (AOP (result), "a", LSB);
8048     }
8049 }
8050 #endif
8051
8052 #if 0
8053 //REMOVE ME!!!
8054 /*-----------------------------------------------------------------*/
8055 /* genrshFour - shift four byte by a known amount != 0             */
8056 /*-----------------------------------------------------------------*/
8057 static void
8058 genrshFour (operand * result, operand * left,
8059             int shCount, int sign)
8060 {
8061   D (emitcode (";", "genrshFour");
8062     );
8063
8064   /* if shifting more that 3 bytes */
8065   if (shCount >= 24)
8066     {
8067       shCount -= 24;
8068       if (shCount)
8069         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8070       else
8071         movLeft2Result (left, MSB32, result, LSB, sign);
8072       addSign (result, MSB16, sign);
8073     }
8074   else if (shCount >= 16)
8075     {
8076       shCount -= 16;
8077       if (shCount)
8078         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8079       else
8080         {
8081           movLeft2Result (left, MSB24, result, LSB, 0);
8082           movLeft2Result (left, MSB32, result, MSB16, sign);
8083         }
8084       addSign (result, MSB24, sign);
8085     }
8086   else if (shCount >= 8)
8087     {
8088       shCount -= 8;
8089       if (shCount == 1)
8090         shiftRLong (left, MSB16, result, sign);
8091       else if (shCount == 0)
8092         {
8093           movLeft2Result (left, MSB16, result, LSB, 0);
8094           movLeft2Result (left, MSB24, result, MSB16, 0);
8095           movLeft2Result (left, MSB32, result, MSB24, sign);
8096           addSign (result, MSB32, sign);
8097         }
8098       else
8099         {
8100           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8101           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8102           /* the last shift is signed */
8103           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8104           addSign (result, MSB32, sign);
8105         }
8106     }
8107   else
8108     {                           /* 1 <= shCount <= 7 */
8109       if (shCount <= 2)
8110         {
8111           shiftRLong (left, LSB, result, sign);
8112           if (shCount == 2)
8113             shiftRLong (result, LSB, result, sign);
8114         }
8115       else
8116         {
8117           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8118           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8119           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8120         }
8121     }
8122 }
8123 #endif
8124
8125 #ifdef BETTER_LITERAL_SHIFT
8126 /*-----------------------------------------------------------------*/
8127 /* genRightShiftLiteral - right shifting by known count            */
8128 /*-----------------------------------------------------------------*/
8129 static bool
8130 genRightShiftLiteral (operand * left,
8131                       operand * right,
8132                       operand * result,
8133                       iCode * ic,
8134                       int sign)
8135 {
8136   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8137   int size;
8138
8139   size = getSize (operandType (result));
8140
8141   D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8142
8143   /* We only handle certain easy cases so far. */
8144   if ((shCount != 0)
8145    && (shCount < (size * 8))
8146    && (size != 1)
8147    && (size != 2))
8148   {
8149       D(emitcode (";", "genRightShiftLiteral wimping out"););   
8150       return FALSE;
8151   }
8152
8153   freeAsmop (right, NULL, ic, TRUE);
8154
8155   aopOp (left, ic, FALSE, FALSE);
8156   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8157
8158 #if VIEW_SIZE
8159   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8160             AOP_SIZE (left));
8161 #endif
8162
8163   /* test the LEFT size !!! */
8164
8165   /* I suppose that the left size >= result size */
8166   if (shCount == 0)
8167   {
8168       size = getDataSize (result);
8169       _startLazyDPSEvaluation();
8170       while (size--)
8171       {
8172         movLeft2Result (left, size, result, size, 0);
8173       }
8174       _endLazyDPSEvaluation();
8175   }
8176   else if (shCount >= (size * 8))
8177     {
8178       if (sign)
8179       {
8180         /* get sign in acc.7 */
8181         MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
8182       }
8183       addSign (result, LSB, sign);
8184     }
8185   else
8186     {
8187       switch (size)
8188         {
8189         case 1:
8190           genrshOne (result, left, shCount, sign);
8191           break;
8192
8193         case 2:
8194           genrshTwo (result, left, shCount, sign);
8195           break;
8196 #if 0
8197         case 4:
8198           genrshFour (result, left, shCount, sign);
8199           break;
8200 #endif    
8201         default:
8202           break;
8203         }
8204
8205       freeAsmop (left, NULL, ic, TRUE);
8206       freeAsmop (result, NULL, ic, TRUE);
8207     }
8208     return TRUE;
8209 }
8210 #endif
8211
8212 /*-----------------------------------------------------------------*/
8213 /* genSignedRightShift - right shift of signed number              */
8214 /*-----------------------------------------------------------------*/
8215 static void
8216 genSignedRightShift (iCode * ic)
8217 {
8218   operand *right, *left, *result;
8219   int size, offset;
8220   char *l;
8221   symbol *tlbl, *tlbl1;
8222
8223   D (emitcode (";", "genSignedRightShift "););
8224
8225   /* we do it the hard way put the shift count in b
8226      and loop thru preserving the sign */
8227
8228   right = IC_RIGHT (ic);
8229   left = IC_LEFT (ic);
8230   result = IC_RESULT (ic);
8231
8232   aopOp (right, ic, FALSE, FALSE);
8233
8234 #ifdef BETTER_LITERAL_SHIFT
8235   if (AOP_TYPE (right) == AOP_LIT)
8236     {
8237       if (genRightShiftLiteral (left, right, result, ic, 1))
8238       {
8239         return;
8240       }
8241     }
8242 #endif
8243   /* shift count is unknown then we have to form
8244      a loop get the loop count in B : Note: we take
8245      only the lower order byte since shifting
8246      more that 32 bits make no sense anyway, ( the
8247      largest size of an object can be only 32 bits ) */
8248
8249   if (AOP_TYPE (right) == AOP_LIT)
8250   {
8251       /* Really should be handled by genRightShiftLiteral,
8252        * but since I'm too lazy to fix that today, at least we can make
8253        * some small improvement.
8254        */
8255        emitcode("mov", "b,#0x%02x",
8256                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8257   }
8258   else
8259   {
8260         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8261         emitcode ("inc", "b");
8262   }
8263   freeAsmop (right, NULL, ic, TRUE);
8264   aopOp (left, ic, FALSE, FALSE);
8265   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8266
8267   /* now move the left to the result if they are not the
8268      same */
8269   if (!sameRegs (AOP (left), AOP (result)) &&
8270       AOP_SIZE (result) > 1)
8271     {
8272
8273       size = AOP_SIZE (result);
8274       offset = 0;
8275       _startLazyDPSEvaluation ();
8276       while (size--)
8277         {
8278           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8279           if (*l == '@' && IS_AOP_PREG (result))
8280             {
8281
8282               emitcode ("mov", "a,%s", l);
8283               aopPut (AOP (result), "a", offset);
8284             }
8285           else
8286             aopPut (AOP (result), l, offset);
8287           offset++;
8288         }
8289       _endLazyDPSEvaluation ();
8290     }
8291
8292   /* mov the highest order bit to OVR */
8293   tlbl = newiTempLabel (NULL);
8294   tlbl1 = newiTempLabel (NULL);
8295
8296   size = AOP_SIZE (result);
8297   offset = size - 1;
8298   emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
8299   emitcode ("rlc", "a");
8300   emitcode ("mov", "ov,c");
8301   /* if it is only one byte then */
8302   if (size == 1)
8303     {
8304       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8305       MOVA (l);
8306       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8307       emitcode ("", "%05d$:", tlbl->key + 100);
8308       emitcode ("mov", "c,ov");
8309       emitcode ("rrc", "a");
8310       emitcode ("", "%05d$:", tlbl1->key + 100);
8311       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8312       aopPut (AOP (result), "a", 0);
8313       goto release;
8314     }
8315
8316   reAdjustPreg (AOP (result));
8317   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8318   emitcode ("", "%05d$:", tlbl->key + 100);
8319   emitcode ("mov", "c,ov");
8320   _startLazyDPSEvaluation ();
8321   while (size--)
8322     {
8323       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8324       MOVA (l);
8325       emitcode ("rrc", "a");
8326       aopPut (AOP (result), "a", offset--);
8327     }
8328   _endLazyDPSEvaluation ();
8329   reAdjustPreg (AOP (result));
8330   emitcode ("", "%05d$:", tlbl1->key + 100);
8331   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8332
8333 release:
8334   freeAsmop (left, NULL, ic, TRUE);
8335   freeAsmop (result, NULL, ic, TRUE);
8336 }
8337
8338 /*-----------------------------------------------------------------*/
8339 /* genRightShift - generate code for right shifting                */
8340 /*-----------------------------------------------------------------*/
8341 static void
8342 genRightShift (iCode * ic)
8343 {
8344   operand *right, *left, *result;
8345   sym_link *retype;
8346   int size, offset;
8347   char *l;
8348   symbol *tlbl, *tlbl1;
8349
8350   D (emitcode (";", "genRightShift "););
8351
8352   /* if signed then we do it the hard way preserve the
8353      sign bit moving it inwards */
8354   retype = getSpec (operandType (IC_RESULT (ic)));
8355
8356   if (!SPEC_USIGN (retype))
8357     {
8358       genSignedRightShift (ic);
8359       return;
8360     }
8361
8362   /* signed & unsigned types are treated the same : i.e. the
8363      signed is NOT propagated inwards : quoting from the
8364      ANSI - standard : "for E1 >> E2, is equivalent to division
8365      by 2**E2 if unsigned or if it has a non-negative value,
8366      otherwise the result is implementation defined ", MY definition
8367      is that the sign does not get propagated */
8368
8369   right = IC_RIGHT (ic);
8370   left = IC_LEFT (ic);
8371   result = IC_RESULT (ic);
8372
8373   aopOp (right, ic, FALSE, FALSE);
8374
8375 #ifdef BETTER_LITERAL_SHIFT
8376   /* if the shift count is known then do it
8377      as efficiently as possible */
8378   if (AOP_TYPE (right) == AOP_LIT)
8379     {
8380       if (genRightShiftLiteral (left, right, result, ic, 0))
8381       {
8382         return;
8383       }
8384     }
8385 #endif
8386
8387   /* shift count is unknown then we have to form
8388      a loop get the loop count in B : Note: we take
8389      only the lower order byte since shifting
8390      more that 32 bits make no sense anyway, ( the
8391      largest size of an object can be only 32 bits ) */
8392   
8393   if (AOP_TYPE (right) == AOP_LIT)
8394   {
8395       /* Really should be handled by genRightShiftLiteral,
8396        * but since I'm too lazy to fix that today, at least we can make
8397        * some small improvement.
8398        */
8399        emitcode("mov", "b,#0x%02x",
8400                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8401   }
8402   else
8403   {
8404         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8405         emitcode ("inc", "b");
8406   }
8407   freeAsmop (right, NULL, ic, TRUE);
8408   aopOp (left, ic, FALSE, FALSE);
8409   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8410
8411   /* now move the left to the result if they are not the
8412      same */
8413   if (!sameRegs (AOP (left), AOP (result)) &&
8414       AOP_SIZE (result) > 1)
8415     {
8416
8417       size = AOP_SIZE (result);
8418       offset = 0;
8419       _startLazyDPSEvaluation ();
8420       while (size--)
8421         {
8422           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8423           if (*l == '@' && IS_AOP_PREG (result))
8424             {
8425
8426               emitcode ("mov", "a,%s", l);
8427               aopPut (AOP (result), "a", offset);
8428             }
8429           else
8430             aopPut (AOP (result), l, offset);
8431           offset++;
8432         }
8433       _endLazyDPSEvaluation ();
8434     }
8435
8436   tlbl = newiTempLabel (NULL);
8437   tlbl1 = newiTempLabel (NULL);
8438   size = AOP_SIZE (result);
8439   offset = size - 1;
8440
8441   /* if it is only one byte then */
8442   if (size == 1)
8443     {
8444       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8445       MOVA (l);
8446       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8447       emitcode ("", "%05d$:", tlbl->key + 100);
8448       CLRC;
8449       emitcode ("rrc", "a");
8450       emitcode ("", "%05d$:", tlbl1->key + 100);
8451       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8452       aopPut (AOP (result), "a", 0);
8453       goto release;
8454     }
8455
8456   reAdjustPreg (AOP (result));
8457   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8458   emitcode ("", "%05d$:", tlbl->key + 100);
8459   CLRC;
8460   _startLazyDPSEvaluation ();
8461   while (size--)
8462     {
8463       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8464       MOVA (l);
8465       emitcode ("rrc", "a");
8466       aopPut (AOP (result), "a", offset--);
8467     }
8468   _endLazyDPSEvaluation ();
8469   reAdjustPreg (AOP (result));
8470
8471   emitcode ("", "%05d$:", tlbl1->key + 100);
8472   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8473
8474 release:
8475   freeAsmop (left, NULL, ic, TRUE);
8476   freeAsmop (result, NULL, ic, TRUE);
8477 }
8478
8479 /*-----------------------------------------------------------------*/
8480 /* genUnpackBits - generates code for unpacking bits               */
8481 /*-----------------------------------------------------------------*/
8482 static void
8483 genUnpackBits (operand * result, char *rname, int ptype)
8484 {
8485   int shCnt;
8486   int rlen = 0;
8487   sym_link *etype;
8488   int offset = 0;
8489
8490   D (emitcode (";", "genUnpackBits ");
8491     );
8492
8493   etype = getSpec (operandType (result));
8494
8495   /* read the first byte  */
8496   switch (ptype)
8497     {
8498
8499     case POINTER:
8500     case IPOINTER:
8501       emitcode ("mov", "a,@%s", rname);
8502       break;
8503
8504     case PPOINTER:
8505       emitcode ("movx", "a,@%s", rname);
8506       break;
8507
8508     case FPOINTER:
8509       emitcode ("movx", "a,@dptr");
8510       break;
8511
8512     case CPOINTER:
8513       emitcode ("clr", "a");
8514       emitcode ("movc", "a,@a+dptr");
8515       break;
8516
8517     case GPOINTER:
8518       emitcode ("lcall", "__gptrget");
8519       break;
8520     }
8521
8522   /* if we have bitdisplacement then it fits   */
8523   /* into this byte completely or if length is */
8524   /* less than a byte                          */
8525   if ((shCnt = SPEC_BSTR (etype)) ||
8526       (SPEC_BLEN (etype) <= 8))
8527     {
8528
8529       /* shift right acc */
8530       AccRsh (shCnt);
8531
8532       emitcode ("anl", "a,#0x%02x",
8533                 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
8534       aopPut (AOP (result), "a", offset);
8535       return;
8536     }
8537
8538   /* bit field did not fit in a byte  */
8539   rlen = SPEC_BLEN (etype) - 8;
8540   aopPut (AOP (result), "a", offset++);
8541
8542   while (1)
8543     {
8544
8545       switch (ptype)
8546         {
8547         case POINTER:
8548         case IPOINTER:
8549           emitcode ("inc", "%s", rname);
8550           emitcode ("mov", "a,@%s", rname);
8551           break;
8552
8553         case PPOINTER:
8554           emitcode ("inc", "%s", rname);
8555           emitcode ("movx", "a,@%s", rname);
8556           break;
8557
8558         case FPOINTER:
8559           emitcode ("inc", "dptr");
8560           emitcode ("movx", "a,@dptr");
8561           break;
8562
8563         case CPOINTER:
8564           emitcode ("clr", "a");
8565           emitcode ("inc", "dptr");
8566           emitcode ("movc", "a,@a+dptr");
8567           break;
8568
8569         case GPOINTER:
8570           emitcode ("inc", "dptr");
8571           emitcode ("lcall", "__gptrget");
8572           break;
8573         }
8574
8575       rlen -= 8;
8576       /* if we are done */
8577       if (rlen < 8)
8578         break;
8579
8580       aopPut (AOP (result), "a", offset++);
8581
8582     }
8583
8584   if (rlen)
8585     {
8586       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
8587       aopPut (AOP (result), "a", offset);
8588     }
8589
8590   return;
8591 }
8592
8593
8594 /*-----------------------------------------------------------------*/
8595 /* genDataPointerGet - generates code when ptr offset is known     */
8596 /*-----------------------------------------------------------------*/
8597 static void
8598 genDataPointerGet (operand * left,
8599                    operand * result,
8600                    iCode * ic)
8601 {
8602   char *l;
8603   char buffer[256];
8604   int size, offset = 0;
8605   aopOp (result, ic, TRUE, FALSE);
8606
8607   /* get the string representation of the name */
8608   l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
8609   size = AOP_SIZE (result);
8610   _startLazyDPSEvaluation ();
8611   while (size--)
8612     {
8613       if (offset)
8614         sprintf (buffer, "(%s + %d)", l + 1, offset);
8615       else
8616         sprintf (buffer, "%s", l + 1);
8617       aopPut (AOP (result), buffer, offset++);
8618     }
8619   _endLazyDPSEvaluation ();
8620
8621   freeAsmop (left, NULL, ic, TRUE);
8622   freeAsmop (result, NULL, ic, TRUE);
8623 }
8624
8625 /*-----------------------------------------------------------------*/
8626 /* genNearPointerGet - emitcode for near pointer fetch             */
8627 /*-----------------------------------------------------------------*/
8628 static void
8629 genNearPointerGet (operand * left,
8630                    operand * result,
8631                    iCode * ic,
8632                    iCode *pi)
8633 {
8634   asmop *aop = NULL;
8635   regs *preg = NULL;
8636   char *rname;
8637   sym_link *rtype, *retype, *letype;
8638   sym_link *ltype = operandType (left);
8639   char buffer[80];
8640
8641   rtype = operandType (result);
8642   retype = getSpec (rtype);
8643   letype = getSpec (ltype);
8644
8645   aopOp (left, ic, FALSE, FALSE);
8646
8647   /* if left is rematerialisable and
8648      result is not bit variable type and
8649      the left is pointer to data space i.e
8650      lower 128 bytes of space */
8651   if (AOP_TYPE (left) == AOP_IMMD &&
8652       !IS_BITVAR (retype) &&
8653       !IS_BITVAR (letype) &&
8654       DCL_TYPE (ltype) == POINTER)
8655     {
8656       genDataPointerGet (left, result, ic);
8657       return;
8658     }
8659
8660   /* if the value is already in a pointer register
8661      then don't need anything more */
8662   if (!AOP_INPREG (AOP (left)))
8663     {
8664       /* otherwise get a free pointer register */
8665       aop = newAsmop (0);
8666       preg = getFreePtr (ic, &aop, FALSE);
8667       emitcode ("mov", "%s,%s",
8668                 preg->name,
8669                 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8670       rname = preg->name;
8671     }
8672   else
8673     rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8674
8675   freeAsmop (left, NULL, ic, TRUE);
8676   aopOp (result, ic, FALSE, FALSE);
8677
8678   /* if bitfield then unpack the bits */
8679   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8680     genUnpackBits (result, rname, POINTER);
8681   else
8682     {
8683       /* we have can just get the values */
8684       int size = AOP_SIZE (result);
8685       int offset = 0;
8686
8687       while (size--)
8688         {
8689           if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8690             {
8691
8692               emitcode ("mov", "a,@%s", rname);
8693               aopPut (AOP (result), "a", offset);
8694             }
8695           else
8696             {
8697               sprintf (buffer, "@%s", rname);
8698               aopPut (AOP (result), buffer, offset);
8699             }
8700           offset++;
8701           if (size || pi)
8702             emitcode ("inc", "%s", rname);
8703         }
8704     }
8705
8706   /* now some housekeeping stuff */
8707   if (aop)
8708     {
8709       /* we had to allocate for this iCode */
8710       if (pi) { /* post increment present */
8711         aopPut(AOP ( left ),rname,0);
8712       }
8713       freeAsmop (NULL, aop, ic, TRUE);
8714     }
8715   else
8716     {
8717       /* we did not allocate which means left
8718          already in a pointer register, then
8719          if size > 0 && this could be used again
8720          we have to point it back to where it
8721          belongs */
8722       if (AOP_SIZE (result) > 1 &&
8723           !OP_SYMBOL (left)->remat &&
8724           (OP_SYMBOL (left)->liveTo > ic->seq ||
8725            ic->depth) &&
8726           !pi)
8727         {
8728           int size = AOP_SIZE (result) - 1;
8729           while (size--)
8730             emitcode ("dec", "%s", rname);
8731         }
8732     }
8733
8734   /* done */
8735   freeAsmop (result, NULL, ic, TRUE);
8736   if (pi) pi->generated = 1;
8737 }
8738
8739 /*-----------------------------------------------------------------*/
8740 /* genPagedPointerGet - emitcode for paged pointer fetch           */
8741 /*-----------------------------------------------------------------*/
8742 static void
8743 genPagedPointerGet (operand * left,
8744                     operand * result,
8745                     iCode * ic,
8746                     iCode * pi)
8747 {
8748   asmop *aop = NULL;
8749   regs *preg = NULL;
8750   char *rname;
8751   sym_link *rtype, *retype, *letype;
8752
8753   rtype = operandType (result);
8754   retype = getSpec (rtype);
8755   letype = getSpec (operandType (left));
8756   aopOp (left, ic, FALSE, FALSE);
8757
8758   /* if the value is already in a pointer register
8759      then don't need anything more */
8760   if (!AOP_INPREG (AOP (left)))
8761     {
8762       /* otherwise get a free pointer register */
8763       aop = newAsmop (0);
8764       preg = getFreePtr (ic, &aop, FALSE);
8765       emitcode ("mov", "%s,%s",
8766                 preg->name,
8767                 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8768       rname = preg->name;
8769     }
8770   else
8771     rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8772
8773   freeAsmop (left, NULL, ic, TRUE);
8774   aopOp (result, ic, FALSE, FALSE);
8775
8776   /* if bitfield then unpack the bits */
8777   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8778     genUnpackBits (result, rname, PPOINTER);
8779   else
8780     {
8781       /* we have can just get the values */
8782       int size = AOP_SIZE (result);
8783       int offset = 0;
8784
8785       while (size--)
8786         {
8787
8788           emitcode ("movx", "a,@%s", rname);
8789           aopPut (AOP (result), "a", offset);
8790
8791           offset++;
8792
8793           if (size || pi)
8794             emitcode ("inc", "%s", rname);
8795         }
8796     }
8797
8798   /* now some housekeeping stuff */
8799   if (aop)
8800     {
8801       /* we had to allocate for this iCode */
8802       if (pi) aopPut ( AOP (left), rname, 0);
8803       freeAsmop (NULL, aop, ic, TRUE);
8804     }
8805   else
8806     {
8807       /* we did not allocate which means left
8808          already in a pointer register, then
8809          if size > 0 && this could be used again
8810          we have to point it back to where it
8811          belongs */
8812       if (AOP_SIZE (result) > 1 &&
8813           !OP_SYMBOL (left)->remat &&
8814           (OP_SYMBOL (left)->liveTo > ic->seq ||
8815            ic->depth) &&
8816           !pi)
8817         {
8818           int size = AOP_SIZE (result) - 1;
8819           while (size--)
8820             emitcode ("dec", "%s", rname);
8821         }
8822     }
8823
8824   /* done */
8825   freeAsmop (result, NULL, ic, TRUE);
8826   if (pi) pi->generated = 1;
8827 }
8828
8829 /*-----------------------------------------------------------------*/
8830 /* genFarPointerGet - gget value from far space                    */
8831 /*-----------------------------------------------------------------*/
8832 static void
8833 genFarPointerGet (operand * left,
8834                   operand * result, iCode * ic, iCode *pi)
8835 {
8836   int size, offset;
8837   sym_link *retype = getSpec (operandType (result));
8838   sym_link *letype = getSpec (operandType (left));
8839   D (emitcode (";", "genFarPointerGet");
8840     );
8841
8842   aopOp (left, ic, FALSE, FALSE);
8843
8844   /* if the operand is already in dptr
8845      then we do nothing else we move the value to dptr */
8846   if (AOP_TYPE (left) != AOP_STR)
8847     {
8848       /* if this is remateriazable */
8849       if (AOP_TYPE (left) == AOP_IMMD)
8850         {
8851           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8852         }
8853       else
8854         {
8855           /* we need to get it byte by byte */
8856           _startLazyDPSEvaluation ();
8857           if (AOP_TYPE (left) != AOP_DPTR)
8858             {
8859               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8860               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8861               if (options.model == MODEL_FLAT24)
8862                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8863             }
8864           else
8865             {
8866               /* We need to generate a load to DPTR indirect through DPTR. */
8867               D (emitcode (";", "genFarPointerGet -- indirection special case.");
8868                 );
8869               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8870               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8871               if (options.model == MODEL_FLAT24)
8872                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8873               emitcode ("pop", "dph");
8874               emitcode ("pop", "dpl");
8875             }
8876           _endLazyDPSEvaluation ();
8877         }
8878     }
8879   /* so dptr know contains the address */
8880   aopOp (result, ic, FALSE, TRUE);
8881
8882   /* if bit then unpack */
8883   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8884     genUnpackBits (result, "dptr", FPOINTER);
8885   else
8886     {
8887       size = AOP_SIZE (result);
8888       offset = 0;
8889
8890       _startLazyDPSEvaluation ();
8891       while (size--)
8892         {
8893
8894           genSetDPTR (0);
8895           _flushLazyDPS ();
8896
8897           emitcode ("movx", "a,@dptr");
8898           if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
8899             emitcode ("inc", "dptr");
8900
8901           aopPut (AOP (result), "a", offset++);
8902         }
8903       _endLazyDPSEvaluation ();
8904     }
8905   if (pi && AOP_TYPE (left) != AOP_IMMD) {
8906     aopPut ( AOP (left), "dpl", 0);
8907     aopPut ( AOP (left), "dph", 1);
8908     if (options.model == MODEL_FLAT24)
8909             aopPut ( AOP (left), "dpx", 2);
8910     pi->generated = 1;
8911   } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
8912              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
8913       
8914       size = AOP_SIZE (result) - 1;
8915       while (size--) emitcode ("lcall","__decdptr");
8916   }
8917
8918   freeAsmop (left, NULL, ic, TRUE);
8919   freeAsmop (result, NULL, ic, TRUE);
8920 }
8921
8922 /*-----------------------------------------------------------------*/
8923 /* emitcodePointerGet - gget value from code space                  */
8924 /*-----------------------------------------------------------------*/
8925 static void
8926 emitcodePointerGet (operand * left,
8927                     operand * result, iCode * ic, iCode *pi)
8928 {
8929   int size, offset;
8930   sym_link *retype = getSpec (operandType (result));
8931
8932   aopOp (left, ic, FALSE, FALSE);
8933
8934   /* if the operand is already in dptr
8935      then we do nothing else we move the value to dptr */
8936   if (AOP_TYPE (left) != AOP_STR)
8937     {
8938       /* if this is remateriazable */
8939       if (AOP_TYPE (left) == AOP_IMMD)
8940         {
8941           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8942         }
8943       else
8944         {                       /* we need to get it byte by byte */
8945           _startLazyDPSEvaluation ();
8946           if (AOP_TYPE (left) != AOP_DPTR)
8947             {
8948               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8949               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8950               if (options.model == MODEL_FLAT24)
8951                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8952             }
8953           else
8954             {
8955               /* We need to generate a load to DPTR indirect through DPTR. */
8956               D (emitcode (";", "gencodePointerGet -- indirection special case.");
8957                 );
8958               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8959               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8960               if (options.model == MODEL_FLAT24)
8961                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8962               emitcode ("pop", "dph");
8963               emitcode ("pop", "dpl");
8964             }
8965           _endLazyDPSEvaluation ();
8966         }
8967     }
8968   /* so dptr know contains the address */
8969   aopOp (result, ic, FALSE, TRUE);
8970
8971   /* if bit then unpack */
8972   if (IS_BITVAR (retype))
8973     genUnpackBits (result, "dptr", CPOINTER);
8974   else
8975     {
8976       size = AOP_SIZE (result);
8977       offset = 0;
8978
8979       _startLazyDPSEvaluation ();
8980       while (size--)
8981         {
8982           genSetDPTR (0);
8983           _flushLazyDPS ();
8984
8985           emitcode ("clr", "a");
8986           emitcode ("movc", "a,@a+dptr");
8987           if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
8988             emitcode ("inc", "dptr");
8989           aopPut (AOP (result), "a", offset++);
8990         }
8991       _endLazyDPSEvaluation ();
8992     }
8993   if (pi && AOP_TYPE (left) != AOP_IMMD) {
8994       aopPut ( AOP (left), "dpl", 0);
8995       aopPut ( AOP (left), "dph", 1);
8996       if (options.model == MODEL_FLAT24)
8997           aopPut ( AOP (left), "dpx", 2);
8998       pi->generated = 1;
8999   } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9000              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9001       
9002       size = AOP_SIZE (result) - 1;
9003       while (size--) emitcode ("lcall","__decdptr");
9004   }
9005   
9006   freeAsmop (left, NULL, ic, TRUE);
9007   freeAsmop (result, NULL, ic, TRUE);
9008 }
9009
9010 /*-----------------------------------------------------------------*/
9011 /* genGenPointerGet - gget value from generic pointer space        */
9012 /*-----------------------------------------------------------------*/
9013 static void
9014 genGenPointerGet (operand * left,
9015                   operand * result, iCode * ic, iCode * pi)
9016 {
9017   int size, offset;
9018   sym_link *retype = getSpec (operandType (result));
9019   sym_link *letype = getSpec (operandType (left));
9020
9021   D (emitcode (";", "genGenPointerGet "); );
9022
9023   aopOp (left, ic, FALSE, (OP_SYMBOL(left)->ruonly ? FALSE : TRUE));
9024
9025   /* if the operand is already in dptr
9026      then we do nothing else we move the value to dptr */
9027   if (AOP_TYPE (left) != AOP_STR)
9028     {
9029       /* if this is remateriazable */
9030       if (AOP_TYPE (left) == AOP_IMMD)
9031         {
9032           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9033           if (AOP(left)->aopu.aop_immd.from_cast_remat) 
9034                   emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, FALSE));
9035           else
9036                   emitcode ("mov", "b,#%d", pointerCode (retype));
9037         }
9038       else
9039         {                       /* we need to get it byte by byte */
9040           _startLazyDPSEvaluation ();
9041           if (AOP(left)->type==AOP_DPTR2) {
9042             char *l;
9043             l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
9044             genSetDPTR(0);
9045             _flushLazyDPS();
9046             emitcode ("mov", "dpl,%s", l);
9047             l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
9048             genSetDPTR(0);
9049             _flushLazyDPS();
9050             emitcode ("mov", "dph,%s", l);
9051             if (options.model == MODEL_FLAT24) {
9052               l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
9053               genSetDPTR(0);
9054               _flushLazyDPS();
9055               emitcode ("mov", "dpx,%s", l);
9056               emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
9057             } else {
9058               emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9059             }
9060           } else {
9061             emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
9062             emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
9063             if (options.model == MODEL_FLAT24) {
9064               emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9065               emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
9066             } else {
9067               emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9068             }
9069           }
9070           _endLazyDPSEvaluation ();
9071         }
9072     }
9073   /* so dptr know contains the address */
9074   aopOp (result, ic, FALSE, TRUE);
9075
9076   /* if bit then unpack */
9077   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9078     genUnpackBits (result, "dptr", GPOINTER);
9079   else
9080     {
9081       size = AOP_SIZE (result);
9082       offset = 0;
9083
9084       while (size--)
9085         {
9086           emitcode ("lcall", "__gptrget");
9087           aopPut (AOP (result), "a", offset++);
9088           if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9089             emitcode ("inc", "dptr");
9090         }
9091     }
9092
9093   if (pi && AOP_TYPE (left) != AOP_IMMD) {
9094     aopPut ( AOP (left), "dpl", 0);
9095     aopPut ( AOP (left), "dph", 1);
9096     if (options.model == MODEL_FLAT24) {
9097         aopPut ( AOP (left), "dpx", 2);
9098         aopPut ( AOP (left), "b", 3);   
9099     } else  aopPut ( AOP (left), "b", 2);       
9100     pi->generated = 1;
9101   } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9102              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9103       
9104       size = AOP_SIZE (result) - 1;
9105       while (size--) emitcode ("lcall","__decdptr");
9106   }
9107
9108   freeAsmop (left, NULL, ic, TRUE);
9109   freeAsmop (result, NULL, ic, TRUE);
9110 }
9111
9112 /*-----------------------------------------------------------------*/
9113 /* genPointerGet - generate code for pointer get                   */
9114 /*-----------------------------------------------------------------*/
9115 static void
9116 genPointerGet (iCode * ic, iCode *pi)
9117 {
9118   operand *left, *result;
9119   sym_link *type, *etype;
9120   int p_type;
9121
9122   D (emitcode (";", "genPointerGet ");
9123     );
9124
9125   left = IC_LEFT (ic);
9126   result = IC_RESULT (ic);
9127
9128   /* depending on the type of pointer we need to
9129      move it to the correct pointer register */
9130   type = operandType (left);
9131   etype = getSpec (type);
9132   /* if left is of type of pointer then it is simple */
9133   if (IS_PTR (type) && !IS_FUNC (type->next))
9134     p_type = DCL_TYPE (type);
9135   else
9136     {
9137       /* we have to go by the storage class */
9138       p_type = PTR_TYPE (SPEC_OCLS (etype));
9139     }
9140   /* special case when cast remat */
9141   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9142       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9143           left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9144           type =   type = operandType (left);
9145           p_type = DCL_TYPE (type);
9146   }
9147   /* now that we have the pointer type we assign
9148      the pointer values */
9149   switch (p_type)
9150     {
9151
9152     case POINTER:
9153     case IPOINTER:
9154       genNearPointerGet (left, result, ic, pi);
9155       break;
9156
9157     case PPOINTER:
9158       genPagedPointerGet (left, result, ic, pi);
9159       break;
9160
9161     case FPOINTER:
9162       genFarPointerGet (left, result, ic, pi);
9163       break;
9164
9165     case CPOINTER:
9166       emitcodePointerGet (left, result, ic, pi);
9167       break;
9168
9169     case GPOINTER:
9170       genGenPointerGet (left, result, ic, pi);
9171       break;
9172     }
9173
9174 }
9175
9176 /*-----------------------------------------------------------------*/
9177 /* genPackBits - generates code for packed bit storage             */
9178 /*-----------------------------------------------------------------*/
9179 static void
9180 genPackBits (sym_link * etype,
9181              operand * right,
9182              char *rname, int p_type)
9183 {
9184   int shCount = 0;
9185   int offset = 0;
9186   int rLen = 0;
9187   int blen, bstr;
9188   char *l;
9189
9190   blen = SPEC_BLEN (etype);
9191   bstr = SPEC_BSTR (etype);
9192
9193   l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9194   MOVA (l);
9195
9196   /* if the bit lenth is less than or    */
9197   /* it exactly fits a byte then         */
9198   if (SPEC_BLEN (etype) <= 8)
9199     {
9200       shCount = SPEC_BSTR (etype);
9201
9202       /* shift left acc */
9203       AccLsh (shCount);
9204
9205       if (SPEC_BLEN (etype) < 8)
9206         {                       /* if smaller than a byte */
9207
9208
9209           switch (p_type)
9210             {
9211             case POINTER:
9212               emitcode ("mov", "b,a");
9213               emitcode ("mov", "a,@%s", rname);
9214               break;
9215
9216             case FPOINTER:
9217               emitcode ("mov", "b,a");
9218               emitcode ("movx", "a,@dptr");
9219               break;
9220
9221             case GPOINTER:
9222               emitcode ("push", "b");
9223               emitcode ("push", "acc");
9224               emitcode ("lcall", "__gptrget");
9225               emitcode ("pop", "b");
9226               break;
9227             }
9228
9229           emitcode ("anl", "a,#0x%02x", (unsigned char)
9230                     ((unsigned char) (0xFF << (blen + bstr)) |
9231                      (unsigned char) (0xFF >> (8 - bstr))));
9232           emitcode ("orl", "a,b");
9233           if (p_type == GPOINTER)
9234             emitcode ("pop", "b");
9235         }
9236     }
9237
9238   switch (p_type)
9239     {
9240     case POINTER:
9241       emitcode ("mov", "@%s,a", rname);
9242       break;
9243
9244     case FPOINTER:
9245       emitcode ("movx", "@dptr,a");
9246       break;
9247
9248     case GPOINTER:
9249       emitcode ("lcall", "__gptrput");
9250       break;
9251     }
9252
9253   /* if we r done */
9254   if (SPEC_BLEN (etype) <= 8)
9255     return;
9256
9257   emitcode ("inc", "%s", rname);
9258   rLen = SPEC_BLEN (etype);
9259
9260   /* now generate for lengths greater than one byte */
9261   while (1)
9262     {
9263
9264       l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
9265
9266       rLen -= 8;
9267       if (rLen < 8)
9268         break;
9269
9270       switch (p_type)
9271         {
9272         case POINTER:
9273           if (*l == '@')
9274             {
9275               MOVA (l);
9276               emitcode ("mov", "@%s,a", rname);
9277             }
9278           else
9279             emitcode ("mov", "@%s,%s", rname, l);
9280           break;
9281
9282         case FPOINTER:
9283           MOVA (l);
9284           emitcode ("movx", "@dptr,a");
9285           break;
9286
9287         case GPOINTER:
9288           MOVA (l);
9289           emitcode ("lcall", "__gptrput");
9290           break;
9291         }
9292       emitcode ("inc", "%s", rname);
9293     }
9294
9295   MOVA (l);
9296
9297   /* last last was not complete */
9298   if (rLen)
9299     {
9300       /* save the byte & read byte */
9301       switch (p_type)
9302         {
9303         case POINTER:
9304           emitcode ("mov", "b,a");
9305           emitcode ("mov", "a,@%s", rname);
9306           break;
9307
9308         case FPOINTER:
9309           emitcode ("mov", "b,a");
9310           emitcode ("movx", "a,@dptr");
9311           break;
9312
9313         case GPOINTER:
9314           emitcode ("push", "b");
9315           emitcode ("push", "acc");
9316           emitcode ("lcall", "__gptrget");
9317           emitcode ("pop", "b");
9318           break;
9319         }
9320
9321       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
9322       emitcode ("orl", "a,b");
9323     }
9324
9325   if (p_type == GPOINTER)
9326     emitcode ("pop", "b");
9327
9328   switch (p_type)
9329     {
9330
9331     case POINTER:
9332       emitcode ("mov", "@%s,a", rname);
9333       break;
9334
9335     case FPOINTER:
9336       emitcode ("movx", "@dptr,a");
9337       break;
9338
9339     case GPOINTER:
9340       emitcode ("lcall", "__gptrput");
9341       break;
9342     }
9343 }
9344 /*-----------------------------------------------------------------*/
9345 /* genDataPointerSet - remat pointer to data space                 */
9346 /*-----------------------------------------------------------------*/
9347 static void
9348 genDataPointerSet (operand * right,
9349                    operand * result,
9350                    iCode * ic)
9351 {
9352   int size, offset = 0;
9353   char *l, buffer[256];
9354
9355   aopOp (right, ic, FALSE, FALSE);
9356
9357   l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
9358   size = AOP_SIZE (right);
9359   while (size--)
9360     {
9361       if (offset)
9362         sprintf (buffer, "(%s + %d)", l + 1, offset);
9363       else
9364         sprintf (buffer, "%s", l + 1);
9365       emitcode ("mov", "%s,%s", buffer,
9366                 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
9367     }
9368
9369   freeAsmop (right, NULL, ic, TRUE);
9370   freeAsmop (result, NULL, ic, TRUE);
9371 }
9372
9373 /*-----------------------------------------------------------------*/
9374 /* genNearPointerSet - emitcode for near pointer put                */
9375 /*-----------------------------------------------------------------*/
9376 static void
9377 genNearPointerSet (operand * right,
9378                    operand * result,
9379                    iCode * ic,
9380                    iCode * pi)
9381 {
9382   asmop *aop = NULL;
9383   regs *preg = NULL;
9384   char *rname, *l;
9385   sym_link *retype, *letype;
9386   sym_link *ptype = operandType (result);
9387
9388   retype = getSpec (operandType (right));
9389   letype = getSpec (ptype);
9390
9391   aopOp (result, ic, FALSE, FALSE);
9392
9393   /* if the result is rematerializable &
9394      in data space & not a bit variable */
9395   if (AOP_TYPE (result) == AOP_IMMD &&
9396       DCL_TYPE (ptype) == POINTER &&
9397       !IS_BITVAR (retype) &&
9398       !IS_BITVAR (letype))
9399     {
9400       genDataPointerSet (right, result, ic);
9401       return;
9402     }
9403
9404   /* if the value is already in a pointer register
9405      then don't need anything more */
9406   if (!AOP_INPREG (AOP (result)))
9407     {
9408       /* otherwise get a free pointer register */
9409       aop = newAsmop (0);
9410       preg = getFreePtr (ic, &aop, FALSE);
9411       emitcode ("mov", "%s,%s",
9412                 preg->name,
9413                 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9414       rname = preg->name;
9415     }
9416   else
9417     rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9418
9419   aopOp (right, ic, FALSE, FALSE);
9420
9421   /* if bitfield then unpack the bits */
9422   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9423     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
9424   else
9425     {
9426       /* we have can just get the values */
9427       int size = AOP_SIZE (right);
9428       int offset = 0;
9429
9430       while (size--)
9431         {
9432           l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
9433           if (*l == '@')
9434             {
9435               MOVA (l);
9436               emitcode ("mov", "@%s,a", rname);
9437             }
9438           else
9439             emitcode ("mov", "@%s,%s", rname, l);
9440           if (size || pi)
9441             emitcode ("inc", "%s", rname);
9442           offset++;
9443         }
9444     }
9445
9446   /* now some housekeeping stuff */
9447   if (aop)
9448     {
9449       /* we had to allocate for this iCode */
9450       if (pi) aopPut (AOP (result),rname,0);
9451       freeAsmop (NULL, aop, ic, TRUE);
9452     }
9453   else
9454     {
9455       /* we did not allocate which means left
9456          already in a pointer register, then
9457          if size > 0 && this could be used again
9458          we have to point it back to where it
9459          belongs */
9460       if (AOP_SIZE (right) > 1 &&
9461           !OP_SYMBOL (result)->remat &&
9462           (OP_SYMBOL (result)->liveTo > ic->seq ||
9463            ic->depth) &&
9464           !pi)
9465         {
9466           int size = AOP_SIZE (right) - 1;
9467           while (size--)
9468             emitcode ("dec", "%s", rname);
9469         }
9470     }
9471
9472   /* done */
9473   if (pi) pi->generated = 1;
9474   freeAsmop (result, NULL, ic, TRUE);
9475   freeAsmop (right, NULL, ic, TRUE);
9476
9477
9478 }
9479
9480 /*-----------------------------------------------------------------*/
9481 /* genPagedPointerSet - emitcode for Paged pointer put             */
9482 /*-----------------------------------------------------------------*/
9483 static void
9484 genPagedPointerSet (operand * right,
9485                     operand * result,
9486                     iCode * ic,
9487                     iCode *pi)
9488 {
9489   asmop *aop = NULL;
9490   regs *preg = NULL;
9491   char *rname, *l;
9492   sym_link *retype, *letype;
9493
9494   retype = getSpec (operandType (right));
9495   letype = getSpec (operandType (result));
9496
9497   aopOp (result, ic, FALSE, FALSE);
9498
9499   /* if the value is already in a pointer register
9500      then don't need anything more */
9501   if (!AOP_INPREG (AOP (result)))
9502     {
9503       /* otherwise get a free pointer register */
9504       aop = newAsmop (0);
9505       preg = getFreePtr (ic, &aop, FALSE);
9506       emitcode ("mov", "%s,%s",
9507                 preg->name,
9508                 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9509       rname = preg->name;
9510     }
9511   else
9512     rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9513
9514   aopOp (right, ic, FALSE, FALSE);
9515
9516   /* if bitfield then unpack the bits */
9517   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9518     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
9519   else
9520     {
9521       /* we have can just get the values */
9522       int size = AOP_SIZE (right);
9523       int offset = 0;
9524
9525       while (size--)
9526         {
9527           l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
9528
9529           MOVA (l);
9530           emitcode ("movx", "@%s,a", rname);
9531
9532           if (size || pi)
9533             emitcode ("inc", "%s", rname);
9534
9535           offset++;
9536         }
9537     }
9538
9539   /* now some housekeeping stuff */
9540   if (aop)
9541     {
9542       if (pi) aopPut (AOP (result),rname,0);
9543       /* we had to allocate for this iCode */
9544       freeAsmop (NULL, aop, ic, TRUE);
9545     }
9546   else
9547     {
9548       /* we did not allocate which means left
9549          already in a pointer register, then
9550          if size > 0 && this could be used again
9551          we have to point it back to where it
9552          belongs */
9553       if (AOP_SIZE (right) > 1 &&
9554           !OP_SYMBOL (result)->remat &&
9555           (OP_SYMBOL (result)->liveTo > ic->seq ||
9556            ic->depth) &&
9557           !pi)
9558         {
9559           int size = AOP_SIZE (right) - 1;
9560           while (size--)
9561             emitcode ("dec", "%s", rname);
9562         }
9563     }
9564
9565   /* done */
9566   if (pi) pi->generated = 1;
9567   freeAsmop (result, NULL, ic, TRUE);
9568   freeAsmop (right, NULL, ic, TRUE);
9569
9570
9571 }
9572
9573 /*-----------------------------------------------------------------*/
9574 /* genFarPointerSet - set value from far space                     */
9575 /*-----------------------------------------------------------------*/
9576 static void
9577 genFarPointerSet (operand * right,
9578                   operand * result, iCode * ic, iCode *pi)
9579 {
9580   int size, offset;
9581   sym_link *retype = getSpec (operandType (right));
9582   sym_link *letype = getSpec (operandType (result));
9583
9584   aopOp (result, ic, FALSE, FALSE);
9585
9586   /* if the operand is already in dptr
9587      then we do nothing else we move the value to dptr */
9588   if (AOP_TYPE (result) != AOP_STR)
9589     {
9590       /* if this is remateriazable */
9591       if (AOP_TYPE (result) == AOP_IMMD)
9592         emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9593       else
9594         {
9595           /* we need to get it byte by byte */
9596           _startLazyDPSEvaluation ();
9597           if (AOP_TYPE (result) != AOP_DPTR)
9598             {
9599               emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9600               emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9601               if (options.model == MODEL_FLAT24)
9602                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9603             }
9604           else
9605             {
9606               /* We need to generate a load to DPTR indirect through DPTR. */
9607               D (emitcode (";", "genFarPointerSet -- indirection special case.");
9608                 );
9609               emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
9610               emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
9611               if (options.model == MODEL_FLAT24)
9612                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9613               emitcode ("pop", "dph");
9614               emitcode ("pop", "dpl");
9615             }
9616           _endLazyDPSEvaluation ();
9617         }
9618     }
9619   /* so dptr know contains the address */
9620   aopOp (right, ic, FALSE, TRUE);
9621
9622   /* if bit then unpack */
9623   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9624     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
9625   else
9626     {
9627       size = AOP_SIZE (right);
9628       offset = 0;
9629
9630       _startLazyDPSEvaluation ();
9631       while (size--)
9632         {
9633           char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9634           MOVA (l);
9635
9636           genSetDPTR (0);
9637           _flushLazyDPS ();
9638
9639           emitcode ("movx", "@dptr,a");
9640           if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
9641             emitcode ("inc", "dptr");
9642         }
9643       _endLazyDPSEvaluation ();
9644     }
9645
9646   if (pi && AOP_TYPE (result) != AOP_IMMD) {
9647       aopPut (AOP(result),"dpl",0);
9648       aopPut (AOP(result),"dph",1);
9649       if (options.model == MODEL_FLAT24)
9650           aopPut (AOP(result),"dpx",2);
9651       pi->generated=1;
9652   } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
9653              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
9654       
9655       size = AOP_SIZE (right) - 1;
9656       while (size--) emitcode ("lcall","__decdptr");
9657   }
9658   freeAsmop (result, NULL, ic, TRUE);
9659   freeAsmop (right, NULL, ic, TRUE);
9660 }
9661
9662 /*-----------------------------------------------------------------*/
9663 /* genGenPointerSet - set value from generic pointer space         */
9664 /*-----------------------------------------------------------------*/
9665 static void
9666 genGenPointerSet (operand * right,
9667                   operand * result, iCode * ic, iCode *pi)
9668 {
9669   int size, offset;
9670   sym_link *retype = getSpec (operandType (right));
9671   sym_link *letype = getSpec (operandType (result));
9672
9673   aopOp (result, ic, FALSE, OP_SYMBOL(result)->ruonly ? FALSE : TRUE);
9674
9675   /* if the operand is already in dptr
9676      then we do nothing else we move the value to dptr */
9677   if (AOP_TYPE (result) != AOP_STR)
9678     {
9679       _startLazyDPSEvaluation ();
9680       /* if this is remateriazable */
9681       if (AOP_TYPE (result) == AOP_IMMD)
9682         {
9683           emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9684           if (AOP(result)->aopu.aop_immd.from_cast_remat) 
9685                   emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, FALSE));
9686           else
9687                   emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9688         }
9689       else
9690         {                       /* we need to get it byte by byte */
9691           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9692           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9693           if (options.model == MODEL_FLAT24) {
9694             emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9695             emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
9696           } else {
9697             emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9698           }
9699         }
9700       _endLazyDPSEvaluation ();
9701     }
9702   /* so dptr know contains the address */
9703   aopOp (right, ic, FALSE, TRUE);
9704
9705   /* if bit then unpack */
9706   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9707     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
9708   else
9709     {
9710       size = AOP_SIZE (right);
9711       offset = 0;
9712
9713       _startLazyDPSEvaluation ();
9714       while (size--)
9715         {
9716           char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9717           MOVA (l);
9718
9719           genSetDPTR (0);
9720           _flushLazyDPS ();
9721
9722           emitcode ("lcall", "__gptrput");
9723           if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
9724             emitcode ("inc", "dptr");
9725         }
9726       _endLazyDPSEvaluation ();
9727     }
9728
9729   if (pi && AOP_TYPE (result) != AOP_IMMD) {
9730       aopPut (AOP(result),"dpl",0);
9731       aopPut (AOP(result),"dph",1);
9732       if (options.model == MODEL_FLAT24) {
9733           aopPut (AOP(result),"dpx",2);
9734           aopPut (AOP(result),"b",3);
9735       } else {
9736           aopPut (AOP(result),"b",2);
9737       }
9738       pi->generated=1;
9739   } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
9740              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
9741       
9742       size = AOP_SIZE (right) - 1;
9743       while (size--) emitcode ("lcall","__decdptr");
9744   }
9745   freeAsmop (result, NULL, ic, TRUE);
9746   freeAsmop (right, NULL, ic, TRUE);
9747 }
9748
9749 /*-----------------------------------------------------------------*/
9750 /* genPointerSet - stores the value into a pointer location        */
9751 /*-----------------------------------------------------------------*/
9752 static void
9753 genPointerSet (iCode * ic, iCode *pi)
9754 {
9755   operand *right, *result;
9756   sym_link *type, *etype;
9757   int p_type;
9758
9759   D (emitcode (";", "genPointerSet ");
9760     );
9761
9762   right = IC_RIGHT (ic);
9763   result = IC_RESULT (ic);
9764
9765   /* depending on the type of pointer we need to
9766      move it to the correct pointer register */
9767   type = operandType (result);
9768   etype = getSpec (type);
9769   /* if left is of type of pointer then it is simple */
9770   if (IS_PTR (type) && !IS_FUNC (type->next))
9771     {
9772       p_type = DCL_TYPE (type);
9773     }
9774   else
9775     {
9776       /* we have to go by the storage class */
9777       p_type = PTR_TYPE (SPEC_OCLS (etype));
9778     }
9779   /* special case when cast remat */
9780   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
9781       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
9782           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
9783           type =   type = operandType (result);
9784           p_type = DCL_TYPE (type);
9785   }
9786
9787   /* now that we have the pointer type we assign
9788      the pointer values */
9789   switch (p_type)
9790     {
9791
9792     case POINTER:
9793     case IPOINTER:
9794       genNearPointerSet (right, result, ic, pi);
9795       break;
9796
9797     case PPOINTER:
9798       genPagedPointerSet (right, result, ic, pi);
9799       break;
9800
9801     case FPOINTER:
9802       genFarPointerSet (right, result, ic, pi);
9803       break;
9804
9805     case GPOINTER:
9806       genGenPointerSet (right, result, ic, pi);
9807       break;
9808     }
9809
9810 }
9811
9812 /*-----------------------------------------------------------------*/
9813 /* genIfx - generate code for Ifx statement                        */
9814 /*-----------------------------------------------------------------*/
9815 static void
9816 genIfx (iCode * ic, iCode * popIc)
9817 {
9818   operand *cond = IC_COND (ic);
9819   int isbit = 0;
9820
9821   D (emitcode (";", "genIfx "););
9822
9823   aopOp (cond, ic, FALSE, FALSE);
9824
9825   /* get the value into acc */
9826   if (AOP_TYPE (cond) != AOP_CRY)
9827     toBoolean (cond);
9828   else
9829     isbit = 1;
9830   /* the result is now in the accumulator */
9831   freeAsmop (cond, NULL, ic, TRUE);
9832
9833   /* if there was something to be popped then do it */
9834   if (popIc)
9835     genIpop (popIc);
9836
9837   /* if the condition is  a bit variable */
9838   if (isbit && IS_ITEMP (cond) &&
9839       SPIL_LOC (cond))
9840     genIfxJump (ic, SPIL_LOC (cond)->rname);
9841   else if (isbit && !IS_ITEMP (cond))
9842     genIfxJump (ic, OP_SYMBOL (cond)->rname);
9843   else
9844     genIfxJump (ic, "a");
9845
9846   ic->generated = 1;
9847 }
9848
9849 /*-----------------------------------------------------------------*/
9850 /* genAddrOf - generates code for address of                       */
9851 /*-----------------------------------------------------------------*/
9852 static void
9853 genAddrOf (iCode * ic)
9854 {
9855   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
9856   int size, offset;
9857
9858   D (emitcode (";", "genAddrOf ");
9859     );
9860
9861   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9862
9863   /* if the operand is on the stack then we
9864      need to get the stack offset of this
9865      variable */
9866   if (sym->onStack) {
9867       
9868       /* if 10 bit stack */
9869       if (options.stack10bit) {
9870           /* if it has an offset then we need to compute it */
9871           if (sym->stack) {
9872               emitcode ("mov", "a,_bpx");
9873               emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
9874               emitcode ("mov", "b,a");
9875               emitcode ("mov", "a,_bpx+1");
9876               emitcode ("addc","a,#0x%02x", (((short) sym->stack) >> 8) & 0xff);
9877               aopPut (AOP (IC_RESULT (ic)), "b", 0);
9878               aopPut (AOP (IC_RESULT (ic)), "a", 1);
9879               aopPut (AOP (IC_RESULT (ic)), "#0x40", 2);
9880           } else {
9881               /* we can just move _bp */
9882               aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
9883               aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
9884               aopPut (AOP (IC_RESULT (ic)), "#0x40", 2);
9885           }       
9886       } else {
9887           /* if it has an offset then we need to compute it */
9888           if (sym->stack) {
9889               emitcode ("mov", "a,_bp");
9890               emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
9891               aopPut (AOP (IC_RESULT (ic)), "a", 0);
9892           } else {
9893               /* we can just move _bp */
9894               aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
9895           }
9896           /* fill the result with zero */
9897           size = AOP_SIZE (IC_RESULT (ic)) - 1;
9898           
9899           
9900           if (options.stack10bit && size < (FPTRSIZE - 1)) {
9901               fprintf (stderr,
9902                        "*** warning: pointer to stack var truncated.\n");
9903           }
9904
9905           offset = 1;
9906           while (size--) {
9907               aopPut (AOP (IC_RESULT (ic)), zero, offset++);
9908           }      
9909       }
9910       goto release;
9911   }
9912
9913   /* object not on stack then we need the name */
9914   size = AOP_SIZE (IC_RESULT (ic));
9915   offset = 0;
9916
9917   while (size--)
9918     {
9919       char s[SDCC_NAME_MAX];
9920       if (offset)
9921         sprintf (s, "#(%s >> %d)",
9922                  sym->rname,
9923                  offset * 8);
9924       else
9925         sprintf (s, "#%s", sym->rname);
9926       aopPut (AOP (IC_RESULT (ic)), s, offset++);
9927     }
9928
9929 release:
9930   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9931
9932 }
9933
9934 /*-----------------------------------------------------------------*/
9935 /* genArrayInit - generates code for address of                       */
9936 /*-----------------------------------------------------------------*/
9937 static void
9938 genArrayInit (iCode * ic)
9939 {
9940     literalList *iLoop;
9941     int         ix, count;
9942     int         elementSize = 0, eIndex;
9943     unsigned    val, lastVal;
9944     sym_link    *type;
9945     operand     *left=IC_LEFT(ic);
9946     
9947     D (emitcode (";", "genArrayInit "););
9948
9949     aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
9950     
9951     if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
9952     {
9953         // Load immediate value into DPTR.
9954         emitcode("mov", "dptr, %s",
9955              aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, TRUE));
9956     }
9957     else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
9958     {
9959 #if 0
9960       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9961               "Unexpected operand to genArrayInit.\n");
9962       exit(1);
9963 #else
9964       // a regression because of SDCCcse.c:1.52
9965       emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9966       emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9967       if (options.model == MODEL_FLAT24)
9968         emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9969 #endif
9970     }
9971     
9972     type = operandType(IC_LEFT(ic));
9973     
9974     if (type && type->next)
9975     {
9976         elementSize = getSize(type->next);
9977     }
9978     else
9979     {
9980         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9981                                 "can't determine element size in genArrayInit.\n");
9982         exit(1);
9983     }
9984     
9985     iLoop = IC_ARRAYILIST(ic);
9986     lastVal = 0xffff;
9987     
9988     while (iLoop)
9989     {
9990         bool firstpass = TRUE;
9991         
9992         emitcode(";", "store %d x 0x%x to DPTR (element size %d)", 
9993                  iLoop->count, (int)iLoop->literalValue, elementSize);
9994         
9995         ix = iLoop->count;
9996         
9997         while (ix)
9998         {
9999             symbol *tlbl = NULL;
10000             
10001             count = ix > 256 ? 256 : ix;
10002             
10003             if (count > 1)
10004             {
10005                 tlbl = newiTempLabel (NULL);
10006                 if (firstpass || (count & 0xff))
10007                 {
10008                     emitcode("mov", "b, #0x%x", count & 0xff);
10009                 }
10010                 
10011                 emitcode ("", "%05d$:", tlbl->key + 100);
10012             }
10013             
10014             firstpass = FALSE;
10015                 
10016             for (eIndex = 0; eIndex < elementSize; eIndex++)
10017             {
10018                 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10019                 if (val != lastVal)
10020                 {
10021                     emitcode("mov", "a, #0x%x", val);
10022                     lastVal = val;
10023                 }
10024                 
10025                 emitcode("movx", "@dptr, a");
10026                 emitcode("inc", "dptr");
10027             }
10028             
10029             if (count > 1)
10030             {
10031                 emitcode("djnz", "b, %05d$", tlbl->key + 100);
10032             }
10033             
10034             ix -= count;
10035         }
10036         
10037         iLoop = iLoop->next;
10038     }
10039     
10040     freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10041 }
10042
10043 /*-----------------------------------------------------------------*/
10044 /* genFarFarAssign - assignment when both are in far space         */
10045 /*-----------------------------------------------------------------*/
10046 static void
10047 genFarFarAssign (operand * result, operand * right, iCode * ic)
10048 {
10049   int size = AOP_SIZE (right);
10050   int offset = 0;
10051   symbol *rSym = NULL;
10052
10053   if (size == 1)
10054   {
10055       /* quick & easy case. */
10056       D(emitcode(";","genFarFarAssign (1 byte case)"););      
10057       MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
10058       freeAsmop (right, NULL, ic, FALSE);
10059       /* now assign DPTR to result */
10060       _G.accInUse++;
10061       aopOp(result, ic, FALSE, FALSE);
10062       _G.accInUse--;
10063       aopPut(AOP(result), "a", 0);
10064       freeAsmop(result, NULL, ic, FALSE);
10065       return;
10066   }
10067   
10068   /* See if we've got an underlying symbol to abuse. */
10069   if (IS_SYMOP(result) && OP_SYMBOL(result))
10070   {
10071       if (IS_TRUE_SYMOP(result))
10072       {
10073           rSym = OP_SYMBOL(result);
10074       }
10075       else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10076       {
10077           rSym = OP_SYMBOL(result)->usl.spillLoc;
10078       }
10079   }
10080              
10081   if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10082   {
10083       /* We can use the '390 auto-toggle feature to good effect here. */
10084       
10085       D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10086       emitcode("mov", "dps, #0x21");    /* Select DPTR2 & auto-toggle. */
10087       emitcode ("mov", "dptr,#%s", rSym->rname); 
10088       /* DP2 = result, DP1 = right, DP1 is current. */
10089       while (size)
10090       {
10091           emitcode("movx", "a,@dptr");
10092           emitcode("movx", "@dptr,a");
10093           if (--size)
10094           {
10095                emitcode("inc", "dptr");
10096                emitcode("inc", "dptr");
10097           }
10098       }
10099       emitcode("mov", "dps, #0");
10100       freeAsmop (right, NULL, ic, FALSE);
10101 #if 0
10102 some alternative code for processors without auto-toggle
10103 no time to test now, so later well put in...kpb
10104         D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10105         emitcode("mov", "dps, #0x01");  /* Select DPTR2. */
10106         emitcode ("mov", "dptr,#%s", rSym->rname); 
10107         /* DP2 = result, DP1 = right, DP1 is current. */
10108         while (size)
10109         {
10110           --size;
10111           emitcode("movx", "a,@dptr");
10112           if (size)
10113             emitcode("inc", "dptr");
10114           emitcode("inc", "dps");
10115           emitcode("movx", "@dptr,a");
10116           if (size)
10117             emitcode("inc", "dptr");
10118           emitcode("inc", "dps");
10119         }
10120         emitcode("mov", "dps, #0");
10121         freeAsmop (right, NULL, ic, FALSE);
10122 #endif
10123   }
10124   else
10125   {
10126       D (emitcode (";", "genFarFarAssign"););
10127       aopOp (result, ic, TRUE, TRUE);
10128
10129       _startLazyDPSEvaluation ();
10130       
10131       while (size--)
10132         {
10133           aopPut (AOP (result),
10134                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
10135           offset++;
10136         }
10137       _endLazyDPSEvaluation ();
10138       freeAsmop (result, NULL, ic, FALSE);
10139       freeAsmop (right, NULL, ic, FALSE);
10140   }
10141 }
10142
10143 /*-----------------------------------------------------------------*/
10144 /* genAssign - generate code for assignment                        */
10145 /*-----------------------------------------------------------------*/
10146 static void
10147 genAssign (iCode * ic)
10148 {
10149   operand *result, *right;
10150   int size, offset;
10151   unsigned long lit = 0L;
10152
10153   D (emitcode (";", "genAssign ");
10154     );
10155
10156   result = IC_RESULT (ic);
10157   right = IC_RIGHT (ic);
10158
10159   /* if they are the same */
10160   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10161     return;
10162
10163   aopOp (right, ic, FALSE, FALSE);
10164
10165   emitcode (";", "genAssign: resultIsFar = %s",
10166             isOperandInFarSpace (result) ?
10167             "TRUE" : "FALSE");
10168
10169   /* special case both in far space */
10170   if ((AOP_TYPE (right) == AOP_DPTR ||
10171        AOP_TYPE (right) == AOP_DPTR2) &&
10172   /* IS_TRUE_SYMOP(result)       && */
10173       isOperandInFarSpace (result))
10174     {
10175       genFarFarAssign (result, right, ic);
10176       return;
10177     }
10178
10179   aopOp (result, ic, TRUE, FALSE);
10180
10181   /* if they are the same registers */
10182   if (sameRegs (AOP (right), AOP (result)))
10183     goto release;
10184
10185   /* if the result is a bit */
10186   if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10187     {
10188       /* if the right size is a literal then
10189          we know what the value is */
10190       if (AOP_TYPE (right) == AOP_LIT)
10191         {
10192           if (((int) operandLitValue (right)))
10193             aopPut (AOP (result), one, 0);
10194           else
10195             aopPut (AOP (result), zero, 0);
10196           goto release;
10197         }
10198
10199       /* the right is also a bit variable */
10200       if (AOP_TYPE (right) == AOP_CRY)
10201         {
10202           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10203           aopPut (AOP (result), "c", 0);
10204           goto release;
10205         }
10206
10207       /* we need to or */
10208       toBoolean (right);
10209       aopPut (AOP (result), "a", 0);
10210       goto release;
10211     }
10212
10213   /* bit variables done */
10214   /* general case */
10215   size = AOP_SIZE (result);
10216   offset = 0;
10217   if (AOP_TYPE (right) == AOP_LIT)
10218     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10219
10220   if ((size > 1) &&
10221       (AOP_TYPE (result) != AOP_REG) &&
10222       (AOP_TYPE (right) == AOP_LIT) &&
10223       !IS_FLOAT (operandType (right)))
10224     {
10225       _startLazyDPSEvaluation ();
10226       while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10227         {
10228           aopPut (AOP (result),
10229                   aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
10230                   offset);
10231           offset++;
10232           size--;
10233         }
10234       /* And now fill the rest with zeros. */
10235       if (size)
10236         {
10237           emitcode ("clr", "a");
10238         }
10239       while (size--)
10240         {
10241           aopPut (AOP (result), "a", offset++);
10242         }
10243       _endLazyDPSEvaluation ();
10244     }
10245   else
10246     {
10247       _startLazyDPSEvaluation ();
10248       while (size--)
10249         {
10250           aopPut (AOP (result),
10251                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10252                   offset);
10253           offset++;
10254         }
10255       _endLazyDPSEvaluation ();
10256     }
10257
10258 release:
10259   freeAsmop (right, NULL, ic, FALSE);
10260   freeAsmop (result, NULL, ic, TRUE);
10261 }
10262
10263 /*-----------------------------------------------------------------*/
10264 /* genJumpTab - generates code for jump table                      */
10265 /*-----------------------------------------------------------------*/
10266 static void
10267 genJumpTab (iCode * ic)
10268 {
10269   symbol *jtab;
10270   char *l;
10271
10272   D (emitcode (";", "genJumpTab ");
10273     );
10274
10275   aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10276   /* get the condition into accumulator */
10277   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
10278   MOVA (l);
10279   /* multiply by four! */
10280   emitcode ("add", "a,acc");
10281   emitcode ("add", "a,acc");
10282   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10283
10284   jtab = newiTempLabel (NULL);
10285   emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
10286   emitcode ("jmp", "@a+dptr");
10287   emitcode ("", "%05d$:", jtab->key + 100);
10288   /* now generate the jump labels */
10289   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10290        jtab = setNextItem (IC_JTLABELS (ic)))
10291     emitcode ("ljmp", "%05d$", jtab->key + 100);
10292
10293 }
10294
10295 /*-----------------------------------------------------------------*/
10296 /* genCast - gen code for casting                                  */
10297 /*-----------------------------------------------------------------*/
10298 static void
10299 genCast (iCode * ic)
10300 {
10301   operand *result = IC_RESULT (ic);
10302   sym_link *ctype = operandType (IC_LEFT (ic));
10303   sym_link *rtype = operandType (IC_RIGHT (ic));
10304   operand *right = IC_RIGHT (ic);
10305   int size, offset;
10306
10307   D (emitcode (";", "genCast ");
10308     );
10309
10310   /* if they are equivalent then do nothing */
10311   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10312     return;
10313
10314   aopOp (right, ic, FALSE, FALSE);
10315   aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
10316
10317   /* if the result is a bit */
10318   // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10319   if (IS_BITVAR(OP_SYMBOL(result)->type))
10320     {
10321       /* if the right size is a literal then
10322          we know what the value is */
10323       if (AOP_TYPE (right) == AOP_LIT)
10324         {
10325           if (((int) operandLitValue (right)))
10326             aopPut (AOP (result), one, 0);
10327           else
10328             aopPut (AOP (result), zero, 0);
10329
10330           goto release;
10331         }
10332
10333       /* the right is also a bit variable */
10334       if (AOP_TYPE (right) == AOP_CRY)
10335         {
10336           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10337           aopPut (AOP (result), "c", 0);
10338           goto release;
10339         }
10340
10341       /* we need to or */
10342       toBoolean (right);
10343       aopPut (AOP (result), "a", 0);
10344       goto release;
10345     }
10346
10347   /* if they are the same size : or less */
10348   if (AOP_SIZE (result) <= AOP_SIZE (right))
10349     {
10350
10351       /* if they are in the same place */
10352       if (sameRegs (AOP (right), AOP (result)))
10353         goto release;
10354
10355       /* if they in different places then copy */
10356       size = AOP_SIZE (result);
10357       offset = 0;
10358       _startLazyDPSEvaluation ();
10359       while (size--)
10360         {
10361           aopPut (AOP (result),
10362                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10363                   offset);
10364           offset++;
10365         }
10366       _endLazyDPSEvaluation ();
10367       goto release;
10368     }
10369
10370
10371   /* if the result is of type pointer */
10372   if (IS_PTR (ctype))
10373     {
10374
10375       int p_type;
10376       sym_link *type = operandType (right);
10377
10378       /* pointer to generic pointer */
10379       if (IS_GENPTR (ctype))
10380         {
10381           char *l = zero;
10382
10383           if (IS_PTR (type))
10384             {
10385               p_type = DCL_TYPE (type);
10386             }
10387           else
10388             {
10389 #if OLD_CAST_BEHAVIOR
10390               /* KV: we are converting a non-pointer type to
10391                * a generic pointer. This (ifdef'd out) code
10392                * says that the resulting generic pointer
10393                * should have the same class as the storage
10394                * location of the non-pointer variable.
10395                *
10396                * For example, converting an int (which happens
10397                * to be stored in DATA space) to a pointer results
10398                * in a DATA generic pointer; if the original int
10399                * in XDATA space, so will be the resulting pointer.
10400                *
10401                * I don't like that behavior, and thus this change:
10402                * all such conversions will be forced to XDATA and
10403                * throw a warning. If you want some non-XDATA
10404                * type, or you want to suppress the warning, you
10405                * must go through an intermediate cast, like so:
10406                *
10407                * char _generic *gp = (char _xdata *)(intVar);
10408                */
10409               sym_link *etype = getSpec (type);
10410
10411               /* we have to go by the storage class */
10412               if (SPEC_OCLS (etype) != generic)
10413                 {
10414                   p_type = PTR_TYPE (SPEC_OCLS (etype));
10415                 }
10416               else
10417 #endif
10418                 {
10419                   /* Converting unknown class (i.e. register variable)
10420                    * to generic pointer. This is not good, but
10421                    * we'll make a guess (and throw a warning).
10422                    */
10423                   p_type = FPOINTER;
10424                   werror (W_INT_TO_GEN_PTR_CAST);
10425                 }
10426             }
10427
10428           /* the first two bytes are known */
10429           size = GPTRSIZE - 1;
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
10441           /* the last byte depending on type */
10442           switch (p_type)
10443             {
10444             case IPOINTER:
10445             case POINTER:
10446               l = zero;
10447               break;
10448             case FPOINTER:
10449               l = one;
10450               break;
10451             case CPOINTER:
10452               l = "#0x02";
10453               break;
10454             case PPOINTER:
10455               l = "#0x03";
10456               break;
10457
10458             default:
10459               /* this should never happen */
10460               werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10461                       "got unknown pointer type");
10462               exit (1);
10463             }
10464           aopPut (AOP (result), l, GPTRSIZE - 1);
10465           goto release;
10466         }
10467
10468       /* just copy the pointers */
10469       size = AOP_SIZE (result);
10470       offset = 0;
10471       _startLazyDPSEvaluation ();
10472       while (size--)
10473         {
10474           aopPut (AOP (result),
10475                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10476                   offset);
10477           offset++;
10478         }
10479       _endLazyDPSEvaluation ();
10480       goto release;
10481     }
10482
10483   /* so we now know that the size of destination is greater
10484      than the size of the source */
10485   /* we move to result for the size of source */
10486   size = AOP_SIZE (right);
10487   offset = 0;
10488   _startLazyDPSEvaluation ();
10489   while (size--)
10490     {
10491       aopPut (AOP (result),
10492               aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10493               offset);
10494       offset++;
10495     }
10496   _endLazyDPSEvaluation ();
10497
10498   /* now depending on the sign of the source && destination */
10499   size = AOP_SIZE (result) - AOP_SIZE (right);
10500   /* if unsigned or not an integral type */
10501   /* also, if the source is a bit, we don't need to sign extend, because
10502    * it can't possibly have set the sign bit.
10503    */
10504   if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
10505     {
10506       while (size--)
10507         {
10508           aopPut (AOP (result), zero, offset++);
10509         }
10510     }
10511   else
10512     {
10513       /* we need to extend the sign :{ */
10514       char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
10515                         FALSE, FALSE, TRUE);
10516       MOVA (l);
10517       emitcode ("rlc", "a");
10518       emitcode ("subb", "a,acc");
10519       while (size--)
10520         aopPut (AOP (result), "a", offset++);
10521     }
10522
10523   /* we are done hurray !!!! */
10524
10525 release:
10526   freeAsmop (right, NULL, ic, TRUE);
10527   freeAsmop (result, NULL, ic, TRUE);
10528
10529 }
10530
10531 /*-----------------------------------------------------------------*/
10532 /* genDjnz - generate decrement & jump if not zero instrucion      */
10533 /*-----------------------------------------------------------------*/
10534 static int
10535 genDjnz (iCode * ic, iCode * ifx)
10536 {
10537   symbol *lbl, *lbl1;
10538   if (!ifx)
10539     return 0;
10540
10541   /* if the if condition has a false label
10542      then we cannot save */
10543   if (IC_FALSE (ifx))
10544     return 0;
10545
10546   /* if the minus is not of the form
10547      a = a - 1 */
10548   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
10549       !IS_OP_LITERAL (IC_RIGHT (ic)))
10550     return 0;
10551
10552   if (operandLitValue (IC_RIGHT (ic)) != 1)
10553     return 0;
10554
10555   /* if the size of this greater than one then no
10556      saving */
10557   if (getSize (operandType (IC_RESULT (ic))) > 1)
10558     return 0;
10559
10560   /* otherwise we can save BIG */
10561   D(emitcode(";", "genDjnz"););
10562
10563   lbl = newiTempLabel (NULL);
10564   lbl1 = newiTempLabel (NULL);
10565
10566   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10567
10568   if (AOP_NEEDSACC(IC_RESULT(ic)))
10569   {
10570       /* If the result is accessed indirectly via
10571        * the accumulator, we must explicitly write
10572        * it back after the decrement.
10573        */
10574       char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
10575       
10576       if (strcmp(rByte, "a"))
10577       {
10578            /* Something is hopelessly wrong */
10579            fprintf(stderr, "*** warning: internal error at %s:%d\n",
10580                    __FILE__, __LINE__);
10581            /* We can just give up; the generated code will be inefficient,
10582             * but what the hey.
10583             */
10584            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10585            return 0;
10586       }
10587       emitcode ("dec", "%s", rByte);
10588       aopPut(AOP(IC_RESULT(ic)), rByte, 0);
10589       emitcode ("jnz", "%05d$", lbl->key + 100);
10590   }
10591   else if (IS_AOP_PREG (IC_RESULT (ic)))
10592     {
10593       emitcode ("dec", "%s",
10594                 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10595       emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10596       emitcode ("jnz", "%05d$", lbl->key + 100);
10597     }
10598   else
10599     {
10600       emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
10601                 lbl->key + 100);
10602     }
10603   emitcode ("sjmp", "%05d$", lbl1->key + 100);
10604   emitcode ("", "%05d$:", lbl->key + 100);
10605   emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
10606   emitcode ("", "%05d$:", lbl1->key + 100);
10607
10608   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10609   ifx->generated = 1;
10610   return 1;
10611 }
10612
10613 /*-----------------------------------------------------------------*/
10614 /* genReceive - generate code for a receive iCode                  */
10615 /*-----------------------------------------------------------------*/
10616 static void
10617 genReceive (iCode * ic)
10618 {
10619
10620   D (emitcode (";", "genReceive ");
10621     );
10622
10623   if (isOperandInFarSpace (IC_RESULT (ic)) &&
10624       (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
10625        IS_TRUE_SYMOP (IC_RESULT (ic))))
10626     {
10627       int size = getSize (operandType (IC_RESULT (ic)));
10628       int offset = fReturnSizeDS390 - size;
10629       while (size--)
10630         {
10631           emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
10632                             fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
10633           offset++;
10634         }
10635       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10636       size = AOP_SIZE (IC_RESULT (ic));
10637       offset = 0;
10638       while (size--)
10639         {
10640           emitcode ("pop", "acc");
10641           aopPut (AOP (IC_RESULT (ic)), "a", offset++);
10642         }
10643
10644     }
10645   else
10646     {
10647       _G.accInUse++;
10648       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10649       _G.accInUse--;
10650       assignResultValue (IC_RESULT (ic));
10651     }
10652
10653   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10654 }
10655
10656 /*-----------------------------------------------------------------*/
10657 /* gen390Code - generate code for Dallas 390 based controllers     */
10658 /*-----------------------------------------------------------------*/
10659 void
10660 gen390Code (iCode * lic)
10661 {
10662   iCode *ic;
10663   int cln = 0;
10664
10665   lineHead = lineCurr = NULL;
10666
10667   if (options.model == MODEL_FLAT24) {
10668     fReturnSizeDS390 = 5;
10669     fReturn = fReturn24;
10670   } else {
10671     fReturnSizeDS390 = 4;
10672     fReturn = fReturn16;
10673     options.stack10bit=0;
10674   }
10675 #if 0
10676   //REMOVE ME!!!
10677   /* print the allocation information */
10678   if (allocInfo)
10679     printAllocInfo (currFunc, codeOutFile);
10680 #endif
10681   /* if debug information required */
10682   if (options.debug && currFunc)
10683     {
10684       cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
10685       _G.debugLine = 1;
10686       if (IS_STATIC (currFunc->etype))
10687         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
10688       else
10689         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
10690       _G.debugLine = 0;
10691     }
10692   /* stack pointer name */
10693   if (options.useXstack)
10694     spname = "_spx";
10695   else
10696     spname = "sp";
10697
10698
10699   for (ic = lic; ic; ic = ic->next)
10700     {
10701
10702       if (cln != ic->lineno)
10703         {
10704           if (options.debug)
10705             {
10706               _G.debugLine = 1;
10707               emitcode ("", "C$%s$%d$%d$%d ==.",
10708                         FileBaseName (ic->filename), ic->lineno,
10709                         ic->level, ic->block);
10710               _G.debugLine = 0;
10711             }
10712           emitcode (";", "%s %d", ic->filename, ic->lineno);
10713           cln = ic->lineno;
10714         }
10715       /* if the result is marked as
10716          spilt and rematerializable or code for
10717          this has already been generated then
10718          do nothing */
10719       if (resultRemat (ic) || ic->generated)
10720         continue;
10721
10722       /* depending on the operation */
10723       switch (ic->op)
10724         {
10725         case '!':
10726           genNot (ic);
10727           break;
10728
10729         case '~':
10730           genCpl (ic);
10731           break;
10732
10733         case UNARYMINUS:
10734           genUminus (ic);
10735           break;
10736
10737         case IPUSH:
10738           genIpush (ic);
10739           break;
10740
10741         case IPOP:
10742           /* IPOP happens only when trying to restore a
10743              spilt live range, if there is an ifx statement
10744              following this pop then the if statement might
10745              be using some of the registers being popped which
10746              would destory the contents of the register so
10747              we need to check for this condition and handle it */
10748           if (ic->next &&
10749               ic->next->op == IFX &&
10750               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
10751             genIfx (ic->next, ic);
10752           else
10753             genIpop (ic);
10754           break;
10755
10756         case CALL:
10757           genCall (ic);
10758           break;
10759
10760         case PCALL:
10761           genPcall (ic);
10762           break;
10763
10764         case FUNCTION:
10765           genFunction (ic);
10766           break;
10767
10768         case ENDFUNCTION:
10769           genEndFunction (ic);
10770           break;
10771
10772         case RETURN:
10773           genRet (ic);
10774           break;
10775
10776         case LABEL:
10777           genLabel (ic);
10778           break;
10779
10780         case GOTO:
10781           genGoto (ic);
10782           break;
10783
10784         case '+':
10785           genPlus (ic);
10786           break;
10787
10788         case '-':
10789           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
10790             genMinus (ic);
10791           break;
10792
10793         case '*':
10794           genMult (ic);
10795           break;
10796
10797         case '/':
10798           genDiv (ic);
10799           break;
10800
10801         case '%':
10802           genMod (ic);
10803           break;
10804
10805         case '>':
10806           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
10807           break;
10808
10809         case '<':
10810           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
10811           break;
10812
10813         case LE_OP:
10814         case GE_OP:
10815         case NE_OP:
10816
10817           /* note these two are xlated by algebraic equivalence
10818              during parsing SDCC.y */
10819           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10820                   "got '>=' or '<=' shouldn't have come here");
10821           break;
10822
10823         case EQ_OP:
10824           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
10825           break;
10826
10827         case AND_OP:
10828           genAndOp (ic);
10829           break;
10830
10831         case OR_OP:
10832           genOrOp (ic);
10833           break;
10834
10835         case '^':
10836           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
10837           break;
10838
10839         case '|':
10840           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
10841           break;
10842
10843         case BITWISEAND:
10844           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
10845           break;
10846
10847         case INLINEASM:
10848           genInline (ic);
10849           break;
10850
10851         case RRC:
10852           genRRC (ic);
10853           break;
10854
10855         case RLC:
10856           genRLC (ic);
10857           break;
10858
10859         case GETHBIT:
10860           genGetHbit (ic);
10861           break;
10862
10863         case LEFT_OP:
10864           genLeftShift (ic);
10865           break;
10866
10867         case RIGHT_OP:
10868           genRightShift (ic);
10869           break;
10870
10871         case GET_VALUE_AT_ADDRESS:
10872           genPointerGet (ic,hasInc(IC_LEFT(ic),ic));
10873           break;
10874
10875         case '=':
10876           if (POINTER_SET (ic))
10877             genPointerSet (ic,hasInc(IC_RESULT(ic),ic));
10878           else
10879             genAssign (ic);
10880           break;
10881
10882         case IFX:
10883           genIfx (ic, NULL);
10884           break;
10885
10886         case ADDRESS_OF:
10887           genAddrOf (ic);
10888           break;
10889
10890         case JUMPTABLE:
10891           genJumpTab (ic);
10892           break;
10893
10894         case CAST:
10895           genCast (ic);
10896           break;
10897
10898         case RECEIVE:
10899           genReceive (ic);
10900           break;
10901
10902         case SEND:
10903           addSet (&_G.sendSet, ic);
10904           break;
10905
10906         case ARRAYINIT:
10907             genArrayInit(ic);
10908             break;
10909             
10910         default:
10911           ic = ic;
10912         }
10913     }
10914
10915
10916   /* now we are ready to call the
10917      peep hole optimizer */
10918   if (!options.nopeep)
10919     peepHole (&lineHead);
10920
10921   /* now do the actual printing */
10922   printLine (lineHead, codeOutFile);
10923   return;
10924 }