Added support for Post Increment to pointerSet routines too
[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,_bp");
464       emitcode ("add", "a,#0x%02x",
465                 ((sym->stack < 0) ?
466                  ((char) (sym->stack - _G.nRegsSaved)) :
467                  ((char) sym->stack)) & 0xff);
468
469       if (useDP2)
470         {
471           if (options.model == MODEL_FLAT24)
472             emitcode ("mov", "dpx1,#0x40");
473           TR_DPTR("#2");
474           emitcode ("mov", "dph1,#0x00");
475           emitcode ("mov", "dpl1, a");
476         }
477       else
478         {
479           if (options.model == MODEL_FLAT24)
480             emitcode ("mov", "dpx,#0x40");
481           emitcode ("mov", "dph,#0x00");
482           emitcode ("mov", "dpl, a");
483         }
484
485       if (_G.accInUse)
486         emitcode ("pop", "acc");
487
488       sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
489       aop->size = getSize (sym->type);
490       return aop;
491     }
492
493   /* if in bit space */
494   if (IN_BITSPACE (space))
495     {
496       sym->aop = aop = newAsmop (AOP_CRY);
497       aop->aopu.aop_dir = sym->rname;
498       aop->size = getSize (sym->type);
499       return aop;
500     }
501   /* if it is in direct space */
502   if (IN_DIRSPACE (space))
503     {
504       sym->aop = aop = newAsmop (AOP_DIR);
505       aop->aopu.aop_dir = sym->rname;
506       aop->size = getSize (sym->type);
507       return aop;
508     }
509
510   /* special case for a function */
511   if (IS_FUNC (sym->type))
512     {
513       sym->aop = aop = newAsmop (AOP_IMMD);
514       aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
515       strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
516       aop->size = FPTRSIZE;
517       return aop;
518     }
519
520   /* only remaining is far space */
521   /* in which case DPTR gets the address */
522   sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
523   if (useDP2)
524     {
525       genSetDPTR (1);
526       _flushLazyDPS ();
527       emitcode ("mov", "dptr,#%s", sym->rname);
528       genSetDPTR (0);
529     }
530   else
531     {
532       emitcode ("mov", "dptr,#%s", sym->rname);
533     }
534   aop->size = getSize (sym->type);
535
536   /* if it is in code space */
537   if (IN_CODESPACE (space))
538     aop->code = 1;
539
540   return aop;
541 }
542
543 /*-----------------------------------------------------------------*/
544 /* aopForRemat - rematerialzes an object                           */
545 /*-----------------------------------------------------------------*/
546 static asmop *
547 aopForRemat (symbol * sym)
548 {
549   iCode *ic = sym->rematiCode;
550   asmop *aop = newAsmop (AOP_IMMD);
551   int ptr_type =0;
552   int val = 0;
553
554   for (;;)
555     {
556       if (ic->op == '+')
557         val += (int) operandLitValue (IC_RIGHT (ic));
558       else if (ic->op == '-')
559         val -= (int) operandLitValue (IC_RIGHT (ic));
560       else if (IS_CAST_ICODE(ic)) {
561               sym_link *from_type = operandType(IC_RIGHT(ic));
562               aop->aopu.aop_immd.from_cast_remat = 1;
563               ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
564               ptr_type = DCL_TYPE(from_type);
565               continue ;
566       } else break;
567       
568       ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
569     }
570
571   if (val)
572     sprintf (buffer, "(%s %c 0x%04x)",
573              OP_SYMBOL (IC_LEFT (ic))->rname,
574              val >= 0 ? '+' : '-',
575              abs (val) & 0xffff);
576   else
577     strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
578
579   aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
580   strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
581   /* set immd2 field if required */
582   if (aop->aopu.aop_immd.from_cast_remat) {
583           sprintf(buffer,"#0x%02x",ptr_type);
584           aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
585           strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
586   }
587
588   return aop;
589 }
590
591 /*-----------------------------------------------------------------*/
592 /* regsInCommon - two operands have some registers in common       */
593 /*-----------------------------------------------------------------*/
594 static bool
595 regsInCommon (operand * op1, operand * op2)
596 {
597   symbol *sym1, *sym2;
598   int i;
599
600   /* if they have registers in common */
601   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
602     return FALSE;
603
604   sym1 = OP_SYMBOL (op1);
605   sym2 = OP_SYMBOL (op2);
606
607   if (sym1->nRegs == 0 || sym2->nRegs == 0)
608     return FALSE;
609
610   for (i = 0; i < sym1->nRegs; i++)
611     {
612       int j;
613       if (!sym1->regs[i])
614         continue;
615
616       for (j = 0; j < sym2->nRegs; j++)
617         {
618           if (!sym2->regs[j])
619             continue;
620
621           if (sym2->regs[j] == sym1->regs[i])
622             return TRUE;
623         }
624     }
625
626   return FALSE;
627 }
628
629 /*-----------------------------------------------------------------*/
630 /* operandsEqu - equivalent                                        */
631 /*-----------------------------------------------------------------*/
632 static bool
633 operandsEqu (operand * op1, operand * op2)
634 {
635   symbol *sym1, *sym2;
636
637   /* if they not symbols */
638   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
639     return FALSE;
640
641   sym1 = OP_SYMBOL (op1);
642   sym2 = OP_SYMBOL (op2);
643
644   /* if both are itemps & one is spilt
645      and the other is not then false */
646   if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
647       sym1->isspilt != sym2->isspilt)
648     return FALSE;
649
650   /* if they are the same */
651   if (sym1 == sym2)
652     return TRUE;
653
654   if (strcmp (sym1->rname, sym2->rname) == 0)
655     return TRUE;
656
657
658   /* if left is a tmp & right is not */
659   if (IS_ITEMP (op1) &&
660       !IS_ITEMP (op2) &&
661       sym1->isspilt &&
662       (sym1->usl.spillLoc == sym2))
663     return TRUE;
664
665   if (IS_ITEMP (op2) &&
666       !IS_ITEMP (op1) &&
667       sym2->isspilt &&
668       sym1->level > 0 &&
669       (sym2->usl.spillLoc == sym1))
670     return TRUE;
671
672   return FALSE;
673 }
674
675 /*-----------------------------------------------------------------*/
676 /* sameRegs - two asmops have the same registers                   */
677 /*-----------------------------------------------------------------*/
678 static bool
679 sameRegs (asmop * aop1, asmop * aop2)
680 {
681   int i;
682
683   if (aop1 == aop2)
684     {
685       if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
686         {
687           return FALSE;
688         }
689       return TRUE;
690     }
691
692   if (aop1->type != AOP_REG ||
693       aop2->type != AOP_REG)
694     return FALSE;
695
696   if (aop1->size != aop2->size)
697     return FALSE;
698
699   for (i = 0; i < aop1->size; i++)
700     if (aop1->aopu.aop_reg[i] !=
701         aop2->aopu.aop_reg[i])
702       return FALSE;
703
704   return TRUE;
705 }
706
707 /*-----------------------------------------------------------------*/
708 /* aopOp - allocates an asmop for an operand  :                    */
709 /*-----------------------------------------------------------------*/
710 static void
711 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
712 {
713   asmop *aop;
714   symbol *sym;
715   int i;
716
717   if (!op)
718     return;
719
720   /* if this a literal */
721   if (IS_OP_LITERAL (op))
722     {
723       op->aop = aop = newAsmop (AOP_LIT);
724       aop->aopu.aop_lit = op->operand.valOperand;
725       aop->size = getSize (operandType (op));
726       return;
727     }
728
729   /* if already has a asmop then continue */
730   if (op->aop)
731     return;
732
733   /* if the underlying symbol has a aop */
734   if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
735     {
736       op->aop = OP_SYMBOL (op)->aop;
737       return;
738     }
739
740   /* if this is a true symbol */
741   if (IS_TRUE_SYMOP (op))
742     {
743       op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
744       return;
745     }
746
747   /* this is a temporary : this has
748      only four choices :
749      a) register
750      b) spillocation
751      c) rematerialize
752      d) conditional
753      e) can be a return use only */
754
755   sym = OP_SYMBOL (op);
756
757
758   /* if the type is a conditional */
759   if (sym->regType == REG_CND)
760     {
761       aop = op->aop = sym->aop = newAsmop (AOP_CRY);
762       aop->size = 0;
763       return;
764     }
765
766   /* if it is spilt then two situations
767      a) is rematerialize
768      b) has a spill location */
769   if (sym->isspilt || sym->nRegs == 0)
770     {
771
772       /* rematerialize it NOW */
773       if (sym->remat)
774         {
775           sym->aop = op->aop = aop =
776             aopForRemat (sym);
777           aop->size = getSize (sym->type);
778           return;
779         }
780
781       if (sym->accuse)
782         {
783           int i;
784           aop = op->aop = sym->aop = newAsmop (AOP_ACC);
785           aop->size = getSize (sym->type);
786           for (i = 0; i < 2; i++)
787             aop->aopu.aop_str[i] = accUse[i];
788           return;
789         }
790
791       if (sym->ruonly)
792         {
793           int i;
794
795           if (useDP2)
796             {
797               /* a AOP_STR uses DPTR, but DPTR is already in use;
798                * we're just hosed.
799                */
800               fprintf (stderr, "*** Internal error: AOP_STR with DPTR in use!\n");
801             }
802
803           aop = op->aop = sym->aop = newAsmop (AOP_STR);
804           aop->size = getSize (sym->type);
805           for (i = 0; i < (int) fReturnSizeDS390; i++)
806             aop->aopu.aop_str[i] = fReturn[i];
807           return;
808         }
809
810       /* else spill location  */
811       sym->aop = op->aop = aop =
812         aopForSym (ic, sym->usl.spillLoc, result, useDP2);
813       aop->size = getSize (sym->type);
814       return;
815     }
816
817   /* must be in a register */
818   sym->aop = op->aop = aop = newAsmop (AOP_REG);
819   aop->size = sym->nRegs;
820   for (i = 0; i < sym->nRegs; i++)
821     aop->aopu.aop_reg[i] = sym->regs[i];
822 }
823
824 /*-----------------------------------------------------------------*/
825 /* freeAsmop - free up the asmop given to an operand               */
826 /*----------------------------------------------------------------*/
827 static void
828 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
829 {
830   asmop *aop;
831
832   if (!op)
833     aop = aaop;
834   else
835     aop = op->aop;
836
837   if (!aop)
838     return;
839
840   if (aop->freed)
841     goto dealloc;
842
843   aop->freed = 1;
844
845   /* depending on the asmop type only three cases need work AOP_RO
846      , AOP_R1 && AOP_STK */
847   switch (aop->type)
848     {
849     case AOP_R0:
850       if (_G.r0Pushed)
851         {
852           if (pop)
853             {
854               emitcode ("pop", "ar0");
855               _G.r0Pushed--;
856             }
857         }
858       bitVectUnSetBit (ic->rUsed, R0_IDX);
859       break;
860
861     case AOP_R1:
862       if (_G.r1Pushed)
863         {
864           if (pop)
865             {
866               emitcode ("pop", "ar1");
867               _G.r1Pushed--;
868             }
869         }
870       bitVectUnSetBit (ic->rUsed, R1_IDX);
871       break;
872
873     case AOP_STK:
874       {
875         int sz = aop->size;
876         int stk = aop->aopu.aop_stk + aop->size;
877         bitVectUnSetBit (ic->rUsed, R0_IDX);
878         bitVectUnSetBit (ic->rUsed, R1_IDX);
879
880         getFreePtr (ic, &aop, FALSE);
881
882         if (options.stack10bit)
883           {
884             /* I'm not sure what to do here yet... */
885             /* #STUB */
886             fprintf (stderr,
887                      "*** Warning: probably generating bad code for "
888                      "10 bit stack mode.\n");
889           }
890
891         if (stk)
892           {
893             emitcode ("mov", "a,_bp");
894             emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
895             emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
896           }
897         else
898           {
899             emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
900           }
901
902         while (sz--)
903           {
904             emitcode ("pop", "acc");
905             emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
906             if (!sz)
907               break;
908             emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
909           }
910         op->aop = aop;
911         freeAsmop (op, NULL, ic, TRUE);
912         if (_G.r0Pushed)
913           {
914             emitcode ("pop", "ar0");
915             _G.r0Pushed--;
916           }
917
918         if (_G.r1Pushed)
919           {
920             emitcode ("pop", "ar1");
921             _G.r1Pushed--;
922           }
923       }
924     }
925
926 dealloc:
927   /* all other cases just dealloc */
928   if (op)
929     {
930       op->aop = NULL;
931       if (IS_SYMOP (op))
932         {
933           OP_SYMBOL (op)->aop = NULL;
934           /* if the symbol has a spill */
935           if (SPIL_LOC (op))
936             SPIL_LOC (op)->aop = NULL;
937         }
938     }
939 }
940
941 /*------------------------------------------------------------------*/
942 /* aopGet - for fetching value of the aop                           */
943 /*                    */
944 /* Set canClobberACC if you are sure it is OK to clobber the value  */
945 /* in the accumulator. Set it FALSE otherwise; FALSE is always safe, */
946 /* just less efficient.               */
947 /*------------------------------------------------------------------*/
948
949 static char *
950 aopGet (asmop * aop,
951         int offset,
952         bool bit16,
953         bool dname,
954         bool canClobberACC)
955 {
956   char *s = buffer;
957   char *rs;
958
959   /* offset is greater than
960      size then zero */
961   if (offset > (aop->size - 1) &&
962       aop->type != AOP_LIT)
963     return zero;
964
965   /* depending on type */
966   switch (aop->type)
967     {
968
969     case AOP_R0:
970     case AOP_R1:
971       /* if we need to increment it */
972       while (offset > aop->coff)
973         {
974           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
975           aop->coff++;
976         }
977
978       while (offset < aop->coff)
979         {
980           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
981           aop->coff--;
982         }
983
984       aop->coff = offset;
985       if (aop->paged)
986         {
987           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
988           return (dname ? "acc" : "a");
989         }
990       sprintf (s, "@%s", aop->aopu.aop_ptr->name);
991       rs = Safe_calloc (1, strlen (s) + 1);
992       strcpy (rs, s);
993       return rs;
994
995     case AOP_DPTR:
996     case AOP_DPTR2:
997
998       if (aop->type == AOP_DPTR2)
999         {
1000           genSetDPTR (1);
1001           if (!canClobberACC)
1002             {
1003                     TR_AP("#1");
1004                     emitcode ("xch", "a, %s", DP2_RESULT_REG);
1005             }
1006         }
1007
1008       _flushLazyDPS ();
1009
1010       while (offset > aop->coff)
1011         {
1012           emitcode ("inc", "dptr");
1013           aop->coff++;
1014         }
1015
1016       while (offset < aop->coff)
1017         {
1018           emitcode ("lcall", "__decdptr");
1019           aop->coff--;
1020         }
1021
1022       aop->coff = offset;
1023       if (aop->code)
1024         {
1025           emitcode ("clr", "a");
1026           emitcode ("movc", "a,@a+dptr");
1027         }
1028       else
1029         {
1030           emitcode ("movx", "a,@dptr");
1031         }
1032
1033       if (aop->type == AOP_DPTR2)
1034         {
1035           genSetDPTR (0);
1036           if (!canClobberACC)
1037             {
1038        TR_AP("#2");
1039               emitcode ("xch", "a, %s", DP2_RESULT_REG);
1040               return DP2_RESULT_REG;
1041             }
1042         }
1043       return (dname ? "acc" : "a");
1044
1045     case AOP_IMMD:
1046       if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
1047               sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
1048       } else if (bit16)
1049         sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
1050       else if (offset)
1051         sprintf (s, "#(%s >> %d)",
1052                  aop->aopu.aop_immd.aop_immd1,
1053                  offset * 8);
1054       else
1055         sprintf (s, "#%s",
1056                  aop->aopu.aop_immd.aop_immd1);
1057       rs = Safe_calloc (1, strlen (s) + 1);
1058       strcpy (rs, s);
1059       return rs;
1060
1061     case AOP_DIR:
1062       if (offset)
1063         sprintf (s, "(%s + %d)",
1064                  aop->aopu.aop_dir,
1065                  offset);
1066       else
1067         sprintf (s, "%s", aop->aopu.aop_dir);
1068       rs = Safe_calloc (1, strlen (s) + 1);
1069       strcpy (rs, s);
1070       return rs;
1071
1072     case AOP_REG:
1073       if (dname)
1074         return aop->aopu.aop_reg[offset]->dname;
1075       else
1076         return aop->aopu.aop_reg[offset]->name;
1077
1078     case AOP_CRY:
1079       emitcode ("clr", "a");
1080       emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1081       emitcode ("rlc", "a");
1082       return (dname ? "acc" : "a");
1083
1084     case AOP_ACC:
1085       if (!offset && dname)
1086         return "acc";
1087       return aop->aopu.aop_str[offset];
1088
1089     case AOP_LIT:
1090       return aopLiteral (aop->aopu.aop_lit, offset);
1091
1092     case AOP_STR:
1093       aop->coff = offset;
1094       if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1095           dname)
1096         return "acc";
1097
1098       return aop->aopu.aop_str[offset];
1099
1100     }
1101
1102   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1103           "aopget got unsupported aop->type");
1104   exit (1);
1105 }
1106 /*-----------------------------------------------------------------*/
1107 /* aopPut - puts a string for a aop                                */
1108 /*-----------------------------------------------------------------*/
1109 static void
1110 aopPut (asmop * aop, char *s, int offset)
1111 {
1112   char *d = buffer;
1113
1114   if (aop->size && offset > (aop->size - 1))
1115     {
1116       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1117               "aopPut got offset > aop->size");
1118       exit (1);
1119     }
1120
1121   /* will assign value to value */
1122   /* depending on where it is ofcourse */
1123   switch (aop->type)
1124     {
1125     case AOP_DIR:
1126       if (offset)
1127         sprintf (d, "(%s + %d)",
1128                  aop->aopu.aop_dir, offset);
1129       else
1130         sprintf (d, "%s", aop->aopu.aop_dir);
1131
1132       if (strcmp (d, s))
1133         emitcode ("mov", "%s,%s", d, s);
1134
1135       break;
1136
1137     case AOP_REG:
1138       if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1139           strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1140         {
1141           if (*s == '@' ||
1142               strcmp (s, "r0") == 0 ||
1143               strcmp (s, "r1") == 0 ||
1144               strcmp (s, "r2") == 0 ||
1145               strcmp (s, "r3") == 0 ||
1146               strcmp (s, "r4") == 0 ||
1147               strcmp (s, "r5") == 0 ||
1148               strcmp (s, "r6") == 0 ||
1149               strcmp (s, "r7") == 0)
1150             emitcode ("mov", "%s,%s",
1151                       aop->aopu.aop_reg[offset]->dname, s);
1152           else
1153             emitcode ("mov", "%s,%s",
1154                       aop->aopu.aop_reg[offset]->name, s);
1155         }
1156       break;
1157
1158     case AOP_DPTR:
1159     case AOP_DPTR2:
1160
1161       if (aop->type == AOP_DPTR2)
1162         {
1163           genSetDPTR (1);
1164         }
1165       _flushLazyDPS ();
1166
1167       if (aop->code)
1168         {
1169           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1170                   "aopPut writting to code space");
1171           exit (1);
1172         }
1173
1174       while (offset > aop->coff)
1175         {
1176           aop->coff++;
1177           emitcode ("inc", "dptr");
1178         }
1179
1180       while (offset < aop->coff)
1181         {
1182           aop->coff--;
1183           emitcode ("lcall", "__decdptr");
1184         }
1185
1186       aop->coff = offset;
1187
1188       /* if not in accumulater */
1189       MOVA (s);
1190
1191       emitcode ("movx", "@dptr,a");
1192
1193       if (aop->type == AOP_DPTR2)
1194         {
1195           genSetDPTR (0);
1196         }
1197       break;
1198
1199     case AOP_R0:
1200     case AOP_R1:
1201       while (offset > aop->coff)
1202         {
1203           aop->coff++;
1204           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1205         }
1206       while (offset < aop->coff)
1207         {
1208           aop->coff--;
1209           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1210         }
1211       aop->coff = offset;
1212
1213       if (aop->paged)
1214         {
1215           MOVA (s);
1216           emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1217
1218         }
1219       else if (*s == '@')
1220         {
1221           MOVA (s);
1222           emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1223         }
1224       else if (strcmp (s, "r0") == 0 ||
1225                strcmp (s, "r1") == 0 ||
1226                strcmp (s, "r2") == 0 ||
1227                strcmp (s, "r3") == 0 ||
1228                strcmp (s, "r4") == 0 ||
1229                strcmp (s, "r5") == 0 ||
1230                strcmp (s, "r6") == 0 ||
1231                strcmp (s, "r7") == 0)
1232         {
1233           char buffer[10];
1234           sprintf (buffer, "a%s", s);
1235           emitcode ("mov", "@%s,%s",
1236                     aop->aopu.aop_ptr->name, buffer);
1237         }
1238       else
1239         emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1240
1241       break;
1242
1243     case AOP_STK:
1244       if (strcmp (s, "a") == 0)
1245         emitcode ("push", "acc");
1246       else
1247         if (*s=='@') {
1248           MOVA(s);
1249           emitcode ("push", "acc");
1250         } else {
1251           emitcode ("push", s);
1252         }
1253
1254       break;
1255
1256     case AOP_CRY:
1257       /* if bit variable */
1258       if (!aop->aopu.aop_dir)
1259         {
1260           emitcode ("clr", "a");
1261           emitcode ("rlc", "a");
1262         }
1263       else
1264         {
1265           if (s == zero)
1266             emitcode ("clr", "%s", aop->aopu.aop_dir);
1267           else if (s == one)
1268             emitcode ("setb", "%s", aop->aopu.aop_dir);
1269           else if (!strcmp (s, "c"))
1270             emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1271           else
1272             {
1273               if (strcmp (s, "a"))
1274                 {
1275                   MOVA (s);
1276                 }
1277               {
1278                 symbol *lbl = newiTempLabel (NULL);
1279                 emitcode ("clr", "c");
1280                 emitcode ("jz", "%05d$", lbl->key + 100);
1281                 emitcode ("cpl", "c");
1282                 emitcode ("", "%05d$:", lbl->key + 100);
1283                 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1284               }
1285             }
1286         }
1287       break;
1288
1289     case AOP_STR:
1290       aop->coff = offset;
1291       if (strcmp (aop->aopu.aop_str[offset], s))
1292         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1293       break;
1294
1295     case AOP_ACC:
1296       aop->coff = offset;
1297       if (!offset && (strcmp (s, "acc") == 0))
1298         break;
1299
1300       if (strcmp (aop->aopu.aop_str[offset], s))
1301         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1302       break;
1303
1304     default:
1305       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1306               "aopPut got unsupported aop->type");
1307       exit (1);
1308     }
1309
1310 }
1311
1312
1313 /*--------------------------------------------------------------------*/
1314 /* reAdjustPreg - points a register back to where it should (coff==0) */
1315 /*--------------------------------------------------------------------*/
1316 static void
1317 reAdjustPreg (asmop * aop)
1318 {
1319   if ((aop->coff==0) || (aop->size <= 1)) {
1320     return;
1321   }
1322
1323   switch (aop->type)
1324     {
1325     case AOP_R0:
1326     case AOP_R1:
1327       while (aop->coff--)
1328         emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1329       break;
1330     case AOP_DPTR:
1331     case AOP_DPTR2:
1332       if (aop->type == AOP_DPTR2)
1333         {
1334           genSetDPTR (1);
1335           _flushLazyDPS ();
1336         }
1337       while (aop->coff--)
1338         {
1339           emitcode ("lcall", "__decdptr");
1340         }
1341
1342       if (aop->type == AOP_DPTR2)
1343         {
1344           genSetDPTR (0);
1345         }
1346       break;
1347
1348     }
1349   aop->coff=0;
1350 }
1351
1352 #define AOP(op) op->aop
1353 #define AOP_TYPE(op) AOP(op)->type
1354 #define AOP_SIZE(op) AOP(op)->size
1355 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1356                        AOP_TYPE(x) == AOP_R0))
1357
1358 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
1359                         AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1360                          AOP(x)->paged))
1361
1362 #define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
1363                       (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1364                       x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1365
1366 /* Workaround for DS80C390 bug: div ab may return bogus results
1367  * if A is accessed in instruction immediately before the div.
1368  *
1369  * Will be fixed in B4 rev of processor, Dallas claims.
1370  */
1371
1372 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L)       \
1373     if (!AOP_NEEDSACC(RIGHT))         \
1374     {               \
1375       /* We can load A first, then B, since     \
1376        * B (the RIGHT operand) won't clobber A,   \
1377        * thus avoiding touching A right before the div. \
1378        */             \
1379       D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1380       L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE);     \
1381       MOVA(L);            \
1382       emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1383     }               \
1384     else              \
1385     {               \
1386       /* Just stuff in a nop after loading A. */    \
1387       emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1388       L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE);   \
1389       MOVA(L);            \
1390       emitcode("nop", "; workaround for DS80C390 div bug.");  \
1391     }
1392
1393 /*-----------------------------------------------------------------*/
1394 /* genNotFloat - generates not for float operations              */
1395 /*-----------------------------------------------------------------*/
1396 static void
1397 genNotFloat (operand * op, operand * res)
1398 {
1399   int size, offset;
1400   char *l;
1401   symbol *tlbl;
1402
1403   D (emitcode (";", "genNotFloat ");
1404     );
1405
1406   /* we will put 127 in the first byte of
1407      the result */
1408   aopPut (AOP (res), "#127", 0);
1409   size = AOP_SIZE (op) - 1;
1410   offset = 1;
1411
1412   _startLazyDPSEvaluation ();
1413   l = aopGet (op->aop, offset++, FALSE, FALSE, TRUE);
1414   MOVA (l);
1415
1416   while (size--)
1417     {
1418       emitcode ("orl", "a,%s",
1419                 aopGet (op->aop,
1420                         offset++, FALSE, FALSE, FALSE));
1421     }
1422   _endLazyDPSEvaluation ();
1423
1424   tlbl = newiTempLabel (NULL);
1425   aopPut (res->aop, one, 1);
1426   emitcode ("jz", "%05d$", (tlbl->key + 100));
1427   aopPut (res->aop, zero, 1);
1428   emitcode ("", "%05d$:", (tlbl->key + 100));
1429
1430   size = res->aop->size - 2;
1431   offset = 2;
1432   /* put zeros in the rest */
1433   while (size--)
1434     aopPut (res->aop, zero, offset++);
1435 }
1436
1437 /*-----------------------------------------------------------------*/
1438 /* opIsGptr: returns non-zero if the passed operand is       */
1439 /* a generic pointer type.             */
1440 /*-----------------------------------------------------------------*/
1441 static int
1442 opIsGptr (operand * op)
1443 {
1444   sym_link *type = operandType (op);
1445
1446   if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1447     {
1448       return 1;
1449     }
1450   return 0;
1451 }
1452
1453 /*-----------------------------------------------------------------*/
1454 /* getDataSize - get the operand data size                         */
1455 /*-----------------------------------------------------------------*/
1456 static int
1457 getDataSize (operand * op)
1458 {
1459   int size;
1460   size = AOP_SIZE (op);
1461   if (size == GPTRSIZE)
1462     {
1463       sym_link *type = operandType (op);
1464       if (IS_GENPTR (type))
1465         {
1466           /* generic pointer; arithmetic operations
1467            * should ignore the high byte (pointer type).
1468            */
1469           size--;
1470         }
1471     }
1472   return size;
1473 }
1474
1475 /*-----------------------------------------------------------------*/
1476 /* outAcc - output Acc                                             */
1477 /*-----------------------------------------------------------------*/
1478 static void
1479 outAcc (operand * result)
1480 {
1481   int size, offset;
1482   size = getDataSize (result);
1483   if (size)
1484     {
1485       aopPut (AOP (result), "a", 0);
1486       size--;
1487       offset = 1;
1488       /* unsigned or positive */
1489       while (size--)
1490         {
1491           aopPut (AOP (result), zero, offset++);
1492         }
1493     }
1494 }
1495
1496 /*-----------------------------------------------------------------*/
1497 /* outBitC - output a bit C                                        */
1498 /*-----------------------------------------------------------------*/
1499 static void
1500 outBitC (operand * result)
1501 {
1502   /* if the result is bit */
1503   if (AOP_TYPE (result) == AOP_CRY)
1504     {
1505       aopPut (AOP (result), "c", 0);
1506     }
1507   else
1508     {
1509       emitcode ("clr", "a");
1510       emitcode ("rlc", "a");
1511       outAcc (result);
1512     }
1513 }
1514
1515 /*-----------------------------------------------------------------*/
1516 /* toBoolean - emit code for orl a,operator(sizeop)                */
1517 /*-----------------------------------------------------------------*/
1518 static void
1519 toBoolean (operand * oper)
1520 {
1521   int   size = AOP_SIZE (oper) - 1;
1522   int   offset = 1;
1523   bool usedB = FALSE;
1524
1525   /* The generic part of a generic pointer should
1526    * not participate in it's truth value.
1527    *
1528    * i.e. 0x10000000 is zero.
1529    */
1530   if (opIsGptr (oper))
1531     {
1532       D (emitcode (";", "toBoolean: generic ptr special case.");
1533         );
1534       size--;
1535     }
1536
1537   _startLazyDPSEvaluation ();
1538   if (AOP_NEEDSACC (oper) && size)
1539     {
1540       usedB = TRUE;
1541       emitcode ("push", "b");
1542       emitcode ("mov", "b, %s", aopGet (AOP (oper), 0, FALSE, FALSE, FALSE));
1543     }
1544   else
1545     {
1546       MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, TRUE));
1547     }
1548   while (size--)
1549     {
1550       if (usedB)
1551         {
1552           emitcode ("orl", "b,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1553         }
1554       else
1555         {
1556           emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1557         }
1558     }
1559   _endLazyDPSEvaluation ();
1560
1561   if (usedB)
1562     {
1563       emitcode ("mov", "a,b");
1564       emitcode ("pop", "b");
1565     }
1566 }
1567
1568
1569 /*-----------------------------------------------------------------*/
1570 /* genNot - generate code for ! operation                          */
1571 /*-----------------------------------------------------------------*/
1572 static void
1573 genNot (iCode * ic)
1574 {
1575   symbol *tlbl;
1576   sym_link *optype = operandType (IC_LEFT (ic));
1577
1578   D (emitcode (";", "genNot ");
1579     );
1580
1581   /* assign asmOps to operand & result */
1582   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1583   aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1584
1585   /* if in bit space then a special case */
1586   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1587     {
1588       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1589       emitcode ("cpl", "c");
1590       outBitC (IC_RESULT (ic));
1591       goto release;
1592     }
1593
1594   /* if type float then do float */
1595   if (IS_FLOAT (optype))
1596     {
1597       genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1598       goto release;
1599     }
1600
1601   toBoolean (IC_LEFT (ic));
1602
1603   tlbl = newiTempLabel (NULL);
1604   emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1605   emitcode ("", "%05d$:", tlbl->key + 100);
1606   outBitC (IC_RESULT (ic));
1607
1608 release:
1609   /* release the aops */
1610   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1611   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1612 }
1613
1614
1615 /*-----------------------------------------------------------------*/
1616 /* genCpl - generate code for complement                           */
1617 /*-----------------------------------------------------------------*/
1618 static void
1619 genCpl (iCode * ic)
1620 {
1621   int offset = 0;
1622   int size;
1623
1624   D (emitcode (";", "genCpl ");
1625     );
1626
1627
1628   /* assign asmOps to operand & result */
1629   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1630   aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1631
1632   /* if both are in bit space then
1633      a special case */
1634   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1635       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1636     {
1637
1638       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1639       emitcode ("cpl", "c");
1640       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1641       goto release;
1642     }
1643
1644   size = AOP_SIZE (IC_RESULT (ic));
1645   _startLazyDPSEvaluation ();
1646   while (size--)
1647     {
1648       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1649       MOVA (l);
1650       emitcode ("cpl", "a");
1651       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1652     }
1653   _endLazyDPSEvaluation ();
1654
1655
1656 release:
1657   /* release the aops */
1658   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1659   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1660 }
1661
1662 /*-----------------------------------------------------------------*/
1663 /* genUminusFloat - unary minus for floating points                */
1664 /*-----------------------------------------------------------------*/
1665 static void
1666 genUminusFloat (operand * op, operand * result)
1667 {
1668   int size, offset = 0;
1669   char *l;
1670   /* for this we just need to flip the
1671      first it then copy the rest in place */
1672   D (emitcode (";", "genUminusFloat");
1673     );
1674
1675   _startLazyDPSEvaluation ();
1676   size = AOP_SIZE (op) - 1;
1677   l = aopGet (AOP (op), 3, FALSE, FALSE, TRUE);
1678   MOVA (l);
1679
1680   emitcode ("cpl", "acc.7");
1681   aopPut (AOP (result), "a", 3);
1682
1683   while (size--)
1684     {
1685       aopPut (AOP (result),
1686               aopGet (AOP (op), offset, FALSE, FALSE, FALSE),
1687               offset);
1688       offset++;
1689     }
1690   _endLazyDPSEvaluation ();
1691 }
1692
1693 /*-----------------------------------------------------------------*/
1694 /* genUminus - unary minus code generation                         */
1695 /*-----------------------------------------------------------------*/
1696 static void
1697 genUminus (iCode * ic)
1698 {
1699   int offset, size;
1700   sym_link *optype, *rtype;
1701
1702   D (emitcode (";", "genUminus ");
1703     );
1704
1705
1706   /* assign asmops */
1707   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1708   aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1709
1710   /* if both in bit space then special
1711      case */
1712   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1713       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1714     {
1715
1716       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1717       emitcode ("cpl", "c");
1718       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1719       goto release;
1720     }
1721
1722   optype = operandType (IC_LEFT (ic));
1723   rtype = operandType (IC_RESULT (ic));
1724
1725   /* if float then do float stuff */
1726   if (IS_FLOAT (optype))
1727     {
1728       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1729       goto release;
1730     }
1731
1732   /* otherwise subtract from zero */
1733   size = AOP_SIZE (IC_LEFT (ic));
1734   offset = 0;
1735   _startLazyDPSEvaluation ();
1736   while (size--)
1737     {
1738       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1739       if (!strcmp (l, "a"))
1740         {
1741           if (offset == 0)
1742             SETC;
1743           emitcode ("cpl", "a");
1744           emitcode ("addc", "a,#0");
1745         }
1746       else
1747         {
1748           if (offset == 0)
1749             CLRC;
1750           emitcode ("clr", "a");
1751           emitcode ("subb", "a,%s", l);
1752         }
1753       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1754     }
1755   _endLazyDPSEvaluation ();
1756
1757   /* if any remaining bytes in the result */
1758   /* we just need to propagate the sign   */
1759   if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1760     {
1761       emitcode ("rlc", "a");
1762       emitcode ("subb", "a,acc");
1763       while (size--)
1764         aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1765     }
1766
1767 release:
1768   /* release the aops */
1769   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1770   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1771 }
1772
1773 /*-----------------------------------------------------------------*/
1774 /* saveRegisters - will look for a call and save the registers     */
1775 /*-----------------------------------------------------------------*/
1776 static void
1777 saveRegisters (iCode * lic)
1778 {
1779   int i;
1780   iCode *ic;
1781   bitVect *rsave;
1782   sym_link *detype;
1783
1784   /* look for call */
1785   for (ic = lic; ic; ic = ic->next)
1786     if (ic->op == CALL || ic->op == PCALL)
1787       break;
1788
1789   if (!ic)
1790     {
1791       fprintf (stderr, "found parameter push with no function call\n");
1792       return;
1793     }
1794
1795   /* if the registers have been saved already then
1796      do nothing */
1797   if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type) ||
1798       IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic))))
1799     return;
1800
1801   /* find the registers in use at this time
1802      and push them away to safety */
1803   rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1804                          ic->rUsed);
1805
1806   ic->regsSaved = 1;
1807   if (options.useXstack)
1808     {
1809       if (bitVectBitValue (rsave, R0_IDX))
1810         emitcode ("mov", "b,r0");
1811       emitcode ("mov", "r0,%s", spname);
1812       for (i = 0; i < ds390_nRegs; i++)
1813         {
1814           if (bitVectBitValue (rsave, i))
1815             {
1816               if (i == R0_IDX)
1817                 emitcode ("mov", "a,b");
1818               else
1819                 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
1820               emitcode ("movx", "@r0,a");
1821               emitcode ("inc", "r0");
1822             }
1823         }
1824       emitcode ("mov", "%s,r0", spname);
1825       if (bitVectBitValue (rsave, R0_IDX))
1826         emitcode ("mov", "r0,b");
1827     }
1828   else
1829     for (i = 0; i < ds390_nRegs; i++)
1830       {
1831         if (bitVectBitValue (rsave, i))
1832           emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
1833       }
1834
1835   detype = getSpec (operandType (IC_LEFT (ic)));
1836 }
1837
1838 /*-----------------------------------------------------------------*/
1839 /* unsaveRegisters - pop the pushed registers                      */
1840 /*-----------------------------------------------------------------*/
1841 static void
1842 unsaveRegisters (iCode * ic)
1843 {
1844   int i;
1845   bitVect *rsave;
1846   /* find the registers in use at this time
1847      and push them away to safety */
1848   rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1849                          ic->rUsed);
1850
1851   if (options.useXstack)
1852     {
1853       emitcode ("mov", "r0,%s", spname);
1854       for (i = ds390_nRegs; i >= 0; i--)
1855         {
1856           if (bitVectBitValue (rsave, i))
1857             {
1858               emitcode ("dec", "r0");
1859               emitcode ("movx", "a,@r0");
1860               if (i == R0_IDX)
1861                 emitcode ("mov", "b,a");
1862               else
1863                 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
1864             }
1865
1866         }
1867       emitcode ("mov", "%s,r0", spname);
1868       if (bitVectBitValue (rsave, R0_IDX))
1869         emitcode ("mov", "r0,b");
1870     }
1871   else
1872     for (i = ds390_nRegs; i >= 0; i--)
1873       {
1874         if (bitVectBitValue (rsave, i))
1875           emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
1876       }
1877
1878 }
1879
1880
1881 /*-----------------------------------------------------------------*/
1882 /* pushSide -                */
1883 /*-----------------------------------------------------------------*/
1884 static void
1885 pushSide (operand * oper, int size)
1886 {
1887   int offset = 0;
1888   _startLazyDPSEvaluation ();
1889   while (size--)
1890     {
1891       char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, FALSE);
1892       if (AOP_TYPE (oper) != AOP_REG &&
1893           AOP_TYPE (oper) != AOP_DIR &&
1894           strcmp (l, "a"))
1895         {
1896           emitcode ("mov", "a,%s", l);
1897           emitcode ("push", "acc");
1898         }
1899       else
1900         emitcode ("push", "%s", l);
1901     }
1902   _endLazyDPSEvaluation ();
1903 }
1904
1905 /*-----------------------------------------------------------------*/
1906 /* assignResultValue -               */
1907 /*-----------------------------------------------------------------*/
1908 static void
1909 assignResultValue (operand * oper)
1910 {
1911   int offset = 0;
1912   int size = AOP_SIZE (oper);
1913
1914   _startLazyDPSEvaluation ();
1915   while (size--)
1916     {
1917       aopPut (AOP (oper), fReturn[offset], offset);
1918       offset++;
1919     }
1920   _endLazyDPSEvaluation ();
1921 }
1922
1923
1924 /*-----------------------------------------------------------------*/
1925 /* genXpush - pushes onto the external stack                       */
1926 /*-----------------------------------------------------------------*/
1927 static void
1928 genXpush (iCode * ic)
1929 {
1930   asmop *aop = newAsmop (0);
1931   regs *r;
1932   int size, offset = 0;
1933
1934   D (emitcode (";", "genXpush ");
1935     );
1936
1937   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1938   r = getFreePtr (ic, &aop, FALSE);
1939
1940
1941   emitcode ("mov", "%s,_spx", r->name);
1942
1943   size = AOP_SIZE (IC_LEFT (ic));
1944   _startLazyDPSEvaluation ();
1945   while (size--)
1946     {
1947
1948       char *l = aopGet (AOP (IC_LEFT (ic)),
1949                         offset++, FALSE, FALSE, TRUE);
1950       MOVA (l);
1951       emitcode ("movx", "@%s,a", r->name);
1952       emitcode ("inc", "%s", r->name);
1953
1954     }
1955   _endLazyDPSEvaluation ();
1956
1957
1958   emitcode ("mov", "_spx,%s", r->name);
1959
1960   freeAsmop (NULL, aop, ic, TRUE);
1961   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1962 }
1963
1964 /*-----------------------------------------------------------------*/
1965 /* genIpush - genrate code for pushing this gets a little complex  */
1966 /*-----------------------------------------------------------------*/
1967 static void
1968 genIpush (iCode * ic)
1969 {
1970   int size, offset = 0;
1971   char *l;
1972
1973   D (emitcode (";", "genIpush ");
1974     );
1975
1976   /* if this is not a parm push : ie. it is spill push
1977      and spill push is always done on the local stack */
1978   if (!ic->parmPush)
1979     {
1980
1981       /* and the item is spilt then do nothing */
1982       if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1983         return;
1984
1985       aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1986       size = AOP_SIZE (IC_LEFT (ic));
1987       /* push it on the stack */
1988       _startLazyDPSEvaluation ();
1989       while (size--)
1990         {
1991           l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, TRUE);
1992           if (*l == '#')
1993             {
1994               MOVA (l);
1995               l = "acc";
1996             }
1997           emitcode ("push", "%s", l);
1998         }
1999       _endLazyDPSEvaluation ();
2000       return;
2001     }
2002
2003   /* this is a paramter push: in this case we call
2004      the routine to find the call and save those
2005      registers that need to be saved */
2006   saveRegisters (ic);
2007
2008   /* if use external stack then call the external
2009      stack pushing routine */
2010   if (options.useXstack)
2011     {
2012       genXpush (ic);
2013       return;
2014     }
2015
2016   /* then do the push */
2017   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2018
2019   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2020   size = AOP_SIZE (IC_LEFT (ic));
2021
2022   _startLazyDPSEvaluation ();
2023   while (size--)
2024     {
2025       l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, FALSE);
2026       if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2027           AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2028           strcmp (l, "a"))
2029         {
2030           emitcode ("mov", "a,%s", l);
2031           emitcode ("push", "acc");
2032         }
2033       else
2034         emitcode ("push", "%s", l);
2035     }
2036   _endLazyDPSEvaluation ();
2037
2038   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2039 }
2040
2041 /*-----------------------------------------------------------------*/
2042 /* genIpop - recover the registers: can happen only for spilling   */
2043 /*-----------------------------------------------------------------*/
2044 static void
2045 genIpop (iCode * ic)
2046 {
2047   int size, offset;
2048
2049   D (emitcode (";", "genIpop ");
2050     );
2051
2052
2053   /* if the temp was not pushed then */
2054   if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2055     return;
2056
2057   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2058   size = AOP_SIZE (IC_LEFT (ic));
2059   offset = (size - 1);
2060   _startLazyDPSEvaluation ();
2061   while (size--)
2062     {
2063       emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2064                                      FALSE, TRUE, TRUE));
2065     }
2066   _endLazyDPSEvaluation ();
2067
2068   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2069 }
2070
2071 /*-----------------------------------------------------------------*/
2072 /* unsaveRBank - restores the resgister bank from stack            */
2073 /*-----------------------------------------------------------------*/
2074 static void
2075 unsaveRBank (int bank, iCode * ic, bool popPsw)
2076 {
2077   int i;
2078   asmop *aop = NULL;
2079   regs *r = NULL;
2080
2081   if (options.useXstack)
2082   {
2083       if (!ic)
2084       {
2085           /* Assume r0 is available for use. */
2086           r = ds390_regWithIdx (R0_IDX);;          
2087       } 
2088       else
2089       {
2090           aop = newAsmop (0);
2091           r = getFreePtr (ic, &aop, FALSE);
2092       }
2093       emitcode ("mov", "%s,_spx", r->name);      
2094   }
2095   
2096   if (popPsw)
2097     {
2098       if (options.useXstack)
2099       {
2100           emitcode ("movx", "a,@%s", r->name);
2101           emitcode ("mov", "psw,a");
2102           emitcode ("dec", "%s", r->name);
2103         }
2104       else
2105       {
2106         emitcode ("pop", "psw");
2107       }
2108     }
2109
2110   for (i = (ds390_nRegs - 1); i >= 0; i--)
2111     {
2112       if (options.useXstack)
2113         {
2114           emitcode ("movx", "a,@%s", r->name);
2115           emitcode ("mov", "(%s+%d),a",
2116                     regs390[i].base, 8 * bank + regs390[i].offset);
2117           emitcode ("dec", "%s", r->name);
2118
2119         }
2120       else
2121         emitcode ("pop", "(%s+%d)",
2122                   regs390[i].base, 8 * bank + regs390[i].offset);
2123     }
2124
2125   if (options.useXstack)
2126     {
2127       emitcode ("mov", "_spx,%s", r->name);
2128     }
2129     
2130   if (aop)
2131   {
2132       freeAsmop (NULL, aop, ic, TRUE);  
2133   }    
2134 }
2135
2136 /*-----------------------------------------------------------------*/
2137 /* saveRBank - saves an entire register bank on the stack          */
2138 /*-----------------------------------------------------------------*/
2139 static void
2140 saveRBank (int bank, iCode * ic, bool pushPsw)
2141 {
2142   int i;
2143   asmop *aop = NULL;
2144   regs *r = NULL;
2145
2146   if (options.useXstack)
2147     {
2148         if (!ic)
2149         {
2150           /* Assume r0 is available for use. */
2151                   r = ds390_regWithIdx (R0_IDX);;
2152         }
2153         else
2154         {
2155           aop = newAsmop (0);
2156           r = getFreePtr (ic, &aop, FALSE);
2157         }
2158         emitcode ("mov", "%s,_spx", r->name);    
2159     }
2160
2161   for (i = 0; i < ds390_nRegs; i++)
2162     {
2163       if (options.useXstack)
2164         {
2165           emitcode ("inc", "%s", r->name);
2166           emitcode ("mov", "a,(%s+%d)",
2167                     regs390[i].base, 8 * bank + regs390[i].offset);
2168           emitcode ("movx", "@%s,a", r->name);
2169         }
2170       else
2171         emitcode ("push", "(%s+%d)",
2172                   regs390[i].base, 8 * bank + regs390[i].offset);
2173     }
2174
2175   if (pushPsw)
2176     {
2177       if (options.useXstack)
2178         {
2179           emitcode ("mov", "a,psw");
2180           emitcode ("movx", "@%s,a", r->name);
2181           emitcode ("inc", "%s", r->name);
2182           emitcode ("mov", "_spx,%s", r->name);
2183         }
2184       else
2185       {
2186         emitcode ("push", "psw");
2187       }
2188
2189       emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2190     }
2191   
2192   if (aop)
2193   {
2194        freeAsmop (NULL, aop, ic, TRUE);
2195   }    
2196     
2197   if (ic)
2198   {  
2199       ic->bankSaved = 1;
2200   }
2201 }
2202
2203 /*-----------------------------------------------------------------*/
2204 /* genCall - generates a call statement                            */
2205 /*-----------------------------------------------------------------*/
2206 static void
2207 genCall (iCode * ic)
2208 {
2209   sym_link *dtype;
2210   bool restoreBank = FALSE;
2211   bool swapBanks = FALSE;
2212
2213   D (emitcode (";", "genCall "););
2214
2215   /* if we are calling a not _naked function that is not using
2216      the same register bank then we need to save the
2217      destination registers on the stack */
2218   dtype = operandType (IC_LEFT (ic));
2219   if (dtype && !IFFUNC_ISNAKED(dtype) &&
2220       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2221       IFFUNC_ISISR (currFunc->type))
2222   {
2223       if (!ic->bankSaved) 
2224       {
2225            /* This is unexpected; the bank should have been saved in
2226             * genFunction.
2227             */
2228            saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2229            restoreBank = TRUE;
2230       }
2231       swapBanks = TRUE;
2232   }
2233   
2234     /* if caller saves & we have not saved then */
2235     if (!ic->regsSaved)
2236       saveRegisters (ic);
2237   
2238   /* if send set is not empty the assign */
2239   /* We've saved all the registers we care about;
2240   * therefore, we may clobber any register not used
2241   * in the calling convention (i.e. anything not in
2242   * fReturn.
2243   */
2244   if (_G.sendSet)
2245     {
2246       iCode *sic;
2247
2248       for (sic = setFirstItem (_G.sendSet); sic;
2249            sic = setNextItem (_G.sendSet))
2250         {
2251           int size, offset = 0;
2252
2253           aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2254           size = AOP_SIZE (IC_LEFT (sic));
2255
2256           _startLazyDPSEvaluation ();
2257           while (size--)
2258             {
2259               char *l = aopGet (AOP(IC_LEFT(sic)), offset,
2260                                 FALSE, FALSE, TRUE);
2261                 if ((AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR) && size)
2262                 {
2263                     emitcode("mov", "%s,%s", regs390[offset].name, l);
2264                 }
2265                 else if (strcmp (l, fReturn[offset]))
2266                 {
2267                     emitcode ("mov", "%s,%s",
2268                               fReturn[offset],
2269                               l);
2270                 }
2271               offset++;
2272             }
2273           _endLazyDPSEvaluation ();
2274           if (AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR)
2275           {
2276               size = AOP_SIZE (IC_LEFT (sic));
2277               if (size)
2278               {
2279                  size--;
2280               }
2281               while (size)
2282               {
2283                    size--;
2284                    emitcode("mov", "%s,%s",
2285                                     fReturn[size], regs390[size].name);
2286               }
2287           }
2288           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2289         }
2290       _G.sendSet = NULL;
2291     }  
2292     
2293   if (swapBanks)
2294   {
2295         emitcode ("mov", "psw,#0x%02x", 
2296            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2297   }
2298
2299   /* make the call */
2300   emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2301                             OP_SYMBOL (IC_LEFT (ic))->rname :
2302                             OP_SYMBOL (IC_LEFT (ic))->name));
2303
2304   if (swapBanks)
2305   {
2306        emitcode ("mov", "psw,#0x%02x", 
2307           ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2308   }
2309
2310   /* if we need assign a result value */
2311   if ((IS_ITEMP (IC_RESULT (ic)) &&
2312        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2313         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2314       IS_TRUE_SYMOP (IC_RESULT (ic)))
2315     {
2316       if (isOperandInFarSpace (IC_RESULT (ic))
2317           && getSize (operandType (IC_RESULT (ic))) <= 2)
2318         {
2319           int size = getSize (operandType (IC_RESULT (ic)));
2320
2321           /* Special case for 1 or 2 byte return in far space. */
2322           MOVA (fReturn[0]);
2323           if (size > 1)
2324             {
2325               emitcode ("mov", "b,%s", fReturn[1]);
2326             }
2327
2328           aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2329           aopPut (AOP (IC_RESULT (ic)), "a", 0);
2330
2331           if (size > 1)
2332             {
2333               aopPut (AOP (IC_RESULT (ic)), "b", 1);
2334             }
2335           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2336         }
2337       else
2338         {
2339           _G.accInUse++;
2340           aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2341           _G.accInUse--;
2342
2343           assignResultValue (IC_RESULT (ic));
2344
2345           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2346         }
2347     }
2348
2349   /* adjust the stack for parameters if
2350      required */
2351   if (ic->parmBytes)
2352     {
2353       int i;
2354       if (ic->parmBytes > 3)
2355         {
2356           emitcode ("mov", "a,%s", spname);
2357           emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2358           emitcode ("mov", "%s,a", spname);
2359         }
2360       else
2361         for (i = 0; i < ic->parmBytes; i++)
2362           emitcode ("dec", "%s", spname);
2363     }
2364
2365   /* if we hade saved some registers then unsave them */
2366   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2367     unsaveRegisters (ic);
2368
2369   /* if register bank was saved then pop them */
2370   if (restoreBank)
2371     unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2372 }
2373
2374 /*-----------------------------------------------------------------*/
2375 /* genPcall - generates a call by pointer statement                */
2376 /*-----------------------------------------------------------------*/
2377 static void
2378 genPcall (iCode * ic)
2379 {
2380   sym_link *dtype;
2381   symbol *rlbl = newiTempLabel (NULL);
2382   bool restoreBank=FALSE;
2383
2384   D (emitcode (";", "genPcall ");
2385     );
2386
2387
2388   /* if caller saves & we have not saved then */
2389   if (!ic->regsSaved)
2390     saveRegisters (ic);
2391
2392   /* if we are calling a function that is not using
2393      the same register bank then we need to save the
2394      destination registers on the stack */
2395   dtype = operandType (IC_LEFT (ic));
2396   if (dtype && !IFFUNC_ISNAKED(dtype) &&
2397       IFFUNC_ISISR (currFunc->type) &&
2398       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2399     saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2400     restoreBank=TRUE;
2401   }
2402
2403   /* push the return address on to the stack */
2404   emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2405   emitcode ("push", "acc");
2406   emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2407   emitcode ("push", "acc");
2408
2409   if (options.model == MODEL_FLAT24)
2410     {
2411       emitcode ("mov", "a,#(%05d$ >> 16)", (rlbl->key + 100));
2412       emitcode ("push", "acc");
2413     }
2414
2415   /* now push the calling address */
2416   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2417
2418   pushSide (IC_LEFT (ic), FPTRSIZE);
2419
2420   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2421
2422   /* if send set is not empty the assign */
2423   if (_G.sendSet)
2424     {
2425       iCode *sic;
2426
2427       for (sic = setFirstItem (_G.sendSet); sic;
2428            sic = setNextItem (_G.sendSet))
2429         {
2430           int size, offset = 0;
2431
2432           aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2433           size = AOP_SIZE (IC_LEFT (sic));
2434           _startLazyDPSEvaluation ();
2435           while (size--)
2436             {
2437               char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2438                                 FALSE, FALSE, TRUE);
2439               if (strcmp (l, fReturn[offset]))
2440                 {
2441                   emitcode ("mov", "%s,%s",
2442                             fReturn[offset],
2443                             l);
2444                 }
2445               offset++;
2446             }
2447           _endLazyDPSEvaluation ();
2448           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2449         }
2450       _G.sendSet = NULL;
2451     }
2452
2453   emitcode ("ret", "");
2454   emitcode ("", "%05d$:", (rlbl->key + 100));
2455
2456
2457   /* if we need assign a result value */
2458   if ((IS_ITEMP (IC_RESULT (ic)) &&
2459        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2460         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2461       IS_TRUE_SYMOP (IC_RESULT (ic)))
2462     {
2463
2464       _G.accInUse++;
2465       aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2466       _G.accInUse--;
2467
2468       assignResultValue (IC_RESULT (ic));
2469
2470       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2471     }
2472
2473   /* adjust the stack for parameters if
2474      required */
2475   if (ic->parmBytes)
2476     {
2477       int i;
2478       if (ic->parmBytes > 3)
2479         {
2480           emitcode ("mov", "a,%s", spname);
2481           emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2482           emitcode ("mov", "%s,a", spname);
2483         }
2484       else
2485         for (i = 0; i < ic->parmBytes; i++)
2486           emitcode ("dec", "%s", spname);
2487
2488     }
2489
2490   /* if register bank was saved then unsave them */
2491   if (restoreBank)
2492     unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2493   
2494   /* if we hade saved some registers then
2495      unsave them */
2496   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2497     unsaveRegisters (ic);
2498
2499 }
2500
2501 /*-----------------------------------------------------------------*/
2502 /* resultRemat - result  is rematerializable                       */
2503 /*-----------------------------------------------------------------*/
2504 static int
2505 resultRemat (iCode * ic)
2506 {
2507   if (SKIP_IC (ic) || ic->op == IFX)
2508     return 0;
2509
2510   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2511     {
2512       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2513       if (sym->remat && !POINTER_SET (ic))
2514         return 1;
2515     }
2516
2517   return 0;
2518 }
2519
2520 #if defined(__BORLANDC__) || defined(_MSC_VER)
2521 #define STRCASECMP stricmp
2522 #else
2523 #define STRCASECMP strcasecmp
2524 #endif
2525
2526 /*-----------------------------------------------------------------*/
2527 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2528 /*-----------------------------------------------------------------*/
2529 static bool
2530 inExcludeList (char *s)
2531 {
2532   int i = 0;
2533
2534   if (options.excludeRegs[i] &&
2535       STRCASECMP (options.excludeRegs[i], "none") == 0)
2536     return FALSE;
2537
2538   for (i = 0; options.excludeRegs[i]; i++)
2539     {
2540       if (options.excludeRegs[i] &&
2541           STRCASECMP (s, options.excludeRegs[i]) == 0)
2542         return TRUE;
2543     }
2544   return FALSE;
2545 }
2546
2547 /*-----------------------------------------------------------------*/
2548 /* genFunction - generated code for function entry                 */
2549 /*-----------------------------------------------------------------*/
2550 static void
2551 genFunction (iCode * ic)
2552 {
2553   symbol *sym;
2554   sym_link *ftype;
2555   bool   switchedPSW = FALSE;
2556
2557   D (emitcode (";", "genFunction "););
2558
2559   _G.nRegsSaved = 0;
2560   /* create the function header */
2561   emitcode (";", "-----------------------------------------");
2562   emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2563   emitcode (";", "-----------------------------------------");
2564
2565   emitcode ("", "%s:", sym->rname);
2566   ftype = operandType (IC_LEFT (ic));
2567
2568   if (IFFUNC_ISNAKED(ftype))
2569   {
2570       emitcode(";", "naked function: no prologue.");
2571       return;
2572   }
2573
2574   /* if critical function then turn interrupts off */
2575   if (IFFUNC_ISCRITICAL (ftype))
2576     emitcode ("clr", "ea");
2577
2578   /* here we need to generate the equates for the
2579      register bank if required */
2580   if (FUNC_REGBANK (ftype) != rbank)
2581     {
2582       int i;
2583
2584       rbank = FUNC_REGBANK (ftype);
2585       for (i = 0; i < ds390_nRegs; i++)
2586         {
2587           if (strcmp (regs390[i].base, "0") == 0)
2588             emitcode ("", "%s = 0x%02x",
2589                       regs390[i].dname,
2590                       8 * rbank + regs390[i].offset);
2591           else
2592             emitcode ("", "%s = %s + 0x%02x",
2593                       regs390[i].dname,
2594                       regs390[i].base,
2595                       8 * rbank + regs390[i].offset);
2596         }
2597     }
2598
2599   /* if this is an interrupt service routine then
2600      save acc, b, dpl, dph  */
2601   if (IFFUNC_ISISR (sym->type))
2602     {
2603
2604       if (!inExcludeList ("acc"))
2605         emitcode ("push", "acc");
2606       if (!inExcludeList ("b"))
2607         emitcode ("push", "b");
2608       if (!inExcludeList ("dpl"))
2609         emitcode ("push", "dpl");
2610       if (!inExcludeList ("dph"))
2611         emitcode ("push", "dph");
2612       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2613         {
2614           emitcode ("push", "dpx");
2615           /* Make sure we're using standard DPTR */
2616           emitcode ("push", "dps");
2617           emitcode ("mov", "dps, #0x00");
2618           if (options.stack10bit)
2619             {
2620               /* This ISR could conceivably use DPTR2. Better save it. */
2621               emitcode ("push", "dpl1");
2622               emitcode ("push", "dph1");
2623               emitcode ("push", "dpx1");
2624               emitcode ("push",  DP2_RESULT_REG);
2625             }
2626         }
2627       /* if this isr has no bank i.e. is going to
2628          run with bank 0 , then we need to save more
2629          registers :-) */
2630       if (!FUNC_REGBANK (sym->type))
2631         {
2632
2633           /* if this function does not call any other
2634              function then we can be economical and
2635              save only those registers that are used */
2636           if (!IFFUNC_HASFCALL(sym->type))
2637             {
2638               int i;
2639
2640               /* if any registers used */
2641               if (sym->regsUsed)
2642                 {
2643                   /* save the registers used */
2644                   for (i = 0; i < sym->regsUsed->size; i++)
2645                     {
2646                       if (bitVectBitValue (sym->regsUsed, i) ||
2647                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2648                         emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2649                     }
2650                 }
2651
2652             }
2653           else
2654             {
2655               /* this function has  a function call cannot
2656                  determines register usage so we will have to push the
2657                  entire bank */
2658               saveRBank (0, ic, FALSE);
2659             }
2660         }
2661         else
2662         {
2663             /* This ISR uses a non-zero bank.
2664              *
2665              * We assume that the bank is available for our
2666              * exclusive use.
2667              *
2668              * However, if this ISR calls a function which uses some
2669              * other bank, we must save that bank entirely.
2670              */
2671             unsigned long banksToSave = 0;
2672             
2673             if (IFFUNC_HASFCALL(sym->type))
2674             {
2675
2676 #define MAX_REGISTER_BANKS 4
2677
2678                 iCode *i;
2679                 int ix;
2680
2681                 for (i = ic; i; i = i->next)
2682                 {
2683                     if (i->op == ENDFUNCTION)
2684                     {
2685                         /* we got to the end OK. */
2686                         break;
2687                     }
2688                     
2689                     if (i->op == CALL)
2690                     {
2691                         sym_link *dtype;
2692                         
2693                         dtype = operandType (IC_LEFT(i));
2694                         if (dtype 
2695                          && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2696                         {
2697                              /* Mark this bank for saving. */
2698                              if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2699                              {
2700                                  werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2701                              }
2702                              else
2703                              {
2704                                  banksToSave |= (1 << FUNC_REGBANK(dtype));
2705                              }
2706                              
2707                              /* And note that we don't need to do it in 
2708                               * genCall.
2709                               */
2710                              i->bankSaved = 1;
2711                         }
2712                     }
2713                     if (i->op == PCALL)
2714                     {
2715                         /* This is a mess; we have no idea what
2716                          * register bank the called function might
2717                          * use.
2718                          *
2719                          * The only thing I can think of to do is
2720                          * throw a warning and hope.
2721                          */
2722                         werror(W_FUNCPTR_IN_USING_ISR);   
2723                     }
2724                 }
2725
2726                 if (banksToSave && options.useXstack)
2727                 {
2728                     /* Since we aren't passing it an ic, 
2729                      * saveRBank will assume r0 is available to abuse.
2730                      *
2731                      * So switch to our (trashable) bank now, so
2732                      * the caller's R0 isn't trashed.
2733                      */
2734                     emitcode ("push", "psw");
2735                     emitcode ("mov", "psw,#0x%02x", 
2736                               (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2737                     switchedPSW = TRUE;
2738                 }
2739                 
2740                 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2741                 {
2742                      if (banksToSave & (1 << ix))
2743                      {
2744                          saveRBank(ix, NULL, FALSE);
2745                      }
2746                 }
2747             }
2748             // jwk: this needs a closer look
2749             SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2750         }
2751     }
2752   else
2753     {
2754       /* if callee-save to be used for this function
2755          then save the registers being used in this function */
2756       if (IFFUNC_CALLEESAVES(sym->type))
2757         {
2758           int i;
2759
2760           /* if any registers used */
2761           if (sym->regsUsed)
2762             {
2763               /* save the registers used */
2764               for (i = 0; i < sym->regsUsed->size; i++)
2765                 {
2766                   if (bitVectBitValue (sym->regsUsed, i) ||
2767                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2768                     {
2769                       emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2770                       _G.nRegsSaved++;
2771                     }
2772                 }
2773             }
2774         }
2775     }
2776
2777   /* set the register bank to the desired value */
2778   if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
2779    && !switchedPSW)
2780     {
2781       emitcode ("push", "psw");
2782       emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2783     }
2784
2785   if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2786     {
2787
2788       if (options.useXstack)
2789         {
2790           emitcode ("mov", "r0,%s", spname);
2791           emitcode ("mov", "a,_bp");
2792           emitcode ("movx", "@r0,a");
2793           emitcode ("inc", "%s", spname);
2794         }
2795       else
2796         {
2797           /* set up the stack */
2798           emitcode ("push", "_bp");     /* save the callers stack  */
2799         }
2800       emitcode ("mov", "_bp,%s", spname);
2801     }
2802
2803   /* adjust the stack for the function */
2804   if (sym->stack)
2805     {
2806
2807       int i = sym->stack;
2808       if (i > 256)
2809         werror (W_STACK_OVERFLOW, sym->name);
2810
2811       if (i > 3 && sym->recvSize < 4)
2812         {
2813
2814           emitcode ("mov", "a,sp");
2815           emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2816           emitcode ("mov", "sp,a");
2817
2818         }
2819       else
2820         while (i--)
2821           emitcode ("inc", "sp");
2822     }
2823
2824   if (sym->xstack)
2825     {
2826
2827       emitcode ("mov", "a,_spx");
2828       emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2829       emitcode ("mov", "_spx,a");
2830     }
2831
2832 }
2833
2834 /*-----------------------------------------------------------------*/
2835 /* genEndFunction - generates epilogue for functions               */
2836 /*-----------------------------------------------------------------*/
2837 static void
2838 genEndFunction (iCode * ic)
2839 {
2840   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2841
2842   D (emitcode (";", "genEndFunction "););
2843
2844   if (IFFUNC_ISNAKED(sym->type))
2845   {
2846       emitcode(";", "naked function: no epilogue.");
2847       return;
2848   }
2849
2850   if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2851     {
2852       emitcode ("mov", "%s,_bp", spname);
2853     }
2854
2855   /* if use external stack but some variables were
2856      added to the local stack then decrement the
2857      local stack */
2858   if (options.useXstack && sym->stack)
2859     {
2860       emitcode ("mov", "a,sp");
2861       emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2862       emitcode ("mov", "sp,a");
2863     }
2864
2865
2866   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2867     {
2868       if (options.useXstack)
2869         {
2870           emitcode ("mov", "r0,%s", spname);
2871           emitcode ("movx", "a,@r0");
2872           emitcode ("mov", "_bp,a");
2873           emitcode ("dec", "%s", spname);
2874         }
2875       else
2876         {
2877           emitcode ("pop", "_bp");
2878         }
2879     }
2880
2881   /* restore the register bank  */
2882   if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
2883   {
2884     if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
2885      || !options.useXstack)
2886     {
2887         /* Special case of ISR using non-zero bank with useXstack
2888          * is handled below.
2889          */
2890         emitcode ("pop", "psw");
2891     }
2892   }
2893
2894   if (IFFUNC_ISISR (sym->type))
2895     {
2896
2897       /* now we need to restore the registers */
2898       /* if this isr has no bank i.e. is going to
2899          run with bank 0 , then we need to save more
2900          registers :-) */
2901       if (!FUNC_REGBANK (sym->type))
2902         {
2903           /* if this function does not call any other
2904              function then we can be economical and
2905              save only those registers that are used */
2906           if (!IFFUNC_HASFCALL(sym->type))
2907             {
2908               int i;
2909
2910               /* if any registers used */
2911               if (sym->regsUsed)
2912                 {
2913                   /* save the registers used */
2914                   for (i = sym->regsUsed->size; i >= 0; i--)
2915                     {
2916                       if (bitVectBitValue (sym->regsUsed, i) ||
2917                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2918                         emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2919                     }
2920                 }
2921
2922             }
2923           else
2924             {
2925               /* this function has  a function call cannot
2926                  determines register usage so we will have to pop the
2927                  entire bank */
2928               unsaveRBank (0, ic, FALSE);
2929             }
2930         }
2931         else
2932         {
2933             /* This ISR uses a non-zero bank.
2934              *
2935              * Restore any register banks saved by genFunction
2936              * in reverse order.
2937              */
2938           // jwk: this needs a closer look
2939             unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2940             int ix;
2941           
2942             for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2943             {
2944                 if (savedBanks & (1 << ix))
2945                 {
2946                     unsaveRBank(ix, NULL, FALSE);
2947                 }
2948             }
2949             
2950             if (options.useXstack)
2951             {
2952                 /* Restore bank AFTER calling unsaveRBank,
2953                  * since it can trash r0.
2954                  */
2955                 emitcode ("pop", "psw");
2956             }
2957         }
2958
2959       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2960         {
2961           if (options.stack10bit)
2962             {
2963               emitcode ("pop", DP2_RESULT_REG);
2964               emitcode ("pop", "dpx1");
2965               emitcode ("pop", "dph1");
2966               emitcode ("pop", "dpl1");
2967             }
2968           emitcode ("pop", "dps");
2969           emitcode ("pop", "dpx");
2970         }
2971       if (!inExcludeList ("dph"))
2972         emitcode ("pop", "dph");
2973       if (!inExcludeList ("dpl"))
2974         emitcode ("pop", "dpl");
2975       if (!inExcludeList ("b"))
2976         emitcode ("pop", "b");
2977       if (!inExcludeList ("acc"))
2978         emitcode ("pop", "acc");
2979
2980       if (IFFUNC_ISCRITICAL (sym->type))
2981         emitcode ("setb", "ea");
2982
2983       /* if debug then send end of function */
2984       if (options.debug && currFunc) {
2985           _G.debugLine = 1;
2986           emitcode ("", "C$%s$%d$%d$%d ==.",
2987                     FileBaseName (ic->filename), currFunc->lastLine,
2988                     ic->level, ic->block);
2989           if (IS_STATIC (currFunc->etype))
2990             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2991           else
2992             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2993           _G.debugLine = 0;
2994         }
2995
2996       emitcode ("reti", "");
2997     }
2998   else
2999     {
3000       if (IFFUNC_ISCRITICAL (sym->type))
3001         emitcode ("setb", "ea");
3002
3003       if (IFFUNC_CALLEESAVES(sym->type))
3004         {
3005           int i;
3006
3007           /* if any registers used */
3008           if (sym->regsUsed)
3009             {
3010               /* save the registers used */
3011               for (i = sym->regsUsed->size; i >= 0; i--)
3012                 {
3013                   if (bitVectBitValue (sym->regsUsed, i) ||
3014                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3015                     emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3016                 }
3017             }
3018
3019         }
3020
3021       /* if debug then send end of function */
3022       if (options.debug && currFunc)
3023         {
3024           _G.debugLine = 1;
3025           emitcode ("", "C$%s$%d$%d$%d ==.",
3026                     FileBaseName (ic->filename), currFunc->lastLine,
3027                     ic->level, ic->block);
3028           if (IS_STATIC (currFunc->etype))
3029             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3030           else
3031             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3032           _G.debugLine = 0;
3033         }
3034
3035       emitcode ("ret", "");
3036     }
3037
3038 }
3039
3040 /*-----------------------------------------------------------------*/
3041 /* genRet - generate code for return statement                     */
3042 /*-----------------------------------------------------------------*/
3043 static void
3044 genRet (iCode * ic)
3045 {
3046   int size, offset = 0, pushed = 0;
3047
3048   D (emitcode (";", "genRet ");
3049     );
3050
3051   /* if we have no return value then
3052      just generate the "ret" */
3053   if (!IC_LEFT (ic))
3054     goto jumpret;
3055
3056   /* we have something to return then
3057      move the return value into place */
3058   aopOp (IC_LEFT (ic), ic, FALSE, TRUE);
3059   size = AOP_SIZE (IC_LEFT (ic));
3060
3061   _startLazyDPSEvaluation ();
3062   while (size--)
3063     {
3064       char *l;
3065       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3066         {
3067           l = aopGet (AOP (IC_LEFT (ic)), offset++,
3068                       FALSE, TRUE, FALSE);
3069           emitcode ("push", "%s", l);
3070           pushed++;
3071         }
3072       else
3073         {
3074           /* Since A is the last element of fReturn,
3075            * is is OK to clobber it in the aopGet.
3076            */
3077           l = aopGet (AOP (IC_LEFT (ic)), offset,
3078                       FALSE, FALSE, TRUE);
3079           if (strcmp (fReturn[offset], l))
3080             emitcode ("mov", "%s,%s", fReturn[offset++], l);
3081         }
3082     }
3083   _endLazyDPSEvaluation ();
3084
3085   if (pushed)
3086     {
3087       while (pushed)
3088         {
3089           pushed--;
3090           if (strcmp (fReturn[pushed], "a"))
3091             emitcode ("pop", fReturn[pushed]);
3092           else
3093             emitcode ("pop", "acc");
3094         }
3095     }
3096   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3097
3098 jumpret:
3099   /* generate a jump to the return label
3100      if the next is not the return statement */
3101   if (!(ic->next && ic->next->op == LABEL &&
3102         IC_LABEL (ic->next) == returnLabel))
3103
3104     emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3105
3106 }
3107
3108 /*-----------------------------------------------------------------*/
3109 /* genLabel - generates a label                                    */
3110 /*-----------------------------------------------------------------*/
3111 static void
3112 genLabel (iCode * ic)
3113 {
3114   /* special case never generate */
3115   if (IC_LABEL (ic) == entryLabel)
3116     return;
3117
3118   D (emitcode (";", "genLabel ");
3119     );
3120
3121   emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3122 }
3123
3124 /*-----------------------------------------------------------------*/
3125 /* genGoto - generates a ljmp                                      */
3126 /*-----------------------------------------------------------------*/
3127 static void
3128 genGoto (iCode * ic)
3129 {
3130   D (emitcode (";", "genGoto ");
3131     );
3132   emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
3133 }
3134
3135 /*-----------------------------------------------------------------*/
3136 /* findLabelBackwards: walks back through the iCode chain looking  */
3137 /* for the given label. Returns number of iCode instructions     */
3138 /* between that label and given ic.          */
3139 /* Returns zero if label not found.          */
3140 /*-----------------------------------------------------------------*/
3141 static int
3142 findLabelBackwards (iCode * ic, int key)
3143 {
3144   int count = 0;
3145
3146   while (ic->prev)
3147     {
3148       ic = ic->prev;
3149       count++;
3150
3151       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3152         {
3153           /* printf("findLabelBackwards = %d\n", count); */
3154           return count;
3155         }
3156     }
3157
3158   return 0;
3159 }
3160
3161 /*-----------------------------------------------------------------*/
3162 /* genPlusIncr :- does addition with increment if possible         */
3163 /*-----------------------------------------------------------------*/
3164 static bool
3165 genPlusIncr (iCode * ic)
3166 {
3167   unsigned int icount;
3168   unsigned int size = getDataSize (IC_RESULT (ic));
3169
3170   /* will try to generate an increment */
3171   /* if the right side is not a literal
3172      we cannot */
3173   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3174     return FALSE;
3175
3176   /* if the literal value of the right hand side
3177      is greater than 4 then it is not worth it */
3178   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3179     return FALSE;
3180
3181   /* if increment 16 bits in register */
3182   if (
3183        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3184        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3185        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3186        (size > 1) &&
3187        (icount == 1))
3188     {
3189       symbol *tlbl;
3190       int emitTlbl;
3191       int labelRange;
3192
3193       /* If the next instruction is a goto and the goto target
3194        * is <= 5 instructions previous to this, we can generate
3195        * jumps straight to that target.
3196        */
3197       if (ic->next && ic->next->op == GOTO
3198           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3199           && labelRange <= 5)
3200         {
3201           emitcode (";", "tail increment optimized (range %d)", labelRange);
3202           tlbl = IC_LABEL (ic->next);
3203           emitTlbl = 0;
3204         }
3205       else
3206         {
3207           tlbl = newiTempLabel (NULL);
3208           emitTlbl = 1;
3209         }
3210       emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3211       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3212           IS_AOP_PREG (IC_RESULT (ic)))
3213         emitcode ("cjne", "%s,#0x00,%05d$"
3214                   ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3215                   ,tlbl->key + 100);
3216       else
3217         {
3218           emitcode ("clr", "a");
3219           emitcode ("cjne", "a,%s,%05d$"
3220                     ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3221                     ,tlbl->key + 100);
3222         }
3223
3224       emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3225       if (size > 2)
3226         {
3227           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3228               IS_AOP_PREG (IC_RESULT (ic)))
3229             emitcode ("cjne", "%s,#0x00,%05d$"
3230                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3231                       ,tlbl->key + 100);
3232           else
3233             emitcode ("cjne", "a,%s,%05d$"
3234                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3235                       ,tlbl->key + 100);
3236
3237           emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3238         }
3239       if (size > 3)
3240         {
3241           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3242               IS_AOP_PREG (IC_RESULT (ic)))
3243             emitcode ("cjne", "%s,#0x00,%05d$"
3244                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3245                       ,tlbl->key + 100);
3246           else
3247             {
3248               emitcode ("cjne", "a,%s,%05d$"
3249                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3250                         ,tlbl->key + 100);
3251             }
3252           emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3253         }
3254
3255       if (emitTlbl)
3256         {
3257           emitcode ("", "%05d$:", tlbl->key + 100);
3258         }
3259       return TRUE;
3260     }
3261
3262   /* if the sizes are greater than 1 then we cannot */
3263   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3264       AOP_SIZE (IC_LEFT (ic)) > 1)
3265     return FALSE;
3266
3267   /* we can if the aops of the left & result match or
3268      if they are in registers and the registers are the
3269      same */
3270   if (
3271        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3272        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3273        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3274     {
3275
3276       if (icount > 3)
3277         {
3278           MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3279           emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3280           aopPut (AOP (IC_RESULT (ic)), "a", 0);
3281         }
3282       else
3283         {
3284
3285           _startLazyDPSEvaluation ();
3286           while (icount--)
3287             {
3288               emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3289             }
3290           _endLazyDPSEvaluation ();
3291         }
3292
3293       return TRUE;
3294     }
3295
3296   return FALSE;
3297 }
3298
3299 /*-----------------------------------------------------------------*/
3300 /* outBitAcc - output a bit in acc                                 */
3301 /*-----------------------------------------------------------------*/
3302 static void
3303 outBitAcc (operand * result)
3304 {
3305   symbol *tlbl = newiTempLabel (NULL);
3306   /* if the result is a bit */
3307   if (AOP_TYPE (result) == AOP_CRY)
3308     {
3309       aopPut (AOP (result), "a", 0);
3310     }
3311   else
3312     {
3313       emitcode ("jz", "%05d$", tlbl->key + 100);
3314       emitcode ("mov", "a,%s", one);
3315       emitcode ("", "%05d$:", tlbl->key + 100);
3316       outAcc (result);
3317     }
3318 }
3319
3320 /*-----------------------------------------------------------------*/
3321 /* genPlusBits - generates code for addition of two bits           */
3322 /*-----------------------------------------------------------------*/
3323 static void
3324 genPlusBits (iCode * ic)
3325 {
3326   D (emitcode (";", "genPlusBits ");
3327     );
3328   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3329     {
3330       symbol *lbl = newiTempLabel (NULL);
3331       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3332       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3333       emitcode ("cpl", "c");
3334       emitcode ("", "%05d$:", (lbl->key + 100));
3335       outBitC (IC_RESULT (ic));
3336     }
3337   else
3338     {
3339       emitcode ("clr", "a");
3340       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3341       emitcode ("rlc", "a");
3342       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3343       emitcode ("addc", "a,#0x00");
3344       outAcc (IC_RESULT (ic));
3345     }
3346 }
3347
3348 static void
3349 adjustArithmeticResult (iCode * ic)
3350 {
3351   if (opIsGptr (IC_RESULT (ic)) &&
3352       opIsGptr (IC_LEFT (ic)) &&
3353       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3354     {
3355       aopPut (AOP (IC_RESULT (ic)),
3356               aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3357               GPTRSIZE - 1);
3358     }
3359
3360   if (opIsGptr (IC_RESULT (ic)) &&
3361       opIsGptr (IC_RIGHT (ic)) &&
3362       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3363     {
3364       aopPut (AOP (IC_RESULT (ic)),
3365             aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3366               GPTRSIZE - 1);
3367     }
3368
3369   if (opIsGptr (IC_RESULT (ic)) &&
3370       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3371       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3372       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3373       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3374     {
3375       char buffer[5];
3376       sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3377       aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3378     }
3379 }
3380
3381 #if 0 // AOP_OP_3 is deprecated; nobody likes Ack errors.
3382       // Please don't bring it back without a really good reason.
3383 // Macro to aopOp all three operands of an ic. Will fatal if this cannot be done
3384 // (because all three operands are in far space).
3385 #define AOP_OP_3(ic) \
3386     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3387     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3388     aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3389               (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3390     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3391         AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3392     { \
3393         /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3394         fprintf(stderr,                                  \
3395                "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno);   \
3396     }
3397 #endif
3398
3399 // Macro to aopOp all three operands of an ic. If this cannot be done, 
3400 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3401 // will be set TRUE. The caller must then handle the case specially, noting
3402 // that the IC_RESULT operand is not aopOp'd.
3403 #define AOP_OP_3_NOFATAL(ic, rc) \
3404     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3405     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3406     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3407         isOperandInFarSpace(IC_RESULT(ic))) \
3408     { \
3409        /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3410        rc = TRUE; \
3411     }  \
3412     else \
3413     { \
3414        aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3415                                      (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3416        rc = FALSE; \
3417        if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3418            AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3419        { \
3420             /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3421             fprintf(stderr,                                  \
3422                     "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno);   \
3423        } \
3424     }
3425
3426 // aopOp the left & right operands of an ic.
3427 #define AOP_OP_2(ic) \
3428     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3429     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3430
3431 // convienience macro.
3432 #define AOP_SET_LOCALS(ic) \
3433     left = IC_LEFT(ic); \
3434     right = IC_RIGHT(ic); \
3435     result = IC_RESULT(ic);
3436
3437
3438 // Given an integer value of pushedSize bytes on the stack,
3439 // adjust it to be resultSize bytes, either by discarding
3440 // the most significant bytes or by zero-padding.
3441 //
3442 // On exit from this macro, pushedSize will have been adjusted to
3443 // equal resultSize, and ACC may be trashed.
3444 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize)            \
3445       /* If the pushed data is bigger than the result,          \
3446        * simply discard unused bytes. Icky, but works.          \
3447        */                                                       \
3448       while (pushedSize > resultSize)                           \
3449       {                                                         \
3450           D (emitcode (";", "discarding unused result byte."););\
3451           emitcode ("pop", "acc");                              \
3452           pushedSize--;                                         \
3453       }                                                         \
3454       if (pushedSize < resultSize)                              \
3455       {                                                         \
3456           emitcode ("clr", "a");                                \
3457           /* Conversly, we haven't pushed enough here.          \
3458            * just zero-pad, and all is well.                    \
3459            */                                                   \
3460           while (pushedSize < resultSize)                       \
3461           {                                                     \
3462               emitcode("push", "acc");                          \
3463               pushedSize++;                                     \
3464           }                                                     \
3465       }                                                         \
3466       assert(pushedSize == resultSize);
3467
3468 /*-----------------------------------------------------------------*/
3469 /* genPlus - generates code for addition                           */
3470 /*-----------------------------------------------------------------*/
3471 static void
3472 genPlus (iCode * ic)
3473 {
3474   int size, offset = 0;
3475   bool pushResult = FALSE;
3476   int rSize;
3477
3478   D (emitcode (";", "genPlus "););
3479
3480   /* special cases :- */
3481
3482   AOP_OP_3_NOFATAL (ic, pushResult);
3483   if (pushResult)
3484     {
3485       D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3486     }
3487
3488   if (!pushResult)
3489     {
3490       /* if literal, literal on the right or
3491          if left requires ACC or right is already
3492          in ACC */
3493       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3494        || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3495           || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3496         {
3497           operand *t = IC_RIGHT (ic);
3498           IC_RIGHT (ic) = IC_LEFT (ic);
3499           IC_LEFT (ic) = t;
3500           emitcode (";", "Swapped plus args.");
3501         }
3502
3503       /* if both left & right are in bit
3504          space */
3505       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3506           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3507         {
3508           genPlusBits (ic);
3509           goto release;
3510         }
3511
3512       /* if left in bit space & right literal */
3513       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3514           AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3515         {
3516           emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3517           /* if result in bit space */
3518           if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3519             {
3520               if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3521                 emitcode ("cpl", "c");
3522               outBitC (IC_RESULT (ic));
3523             }
3524           else
3525             {
3526               size = getDataSize (IC_RESULT (ic));
3527               _startLazyDPSEvaluation ();
3528               while (size--)
3529                 {
3530                   MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3531                   emitcode ("addc", "a,#00");
3532                   aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3533                 }
3534               _endLazyDPSEvaluation ();
3535             }
3536           goto release;
3537         }
3538
3539       /* if I can do an increment instead
3540          of add then GOOD for ME */
3541       if (genPlusIncr (ic) == TRUE)
3542         {
3543           emitcode (";", "did genPlusIncr");
3544           goto release;
3545         }
3546
3547     }
3548   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3549
3550   _startLazyDPSEvaluation ();
3551   while (size--)
3552     {
3553       if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
3554         {
3555           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3556           if (offset == 0)
3557             emitcode ("add", "a,%s",
3558                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3559           else
3560             emitcode ("addc", "a,%s",
3561                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3562         }
3563       else
3564         {
3565           if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
3566           {
3567               /* right is going to use ACC or we would have taken the
3568                * above branch.
3569                */
3570               assert(AOP_NEEDSACC(IC_RIGHT(ic)));
3571        TR_AP("#3");
3572               D(emitcode(";", "+ AOP_ACC special case."););
3573               emitcode("xch", "a, %s", DP2_RESULT_REG);
3574           }
3575           MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3576           if (offset == 0)
3577           {
3578             if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
3579             {
3580          TR_AP("#4");
3581                 emitcode("add", "a, %s", DP2_RESULT_REG); 
3582             }
3583             else
3584             {
3585                 emitcode ("add", "a,%s",
3586                         aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE, FALSE));
3587             }
3588           }
3589           else
3590           {
3591             emitcode ("addc", "a,%s",
3592                   aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3593           }
3594         }
3595       if (!pushResult)
3596         {
3597           aopPut (AOP (IC_RESULT (ic)), "a", offset);
3598         }
3599       else
3600         {
3601           emitcode ("push", "acc");
3602         }
3603       offset++;
3604     }
3605   _endLazyDPSEvaluation ();
3606
3607   if (pushResult)
3608     {
3609       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3610
3611       size = getDataSize (IC_LEFT (ic));
3612       rSize = getDataSize (IC_RESULT (ic));
3613
3614       ADJUST_PUSHED_RESULT(size, rSize);
3615
3616       _startLazyDPSEvaluation ();
3617       while (size--)
3618         {
3619           emitcode ("pop", "acc");
3620           aopPut (AOP (IC_RESULT (ic)), "a", size);
3621         }
3622       _endLazyDPSEvaluation ();
3623     }
3624
3625   adjustArithmeticResult (ic);
3626
3627 release:
3628   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3629   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3630   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3631 }
3632
3633 /*-----------------------------------------------------------------*/
3634 /* genMinusDec :- does subtraction with deccrement if possible     */
3635 /*-----------------------------------------------------------------*/
3636 static bool
3637 genMinusDec (iCode * ic)
3638 {
3639   unsigned int icount;
3640   unsigned int size = getDataSize (IC_RESULT (ic));
3641
3642   /* will try to generate an increment */
3643   /* if the right side is not a literal
3644      we cannot */
3645   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3646     return FALSE;
3647
3648   /* if the literal value of the right hand side
3649      is greater than 4 then it is not worth it */
3650   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3651     return FALSE;
3652
3653   /* if decrement 16 bits in register */
3654   if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3655       AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3656       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3657       (size > 1) &&
3658       (icount == 1))
3659     {
3660       symbol *tlbl;
3661       int emitTlbl;
3662       int labelRange;
3663
3664       /* If the next instruction is a goto and the goto target
3665          * is <= 5 instructions previous to this, we can generate
3666          * jumps straight to that target.
3667        */
3668       if (ic->next && ic->next->op == GOTO
3669           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3670           && labelRange <= 5)
3671         {
3672           emitcode (";", "tail decrement optimized (range %d)", labelRange);
3673           tlbl = IC_LABEL (ic->next);
3674           emitTlbl = 0;
3675         }
3676       else
3677         {
3678           tlbl = newiTempLabel (NULL);
3679           emitTlbl = 1;
3680         }
3681
3682       emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3683       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3684           AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3685           IS_AOP_PREG (IC_RESULT (ic)))
3686         emitcode ("cjne", "%s,#0xff,%05d$"
3687                   ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3688                   ,tlbl->key + 100);
3689       else
3690         {
3691           emitcode ("mov", "a,#0xff");
3692           emitcode ("cjne", "a,%s,%05d$"
3693                     ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3694                     ,tlbl->key + 100);
3695         }
3696       emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3697       if (size > 2)
3698         {
3699           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3700               AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3701               IS_AOP_PREG (IC_RESULT (ic)))
3702             emitcode ("cjne", "%s,#0xff,%05d$"
3703                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3704                       ,tlbl->key + 100);
3705           else
3706             {
3707               emitcode ("cjne", "a,%s,%05d$"
3708                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3709                         ,tlbl->key + 100);
3710             }
3711           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3712         }
3713       if (size > 3)
3714         {
3715           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3716               AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3717               IS_AOP_PREG (IC_RESULT (ic)))
3718             emitcode ("cjne", "%s,#0xff,%05d$"
3719                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3720                       ,tlbl->key + 100);
3721           else
3722             {
3723               emitcode ("cjne", "a,%s,%05d$"
3724                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3725                         ,tlbl->key + 100);
3726             }
3727           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3728         }
3729       if (emitTlbl)
3730         {
3731           emitcode ("", "%05d$:", tlbl->key + 100);
3732         }
3733       return TRUE;
3734     }
3735
3736   /* if the sizes are greater than 1 then we cannot */
3737   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3738       AOP_SIZE (IC_LEFT (ic)) > 1)
3739     return FALSE;
3740
3741   /* we can if the aops of the left & result match or
3742      if they are in registers and the registers are the
3743      same */
3744   if (
3745        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3746        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3747        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3748     {
3749
3750       _startLazyDPSEvaluation ();
3751       while (icount--)
3752         {
3753           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
3754         }
3755       _endLazyDPSEvaluation ();
3756
3757       return TRUE;
3758     }
3759
3760   return FALSE;
3761 }
3762
3763 /*-----------------------------------------------------------------*/
3764 /* addSign - complete with sign                                    */
3765 /*-----------------------------------------------------------------*/
3766 static void
3767 addSign (operand * result, int offset, int sign)
3768 {
3769   int size = (getDataSize (result) - offset);
3770   if (size > 0)
3771     {
3772       _startLazyDPSEvaluation();
3773       if (sign)
3774         {
3775           emitcode ("rlc", "a");
3776           emitcode ("subb", "a,acc");
3777           while (size--)
3778           {
3779             aopPut (AOP (result), "a", offset++);
3780           }
3781         }
3782       else
3783       {
3784         while (size--)
3785         {
3786           aopPut (AOP (result), zero, offset++);
3787         }
3788       }
3789       _endLazyDPSEvaluation();
3790     }
3791 }
3792
3793 /*-----------------------------------------------------------------*/
3794 /* genMinusBits - generates code for subtraction  of two bits      */
3795 /*-----------------------------------------------------------------*/
3796 static void
3797 genMinusBits (iCode * ic)
3798 {
3799   symbol *lbl = newiTempLabel (NULL);
3800
3801   D (emitcode (";", "genMinusBits "););
3802
3803   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3804     {
3805       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3806       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3807       emitcode ("cpl", "c");
3808       emitcode ("", "%05d$:", (lbl->key + 100));
3809       outBitC (IC_RESULT (ic));
3810     }
3811   else
3812     {
3813       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3814       emitcode ("subb", "a,acc");
3815       emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3816       emitcode ("inc", "a");
3817       emitcode ("", "%05d$:", (lbl->key + 100));
3818       aopPut (AOP (IC_RESULT (ic)), "a", 0);
3819       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3820     }
3821 }
3822
3823 /*-----------------------------------------------------------------*/
3824 /* genMinus - generates code for subtraction                       */
3825 /*-----------------------------------------------------------------*/
3826 static void
3827 genMinus (iCode * ic)
3828 {
3829   int size, offset = 0;
3830   int rSize;
3831   unsigned long lit = 0L;
3832   bool pushResult = FALSE;
3833
3834   D (emitcode (";", "genMinus "););
3835
3836   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3837   aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
3838   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
3839       (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
3840     {
3841       pushResult = TRUE;
3842     }
3843   else
3844     {
3845       aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
3846
3847       /* special cases :- */
3848       /* if both left & right are in bit space */
3849       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3850           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3851         {
3852           genMinusBits (ic);
3853           goto release;
3854         }
3855
3856       /* if I can do an decrement instead
3857          of subtract then GOOD for ME */
3858       if (genMinusDec (ic) == TRUE)
3859         goto release;
3860
3861     }
3862
3863   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3864
3865   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3866     {
3867       CLRC;
3868     }
3869   else
3870     {
3871       lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3872       lit = -(long) lit;
3873     }
3874
3875
3876   /* if literal, add a,#-lit, else normal subb */
3877   _startLazyDPSEvaluation ();
3878   while (size--)
3879     {
3880       MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3881       if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3882         emitcode ("subb", "a,%s",
3883                   aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3884       else
3885         {
3886           /* first add without previous c */
3887           if (!offset) {
3888             if (!size && lit==-1) {
3889               emitcode ("dec", "a");
3890             } else {
3891               emitcode ("add", "a,#0x%02x",
3892                         (unsigned int) (lit & 0x0FFL));
3893             }
3894           } else {
3895             emitcode ("addc", "a,#0x%02x",
3896                       (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3897           }
3898         }
3899
3900       if (pushResult)
3901         {
3902           emitcode ("push", "acc");
3903         }
3904       else
3905         {
3906           aopPut (AOP (IC_RESULT (ic)), "a", offset);
3907         }
3908       offset++;
3909     }
3910   _endLazyDPSEvaluation ();
3911
3912   if (pushResult)
3913     {
3914       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3915
3916       size = getDataSize (IC_LEFT (ic));
3917       rSize = getDataSize (IC_RESULT (ic));
3918
3919       ADJUST_PUSHED_RESULT(size, rSize);
3920
3921       _startLazyDPSEvaluation ();
3922       while (size--)
3923         {
3924           emitcode ("pop", "acc");
3925           aopPut (AOP (IC_RESULT (ic)), "a", size);
3926         }
3927       _endLazyDPSEvaluation ();
3928     }
3929
3930   adjustArithmeticResult (ic);
3931
3932 release:
3933   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3934   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3935   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3936 }
3937
3938
3939 /*-----------------------------------------------------------------*/
3940 /* genMultbits :- multiplication of bits                           */
3941 /*-----------------------------------------------------------------*/
3942 static void
3943 genMultbits (operand * left,
3944              operand * right,
3945              operand * result,
3946              iCode   * ic)
3947 {
3948   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3949   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3950   aopOp(result, ic, TRUE, FALSE);
3951   outBitC (result);
3952 }
3953
3954
3955 /*-----------------------------------------------------------------*/
3956 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
3957 /*-----------------------------------------------------------------*/
3958 static void
3959 genMultOneByte (operand * left,
3960                 operand * right,
3961                 operand * result,
3962                 iCode   * ic)
3963 {
3964   sym_link *opetype = operandType (result);
3965   symbol *lbl;
3966
3967
3968   /* (if two literals: the value is computed before) */
3969   /* if one literal, literal on the right */
3970   if (AOP_TYPE (left) == AOP_LIT)
3971     {
3972       operand *t = right;
3973       right = left;
3974       left = t;
3975       emitcode (";", "swapped left and right");
3976     }
3977
3978   if (SPEC_USIGN(opetype)
3979       // ignore the sign of left and right, what else can we do?
3980       || (SPEC_USIGN(operandType(left)) && 
3981           SPEC_USIGN(operandType(right)))) {
3982     // just an unsigned 8*8=8/16 multiply
3983     //emitcode (";","unsigned");
3984     emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3985     MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3986     emitcode ("mul", "ab");
3987    
3988     _G.accInUse++;
3989     aopOp(result, ic, TRUE, FALSE);
3990       
3991       if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
3992       {
3993           // this should never happen
3994           fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
3995                    AOP_SIZE(result), __FILE__, lineno);
3996           exit (1);
3997       }      
3998       
3999     aopPut (AOP (result), "a", 0);
4000     _G.accInUse--;
4001     if (AOP_SIZE(result)==2) 
4002     {
4003       aopPut (AOP (result), "b", 1);
4004     }
4005     return;
4006   }
4007
4008   // we have to do a signed multiply
4009
4010   emitcode (";", "signed");
4011   emitcode ("clr", "F0"); // reset sign flag
4012   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4013
4014   lbl=newiTempLabel(NULL);
4015   emitcode ("jnb", "acc.7,%05d$",  lbl->key+100);
4016   // left side is negative, 8-bit two's complement, this fails for -128
4017   emitcode ("setb", "F0"); // set sign flag
4018   emitcode ("cpl", "a");
4019   emitcode ("inc", "a");
4020
4021   emitcode ("", "%05d$:", lbl->key+100);
4022
4023   /* if literal */
4024   if (AOP_TYPE(right)==AOP_LIT) {
4025     signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
4026     /* AND literal negative */
4027     if ((int) val < 0) {
4028       emitcode ("cpl", "F0"); // complement sign flag
4029       emitcode ("mov", "b,#0x%02x", -val);
4030     } else {
4031       emitcode ("mov", "b,#0x%02x", val);
4032     }
4033   } else {
4034     lbl=newiTempLabel(NULL);
4035     emitcode ("mov", "b,a");
4036     emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4037     emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
4038     // right side is negative, 8-bit two's complement
4039     emitcode ("cpl", "F0"); // complement sign flag
4040     emitcode ("cpl", "a");
4041     emitcode ("inc", "a");
4042     emitcode ("", "%05d$:", lbl->key+100);
4043   }
4044   emitcode ("mul", "ab");
4045     
4046   _G.accInUse++;
4047   aopOp(result, ic, TRUE, FALSE);
4048     
4049   if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4050   {
4051     // this should never happen
4052       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4053                AOP_SIZE(result), __FILE__, lineno);
4054       exit (1);
4055   }    
4056     
4057   lbl=newiTempLabel(NULL);
4058   emitcode ("jnb", "F0,%05d$", lbl->key+100);
4059   // only ONE op was negative, we have to do a 8/16-bit two's complement
4060   emitcode ("cpl", "a"); // lsb
4061   if (AOP_SIZE(result)==1) {
4062     emitcode ("inc", "a");
4063   } else {
4064     emitcode ("add", "a,#1");
4065     emitcode ("xch", "a,b");
4066     emitcode ("cpl", "a"); // msb
4067     emitcode ("addc", "a,#0");
4068     emitcode ("xch", "a,b");
4069   }
4070
4071   emitcode ("", "%05d$:", lbl->key+100);
4072   aopPut (AOP (result), "a", 0);
4073   _G.accInUse--;
4074   if (AOP_SIZE(result)==2) {
4075     aopPut (AOP (result), "b", 1);
4076   }
4077 }
4078
4079 /*-----------------------------------------------------------------*/
4080 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply    */
4081 /*-----------------------------------------------------------------*/
4082 static void genMultTwoByte (operand *left, operand *right, 
4083                             operand *result, iCode *ic)
4084 {
4085         sym_link *retype = getSpec(operandType(right));
4086         sym_link *letype = getSpec(operandType(left));
4087         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4088         symbol *lbl;
4089
4090         if (AOP_TYPE (left) == AOP_LIT) {
4091                 operand *t = right;
4092                 right = left;
4093                 left = t;
4094         }
4095         /* save EA bit in F1 */
4096         lbl = newiTempLabel(NULL);
4097         emitcode ("setb","F1");
4098         emitcode ("jbc","EA,%05d$",lbl->key+100);
4099         emitcode ("clr","F1");
4100         emitcode("","%05d$:",lbl->key+100);
4101
4102         /* load up MB with right */
4103         if (!umult) {
4104                 emitcode("clr","F0");
4105                 if (AOP_TYPE(right) == AOP_LIT) {
4106                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
4107                         if (val < 0) {
4108                                 emitcode("setb","F0");
4109                                 val = -val;
4110                         }
4111                         emitcode ("mov","mb,#0x%02x",val & 0xff);
4112                         emitcode ("mov","mb,#0x%02x",(val >> 8) & 0xff);                    
4113                 } else {
4114                         lbl = newiTempLabel(NULL);
4115                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4116                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4117                         emitcode ("jnb","acc.7,%05d$",lbl->key+100);            
4118                         emitcode ("xch", "a,b");
4119                         emitcode ("cpl","a");
4120                         emitcode ("add", "a,#1");
4121                         emitcode ("xch", "a,b");
4122                         emitcode ("cpl", "a"); // msb
4123                         emitcode ("addc", "a,#0");
4124                         emitcode ("setb","F0");
4125                         emitcode ("","%05d$:",lbl->key+100);
4126                         emitcode ("mov","mb,b");
4127                         emitcode ("mov","mb,a");
4128                 }
4129         } else {
4130                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4131                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4132         }
4133         /* load up MA with left */
4134         if (!umult) {
4135                 lbl = newiTempLabel(NULL);
4136                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4137                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4138                 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4139                 emitcode ("xch", "a,b");
4140                 emitcode ("cpl","a");
4141                 emitcode ("add", "a,#1");
4142                 emitcode ("xch", "a,b");
4143                 emitcode ("cpl", "a"); // msb
4144                 emitcode ("addc","a,#0");
4145                 emitcode ("jbc","F0,%05d$",lbl->key+100);
4146                 emitcode ("setb","F0");
4147                 emitcode ("","%05d$:",lbl->key+100);
4148                 emitcode ("mov","ma,b");
4149                 emitcode ("mov","ma,a");
4150         } else {
4151                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4152                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4153         }
4154         /* wait for multiplication to finish */
4155         lbl = newiTempLabel(NULL);
4156         emitcode("","%05d$:", lbl->key+100);
4157         emitcode("mov","a,mcnt1");
4158         emitcode("anl","a,#0x80");
4159         emitcode("jnz","%05d$",lbl->key+100);
4160         
4161         freeAsmop (left, NULL, ic, TRUE);
4162         freeAsmop (right, NULL, ic,TRUE);
4163         aopOp(result, ic, TRUE, FALSE);
4164
4165         /* if unsigned then simple */   
4166         if (umult) {
4167                 emitcode ("mov","a,ma");
4168                 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4169                 emitcode ("mov","a,ma");
4170                 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4171                 aopPut(AOP(result),"ma",1);
4172                 aopPut(AOP(result),"ma",0);
4173         } else {
4174                 emitcode("push","ma");
4175                 emitcode("push","ma");
4176                 emitcode("push","ma");
4177                 MOVA("ma");
4178                 /* negate result if needed */
4179                 lbl = newiTempLabel(NULL);      
4180                 emitcode("jnb","F0,%05d$",lbl->key+100);
4181                 emitcode("cpl","a");
4182                 emitcode("add","a,#1");
4183                 emitcode("","%05d$:", lbl->key+100);
4184                 if (AOP_TYPE(result) == AOP_ACC)
4185                 {
4186                     D(emitcode(";", "ACC special case."););
4187                     /* We know result is the only live aop, and 
4188                      * it's obviously not a DPTR2, so AP is available.
4189                      */
4190                     emitcode("mov", "%s,acc", DP2_RESULT_REG);
4191                 }
4192                 else
4193                 {
4194                     aopPut(AOP(result),"a",0);
4195                 }
4196             
4197                 emitcode("pop","acc");
4198                 lbl = newiTempLabel(NULL);      
4199                 emitcode("jnb","F0,%05d$",lbl->key+100);
4200                 emitcode("cpl","a");
4201                 emitcode("addc","a,#0");
4202                 emitcode("","%05d$:", lbl->key+100);
4203                 aopPut(AOP(result),"a",1);
4204                 emitcode("pop","acc");
4205                 if (AOP_SIZE(result) >= 3) {
4206                         lbl = newiTempLabel(NULL);      
4207                         emitcode("jnb","F0,%05d$",lbl->key+100);
4208                         emitcode("cpl","a");
4209                         emitcode("addc","a,#0");                        
4210                         emitcode("","%05d$:", lbl->key+100);
4211                         aopPut(AOP(result),"a",2);
4212                 }
4213                 emitcode("pop","acc");
4214                 if (AOP_SIZE(result) >= 4) {
4215                         lbl = newiTempLabel(NULL);      
4216                         emitcode("jnb","F0,%05d$",lbl->key+100);
4217                         emitcode("cpl","a");
4218                         emitcode("addc","a,#0");                        
4219                         emitcode("","%05d$:", lbl->key+100);
4220                         aopPut(AOP(result),"a",3);
4221                 }
4222                 if (AOP_TYPE(result) == AOP_ACC)
4223                 {
4224                     /* We stashed the result away above. */
4225                     emitcode("mov", "acc,%s", DP2_RESULT_REG);
4226                 }           
4227                 
4228         }
4229         freeAsmop (result, NULL, ic, TRUE);
4230
4231         /* restore EA bit in F1 */
4232         lbl = newiTempLabel(NULL);
4233         emitcode ("jnb","F1,%05d$",lbl->key+100);
4234         emitcode ("setb","EA");
4235         emitcode("","%05d$:",lbl->key+100);
4236         return ;
4237 }
4238
4239 /*-----------------------------------------------------------------*/
4240 /* genMult - generates code for multiplication                     */
4241 /*-----------------------------------------------------------------*/
4242 static void
4243 genMult (iCode * ic)
4244 {
4245   operand *left = IC_LEFT (ic);
4246   operand *right = IC_RIGHT (ic);
4247   operand *result = IC_RESULT (ic);
4248
4249   D (emitcode (";", "genMult "););
4250
4251   /* assign the amsops */
4252   AOP_OP_2 (ic);
4253
4254   /* special cases first */
4255   /* both are bits */
4256   if (AOP_TYPE (left) == AOP_CRY &&
4257       AOP_TYPE (right) == AOP_CRY)
4258     {
4259       genMultbits (left, right, result, ic);
4260       goto release;
4261     }
4262
4263   /* if both are of size == 1 */
4264   if (AOP_SIZE (left) == 1 &&
4265       AOP_SIZE (right) == 1)
4266     {
4267       genMultOneByte (left, right, result, ic);
4268       goto release;
4269     }
4270
4271   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4272           /* use the ds390 ARITHMETIC accel UNIT */
4273           genMultTwoByte (left, right, result, ic);
4274           return ;
4275   }
4276   /* should have been converted to function call */
4277   assert (0);
4278
4279 release:
4280   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4281   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4282   freeAsmop (result, NULL, ic, TRUE);
4283 }
4284
4285 /*-----------------------------------------------------------------*/
4286 /* genDivbits :- division of bits                                  */
4287 /*-----------------------------------------------------------------*/
4288 static void
4289 genDivbits (operand * left,
4290             operand * right,
4291             operand * result,
4292             iCode   * ic)
4293 {
4294
4295   char *l;
4296
4297   /* the result must be bit */
4298   LOAD_AB_FOR_DIV (left, right, l);
4299   emitcode ("div", "ab");
4300   emitcode ("rrc", "a");
4301   aopOp(result, ic, TRUE, FALSE);
4302     
4303   aopPut (AOP (result), "c", 0);
4304 }
4305
4306 /*-----------------------------------------------------------------*/
4307 /* genDivOneByte : 8 bit division                                  */
4308 /*-----------------------------------------------------------------*/
4309 static void
4310 genDivOneByte (operand * left,
4311                operand * right,
4312                operand * result,
4313                iCode   * ic)
4314 {
4315   sym_link *opetype = operandType (result);
4316   char *l;
4317   symbol *lbl;
4318   int size, offset;
4319
4320   offset = 1;
4321   /* signed or unsigned */
4322   if (SPEC_USIGN (opetype))
4323     {
4324         /* unsigned is easy */
4325         LOAD_AB_FOR_DIV (left, right, l);
4326         emitcode ("div", "ab");
4327
4328         _G.accInUse++;
4329         aopOp(result, ic, TRUE, FALSE);
4330         aopPut (AOP (result), "a", 0);
4331         _G.accInUse--;
4332
4333         size = AOP_SIZE (result) - 1;
4334         
4335         while (size--)
4336         {
4337             aopPut (AOP (result), zero, offset++);
4338         }
4339       return;
4340     }
4341
4342   /* signed is a little bit more difficult */
4343
4344   /* save the signs of the operands */
4345   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4346   MOVA (l);
4347   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4348   emitcode ("push", "acc");     /* save it on the stack */
4349
4350   /* now sign adjust for both left & right */
4351   l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4352   MOVA (l);
4353   lbl = newiTempLabel (NULL);
4354   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4355   emitcode ("cpl", "a");
4356   emitcode ("inc", "a");
4357   emitcode ("", "%05d$:", (lbl->key + 100));
4358   emitcode ("mov", "b,a");
4359
4360   /* sign adjust left side */
4361   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4362   MOVA (l);
4363
4364   lbl = newiTempLabel (NULL);
4365   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4366   emitcode ("cpl", "a");
4367   emitcode ("inc", "a");
4368   emitcode ("", "%05d$:", (lbl->key + 100));
4369
4370   /* now the division */
4371   emitcode ("nop", "; workaround for DS80C390 div bug.");
4372   emitcode ("div", "ab");
4373   /* we are interested in the lower order
4374      only */
4375   emitcode ("mov", "b,a");
4376   lbl = newiTempLabel (NULL);
4377   emitcode ("pop", "acc");
4378   /* if there was an over flow we don't
4379      adjust the sign of the result */
4380   emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4381   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4382   CLRC;
4383   emitcode ("clr", "a");
4384   emitcode ("subb", "a,b");
4385   emitcode ("mov", "b,a");
4386   emitcode ("", "%05d$:", (lbl->key + 100));
4387
4388   /* now we are done */
4389     _G.accInUse++;
4390     aopOp(result, ic, TRUE, FALSE);
4391     
4392     aopPut (AOP (result), "b", 0);
4393     
4394     size = AOP_SIZE (result) - 1;
4395     
4396     if (size > 0)
4397     {
4398       emitcode ("mov", "c,b.7");
4399       emitcode ("subb", "a,acc");
4400     }
4401     while (size--)
4402     {
4403         aopPut (AOP (result), "a", offset++);
4404     }
4405     _G.accInUse--;
4406
4407 }
4408
4409 /*-----------------------------------------------------------------*/
4410 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide       */
4411 /*-----------------------------------------------------------------*/
4412 static void genDivTwoByte (operand *left, operand *right, 
4413                             operand *result, iCode *ic)
4414 {
4415         sym_link *retype = getSpec(operandType(right));
4416         sym_link *letype = getSpec(operandType(left));
4417         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4418         symbol *lbl;
4419
4420         /* save EA bit in F1 */
4421         lbl = newiTempLabel(NULL);
4422         emitcode ("setb","F1");
4423         emitcode ("jbc","EA,%05d$",lbl->key+100);
4424         emitcode ("clr","F1");
4425         emitcode("","%05d$:",lbl->key+100);
4426
4427         /* load up MA with left */
4428         if (!umult) {
4429                 emitcode("clr","F0");
4430                 lbl = newiTempLabel(NULL);
4431                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4432                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4433                 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4434                 emitcode ("xch", "a,b");
4435                 emitcode ("cpl","a");
4436                 emitcode ("add", "a,#1");
4437                 emitcode ("xch", "a,b");
4438                 emitcode ("cpl", "a"); // msb
4439                 emitcode ("addc","a,#0");
4440                 emitcode ("setb","F0");
4441                 emitcode ("","%05d$:",lbl->key+100);
4442                 emitcode ("mov","ma,b");
4443                 emitcode ("mov","ma,a");
4444         } else {
4445                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4446                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4447         }
4448
4449         /* load up MB with right */
4450         if (!umult) {
4451                 if (AOP_TYPE(right) == AOP_LIT) {
4452                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
4453                         if (val < 0) {
4454                                 lbl = newiTempLabel(NULL);
4455                                 emitcode ("jbc","F0,%05d$",lbl->key+100);
4456                                 emitcode("setb","F0");
4457                                 emitcode ("","%05d$:",lbl->key+100);
4458                                 val = -val;
4459                         } 
4460                         emitcode ("mov","mb,#0x%02x",val & 0xff);                   
4461                         emitcode ("mov","mb,#0x%02x",(val >> 8) & 0xff);
4462                 } else {
4463                         lbl = newiTempLabel(NULL);
4464                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4465                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4466                         emitcode ("jnb","acc.7,%05d$",lbl->key+100);            
4467                         emitcode ("xch", "a,b");
4468                         emitcode ("cpl","a");
4469                         emitcode ("add", "a,#1");
4470                         emitcode ("xch", "a,b");
4471                         emitcode ("cpl", "a"); // msb
4472                         emitcode ("addc", "a,#0");
4473                         emitcode ("jbc","F0,%05d$",lbl->key+100);
4474                         emitcode ("setb","F0");
4475                         emitcode ("","%05d$:",lbl->key+100);
4476                         emitcode ("mov","mb,b");
4477                         emitcode ("mov","mb,a");
4478                 }
4479         } else {
4480                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4481                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4482         }
4483
4484         /* wait for multiplication to finish */
4485         lbl = newiTempLabel(NULL);
4486         emitcode("","%05d$:", lbl->key+100);
4487         emitcode("mov","a,mcnt1");
4488         emitcode("anl","a,#0x80");
4489         emitcode("jnz","%05d$",lbl->key+100);
4490         
4491         freeAsmop (left, NULL, ic, TRUE);
4492         freeAsmop (right, NULL, ic,TRUE);
4493         aopOp(result, ic, TRUE, FALSE);
4494
4495         /* if unsigned then simple */   
4496         if (umult) {
4497                 aopPut(AOP(result),"ma",1);
4498                 aopPut(AOP(result),"ma",0);
4499         } else {
4500                 emitcode("push","ma");
4501                 MOVA("ma");
4502                 /* negate result if needed */
4503                 lbl = newiTempLabel(NULL);      
4504                 emitcode("jnb","F0,%05d$",lbl->key+100);
4505                 emitcode("cpl","a");
4506                 emitcode("add","a,#1");
4507                 emitcode("","%05d$:", lbl->key+100);
4508                 aopPut(AOP(result),"a",0);
4509                 emitcode("pop","acc");
4510                 lbl = newiTempLabel(NULL);      
4511                 emitcode("jnb","F0,%05d$",lbl->key+100);
4512                 emitcode("cpl","a");
4513                 emitcode("addc","a,#0");
4514                 emitcode("","%05d$:", lbl->key+100);
4515                 aopPut(AOP(result),"a",1);
4516         }
4517         freeAsmop (result, NULL, ic, TRUE);
4518         /* restore EA bit in F1 */
4519         lbl = newiTempLabel(NULL);
4520         emitcode ("jnb","F1,%05d$",lbl->key+100);
4521         emitcode ("setb","EA");
4522         emitcode("","%05d$:",lbl->key+100);
4523         return ;
4524 }
4525
4526 /*-----------------------------------------------------------------*/
4527 /* genDiv - generates code for division                            */
4528 /*-----------------------------------------------------------------*/
4529 static void
4530 genDiv (iCode * ic)
4531 {
4532   operand *left = IC_LEFT (ic);
4533   operand *right = IC_RIGHT (ic);
4534   operand *result = IC_RESULT (ic);
4535
4536   D (emitcode (";", "genDiv "););
4537
4538   /* assign the amsops */
4539   AOP_OP_2 (ic);
4540
4541   /* special cases first */
4542   /* both are bits */
4543   if (AOP_TYPE (left) == AOP_CRY &&
4544       AOP_TYPE (right) == AOP_CRY)
4545     {
4546       genDivbits (left, right, result, ic);
4547       goto release;
4548     }
4549
4550   /* if both are of size == 1 */
4551   if (AOP_SIZE (left) == 1 &&
4552       AOP_SIZE (right) == 1)
4553     {
4554       genDivOneByte (left, right, result, ic);
4555       goto release;
4556     }
4557
4558   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4559           /* use the ds390 ARITHMETIC accel UNIT */
4560           genDivTwoByte (left, right, result, ic);
4561           return ;
4562   }
4563   /* should have been converted to function call */
4564   assert (0);
4565 release:
4566   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4567   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4568   freeAsmop (result, NULL, ic, TRUE);
4569 }
4570
4571 /*-----------------------------------------------------------------*/
4572 /* genModbits :- modulus of bits                                   */
4573 /*-----------------------------------------------------------------*/
4574 static void
4575 genModbits (operand * left,
4576             operand * right,
4577             operand * result,
4578             iCode   * ic)
4579 {
4580
4581   char *l;
4582
4583   /* the result must be bit */
4584   LOAD_AB_FOR_DIV (left, right, l);
4585   emitcode ("div", "ab");
4586   emitcode ("mov", "a,b");
4587   emitcode ("rrc", "a");
4588   aopOp(result, ic, TRUE, FALSE);
4589   aopPut (AOP (result), "c", 0);
4590 }
4591
4592 /*-----------------------------------------------------------------*/
4593 /* genModOneByte : 8 bit modulus                                   */
4594 /*-----------------------------------------------------------------*/
4595 static void
4596 genModOneByte (operand * left,
4597                operand * right,
4598                operand * result,
4599                iCode   * ic)
4600 {
4601   sym_link *opetype = operandType (result);
4602   char *l;
4603   symbol *lbl;
4604
4605   /* signed or unsigned */
4606   if (SPEC_USIGN (opetype))
4607     {
4608       /* unsigned is easy */
4609       LOAD_AB_FOR_DIV (left, right, l);
4610       emitcode ("div", "ab");
4611       aopOp(result, ic, TRUE, FALSE);   
4612       aopPut (AOP (result), "b", 0);
4613       return;
4614     }
4615
4616   /* signed is a little bit more difficult */
4617
4618   /* save the signs of the operands */
4619   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4620   MOVA (l);
4621
4622   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4623   emitcode ("push", "acc");     /* save it on the stack */
4624
4625   /* now sign adjust for both left & right */
4626   l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4627   MOVA (l);
4628
4629   lbl = newiTempLabel (NULL);
4630   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4631   emitcode ("cpl", "a");
4632   emitcode ("inc", "a");
4633   emitcode ("", "%05d$:", (lbl->key + 100));
4634   emitcode ("mov", "b,a");
4635
4636   /* sign adjust left side */
4637   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4638   MOVA (l);
4639
4640   lbl = newiTempLabel (NULL);
4641   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4642   emitcode ("cpl", "a");
4643   emitcode ("inc", "a");
4644   emitcode ("", "%05d$:", (lbl->key + 100));
4645
4646   /* now the multiplication */
4647   emitcode ("nop", "; workaround for DS80C390 div bug.");
4648   emitcode ("div", "ab");
4649   /* we are interested in the lower order
4650      only */
4651   lbl = newiTempLabel (NULL);
4652   emitcode ("pop", "acc");
4653   /* if there was an over flow we don't
4654      adjust the sign of the result */
4655   emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4656   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4657   CLRC;
4658   emitcode ("clr", "a");
4659   emitcode ("subb", "a,b");
4660   emitcode ("mov", "b,a");
4661   emitcode ("", "%05d$:", (lbl->key + 100));
4662
4663   /* now we are done */
4664   aopOp(result, ic, TRUE, FALSE);    
4665   aopPut (AOP (result), "b", 0);
4666
4667 }
4668
4669 /*-----------------------------------------------------------------*/
4670 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus      */
4671 /*-----------------------------------------------------------------*/
4672 static void genModTwoByte (operand *left, operand *right, 
4673                             operand *result, iCode *ic)
4674 {
4675         sym_link *retype = getSpec(operandType(right));
4676         sym_link *letype = getSpec(operandType(left));
4677         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4678         symbol *lbl;
4679
4680         /* load up MA with left */
4681         /* save EA bit in F1 */
4682         lbl = newiTempLabel(NULL);
4683         emitcode ("setb","F1");
4684         emitcode ("jbc","EA,%05d$",lbl->key+100);
4685         emitcode ("clr","F1");
4686         emitcode("","%05d$:",lbl->key+100);
4687
4688         if (!umult) {
4689                 lbl = newiTempLabel(NULL);
4690                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4691                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4692                 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4693                 emitcode ("xch", "a,b");
4694                 emitcode ("cpl","a");
4695                 emitcode ("add", "a,#1");
4696                 emitcode ("xch", "a,b");
4697                 emitcode ("cpl", "a"); // msb
4698                 emitcode ("addc","a,#0");
4699                 emitcode ("","%05d$:",lbl->key+100);
4700                 emitcode ("mov","ma,b");
4701                 emitcode ("mov","ma,a");
4702         } else {
4703                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4704                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4705         }
4706
4707         /* load up MB with right */
4708         if (!umult) {
4709                 if (AOP_TYPE(right) == AOP_LIT) {
4710                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
4711                         if (val < 0) {
4712                                 val = -val;
4713                         } 
4714                         emitcode ("mov","mb,#0x%02x",val & 0xff);
4715                         emitcode ("mov","mb,#0x%02x",(val >> 8) & 0xff);                    
4716                 } else {
4717                         lbl = newiTempLabel(NULL);
4718                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4719                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4720                         emitcode ("jnb","acc.7,%05d$",lbl->key+100);            
4721                         emitcode ("xch", "a,b");
4722                         emitcode ("cpl","a");
4723                         emitcode ("add", "a,#1");
4724                         emitcode ("xch", "a,b");
4725                         emitcode ("cpl", "a"); // msb
4726                         emitcode ("addc", "a,#0");
4727                         emitcode ("","%05d$:",lbl->key+100);
4728                         emitcode ("mov","mb,b");
4729                         emitcode ("mov","mb,a");
4730                 }
4731         } else {
4732                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4733                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4734         }
4735
4736         /* wait for multiplication to finish */
4737         lbl = newiTempLabel(NULL);
4738         emitcode("","%05d$:", lbl->key+100);
4739         emitcode("mov","a,mcnt1");
4740         emitcode("anl","a,#0x80");
4741         emitcode("jnz","%05d$",lbl->key+100);
4742         
4743         freeAsmop (left, NULL, ic, TRUE);
4744         freeAsmop (right, NULL, ic,TRUE);
4745         aopOp(result, ic, TRUE, FALSE);
4746
4747         aopPut(AOP(result),"mb",1);
4748         aopPut(AOP(result),"mb",0);
4749         freeAsmop (result, NULL, ic, TRUE);
4750
4751         /* restore EA bit in F1 */
4752         lbl = newiTempLabel(NULL);
4753         emitcode ("jnb","F1,%05d$",lbl->key+100);
4754         emitcode ("setb","EA");
4755         emitcode("","%05d$:",lbl->key+100);
4756         return ;
4757 }
4758
4759 /*-----------------------------------------------------------------*/
4760 /* genMod - generates code for division                            */
4761 /*-----------------------------------------------------------------*/
4762 static void
4763 genMod (iCode * ic)
4764 {
4765   operand *left = IC_LEFT (ic);
4766   operand *right = IC_RIGHT (ic);
4767   operand *result = IC_RESULT (ic);
4768
4769   D (emitcode (";", "genMod "); );
4770
4771   /* assign the amsops */
4772   AOP_OP_2 (ic);
4773
4774   /* special cases first */
4775   /* both are bits */
4776   if (AOP_TYPE (left) == AOP_CRY &&
4777       AOP_TYPE (right) == AOP_CRY)
4778     {
4779       genModbits (left, right, result, ic);
4780       goto release;
4781     }
4782
4783   /* if both are of size == 1 */
4784   if (AOP_SIZE (left) == 1 &&
4785       AOP_SIZE (right) == 1)
4786     {
4787       genModOneByte (left, right, result, ic);
4788       goto release;
4789     }
4790
4791   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4792           /* use the ds390 ARITHMETIC accel UNIT */
4793           genModTwoByte (left, right, result, ic);
4794           return ;
4795   }
4796
4797   /* should have been converted to function call */
4798   assert (0);
4799
4800 release:
4801   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4802   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4803   freeAsmop (result, NULL, ic, TRUE);
4804 }
4805
4806 /*-----------------------------------------------------------------*/
4807 /* genIfxJump :- will create a jump depending on the ifx           */
4808 /*-----------------------------------------------------------------*/
4809 static void
4810 genIfxJump (iCode * ic, char *jval)
4811 {
4812   symbol *jlbl;
4813   symbol *tlbl = newiTempLabel (NULL);
4814   char *inst;
4815
4816   D (emitcode (";", "genIfxJump ");
4817     );
4818
4819   /* if true label then we jump if condition
4820      supplied is true */
4821   if (IC_TRUE (ic))
4822     {
4823       jlbl = IC_TRUE (ic);
4824       inst = ((strcmp (jval, "a") == 0 ? "jz" :
4825                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4826     }
4827   else
4828     {
4829       /* false label is present */
4830       jlbl = IC_FALSE (ic);
4831       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4832                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4833     }
4834   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4835     emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4836   else
4837     emitcode (inst, "%05d$", tlbl->key + 100);
4838   emitcode ("ljmp", "%05d$", jlbl->key + 100);
4839   emitcode ("", "%05d$:", tlbl->key + 100);
4840
4841   /* mark the icode as generated */
4842   ic->generated = 1;
4843 }
4844
4845 /*-----------------------------------------------------------------*/
4846 /* genCmp :- greater or less than comparison                       */
4847 /*-----------------------------------------------------------------*/
4848 static void
4849 genCmp (operand * left, operand * right,
4850         iCode * ic, iCode * ifx, int sign)
4851 {
4852   int size, offset = 0;
4853   unsigned long lit = 0L;
4854   operand *result;
4855
4856   D (emitcode (";", "genCmp");
4857     );
4858
4859   result = IC_RESULT (ic);
4860
4861   /* if left & right are bit variables */
4862   if (AOP_TYPE (left) == AOP_CRY &&
4863       AOP_TYPE (right) == AOP_CRY)
4864     {
4865       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4866       emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
4867     }
4868   else
4869     {
4870       /* subtract right from left if at the
4871          end the carry flag is set then we know that
4872          left is greater than right */
4873       size = max (AOP_SIZE (left), AOP_SIZE (right));
4874
4875       /* if unsigned char cmp with lit, do cjne left,#right,zz */
4876       if ((size == 1) && !sign &&
4877           (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4878         {
4879           symbol *lbl = newiTempLabel (NULL);
4880           emitcode ("cjne", "%s,%s,%05d$",
4881                     aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
4882                     aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4883                     lbl->key + 100);
4884           emitcode ("", "%05d$:", lbl->key + 100);
4885         }
4886       else
4887         {
4888           if (AOP_TYPE (right) == AOP_LIT)
4889             {
4890               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4891               /* optimize if(x < 0) or if(x >= 0) */
4892               if (lit == 0L)
4893                 {
4894                   if (!sign)
4895                     {
4896                       CLRC;
4897                     }
4898                   else
4899                     {
4900                       MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
4901
4902                       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4903                       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4904
4905                       aopOp (result, ic, FALSE, FALSE);
4906
4907                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4908                         {
4909                           freeAsmop (result, NULL, ic, TRUE);
4910                           genIfxJump (ifx, "acc.7");
4911                           return;
4912                         }
4913                       else
4914                         {
4915                           emitcode ("rlc", "a");
4916                         }
4917                       goto release_freedLR;
4918                     }
4919                   goto release;
4920                 }
4921             }
4922           CLRC;
4923           while (size--)
4924             {
4925               emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
4926               MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4927               emitcode (";", "genCmp #2");
4928               if (sign && (size == 0))
4929                 {
4930                   emitcode (";", "genCmp #3");
4931                   emitcode ("xrl", "a,#0x80");
4932                   if (AOP_TYPE (right) == AOP_LIT)
4933                     {
4934                       unsigned long lit = (unsigned long)
4935                       floatFromVal (AOP (right)->aopu.aop_lit);
4936                       emitcode (";", "genCmp #3.1");
4937                       emitcode ("subb", "a,#0x%02x",
4938                                 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4939                     }
4940                   else
4941                     {
4942                       emitcode (";", "genCmp #3.2");
4943                       if (AOP_NEEDSACC (right))
4944                         {
4945                           emitcode ("push", "acc");
4946                         }
4947                       emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
4948                                                        FALSE, FALSE, FALSE));
4949                       emitcode ("xrl", "b,#0x80");
4950                       if (AOP_NEEDSACC (right))
4951                         {
4952                           emitcode ("pop", "acc");
4953                         }
4954                       emitcode ("subb", "a,b");
4955                     }
4956                 }
4957               else
4958                 {
4959                   const char *s;
4960
4961                   emitcode (";", "genCmp #4");
4962                   if (AOP_NEEDSACC (right))
4963                     {
4964                       /* Yuck!! */
4965                       emitcode (";", "genCmp #4.1");
4966                       emitcode ("xch", "a, b");
4967                       MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
4968                       emitcode ("xch", "a, b");
4969                       s = "b";
4970                     }
4971                   else
4972                     {
4973                       emitcode (";", "genCmp #4.2");
4974                       s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
4975                     }
4976
4977                   emitcode ("subb", "a,%s", s);
4978                 }
4979             }
4980         }
4981     }
4982
4983 release:
4984 /* Don't need the left & right operands any more; do need the result. */
4985   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4986   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4987
4988   aopOp (result, ic, FALSE, FALSE);
4989
4990 release_freedLR:
4991
4992   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4993     {
4994       outBitC (result);
4995     }
4996   else
4997     {
4998       /* if the result is used in the next
4999          ifx conditional branch then generate
5000          code a little differently */
5001       if (ifx)
5002         {
5003           genIfxJump (ifx, "c");
5004         }
5005       else
5006         {
5007           outBitC (result);
5008         }
5009       /* leave the result in acc */
5010     }
5011   freeAsmop (result, NULL, ic, TRUE);
5012 }
5013
5014 /*-----------------------------------------------------------------*/
5015 /* genCmpGt :- greater than comparison                             */
5016 /*-----------------------------------------------------------------*/
5017 static void
5018 genCmpGt (iCode * ic, iCode * ifx)
5019 {
5020   operand *left, *right;
5021   sym_link *letype, *retype;
5022   int sign;
5023
5024   D (emitcode (";", "genCmpGt ");
5025     );
5026
5027   left = IC_LEFT (ic);
5028   right = IC_RIGHT (ic);
5029
5030   letype = getSpec (operandType (left));
5031   retype = getSpec (operandType (right));
5032   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5033
5034   /* assign the left & right amsops */
5035   AOP_OP_2 (ic);
5036
5037   genCmp (right, left, ic, ifx, sign);
5038 }
5039
5040 /*-----------------------------------------------------------------*/
5041 /* genCmpLt - less than comparisons                                */
5042 /*-----------------------------------------------------------------*/
5043 static void
5044 genCmpLt (iCode * ic, iCode * ifx)
5045 {
5046   operand *left, *right;
5047   sym_link *letype, *retype;
5048   int sign;
5049
5050   D (emitcode (";", "genCmpLt "););
5051
5052   left = IC_LEFT (ic);
5053   right = IC_RIGHT (ic);
5054
5055   letype = getSpec (operandType (left));
5056   retype = getSpec (operandType (right));
5057   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5058
5059   /* assign the left & right amsops */
5060   AOP_OP_2 (ic);
5061
5062   genCmp (left, right, ic, ifx, sign);
5063 }
5064
5065 /*-----------------------------------------------------------------*/
5066 /* gencjneshort - compare and jump if not equal                    */
5067 /*-----------------------------------------------------------------*/
5068 static void
5069 gencjneshort (operand * left, operand * right, symbol * lbl)
5070 {
5071   int size = max (AOP_SIZE (left), AOP_SIZE (right));
5072   int offset = 0;
5073   unsigned long lit = 0L;
5074
5075   D (emitcode (";", "gencjneshort");
5076     );
5077
5078   /* if the left side is a literal or
5079      if the right is in a pointer register and left
5080      is not */
5081   if ((AOP_TYPE (left) == AOP_LIT) ||
5082       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5083     {
5084       operand *t = right;
5085       right = left;
5086       left = t;
5087     }
5088
5089   if (AOP_TYPE (right) == AOP_LIT)
5090     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5091
5092   if (opIsGptr (left) || opIsGptr (right))
5093     {
5094       /* We are comparing a generic pointer to something.
5095        * Exclude the generic type byte from the comparison.
5096        */
5097       size--;
5098       D (emitcode (";", "cjneshort: generic ptr special case.");
5099         )
5100     }
5101
5102
5103   /* if the right side is a literal then anything goes */
5104   if (AOP_TYPE (right) == AOP_LIT &&
5105       AOP_TYPE (left) != AOP_DIR)
5106     {
5107       while (size--)
5108         {
5109           char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5110           MOVA (l);
5111           emitcode ("cjne", "a,%s,%05d$",
5112                     aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
5113                     lbl->key + 100);
5114           offset++;
5115         }
5116     }
5117
5118   /* if the right side is in a register or in direct space or
5119      if the left is a pointer register & right is not */
5120   else if (AOP_TYPE (right) == AOP_REG ||
5121            AOP_TYPE (right) == AOP_DIR ||
5122            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5123            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5124     {
5125       while (size--)
5126         {
5127           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5128           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5129               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5130             emitcode ("jnz", "%05d$", lbl->key + 100);
5131           else
5132             emitcode ("cjne", "a,%s,%05d$",
5133                       aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
5134                       lbl->key + 100);
5135           offset++;
5136         }
5137     }
5138   else
5139     {
5140       /* right is a pointer reg need both a & b */
5141       while (size--)
5142         {
5143           char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5144           if (strcmp (l, "b"))
5145             emitcode ("mov", "b,%s", l);
5146           MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5147           emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
5148           offset++;
5149         }
5150     }
5151 }
5152
5153 /*-----------------------------------------------------------------*/
5154 /* gencjne - compare and jump if not equal                         */
5155 /*-----------------------------------------------------------------*/
5156 static void
5157 gencjne (operand * left, operand * right, symbol * lbl)
5158 {
5159   symbol *tlbl = newiTempLabel (NULL);
5160
5161   D (emitcode (";", "gencjne");
5162     );
5163
5164   gencjneshort (left, right, lbl);
5165
5166   emitcode ("mov", "a,%s", one);
5167   emitcode ("sjmp", "%05d$", tlbl->key + 100);
5168   emitcode ("", "%05d$:", lbl->key + 100);
5169   emitcode ("clr", "a");
5170   emitcode ("", "%05d$:", tlbl->key + 100);
5171 }
5172
5173 /*-----------------------------------------------------------------*/
5174 /* genCmpEq - generates code for equal to                          */
5175 /*-----------------------------------------------------------------*/
5176 static void
5177 genCmpEq (iCode * ic, iCode * ifx)
5178 {
5179   operand *left, *right, *result;
5180
5181   D (emitcode (";", "genCmpEq ");
5182     );
5183
5184   AOP_OP_2 (ic);
5185   AOP_SET_LOCALS (ic);
5186
5187   /* if literal, literal on the right or
5188      if the right is in a pointer register and left
5189      is not */
5190   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5191       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5192     {
5193       operand *t = IC_RIGHT (ic);
5194       IC_RIGHT (ic) = IC_LEFT (ic);
5195       IC_LEFT (ic) = t;
5196     }
5197
5198   if (ifx &&                    /* !AOP_SIZE(result) */
5199       OP_SYMBOL (result) &&
5200       OP_SYMBOL (result)->regType == REG_CND)
5201     {
5202       symbol *tlbl;
5203       /* if they are both bit variables */
5204       if (AOP_TYPE (left) == AOP_CRY &&
5205           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5206         {
5207           if (AOP_TYPE (right) == AOP_LIT)
5208             {
5209               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5210               if (lit == 0L)
5211                 {
5212                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5213                   emitcode ("cpl", "c");
5214                 }
5215               else if (lit == 1L)
5216                 {
5217                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5218                 }
5219               else
5220                 {
5221                   emitcode ("clr", "c");
5222                 }
5223               /* AOP_TYPE(right) == AOP_CRY */
5224             }
5225           else
5226             {
5227               symbol *lbl = newiTempLabel (NULL);
5228               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5229               emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5230               emitcode ("cpl", "c");
5231               emitcode ("", "%05d$:", (lbl->key + 100));
5232             }
5233           /* if true label then we jump if condition
5234              supplied is true */
5235           tlbl = newiTempLabel (NULL);
5236           if (IC_TRUE (ifx))
5237             {
5238               emitcode ("jnc", "%05d$", tlbl->key + 100);
5239               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5240             }
5241           else
5242             {
5243               emitcode ("jc", "%05d$", tlbl->key + 100);
5244               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5245             }
5246           emitcode ("", "%05d$:", tlbl->key + 100);
5247         }
5248       else
5249         {
5250           tlbl = newiTempLabel (NULL);
5251           gencjneshort (left, right, tlbl);
5252           if (IC_TRUE (ifx))
5253             {
5254               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5255               emitcode ("", "%05d$:", tlbl->key + 100);
5256             }
5257           else
5258             {
5259               symbol *lbl = newiTempLabel (NULL);
5260               emitcode ("sjmp", "%05d$", lbl->key + 100);
5261               emitcode ("", "%05d$:", tlbl->key + 100);
5262               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5263               emitcode ("", "%05d$:", lbl->key + 100);
5264             }
5265         }
5266       /* mark the icode as generated */
5267       ifx->generated = 1;
5268
5269       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5270       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5271       return;
5272     }
5273
5274   /* if they are both bit variables */
5275   if (AOP_TYPE (left) == AOP_CRY &&
5276       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5277     {
5278       if (AOP_TYPE (right) == AOP_LIT)
5279         {
5280           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5281           if (lit == 0L)
5282             {
5283               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5284               emitcode ("cpl", "c");
5285             }
5286           else if (lit == 1L)
5287             {
5288               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5289             }
5290           else
5291             {
5292               emitcode ("clr", "c");
5293             }
5294           /* AOP_TYPE(right) == AOP_CRY */
5295         }
5296       else
5297         {
5298           symbol *lbl = newiTempLabel (NULL);
5299           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5300           emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5301           emitcode ("cpl", "c");
5302           emitcode ("", "%05d$:", (lbl->key + 100));
5303         }
5304
5305       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5306       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5307
5308       aopOp (result, ic, TRUE, FALSE);
5309
5310       /* c = 1 if egal */
5311       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5312         {
5313           outBitC (result);
5314           goto release;
5315         }
5316       if (ifx)
5317         {
5318           genIfxJump (ifx, "c");
5319           goto release;
5320         }
5321       /* if the result is used in an arithmetic operation
5322          then put the result in place */
5323       outBitC (result);
5324     }
5325   else
5326     {
5327       gencjne (left, right, newiTempLabel (NULL));
5328
5329       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5330       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5331
5332       aopOp (result, ic, TRUE, FALSE);
5333
5334       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5335         {
5336           aopPut (AOP (result), "a", 0);
5337           goto release;
5338         }
5339       if (ifx)
5340         {
5341           genIfxJump (ifx, "a");
5342           goto release;
5343         }
5344       /* if the result is used in an arithmetic operation
5345          then put the result in place */
5346       if (AOP_TYPE (result) != AOP_CRY)
5347         outAcc (result);
5348       /* leave the result in acc */
5349     }
5350
5351 release:
5352   freeAsmop (result, NULL, ic, TRUE);
5353 }
5354
5355 /*-----------------------------------------------------------------*/
5356 /* ifxForOp - returns the icode containing the ifx for operand     */
5357 /*-----------------------------------------------------------------*/
5358 static iCode *
5359 ifxForOp (operand * op, iCode * ic)
5360 {
5361   /* if true symbol then needs to be assigned */
5362   if (IS_TRUE_SYMOP (op))
5363     return NULL;
5364
5365   /* if this has register type condition and
5366      the next instruction is ifx with the same operand
5367      and live to of the operand is upto the ifx only then */
5368   if (ic->next &&
5369       ic->next->op == IFX &&
5370       IC_COND (ic->next)->key == op->key &&
5371       OP_SYMBOL (op)->liveTo <= ic->next->seq)
5372     return ic->next;
5373
5374   return NULL;
5375 }
5376 /*-----------------------------------------------------------------*/
5377 /* hasInc - operand is incremented before any other use            */
5378 /*-----------------------------------------------------------------*/
5379 static iCode *
5380 hasInc (operand *op, iCode *ic)
5381 {
5382   sym_link *type = operandType(op);
5383   sym_link *retype = getSpec (type);
5384   iCode *lic = ic->next;
5385   int isize ;
5386   
5387   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5388   if (!IS_SYMOP(op)) return NULL;
5389
5390   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5391   isize = getSize(type->next);
5392   while (lic) {
5393     /* if operand of the form op = op + <sizeof *op> */
5394     if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5395         isOperandEqual(IC_RESULT(lic),op) && 
5396         isOperandLiteral(IC_RIGHT(lic)) &&
5397         operandLitValue(IC_RIGHT(lic)) == isize) {
5398       return lic;
5399     }
5400     /* if the operand used or deffed */
5401     if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5402       return NULL;
5403     }
5404     lic = lic->next;
5405   }
5406   return NULL;
5407 }
5408
5409 /*-----------------------------------------------------------------*/
5410 /* genAndOp - for && operation                                     */
5411 /*-----------------------------------------------------------------*/
5412 static void
5413 genAndOp (iCode * ic)
5414 {
5415   operand *left, *right, *result;
5416   symbol *tlbl;
5417
5418   D (emitcode (";", "genAndOp "););
5419
5420   /* note here that && operations that are in an
5421      if statement are taken away by backPatchLabels
5422      only those used in arthmetic operations remain */
5423   AOP_OP_2 (ic);
5424   AOP_SET_LOCALS (ic);
5425
5426   /* if both are bit variables */
5427   if (AOP_TYPE (left) == AOP_CRY &&
5428       AOP_TYPE (right) == AOP_CRY)
5429     {
5430       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5431       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5432       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5433       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5434   
5435       aopOp (result,ic,FALSE, FALSE);
5436       outBitC (result);
5437     }
5438   else
5439     {
5440       tlbl = newiTempLabel (NULL);
5441       toBoolean (left);
5442       emitcode ("jz", "%05d$", tlbl->key + 100);
5443       toBoolean (right);
5444       emitcode ("", "%05d$:", tlbl->key + 100);
5445       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5446       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5447   
5448       aopOp (result,ic,FALSE, FALSE);
5449       outBitAcc (result);
5450     }
5451     freeAsmop (result, NULL, ic, TRUE);
5452 }
5453
5454
5455 /*-----------------------------------------------------------------*/
5456 /* genOrOp - for || operation                                      */
5457 /*-----------------------------------------------------------------*/
5458 static void
5459 genOrOp (iCode * ic)
5460 {
5461   operand *left, *right, *result;
5462   symbol *tlbl;
5463
5464   D (emitcode (";", "genOrOp "););
5465
5466   /* note here that || operations that are in an
5467      if statement are taken away by backPatchLabels
5468      only those used in arthmetic operations remain */
5469   AOP_OP_2 (ic);
5470   AOP_SET_LOCALS (ic);
5471
5472   /* if both are bit variables */
5473   if (AOP_TYPE (left) == AOP_CRY &&
5474       AOP_TYPE (right) == AOP_CRY)
5475     {
5476       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5477       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5478       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5479       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5480   
5481       aopOp (result,ic,FALSE, FALSE);
5482       
5483       outBitC (result);
5484     }
5485   else
5486     {
5487       tlbl = newiTempLabel (NULL);
5488       toBoolean (left);
5489       emitcode ("jnz", "%05d$", tlbl->key + 100);
5490       toBoolean (right);
5491       emitcode ("", "%05d$:", tlbl->key + 100);
5492       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5493       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5494   
5495       aopOp (result,ic,FALSE, FALSE);
5496       
5497       outBitAcc (result);
5498     }
5499
5500   freeAsmop (result, NULL, ic, TRUE);
5501 }
5502
5503 /*-----------------------------------------------------------------*/
5504 /* isLiteralBit - test if lit == 2^n                               */
5505 /*-----------------------------------------------------------------*/
5506 static int
5507 isLiteralBit (unsigned long lit)
5508 {
5509   unsigned long pw[32] =
5510   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5511    0x100L, 0x200L, 0x400L, 0x800L,
5512    0x1000L, 0x2000L, 0x4000L, 0x8000L,
5513    0x10000L, 0x20000L, 0x40000L, 0x80000L,
5514    0x100000L, 0x200000L, 0x400000L, 0x800000L,
5515    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5516    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5517   int idx;
5518
5519   for (idx = 0; idx < 32; idx++)
5520     if (lit == pw[idx])
5521       return idx + 1;
5522   return 0;
5523 }
5524
5525 /*-----------------------------------------------------------------*/
5526 /* continueIfTrue -                                                */
5527 /*-----------------------------------------------------------------*/
5528 static void
5529 continueIfTrue (iCode * ic)
5530 {
5531   if (IC_TRUE (ic))
5532     emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5533   ic->generated = 1;
5534 }
5535
5536 /*-----------------------------------------------------------------*/
5537 /* jmpIfTrue -                                                     */
5538 /*-----------------------------------------------------------------*/
5539 static void
5540 jumpIfTrue (iCode * ic)
5541 {
5542   if (!IC_TRUE (ic))
5543     emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5544   ic->generated = 1;
5545 }
5546
5547 /*-----------------------------------------------------------------*/
5548 /* jmpTrueOrFalse -                                                */
5549 /*-----------------------------------------------------------------*/
5550 static void
5551 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
5552 {
5553   // ugly but optimized by peephole
5554   if (IC_TRUE (ic))
5555     {
5556       symbol *nlbl = newiTempLabel (NULL);
5557       emitcode ("sjmp", "%05d$", nlbl->key + 100);
5558       emitcode ("", "%05d$:", tlbl->key + 100);
5559       emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5560       emitcode ("", "%05d$:", nlbl->key + 100);
5561     }
5562   else
5563     {
5564       emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5565       emitcode ("", "%05d$:", tlbl->key + 100);
5566     }
5567   ic->generated = 1;
5568 }
5569
5570 // Generate code to perform a bit-wise logic operation
5571 // on two operands in far space (assumed to already have been 
5572 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
5573 // in far space. This requires pushing the result on the stack
5574 // then popping it into the result.
5575 static void
5576 genFarFarLogicOp(iCode *ic, char *logicOp)
5577 {
5578       int size, resultSize, compSize;
5579       int offset = 0;
5580       
5581       TR_AP("#5");
5582       D(emitcode(";", "%s special case for 3 far operands.", logicOp););
5583       compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ? 
5584                   AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
5585       
5586       _startLazyDPSEvaluation();
5587       for (size = compSize; (size--); offset++)
5588       {
5589           MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
5590           emitcode ("mov", "%s, acc", DP2_RESULT_REG);
5591           MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
5592           
5593           emitcode (logicOp, "a,%s", DP2_RESULT_REG);
5594           emitcode ("push", "acc");
5595       }
5596       _endLazyDPSEvaluation();
5597      
5598       freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5599       freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5600       aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
5601      
5602       resultSize = AOP_SIZE(IC_RESULT(ic));
5603
5604       ADJUST_PUSHED_RESULT(compSize, resultSize);
5605
5606       _startLazyDPSEvaluation();
5607       while (compSize--)
5608       {
5609           emitcode ("pop", "acc");
5610           aopPut (AOP (IC_RESULT (ic)), "a", compSize);
5611       }
5612       _endLazyDPSEvaluation();
5613       freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
5614 }
5615
5616
5617 /*-----------------------------------------------------------------*/
5618 /* genAnd  - code for and                                          */
5619 /*-----------------------------------------------------------------*/
5620 static void
5621 genAnd (iCode * ic, iCode * ifx)
5622 {
5623   operand *left, *right, *result;
5624   int size, offset = 0;
5625   unsigned long lit = 0L;
5626   int bytelit = 0;
5627   char buffer[10];
5628   bool pushResult;
5629
5630   D (emitcode (";", "genAnd "););
5631
5632   AOP_OP_3_NOFATAL (ic, pushResult);
5633   AOP_SET_LOCALS (ic);
5634
5635   if (pushResult)
5636   {
5637       genFarFarLogicOp(ic, "anl");
5638       return;
5639   }  
5640
5641 #ifdef DEBUG_TYPE
5642   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5643             AOP_TYPE (result),
5644             AOP_TYPE (left), AOP_TYPE (right));
5645   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5646             AOP_SIZE (result),
5647             AOP_SIZE (left), AOP_SIZE (right));
5648 #endif
5649
5650   /* if left is a literal & right is not then exchange them */
5651   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5652 #ifdef LOGIC_OPS_BROKEN      
5653     ||  AOP_NEEDSACC (left)
5654 #endif
5655     )
5656     {
5657       operand *tmp = right;
5658       right = left;
5659       left = tmp;
5660     }
5661
5662   /* if result = right then exchange them */
5663   if (sameRegs (AOP (result), AOP (right)))
5664     {
5665       operand *tmp = right;
5666       right = left;
5667       left = tmp;
5668     }
5669
5670   /* if right is bit then exchange them */
5671   if (AOP_TYPE (right) == AOP_CRY &&
5672       AOP_TYPE (left) != AOP_CRY)
5673     {
5674       operand *tmp = right;
5675       right = left;
5676       left = tmp;
5677     }
5678   if (AOP_TYPE (right) == AOP_LIT)
5679     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5680
5681   size = AOP_SIZE (result);
5682
5683   // if(bit & yy)
5684   // result = bit & yy;
5685   if (AOP_TYPE (left) == AOP_CRY)
5686     {
5687       // c = bit & literal;
5688       if (AOP_TYPE (right) == AOP_LIT)
5689         {
5690           if (lit & 1)
5691             {
5692               if (size && sameRegs (AOP (result), AOP (left)))
5693                 // no change
5694                 goto release;
5695               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5696             }
5697           else
5698             {
5699               // bit(result) = 0;
5700               if (size && (AOP_TYPE (result) == AOP_CRY))
5701                 {
5702                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5703                   goto release;
5704                 }
5705               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5706                 {
5707                   jumpIfTrue (ifx);
5708                   goto release;
5709                 }
5710               emitcode ("clr", "c");
5711             }
5712         }
5713       else
5714         {
5715           if (AOP_TYPE (right) == AOP_CRY)
5716             {
5717               // c = bit & bit;
5718               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5719               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5720             }
5721           else
5722             {
5723               // c = bit & val;
5724               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
5725               // c = lsb
5726               emitcode ("rrc", "a");
5727               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5728             }
5729         }
5730       // bit = c
5731       // val = c
5732       if (size)
5733         outBitC (result);
5734       // if(bit & ...)
5735       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5736         genIfxJump (ifx, "c");
5737       goto release;
5738     }
5739
5740   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5741   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5742   if ((AOP_TYPE (right) == AOP_LIT) &&
5743       (AOP_TYPE (result) == AOP_CRY) &&
5744       (AOP_TYPE (left) != AOP_CRY))
5745     {
5746       int posbit = isLiteralBit (lit);
5747       /* left &  2^n */
5748       if (posbit)
5749         {
5750           posbit--;
5751           MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
5752           // bit = left & 2^n
5753           if (size)
5754             emitcode ("mov", "c,acc.%d", posbit & 0x07);
5755           // if(left &  2^n)
5756           else
5757             {
5758               if (ifx)
5759                 {
5760                   sprintf (buffer, "acc.%d", posbit & 0x07);
5761                   genIfxJump (ifx, buffer);
5762                 }
5763               goto release;
5764             }
5765         }
5766       else
5767         {
5768           symbol *tlbl = newiTempLabel (NULL);
5769           int sizel = AOP_SIZE (left);
5770           if (size)
5771             emitcode ("setb", "c");
5772           while (sizel--)
5773             {
5774               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5775                 {
5776                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5777                   // byte ==  2^n ?
5778                   if ((posbit = isLiteralBit (bytelit)) != 0)
5779                     emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5780                   else
5781                     {
5782                       if (bytelit != 0x0FFL)
5783                         emitcode ("anl", "a,%s",
5784                           aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
5785                       emitcode ("jnz", "%05d$", tlbl->key + 100);
5786                     }
5787                 }
5788               offset++;
5789             }
5790           // bit = left & literal
5791           if (size)
5792             {
5793               emitcode ("clr", "c");
5794               emitcode ("", "%05d$:", tlbl->key + 100);
5795             }
5796           // if(left & literal)
5797           else
5798             {
5799               if (ifx)
5800                 jmpTrueOrFalse (ifx, tlbl);
5801               goto release;
5802             }
5803         }
5804       outBitC (result);
5805       goto release;
5806     }
5807
5808   /* if left is same as result */
5809   if (sameRegs (AOP (result), AOP (left)))
5810     {
5811       for (; size--; offset++)
5812         {
5813           if (AOP_TYPE (right) == AOP_LIT)
5814             {
5815               if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5816                 continue;
5817               else if (bytelit == 0)
5818                 aopPut (AOP (result), zero, offset);
5819               else if (IS_AOP_PREG (result))
5820                 {
5821                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5822                   emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5823                   aopPut (AOP (result), "a", offset);
5824                 }
5825               else
5826                 emitcode ("anl", "%s,%s",
5827                           aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5828                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5829             }
5830           else
5831             {
5832               if (AOP_TYPE (left) == AOP_ACC)
5833                 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5834               else
5835                 {
5836                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5837                   if (IS_AOP_PREG (result))
5838                     {
5839                       emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5840                       aopPut (AOP (result), "a", offset);
5841
5842                     }
5843                   else
5844                     emitcode ("anl", "%s,a",
5845                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5846                 }
5847             }
5848         }
5849     }
5850   else
5851     {
5852       // left & result in different registers
5853       if (AOP_TYPE (result) == AOP_CRY)
5854         {
5855           // result = bit
5856           // if(size), result in bit
5857           // if(!size && ifx), conditional oper: if(left & right)
5858           symbol *tlbl = newiTempLabel (NULL);
5859           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5860           if (size)
5861             emitcode ("setb", "c");
5862           while (sizer--)
5863             {
5864               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5865                 emitcode ("anl", "a,%s",
5866                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5867               } else {
5868                 if (AOP_TYPE(left)==AOP_ACC) {
5869                   emitcode("mov", "b,a");
5870                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5871                   emitcode("anl", "a,b");
5872                 }else {
5873                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5874                   emitcode ("anl", "a,%s",
5875                             aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5876                 }
5877               }
5878               emitcode ("jnz", "%05d$", tlbl->key + 100);
5879               offset++;
5880             }
5881           if (size)
5882             {
5883               CLRC;
5884               emitcode ("", "%05d$:", tlbl->key + 100);
5885               outBitC (result);
5886             }
5887           else if (ifx)
5888             jmpTrueOrFalse (ifx, tlbl);
5889         }
5890       else
5891         {
5892           for (; (size--); offset++)
5893             {
5894               // normal case
5895               // result = left & right
5896               if (AOP_TYPE (right) == AOP_LIT)
5897                 {
5898                   if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5899                     {
5900                       aopPut (AOP (result),
5901                            aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5902                               offset);
5903                       continue;
5904                     }
5905                   else if (bytelit == 0)
5906                     {
5907                       aopPut (AOP (result), zero, offset);
5908                       continue;
5909                     }
5910                   D (emitcode (";", "better literal AND."););
5911                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5912                   emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
5913                                                     FALSE, FALSE, FALSE));
5914
5915                 }
5916               else
5917                 {
5918                   // faster than result <- left, anl result,right
5919                   // and better if result is SFR
5920                   if (AOP_TYPE (left) == AOP_ACC)
5921                     {
5922                       emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
5923                                                        FALSE, FALSE, FALSE));
5924                     }
5925                   else
5926                     {
5927                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
5928                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
5929                       {
5930                           emitcode("mov", "b,a");
5931                           rOp = "b";
5932                       }
5933                         
5934                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5935                       emitcode ("anl", "a,%s", rOp);
5936                     }                   
5937                 }
5938               aopPut (AOP (result), "a", offset);
5939             }
5940         }
5941     }
5942
5943 release:
5944   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5945   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5946   freeAsmop (result, NULL, ic, TRUE);
5947 }
5948
5949
5950 /*-----------------------------------------------------------------*/
5951 /* genOr  - code for or                                            */
5952 /*-----------------------------------------------------------------*/
5953 static void
5954 genOr (iCode * ic, iCode * ifx)
5955 {
5956   operand *left, *right, *result;
5957   int size, offset = 0;
5958   unsigned long lit = 0L;
5959   bool     pushResult;
5960
5961   D (emitcode (";", "genOr "););
5962
5963   AOP_OP_3_NOFATAL (ic, pushResult);
5964   AOP_SET_LOCALS (ic);
5965
5966   if (pushResult)
5967   {
5968       genFarFarLogicOp(ic, "orl");
5969       return;
5970   }
5971
5972
5973 #ifdef DEBUG_TYPE
5974   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5975             AOP_TYPE (result),
5976             AOP_TYPE (left), AOP_TYPE (right));
5977   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5978             AOP_SIZE (result),
5979             AOP_SIZE (left), AOP_SIZE (right));
5980 #endif
5981
5982   /* if left is a literal & right is not then exchange them */
5983   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5984 #ifdef LOGIC_OPS_BROKEN
5985    || AOP_NEEDSACC (left) // I think this is a net loss now.
5986 #endif      
5987       )
5988     {
5989       operand *tmp = right;
5990       right = left;
5991       left = tmp;
5992     }
5993
5994   /* if result = right then exchange them */
5995   if (sameRegs (AOP (result), AOP (right)))
5996     {
5997       operand *tmp = right;
5998       right = left;
5999       left = tmp;
6000     }
6001
6002   /* if right is bit then exchange them */
6003   if (AOP_TYPE (right) == AOP_CRY &&
6004       AOP_TYPE (left) != AOP_CRY)
6005     {
6006       operand *tmp = right;
6007       right = left;
6008       left = tmp;
6009     }
6010   if (AOP_TYPE (right) == AOP_LIT)
6011     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6012
6013   size = AOP_SIZE (result);
6014
6015   // if(bit | yy)
6016   // xx = bit | yy;
6017   if (AOP_TYPE (left) == AOP_CRY)
6018     {
6019       if (AOP_TYPE (right) == AOP_LIT)
6020         {
6021           // c = bit & literal;
6022           if (lit)
6023             {
6024               // lit != 0 => result = 1
6025               if (AOP_TYPE (result) == AOP_CRY)
6026                 {
6027                   if (size)
6028                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6029                   else if (ifx)
6030                     continueIfTrue (ifx);
6031                   goto release;
6032                 }
6033               emitcode ("setb", "c");
6034             }
6035           else
6036             {
6037               // lit == 0 => result = left
6038               if (size && sameRegs (AOP (result), AOP (left)))
6039                 goto release;
6040               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6041             }
6042         }
6043       else
6044         {
6045           if (AOP_TYPE (right) == AOP_CRY)
6046             {
6047               // c = bit | bit;
6048               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6049               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6050             }
6051           else
6052             {
6053               // c = bit | val;
6054               symbol *tlbl = newiTempLabel (NULL);
6055               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6056                 emitcode ("setb", "c");
6057               emitcode ("jb", "%s,%05d$",
6058                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
6059               toBoolean (right);
6060               emitcode ("jnz", "%05d$", tlbl->key + 100);
6061               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6062                 {
6063                   jmpTrueOrFalse (ifx, tlbl);
6064                   goto release;
6065                 }
6066               else
6067                 {
6068                   CLRC;
6069                   emitcode ("", "%05d$:", tlbl->key + 100);
6070                 }
6071             }
6072         }
6073       // bit = c
6074       // val = c
6075       if (size)
6076         outBitC (result);
6077       // if(bit | ...)
6078       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6079         genIfxJump (ifx, "c");
6080       goto release;
6081     }
6082
6083   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6084   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6085   if ((AOP_TYPE (right) == AOP_LIT) &&
6086       (AOP_TYPE (result) == AOP_CRY) &&
6087       (AOP_TYPE (left) != AOP_CRY))
6088     {
6089       if (lit)
6090         {
6091           // result = 1
6092           if (size)
6093             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6094           else
6095             continueIfTrue (ifx);
6096           goto release;
6097         }
6098       else
6099         {
6100           // lit = 0, result = boolean(left)
6101           if (size)
6102             emitcode ("setb", "c");
6103           toBoolean (right);
6104           if (size)
6105             {
6106               symbol *tlbl = newiTempLabel (NULL);
6107               emitcode ("jnz", "%05d$", tlbl->key + 100);
6108               CLRC;
6109               emitcode ("", "%05d$:", tlbl->key + 100);
6110             }
6111           else
6112             {
6113               genIfxJump (ifx, "a");
6114               goto release;
6115             }
6116         }
6117       outBitC (result);
6118       goto release;
6119     }
6120
6121   /* if left is same as result */
6122   if (sameRegs (AOP (result), AOP (left)))
6123     {
6124       for (; size--; offset++)
6125         {
6126           if (AOP_TYPE (right) == AOP_LIT)
6127             {
6128               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6129                 {
6130                   continue;
6131                 }
6132               else
6133                 {
6134                   if (IS_AOP_PREG (left))
6135                     {
6136                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6137                       emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6138                       aopPut (AOP (result), "a", offset);
6139                     }
6140                   else
6141                     {
6142                       emitcode ("orl", "%s,%s",
6143                             aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6144                          aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6145                     }
6146                 }
6147             }
6148           else
6149             {
6150               if (AOP_TYPE (left) == AOP_ACC)
6151                 {
6152                   emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6153                 }
6154               else
6155                 {
6156                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6157                   if (IS_AOP_PREG (left))
6158                     {
6159                       emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6160                       aopPut (AOP (result), "a", offset);
6161                     }
6162                   else
6163                     {
6164                       emitcode ("orl", "%s,a",
6165                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6166                     }
6167                 }
6168             }
6169         }
6170     }
6171   else
6172     {
6173       // left & result in different registers
6174       if (AOP_TYPE (result) == AOP_CRY)
6175         {
6176           // result = bit
6177           // if(size), result in bit
6178           // if(!size && ifx), conditional oper: if(left | right)
6179           symbol *tlbl = newiTempLabel (NULL);
6180           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6181           if (size)
6182             emitcode ("setb", "c");
6183           while (sizer--)
6184             {
6185               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6186                 emitcode ("orl", "a,%s",
6187                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6188               } else {
6189                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6190                 emitcode ("orl", "a,%s",
6191                           aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6192               }
6193               emitcode ("jnz", "%05d$", tlbl->key + 100);
6194               offset++;
6195             }
6196           if (size)
6197             {
6198               CLRC;
6199               emitcode ("", "%05d$:", tlbl->key + 100);
6200               outBitC (result);
6201             }
6202           else if (ifx)
6203             jmpTrueOrFalse (ifx, tlbl);
6204         }
6205       else
6206         {
6207             _startLazyDPSEvaluation();
6208           for (; (size--); offset++)
6209             {
6210               // normal case
6211               // result = left & right
6212               if (AOP_TYPE (right) == AOP_LIT)
6213                 {
6214                   if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6215                     {
6216                       aopPut (AOP (result),
6217                            aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6218                               offset);
6219                       continue;
6220                     }
6221                   D (emitcode (";", "better literal OR."););
6222                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6223                   emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
6224                                                     FALSE, FALSE, FALSE));
6225
6226                 }
6227               else
6228                 {
6229                   // faster than result <- left, anl result,right
6230                   // and better if result is SFR
6231                   if (AOP_TYPE (left) == AOP_ACC)
6232                     {
6233                       emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
6234                                                        FALSE, FALSE, FALSE));
6235                     }
6236                   else
6237                     {
6238                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6239                         
6240                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6241                       {
6242                           emitcode("mov", "b,a");
6243                           rOp = "b";
6244                       }
6245                         
6246                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6247                       emitcode ("orl", "a,%s", rOp);
6248                     }
6249                 }
6250               aopPut (AOP (result), "a", offset);
6251             }
6252             _endLazyDPSEvaluation();
6253         }
6254     }
6255
6256 release:
6257   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6258   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6259   freeAsmop (result, NULL, ic, TRUE);
6260 }
6261
6262 /*-----------------------------------------------------------------*/
6263 /* genXor - code for xclusive or                                   */
6264 /*-----------------------------------------------------------------*/
6265 static void
6266 genXor (iCode * ic, iCode * ifx)
6267 {
6268   operand *left, *right, *result;
6269   int size, offset = 0;
6270   unsigned long lit = 0L;
6271   bool pushResult;
6272
6273   D (emitcode (";", "genXor "););
6274
6275   AOP_OP_3_NOFATAL (ic, pushResult);
6276   AOP_SET_LOCALS (ic);
6277
6278   if (pushResult)
6279   {
6280       genFarFarLogicOp(ic, "xrl");
6281       return;
6282   }  
6283
6284 #ifdef DEBUG_TYPE
6285   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6286             AOP_TYPE (result),
6287             AOP_TYPE (left), AOP_TYPE (right));
6288   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6289             AOP_SIZE (result),
6290             AOP_SIZE (left), AOP_SIZE (right));
6291 #endif
6292
6293   /* if left is a literal & right is not ||
6294      if left needs acc & right does not */
6295   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) 
6296 #ifdef LOGIC_OPS_BROKEN      
6297       || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6298 #endif
6299      )
6300     {
6301       operand *tmp = right;
6302       right = left;
6303       left = tmp;
6304     }
6305
6306   /* if result = right then exchange them */
6307   if (sameRegs (AOP (result), AOP (right)))
6308     {
6309       operand *tmp = right;
6310       right = left;
6311       left = tmp;
6312     }
6313
6314   /* if right is bit then exchange them */
6315   if (AOP_TYPE (right) == AOP_CRY &&
6316       AOP_TYPE (left) != AOP_CRY)
6317     {
6318       operand *tmp = right;
6319       right = left;
6320       left = tmp;
6321     }
6322   if (AOP_TYPE (right) == AOP_LIT)
6323     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6324
6325   size = AOP_SIZE (result);
6326
6327   // if(bit ^ yy)
6328   // xx = bit ^ yy;
6329   if (AOP_TYPE (left) == AOP_CRY)
6330     {
6331       if (AOP_TYPE (right) == AOP_LIT)
6332         {
6333           // c = bit & literal;
6334           if (lit >> 1)
6335             {
6336               // lit>>1  != 0 => result = 1
6337               if (AOP_TYPE (result) == AOP_CRY)
6338                 {
6339                   if (size)
6340                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6341                   else if (ifx)
6342                     continueIfTrue (ifx);
6343                   goto release;
6344                 }
6345               emitcode ("setb", "c");
6346             }
6347           else
6348             {
6349               // lit == (0 or 1)
6350               if (lit == 0)
6351                 {
6352                   // lit == 0, result = left
6353                   if (size && sameRegs (AOP (result), AOP (left)))
6354                     goto release;
6355                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6356                 }
6357               else
6358                 {
6359                   // lit == 1, result = not(left)
6360                   if (size && sameRegs (AOP (result), AOP (left)))
6361                     {
6362                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6363                       goto release;
6364                     }
6365                   else
6366                     {
6367                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6368                       emitcode ("cpl", "c");
6369                     }
6370                 }
6371             }
6372
6373         }
6374       else
6375         {
6376           // right != literal
6377           symbol *tlbl = newiTempLabel (NULL);
6378           if (AOP_TYPE (right) == AOP_CRY)
6379             {
6380               // c = bit ^ bit;
6381               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6382             }
6383           else
6384             {
6385               int sizer = AOP_SIZE (right);
6386               // c = bit ^ val
6387               // if val>>1 != 0, result = 1
6388               emitcode ("setb", "c");
6389               while (sizer)
6390                 {
6391                   MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
6392                   if (sizer == 1)
6393                     // test the msb of the lsb
6394                     emitcode ("anl", "a,#0xfe");
6395                   emitcode ("jnz", "%05d$", tlbl->key + 100);
6396                   sizer--;
6397                 }
6398               // val = (0,1)
6399               emitcode ("rrc", "a");
6400             }
6401           emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6402           emitcode ("cpl", "c");
6403           emitcode ("", "%05d$:", (tlbl->key + 100));
6404         }
6405       // bit = c
6406       // val = c
6407       if (size)
6408         outBitC (result);
6409       // if(bit | ...)
6410       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6411         genIfxJump (ifx, "c");
6412       goto release;
6413     }
6414
6415   if (sameRegs (AOP (result), AOP (left)))
6416     {
6417       /* if left is same as result */
6418       for (; size--; offset++)
6419         {
6420           if (AOP_TYPE (right) == AOP_LIT)
6421             {
6422               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6423                 continue;
6424               else if (IS_AOP_PREG (left))
6425                 {
6426                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6427                   emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6428                   aopPut (AOP (result), "a", offset);
6429                 }
6430               else
6431                 emitcode ("xrl", "%s,%s",
6432                           aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6433                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6434             }
6435           else
6436             {
6437               if (AOP_TYPE (left) == AOP_ACC)
6438                 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6439               else
6440                 {
6441                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6442                   if (IS_AOP_PREG (left))
6443                     {
6444                       emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6445                       aopPut (AOP (result), "a", offset);
6446                     }
6447                   else
6448                     emitcode ("xrl", "%s,a",
6449                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6450                 }
6451             }
6452         }
6453     }
6454   else
6455     {
6456       // left & result in different registers
6457       if (AOP_TYPE (result) == AOP_CRY)
6458         {
6459           // result = bit
6460           // if(size), result in bit
6461           // if(!size && ifx), conditional oper: if(left ^ right)
6462           symbol *tlbl = newiTempLabel (NULL);
6463           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6464           if (size)
6465             emitcode ("setb", "c");
6466           while (sizer--)
6467             {
6468               if ((AOP_TYPE (right) == AOP_LIT) &&
6469                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6470                 {
6471                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6472                 }
6473               else
6474                 {
6475                   if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6476                     emitcode ("xrl", "a,%s",
6477                               aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6478                   } else {
6479                     MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6480                     emitcode ("xrl", "a,%s",
6481                               aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6482                   }
6483                 }
6484               emitcode ("jnz", "%05d$", tlbl->key + 100);
6485               offset++;
6486             }
6487           if (size)
6488             {
6489               CLRC;
6490               emitcode ("", "%05d$:", tlbl->key + 100);
6491               outBitC (result);
6492             }
6493           else if (ifx)
6494             jmpTrueOrFalse (ifx, tlbl);
6495         }
6496       else
6497         for (; (size--); offset++)
6498           {
6499             // normal case
6500             // result = left & right
6501             if (AOP_TYPE (right) == AOP_LIT)
6502               {
6503                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6504                   {
6505                     aopPut (AOP (result),
6506                             aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6507                             offset);
6508                     continue;
6509                   }
6510                 D (emitcode (";", "better literal XOR.");
6511                   );
6512                 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6513                 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
6514                                                   FALSE, FALSE, FALSE));
6515               }
6516             else
6517               {
6518                 // faster than result <- left, anl result,right
6519                 // and better if result is SFR
6520                 if (AOP_TYPE (left) == AOP_ACC)
6521                   {
6522                     emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
6523                                                      FALSE, FALSE, FALSE));
6524                   }
6525                 else
6526                   {
6527                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6528                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6529                       {
6530                           emitcode("mov", "b,a");
6531                           rOp = "b";
6532                       }
6533                         
6534                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6535                       emitcode ("xrl", "a,%s", rOp);
6536                   }
6537               }
6538             aopPut (AOP (result), "a", offset);
6539           }
6540     }
6541
6542 release:
6543   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6544   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6545   freeAsmop (result, NULL, ic, TRUE);
6546 }
6547
6548 /*-----------------------------------------------------------------*/
6549 /* genInline - write the inline code out                           */
6550 /*-----------------------------------------------------------------*/
6551 static void
6552 genInline (iCode * ic)
6553 {
6554   char *buffer, *bp, *bp1;
6555
6556   D (emitcode (";", "genInline ");
6557     );
6558
6559   _G.inLine += (!options.asmpeep);
6560
6561   buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6562   strcpy (buffer, IC_INLINE (ic));
6563
6564   /* emit each line as a code */
6565   while (*bp)
6566     {
6567       if (*bp == '\n')
6568         {
6569           *bp++ = '\0';
6570           emitcode (bp1, "");
6571           bp1 = bp;
6572         }
6573       else
6574         {
6575           if (*bp == ':')
6576             {
6577               bp++;
6578               *bp = '\0';
6579               bp++;
6580               emitcode (bp1, "");
6581               bp1 = bp;
6582             }
6583           else
6584             bp++;
6585         }
6586     }
6587   if (bp1 != bp)
6588     emitcode (bp1, "");
6589   /*     emitcode("",buffer); */
6590   _G.inLine -= (!options.asmpeep);
6591 }
6592
6593 /*-----------------------------------------------------------------*/
6594 /* genRRC - rotate right with carry                                */
6595 /*-----------------------------------------------------------------*/
6596 static void
6597 genRRC (iCode * ic)
6598 {
6599   operand *left, *result;
6600   int size, offset = 0;
6601   char *l;
6602
6603   D (emitcode (";", "genRRC ");
6604     );
6605
6606   /* rotate right with carry */
6607   left = IC_LEFT (ic);
6608   result = IC_RESULT (ic);
6609   aopOp (left, ic, FALSE, FALSE);
6610   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6611
6612   /* move it to the result */
6613   size = AOP_SIZE (result);
6614   offset = size - 1;
6615   CLRC;
6616
6617   _startLazyDPSEvaluation ();
6618   while (size--)
6619     {
6620       l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6621       MOVA (l);
6622       emitcode ("rrc", "a");
6623       if (AOP_SIZE (result) > 1)
6624         aopPut (AOP (result), "a", offset--);
6625     }
6626   _endLazyDPSEvaluation ();
6627
6628   /* now we need to put the carry into the
6629      highest order byte of the result */
6630   if (AOP_SIZE (result) > 1)
6631     {
6632       l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
6633       MOVA (l);
6634     }
6635   emitcode ("mov", "acc.7,c");
6636   aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
6637   freeAsmop (left, NULL, ic, TRUE);
6638   freeAsmop (result, NULL, ic, TRUE);
6639 }
6640
6641 /*-----------------------------------------------------------------*/
6642 /* genRLC - generate code for rotate left with carry               */
6643 /*-----------------------------------------------------------------*/
6644 static void
6645 genRLC (iCode * ic)
6646 {
6647   operand *left, *result;
6648   int size, offset = 0;
6649   char *l;
6650
6651   D (emitcode (";", "genRLC ");
6652     );
6653
6654   /* rotate right with carry */
6655   left = IC_LEFT (ic);
6656   result = IC_RESULT (ic);
6657   aopOp (left, ic, FALSE, FALSE);
6658   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6659
6660   /* move it to the result */
6661   size = AOP_SIZE (result);
6662   offset = 0;
6663   if (size--)
6664     {
6665       l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6666       MOVA (l);
6667       emitcode ("add", "a,acc");
6668       if (AOP_SIZE (result) > 1)
6669         {
6670           aopPut (AOP (result), "a", offset++);
6671         }
6672
6673       _startLazyDPSEvaluation ();
6674       while (size--)
6675         {
6676           l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6677           MOVA (l);
6678           emitcode ("rlc", "a");
6679           if (AOP_SIZE (result) > 1)
6680             aopPut (AOP (result), "a", offset++);
6681         }
6682       _endLazyDPSEvaluation ();
6683     }
6684   /* now we need to put the carry into the
6685      highest order byte of the result */
6686   if (AOP_SIZE (result) > 1)
6687     {
6688       l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
6689       MOVA (l);
6690     }
6691   emitcode ("mov", "acc.0,c");
6692   aopPut (AOP (result), "a", 0);
6693   freeAsmop (left, NULL, ic, TRUE);
6694   freeAsmop (result, NULL, ic, TRUE);
6695 }
6696
6697 /*-----------------------------------------------------------------*/
6698 /* genGetHbit - generates code get highest order bit               */
6699 /*-----------------------------------------------------------------*/
6700 static void
6701 genGetHbit (iCode * ic)
6702 {
6703   operand *left, *result;
6704   left = IC_LEFT (ic);
6705   result = IC_RESULT (ic);
6706   aopOp (left, ic, FALSE, FALSE);
6707   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6708
6709   D (emitcode (";", "genGetHbit ");
6710     );
6711
6712   /* get the highest order byte into a */
6713   MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
6714   if (AOP_TYPE (result) == AOP_CRY)
6715     {
6716       emitcode ("rlc", "a");
6717       outBitC (result);
6718     }
6719   else
6720     {
6721       emitcode ("rl", "a");
6722       emitcode ("anl", "a,#0x01");
6723       outAcc (result);
6724     }
6725
6726
6727   freeAsmop (left, NULL, ic, TRUE);
6728   freeAsmop (result, NULL, ic, TRUE);
6729 }
6730
6731 /*-----------------------------------------------------------------*/
6732 /* AccRol - rotate left accumulator by known count                 */
6733 /*-----------------------------------------------------------------*/
6734 static void
6735 AccRol (int shCount)
6736 {
6737   shCount &= 0x0007;            // shCount : 0..7
6738
6739   switch (shCount)
6740     {
6741     case 0:
6742       break;
6743     case 1:
6744       emitcode ("rl", "a");
6745       break;
6746     case 2:
6747       emitcode ("rl", "a");
6748       emitcode ("rl", "a");
6749       break;
6750     case 3:
6751       emitcode ("swap", "a");
6752       emitcode ("rr", "a");
6753       break;
6754     case 4:
6755       emitcode ("swap", "a");
6756       break;
6757     case 5:
6758       emitcode ("swap", "a");
6759       emitcode ("rl", "a");
6760       break;
6761     case 6:
6762       emitcode ("rr", "a");
6763       emitcode ("rr", "a");
6764       break;
6765     case 7:
6766       emitcode ("rr", "a");
6767       break;
6768     }
6769 }
6770
6771 /*-----------------------------------------------------------------*/
6772 /* AccLsh - left shift accumulator by known count                  */
6773 /*-----------------------------------------------------------------*/
6774 static void
6775 AccLsh (int shCount)
6776 {
6777   if (shCount != 0)
6778     {
6779       if (shCount == 1)
6780         emitcode ("add", "a,acc");
6781       else if (shCount == 2)
6782         {
6783           emitcode ("add", "a,acc");
6784           emitcode ("add", "a,acc");
6785         }
6786       else
6787         {
6788           /* rotate left accumulator */
6789           AccRol (shCount);
6790           /* and kill the lower order bits */
6791           emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6792         }
6793     }
6794 }
6795
6796 /*-----------------------------------------------------------------*/
6797 /* AccRsh - right shift accumulator by known count                 */
6798 /*-----------------------------------------------------------------*/
6799 static void
6800 AccRsh (int shCount)
6801 {
6802   if (shCount != 0)
6803     {
6804       if (shCount == 1)
6805         {
6806           CLRC;
6807           emitcode ("rrc", "a");
6808         }
6809       else
6810         {
6811           /* rotate right accumulator */
6812           AccRol (8 - shCount);
6813           /* and kill the higher order bits */
6814           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6815         }
6816     }
6817 }
6818
6819 #ifdef BETTER_LITERAL_SHIFT
6820 /*-----------------------------------------------------------------*/
6821 /* AccSRsh - signed right shift accumulator by known count                 */
6822 /*-----------------------------------------------------------------*/
6823 static void
6824 AccSRsh (int shCount)
6825 {
6826   symbol *tlbl;
6827   if (shCount != 0)
6828     {
6829       if (shCount == 1)
6830         {
6831           emitcode ("mov", "c,acc.7");
6832           emitcode ("rrc", "a");
6833         }
6834       else if (shCount == 2)
6835         {
6836           emitcode ("mov", "c,acc.7");
6837           emitcode ("rrc", "a");
6838           emitcode ("mov", "c,acc.7");
6839           emitcode ("rrc", "a");
6840         }
6841       else
6842         {
6843           tlbl = newiTempLabel (NULL);
6844           /* rotate right accumulator */
6845           AccRol (8 - shCount);
6846           /* and kill the higher order bits */
6847           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6848           emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6849           emitcode ("orl", "a,#0x%02x",
6850                     (unsigned char) ~SRMask[shCount]);
6851           emitcode ("", "%05d$:", tlbl->key + 100);
6852         }
6853     }
6854 }
6855 #endif
6856
6857 #ifdef BETTER_LITERAL_SHIFT
6858 /*-----------------------------------------------------------------*/
6859 /* shiftR1Left2Result - shift right one byte from left to result   */
6860 /*-----------------------------------------------------------------*/
6861 static void
6862 shiftR1Left2Result (operand * left, int offl,
6863                     operand * result, int offr,
6864                     int shCount, int sign)
6865 {
6866   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6867   /* shift right accumulator */
6868   if (sign)
6869     AccSRsh (shCount);
6870   else
6871     AccRsh (shCount);
6872   aopPut (AOP (result), "a", offr);
6873 }
6874 #endif
6875
6876 #ifdef BETTER_LITERAL_SHIFT
6877 /*-----------------------------------------------------------------*/
6878 /* shiftL1Left2Result - shift left one byte from left to result    */
6879 /*-----------------------------------------------------------------*/
6880 static void
6881 shiftL1Left2Result (operand * left, int offl,
6882                     operand * result, int offr, int shCount)
6883 {
6884   MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6885   /* shift left accumulator */
6886   AccLsh (shCount);
6887   aopPut (AOP (result), "a", offr);
6888 }
6889 #endif
6890
6891 #ifdef BETTER_LITERAL_SHIFT
6892 /*-----------------------------------------------------------------*/
6893 /* movLeft2Result - move byte from left to result                  */
6894 /*-----------------------------------------------------------------*/
6895 static void
6896 movLeft2Result (operand * left, int offl,
6897                 operand * result, int offr, int sign)
6898 {
6899   char *l;
6900   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6901   {
6902       l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
6903
6904       if (*l == '@' && (IS_AOP_PREG (result)))
6905       {
6906           emitcode ("mov", "a,%s", l);
6907           aopPut (AOP (result), "a", offr);
6908       }
6909       else
6910       {
6911           if (!sign)
6912           {
6913             aopPut (AOP (result), l, offr);
6914           }
6915           else
6916             {
6917               /* MSB sign in acc.7 ! */
6918               if (getDataSize (left) == offl + 1)
6919                 {
6920                   emitcode ("mov", "a,%s", l);
6921                   aopPut (AOP (result), "a", offr);
6922                 }
6923             }
6924       }
6925   }
6926 }
6927 #endif
6928
6929 #ifdef BETTER_LITERAL_SHIFT
6930 /*-----------------------------------------------------------------*/
6931 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
6932 /*-----------------------------------------------------------------*/
6933 static void
6934 AccAXRrl1 (char *x)
6935 {
6936   emitcode ("rrc", "a");
6937   emitcode ("xch", "a,%s", x);
6938   emitcode ("rrc", "a");
6939   emitcode ("xch", "a,%s", x);
6940 }
6941 #endif
6942
6943 #ifdef BETTER_LITERAL_SHIFT
6944 //REMOVE ME!!!
6945 /*-----------------------------------------------------------------*/
6946 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
6947 /*-----------------------------------------------------------------*/
6948 static void
6949 AccAXLrl1 (char *x)
6950 {
6951   emitcode ("xch", "a,%s", x);
6952   emitcode ("rlc", "a");
6953   emitcode ("xch", "a,%s", x);
6954   emitcode ("rlc", "a");
6955 }
6956 #endif
6957
6958 #ifdef BETTER_LITERAL_SHIFT
6959 /*-----------------------------------------------------------------*/
6960 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
6961 /*-----------------------------------------------------------------*/
6962 static void
6963 AccAXLsh1 (char *x)
6964 {
6965   emitcode ("xch", "a,%s", x);
6966   emitcode ("add", "a,acc");
6967   emitcode ("xch", "a,%s", x);
6968   emitcode ("rlc", "a");
6969 }
6970 #endif
6971
6972 #ifdef BETTER_LITERAL_SHIFT
6973 /*-----------------------------------------------------------------*/
6974 /* AccAXLsh - left shift a:x by known count (0..7)                 */
6975 /*-----------------------------------------------------------------*/
6976 static void
6977 AccAXLsh (char *x, int shCount)
6978 {
6979   switch (shCount)
6980     {
6981     case 0:
6982       break;
6983     case 1:
6984       AccAXLsh1 (x);
6985       break;
6986     case 2:
6987       AccAXLsh1 (x);
6988       AccAXLsh1 (x);
6989       break;
6990     case 3:
6991     case 4:
6992     case 5:                     // AAAAABBB:CCCCCDDD
6993
6994       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
6995
6996       emitcode ("anl", "a,#0x%02x",
6997                 SLMask[shCount]);       // BBB00000:CCCCCDDD
6998
6999       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
7000
7001       AccRol (shCount);         // DDDCCCCC:BBB00000
7002
7003       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
7004
7005       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
7006
7007       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
7008
7009       emitcode ("anl", "a,#0x%02x",
7010                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
7011
7012       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
7013
7014       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
7015
7016       break;
7017     case 6:                     // AAAAAABB:CCCCCCDD
7018       emitcode ("anl", "a,#0x%02x",
7019                 SRMask[shCount]);       // 000000BB:CCCCCCDD
7020       emitcode ("mov", "c,acc.0");      // c = B
7021       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
7022 #if 0
7023       AccAXRrl1 (x);            // BCCCCCCD:D000000B
7024       AccAXRrl1 (x);            // BBCCCCCC:DD000000
7025 #else
7026       emitcode("rrc","a"); 
7027       emitcode("xch","a,%s", x); 
7028       emitcode("rrc","a"); 
7029       emitcode("mov","c,acc.0"); //<< get correct bit 
7030       emitcode("xch","a,%s", x); 
7031
7032       emitcode("rrc","a"); 
7033       emitcode("xch","a,%s", x); 
7034       emitcode("rrc","a"); 
7035       emitcode("xch","a,%s", x); 
7036 #endif
7037       break;
7038     case 7:                     // a:x <<= 7
7039
7040       emitcode ("anl", "a,#0x%02x",
7041                 SRMask[shCount]);       // 0000000B:CCCCCCCD
7042
7043       emitcode ("mov", "c,acc.0");      // c = B
7044
7045       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
7046
7047       AccAXRrl1 (x);            // BCCCCCCC:D0000000
7048
7049       break;
7050     default:
7051       break;
7052     }
7053 }
7054 #endif
7055
7056 #ifdef BETTER_LITERAL_SHIFT
7057 //REMOVE ME!!!
7058 /*-----------------------------------------------------------------*/
7059 /* AccAXRsh - right shift a:x known count (0..7)                   */
7060 /*-----------------------------------------------------------------*/
7061 static void
7062 AccAXRsh (char *x, int shCount)
7063 {
7064   switch (shCount)
7065     {
7066     case 0:
7067       break;
7068     case 1:
7069       CLRC;
7070       AccAXRrl1 (x);            // 0->a:x
7071
7072       break;
7073     case 2:
7074       CLRC;
7075       AccAXRrl1 (x);            // 0->a:x
7076
7077       CLRC;
7078       AccAXRrl1 (x);            // 0->a:x
7079
7080       break;
7081     case 3:
7082     case 4:
7083     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7084
7085       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
7086
7087       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7088
7089       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7090
7091       emitcode ("anl", "a,#0x%02x",
7092                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7093
7094       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7095
7096       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7097
7098       emitcode ("anl", "a,#0x%02x",
7099                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7100
7101       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7102
7103       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7104
7105       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
7106
7107       break;
7108     case 6:                     // AABBBBBB:CCDDDDDD
7109
7110       emitcode ("mov", "c,acc.7");
7111       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7112
7113       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7114
7115       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7116
7117       emitcode ("anl", "a,#0x%02x",
7118                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7119
7120       break;
7121     case 7:                     // ABBBBBBB:CDDDDDDD
7122
7123       emitcode ("mov", "c,acc.7");      // c = A
7124
7125       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7126
7127       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7128
7129       emitcode ("anl", "a,#0x%02x",
7130                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7131
7132       break;
7133     default:
7134       break;
7135     }
7136 }
7137 #endif
7138
7139 #ifdef BETTER_LITERAL_SHIFT
7140 /*-----------------------------------------------------------------*/
7141 /* AccAXRshS - right shift signed a:x known count (0..7)           */
7142 /*-----------------------------------------------------------------*/
7143 static void
7144 AccAXRshS (char *x, int shCount)
7145 {
7146   symbol *tlbl;
7147   switch (shCount)
7148     {
7149     case 0:
7150       break;
7151     case 1:
7152       emitcode ("mov", "c,acc.7");
7153       AccAXRrl1 (x);            // s->a:x
7154
7155       break;
7156     case 2:
7157       emitcode ("mov", "c,acc.7");
7158       AccAXRrl1 (x);            // s->a:x
7159
7160       emitcode ("mov", "c,acc.7");
7161       AccAXRrl1 (x);            // s->a:x
7162
7163       break;
7164     case 3:
7165     case 4:
7166     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7167
7168       tlbl = newiTempLabel (NULL);
7169       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
7170
7171       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7172
7173       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7174
7175       emitcode ("anl", "a,#0x%02x",
7176                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7177
7178       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7179
7180       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7181
7182       emitcode ("anl", "a,#0x%02x",
7183                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7184
7185       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7186
7187       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7188
7189       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
7190
7191       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7192       emitcode ("orl", "a,#0x%02x",
7193                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
7194
7195       emitcode ("", "%05d$:", tlbl->key + 100);
7196       break;                    // SSSSAAAA:BBBCCCCC
7197
7198     case 6:                     // AABBBBBB:CCDDDDDD
7199
7200       tlbl = newiTempLabel (NULL);
7201       emitcode ("mov", "c,acc.7");
7202       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7203
7204       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7205
7206       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7207
7208       emitcode ("anl", "a,#0x%02x",
7209                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7210
7211       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7212       emitcode ("orl", "a,#0x%02x",
7213                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
7214
7215       emitcode ("", "%05d$:", tlbl->key + 100);
7216       break;
7217     case 7:                     // ABBBBBBB:CDDDDDDD
7218
7219       tlbl = newiTempLabel (NULL);
7220       emitcode ("mov", "c,acc.7");      // c = A
7221
7222       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7223
7224       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7225
7226       emitcode ("anl", "a,#0x%02x",
7227                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7228
7229       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7230       emitcode ("orl", "a,#0x%02x",
7231                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
7232
7233       emitcode ("", "%05d$:", tlbl->key + 100);
7234       break;
7235     default:
7236       break;
7237     }
7238 }
7239 #endif
7240
7241 #ifdef BETTER_LITERAL_SHIFT
7242 static void
7243 _loadLeftIntoAx(char    **lsb, 
7244                 operand *left, 
7245                 operand *result,
7246                 int     offl,
7247                 int     offr)
7248 {
7249   // Get the initial value from left into a pair of registers.
7250   // MSB must be in A, LSB can be any register.
7251   //
7252   // If the result is held in registers, it is an optimization
7253   // if the LSB can be held in the register which will hold the,
7254   // result LSB since this saves us from having to copy it into
7255   // the result following AccAXLsh.
7256   //
7257   // If the result is addressed indirectly, this is not a gain.
7258   if (AOP_NEEDSACC(result))
7259   {
7260        char *leftByte;
7261        
7262        _startLazyDPSEvaluation();
7263       if (AOP_TYPE(left) == AOP_DPTR2)
7264        {
7265            // Get MSB in A.
7266            MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
7267            // get LSB in DP2_RESULT_REG.
7268            leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
7269            assert(!strcmp(leftByte, DP2_RESULT_REG));
7270        }
7271        else
7272        {
7273            // get LSB into DP2_RESULT_REG
7274            leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
7275            if (strcmp(leftByte, DP2_RESULT_REG))
7276            {
7277                TR_AP("#7");
7278                emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7279            }
7280            // And MSB in A.
7281            leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
7282            assert(strcmp(leftByte, DP2_RESULT_REG));
7283            MOVA(leftByte);
7284        }
7285        _endLazyDPSEvaluation();
7286        *lsb = DP2_RESULT_REG;
7287   }
7288   else
7289   {
7290       if (sameRegs (AOP (result), AOP (left)) &&
7291         ((offl + MSB16) == offr))
7292       {
7293           /* don't crash result[offr] */
7294           MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
7295           emitcode ("xch", "a,%s", 
7296                     aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
7297       }
7298       else
7299       {
7300           movLeft2Result (left, offl, result, offr, 0);
7301           MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
7302       }
7303       *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
7304       assert(strcmp(*lsb,"a"));      
7305   }
7306 }
7307
7308 static void
7309 _storeAxResults(char    *lsb,
7310                 operand *result,
7311                 int     offr)
7312 {
7313   _startLazyDPSEvaluation();
7314   if (AOP_NEEDSACC(result))
7315   {
7316       /* We have to explicitly update the result LSB.
7317        */
7318       emitcode("xch","a,%s", lsb);
7319       aopPut(AOP(result), "a", offr);
7320       emitcode("mov","a,%s", lsb);
7321   }
7322   if (getDataSize (result) > 1)
7323   {
7324       aopPut (AOP (result), "a", offr + MSB16);
7325   }
7326   _endLazyDPSEvaluation();
7327 }
7328
7329 /*-----------------------------------------------------------------*/
7330 /* shiftL2Left2Result - shift left two bytes from left to result   */
7331 /*-----------------------------------------------------------------*/
7332 static void
7333 shiftL2Left2Result (operand * left, int offl,
7334                     operand * result, int offr, int shCount)
7335 {
7336   char *lsb;
7337
7338   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7339   
7340   AccAXLsh (lsb, shCount);
7341   
7342   _storeAxResults(lsb, result, offr);
7343 }
7344 #endif
7345
7346 #ifdef BETTER_LITERAL_SHIFT
7347 /*-----------------------------------------------------------------*/
7348 /* shiftR2Left2Result - shift right two bytes from left to result  */
7349 /*-----------------------------------------------------------------*/
7350 static void
7351 shiftR2Left2Result (operand * left, int offl,
7352                     operand * result, int offr,
7353                     int shCount, int sign)
7354 {
7355   char *lsb;
7356   
7357   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7358   
7359   /* a:x >> shCount (x = lsb(result)) */
7360   if (sign)
7361   {
7362      AccAXRshS(lsb, shCount);
7363   }
7364   else
7365   {
7366     AccAXRsh(lsb, shCount);
7367   }
7368   
7369   _storeAxResults(lsb, result, offr);
7370 }
7371 #endif
7372
7373 #if 0
7374 //REMOVE ME!!!
7375 /*-----------------------------------------------------------------*/
7376 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7377 /*-----------------------------------------------------------------*/
7378 static void
7379 shiftLLeftOrResult (operand * left, int offl,
7380                     operand * result, int offr, int shCount)
7381 {
7382   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7383   /* shift left accumulator */
7384   AccLsh (shCount);
7385   /* or with result */
7386   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7387   /* back to result */
7388   aopPut (AOP (result), "a", offr);
7389 }
7390 #endif
7391
7392 #if 0
7393 //REMOVE ME!!!
7394 /*-----------------------------------------------------------------*/
7395 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7396 /*-----------------------------------------------------------------*/
7397 static void
7398 shiftRLeftOrResult (operand * left, int offl,
7399                     operand * result, int offr, int shCount)
7400 {
7401   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7402   /* shift right accumulator */
7403   AccRsh (shCount);
7404   /* or with result */
7405   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7406   /* back to result */
7407   aopPut (AOP (result), "a", offr);
7408 }
7409 #endif
7410
7411 #ifdef BETTER_LITERAL_SHIFT
7412 /*-----------------------------------------------------------------*/
7413 /* genlshOne - left shift a one byte quantity by known count       */
7414 /*-----------------------------------------------------------------*/
7415 static void
7416 genlshOne (operand * result, operand * left, int shCount)
7417 {
7418   D (emitcode (";", "genlshOne "););
7419   shiftL1Left2Result (left, LSB, result, LSB, shCount);
7420 }
7421 #endif
7422
7423 #ifdef BETTER_LITERAL_SHIFT
7424 /*-----------------------------------------------------------------*/
7425 /* genlshTwo - left shift two bytes by known amount != 0           */
7426 /*-----------------------------------------------------------------*/
7427 static void
7428 genlshTwo (operand * result, operand * left, int shCount)
7429 {
7430   int size;
7431
7432   D (emitcode (";", "genlshTwo "););
7433
7434   size = getDataSize (result);
7435
7436   /* if shCount >= 8 */
7437   if (shCount >= 8)
7438   {
7439       shCount -= 8;
7440
7441       _startLazyDPSEvaluation();
7442
7443       if (size > 1)
7444         {
7445           if (shCount)
7446           {
7447             _endLazyDPSEvaluation();
7448             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7449             aopPut (AOP (result), zero, LSB);       
7450           }
7451           else
7452           {
7453             movLeft2Result (left, LSB, result, MSB16, 0);
7454             aopPut (AOP (result), zero, LSB);
7455             _endLazyDPSEvaluation();
7456           }
7457         }
7458         else
7459         {
7460           aopPut (AOP (result), zero, LSB);
7461           _endLazyDPSEvaluation();
7462         }
7463   }
7464
7465   /*  1 <= shCount <= 7 */
7466   else
7467     {
7468       if (size == 1)
7469       {
7470         shiftL1Left2Result (left, LSB, result, LSB, shCount);
7471       }
7472       else
7473       {
7474         shiftL2Left2Result (left, LSB, result, LSB, shCount);
7475       }
7476     }
7477 }
7478 #endif
7479
7480 #if 0
7481 //REMOVE ME!!!
7482 /*-----------------------------------------------------------------*/
7483 /* shiftLLong - shift left one long from left to result            */
7484 /* offl = LSB or MSB16                                             */
7485 /*-----------------------------------------------------------------*/
7486 static void
7487 shiftLLong (operand * left, operand * result, int offr)
7488 {
7489   char *l;
7490   int size = AOP_SIZE (result);
7491
7492   if (size >= LSB + offr)
7493     {
7494       l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
7495       MOVA (l);
7496       emitcode ("add", "a,acc");
7497       if (sameRegs (AOP (left), AOP (result)) &&
7498           size >= MSB16 + offr && offr != LSB)
7499         emitcode ("xch", "a,%s",
7500                   aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
7501       else
7502         aopPut (AOP (result), "a", LSB + offr);
7503     }
7504
7505   if (size >= MSB16 + offr)
7506     {
7507       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7508         {
7509           l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
7510           MOVA (l);
7511         }
7512       emitcode ("rlc", "a");
7513       if (sameRegs (AOP (left), AOP (result)) &&
7514           size >= MSB24 + offr && offr != LSB)
7515         emitcode ("xch", "a,%s",
7516                   aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
7517       else
7518         aopPut (AOP (result), "a", MSB16 + offr);
7519     }
7520
7521   if (size >= MSB24 + offr)
7522     {
7523       if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7524         {
7525           l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
7526           MOVA (l);
7527         }
7528       emitcode ("rlc", "a");
7529       if (sameRegs (AOP (left), AOP (result)) &&
7530           size >= MSB32 + offr && offr != LSB)
7531         emitcode ("xch", "a,%s",
7532                   aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
7533       else
7534         aopPut (AOP (result), "a", MSB24 + offr);
7535     }
7536
7537   if (size > MSB32 + offr)
7538     {
7539       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7540         {
7541           l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
7542           MOVA (l);
7543         }
7544       emitcode ("rlc", "a");
7545       aopPut (AOP (result), "a", MSB32 + offr);
7546     }
7547   if (offr != LSB)
7548     aopPut (AOP (result), zero, LSB);
7549 }
7550 #endif
7551
7552 #if 0
7553 //REMOVE ME!!!
7554 /*-----------------------------------------------------------------*/
7555 /* genlshFour - shift four byte by a known amount != 0             */
7556 /*-----------------------------------------------------------------*/
7557 static void
7558 genlshFour (operand * result, operand * left, int shCount)
7559 {
7560   int size;
7561
7562   D (emitcode (";", "genlshFour ");
7563     );
7564
7565   size = AOP_SIZE (result);
7566
7567   /* if shifting more that 3 bytes */
7568   if (shCount >= 24)
7569     {
7570       shCount -= 24;
7571       if (shCount)
7572         /* lowest order of left goes to the highest
7573            order of the destination */
7574         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7575       else
7576         movLeft2Result (left, LSB, result, MSB32, 0);
7577       aopPut (AOP (result), zero, LSB);
7578       aopPut (AOP (result), zero, MSB16);
7579       aopPut (AOP (result), zero, MSB24);
7580       return;
7581     }
7582
7583   /* more than two bytes */
7584   else if (shCount >= 16)
7585     {
7586       /* lower order two bytes goes to higher order two bytes */
7587       shCount -= 16;
7588       /* if some more remaining */
7589       if (shCount)
7590         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7591       else
7592         {
7593           movLeft2Result (left, MSB16, result, MSB32, 0);
7594           movLeft2Result (left, LSB, result, MSB24, 0);
7595         }
7596       aopPut (AOP (result), zero, MSB16);
7597       aopPut (AOP (result), zero, LSB);
7598       return;
7599     }
7600
7601   /* if more than 1 byte */
7602   else if (shCount >= 8)
7603     {
7604       /* lower order three bytes goes to higher order  three bytes */
7605       shCount -= 8;
7606       if (size == 2)
7607         {
7608           if (shCount)
7609             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7610           else
7611             movLeft2Result (left, LSB, result, MSB16, 0);
7612         }
7613       else
7614         {                       /* size = 4 */
7615           if (shCount == 0)
7616             {
7617               movLeft2Result (left, MSB24, result, MSB32, 0);
7618               movLeft2Result (left, MSB16, result, MSB24, 0);
7619               movLeft2Result (left, LSB, result, MSB16, 0);
7620               aopPut (AOP (result), zero, LSB);
7621             }
7622           else if (shCount == 1)
7623             shiftLLong (left, result, MSB16);
7624           else
7625             {
7626               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7627               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7628               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7629               aopPut (AOP (result), zero, LSB);
7630             }
7631         }
7632     }
7633
7634   /* 1 <= shCount <= 7 */
7635   else if (shCount <= 2)
7636     {
7637       shiftLLong (left, result, LSB);
7638       if (shCount == 2)
7639         shiftLLong (result, result, LSB);
7640     }
7641   /* 3 <= shCount <= 7, optimize */
7642   else
7643     {
7644       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7645       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7646       shiftL2Left2Result (left, LSB, result, LSB, shCount);
7647     }
7648 }
7649 #endif
7650
7651 #ifdef BETTER_LITERAL_SHIFT
7652 /*-----------------------------------------------------------------*/
7653 /* genLeftShiftLiteral - left shifting by known count              */
7654 /*-----------------------------------------------------------------*/
7655 static bool
7656 genLeftShiftLiteral (operand * left,
7657                      operand * right,
7658                      operand * result,
7659                      iCode * ic)
7660 {
7661   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7662   int size;
7663
7664   size = getSize (operandType (result));
7665
7666   D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
7667
7668   /* We only handle certain easy cases so far. */
7669   if ((shCount != 0)
7670    && (shCount < (size * 8))
7671    && (size != 1)
7672    && (size != 2))
7673   {
7674       D(emitcode (";", "genLeftShiftLiteral wimping out"););    
7675       return FALSE;
7676   }
7677
7678   freeAsmop (right, NULL, ic, TRUE);
7679
7680   aopOp(left, ic, FALSE, FALSE);
7681   aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
7682
7683 #if 1 // debug spew
7684   if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
7685   {
7686         emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
7687         if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
7688         {
7689            emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
7690         }
7691   }
7692   if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
7693   {
7694         emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
7695         if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
7696         {
7697            emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
7698         }       
7699   }  
7700 #endif
7701   
7702 #if VIEW_SIZE
7703   emitcode ("; shift left ", "result %d, left %d", size,
7704             AOP_SIZE (left));
7705 #endif
7706
7707   /* I suppose that the left size >= result size */
7708   if (shCount == 0)
7709   {
7710         _startLazyDPSEvaluation();
7711         while (size--)
7712         {
7713           movLeft2Result (left, size, result, size, 0);
7714         }
7715         _endLazyDPSEvaluation();
7716   }
7717   else if (shCount >= (size * 8))
7718   {
7719     _startLazyDPSEvaluation();
7720     while (size--)
7721     {
7722       aopPut (AOP (result), zero, size);
7723     }
7724     _endLazyDPSEvaluation();
7725   }
7726   else
7727   {
7728       switch (size)
7729         {
7730         case 1:
7731           genlshOne (result, left, shCount);
7732           break;
7733
7734         case 2:
7735           genlshTwo (result, left, shCount);
7736           break;
7737 #if 0
7738         case 4:
7739           genlshFour (result, left, shCount);
7740           break;
7741 #endif
7742         default:
7743           fprintf(stderr, "*** ack! mystery literal shift!\n");   
7744           break;
7745         }
7746     }
7747   freeAsmop (left, NULL, ic, TRUE);
7748   freeAsmop (result, NULL, ic, TRUE);
7749   return TRUE;
7750 }
7751 #endif
7752
7753 /*-----------------------------------------------------------------*/
7754 /* genLeftShift - generates code for left shifting                 */
7755 /*-----------------------------------------------------------------*/
7756 static void
7757 genLeftShift (iCode * ic)
7758 {
7759   operand *left, *right, *result;
7760   int size, offset;
7761   char *l;
7762   symbol *tlbl, *tlbl1;
7763
7764   D (emitcode (";", "genLeftShift "););
7765
7766   right = IC_RIGHT (ic);
7767   left = IC_LEFT (ic);
7768   result = IC_RESULT (ic);
7769
7770   aopOp (right, ic, FALSE, FALSE);
7771
7772
7773 #ifdef BETTER_LITERAL_SHIFT
7774   /* if the shift count is known then do it
7775      as efficiently as possible */
7776   if (AOP_TYPE (right) == AOP_LIT)
7777     {
7778       if (genLeftShiftLiteral (left, right, result, ic))
7779       {
7780         return;
7781       }
7782     }
7783 #endif
7784
7785   /* shift count is unknown then we have to form
7786      a loop get the loop count in B : Note: we take
7787      only the lower order byte since shifting
7788      more that 32 bits make no sense anyway, ( the
7789      largest size of an object can be only 32 bits ) */
7790
7791   if (AOP_TYPE (right) == AOP_LIT)
7792   {
7793       /* Really should be handled by genLeftShiftLiteral,
7794        * but since I'm too lazy to fix that today, at least we can make
7795        * some small improvement.
7796        */
7797        emitcode("mov", "b,#0x%02x",
7798                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7799   }
7800   else
7801   {
7802         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7803         emitcode ("inc", "b");
7804   }
7805   freeAsmop (right, NULL, ic, TRUE);
7806   aopOp (left, ic, FALSE, FALSE);
7807   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7808
7809   /* now move the left to the result if they are not the
7810      same */
7811   if (!sameRegs (AOP (left), AOP (result)) &&
7812       AOP_SIZE (result) > 1)
7813     {
7814
7815       size = AOP_SIZE (result);
7816       offset = 0;
7817       _startLazyDPSEvaluation ();
7818       while (size--)
7819         {
7820           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7821           if (*l == '@' && (IS_AOP_PREG (result)))
7822             {
7823
7824               emitcode ("mov", "a,%s", l);
7825               aopPut (AOP (result), "a", offset);
7826             }
7827           else
7828             aopPut (AOP (result), l, offset);
7829           offset++;
7830         }
7831       _endLazyDPSEvaluation ();
7832     }
7833
7834   tlbl = newiTempLabel (NULL);
7835   size = AOP_SIZE (result);
7836   offset = 0;
7837   tlbl1 = newiTempLabel (NULL);
7838
7839   /* if it is only one byte then */
7840   if (size == 1)
7841     {
7842       symbol *tlbl1 = newiTempLabel (NULL);
7843
7844       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7845       MOVA (l);
7846       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7847       emitcode ("", "%05d$:", tlbl->key + 100);
7848       emitcode ("add", "a,acc");
7849       emitcode ("", "%05d$:", tlbl1->key + 100);
7850       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7851       aopPut (AOP (result), "a", 0);
7852       goto release;
7853     }
7854
7855   reAdjustPreg (AOP (result));
7856
7857   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7858   emitcode ("", "%05d$:", tlbl->key + 100);
7859   l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7860   MOVA (l);
7861   emitcode ("add", "a,acc");
7862   aopPut (AOP (result), "a", offset++);
7863   _startLazyDPSEvaluation ();
7864   while (--size)
7865     {
7866       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7867       MOVA (l);
7868       emitcode ("rlc", "a");
7869       aopPut (AOP (result), "a", offset++);
7870     }
7871   _endLazyDPSEvaluation ();
7872   reAdjustPreg (AOP (result));
7873
7874   emitcode ("", "%05d$:", tlbl1->key + 100);
7875   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7876 release:
7877   freeAsmop (left, NULL, ic, TRUE);
7878   freeAsmop (result, NULL, ic, TRUE);
7879 }
7880
7881 #ifdef BETTER_LITERAL_SHIFT
7882 /*-----------------------------------------------------------------*/
7883 /* genrshOne - right shift a one byte quantity by known count      */
7884 /*-----------------------------------------------------------------*/
7885 static void
7886 genrshOne (operand * result, operand * left,
7887            int shCount, int sign)
7888 {
7889   D (emitcode (";", "genrshOne"););
7890   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7891 }
7892 #endif
7893
7894 #ifdef BETTER_LITERAL_SHIFT
7895 /*-----------------------------------------------------------------*/
7896 /* genrshTwo - right shift two bytes by known amount != 0          */
7897 /*-----------------------------------------------------------------*/
7898 static void
7899 genrshTwo (operand * result, operand * left,
7900            int shCount, int sign)
7901 {
7902   D (emitcode (";", "genrshTwo"););
7903
7904   /* if shCount >= 8 */
7905   if (shCount >= 8)
7906     {
7907       shCount -= 8;
7908       _startLazyDPSEvaluation();
7909       if (shCount)
7910       {
7911         shiftR1Left2Result (left, MSB16, result, LSB,
7912                             shCount, sign);
7913       }                     
7914       else
7915       {
7916         movLeft2Result (left, MSB16, result, LSB, sign);
7917       }
7918       addSign (result, MSB16, sign);
7919       _endLazyDPSEvaluation();
7920     }
7921
7922   /*  1 <= shCount <= 7 */
7923   else
7924   {
7925     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7926   }
7927 }
7928 #endif
7929
7930 #if 0
7931 //REMOVE ME!!!
7932 /*-----------------------------------------------------------------*/
7933 /* shiftRLong - shift right one long from left to result           */
7934 /* offl = LSB or MSB16                                             */
7935 /*-----------------------------------------------------------------*/
7936 static void
7937 shiftRLong (operand * left, int offl,
7938             operand * result, int sign)
7939 {
7940   int isSameRegs=sameRegs(AOP(left),AOP(result));
7941
7942   if (isSameRegs && offl>1) {
7943     // we are in big trouble, but this shouldn't happen
7944     werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
7945   }
7946
7947   MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7948   
7949   if (offl==MSB16) {
7950     // shift is > 8
7951     if (sign) {
7952       emitcode ("rlc", "a");
7953       emitcode ("subb", "a,acc");
7954       emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
7955     } else {
7956       aopPut (AOP(result), zero, MSB32);
7957     }
7958   }
7959
7960   if (!sign) {
7961     emitcode ("clr", "c");
7962   } else {
7963     emitcode ("mov", "c,acc.7");
7964   }
7965
7966   emitcode ("rrc", "a");
7967
7968   if (isSameRegs && offl==MSB16) {
7969     emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
7970   } else {
7971     aopPut (AOP (result), "a", MSB32);
7972     MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
7973   }
7974
7975   emitcode ("rrc", "a");
7976   if (isSameRegs && offl==1) {
7977     emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
7978   } else {
7979     aopPut (AOP (result), "a", MSB24);
7980     MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
7981   }
7982   emitcode ("rrc", "a");
7983   aopPut (AOP (result), "a", MSB16 - offl);
7984
7985   if (offl == LSB)
7986     {
7987       MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
7988       emitcode ("rrc", "a");
7989       aopPut (AOP (result), "a", LSB);
7990     }
7991 }
7992 #endif
7993
7994 #if 0
7995 //REMOVE ME!!!
7996 /*-----------------------------------------------------------------*/
7997 /* genrshFour - shift four byte by a known amount != 0             */
7998 /*-----------------------------------------------------------------*/
7999 static void
8000 genrshFour (operand * result, operand * left,
8001             int shCount, int sign)
8002 {
8003   D (emitcode (";", "genrshFour");
8004     );
8005
8006   /* if shifting more that 3 bytes */
8007   if (shCount >= 24)
8008     {
8009       shCount -= 24;
8010       if (shCount)
8011         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8012       else
8013         movLeft2Result (left, MSB32, result, LSB, sign);
8014       addSign (result, MSB16, sign);
8015     }
8016   else if (shCount >= 16)
8017     {
8018       shCount -= 16;
8019       if (shCount)
8020         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8021       else
8022         {
8023           movLeft2Result (left, MSB24, result, LSB, 0);
8024           movLeft2Result (left, MSB32, result, MSB16, sign);
8025         }
8026       addSign (result, MSB24, sign);
8027     }
8028   else if (shCount >= 8)
8029     {
8030       shCount -= 8;
8031       if (shCount == 1)
8032         shiftRLong (left, MSB16, result, sign);
8033       else if (shCount == 0)
8034         {
8035           movLeft2Result (left, MSB16, result, LSB, 0);
8036           movLeft2Result (left, MSB24, result, MSB16, 0);
8037           movLeft2Result (left, MSB32, result, MSB24, sign);
8038           addSign (result, MSB32, sign);
8039         }
8040       else
8041         {
8042           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8043           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8044           /* the last shift is signed */
8045           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8046           addSign (result, MSB32, sign);
8047         }
8048     }
8049   else
8050     {                           /* 1 <= shCount <= 7 */
8051       if (shCount <= 2)
8052         {
8053           shiftRLong (left, LSB, result, sign);
8054           if (shCount == 2)
8055             shiftRLong (result, LSB, result, sign);
8056         }
8057       else
8058         {
8059           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8060           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8061           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8062         }
8063     }
8064 }
8065 #endif
8066
8067 #ifdef BETTER_LITERAL_SHIFT
8068 /*-----------------------------------------------------------------*/
8069 /* genRightShiftLiteral - right shifting by known count            */
8070 /*-----------------------------------------------------------------*/
8071 static bool
8072 genRightShiftLiteral (operand * left,
8073                       operand * right,
8074                       operand * result,
8075                       iCode * ic,
8076                       int sign)
8077 {
8078   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8079   int size;
8080
8081   size = getSize (operandType (result));
8082
8083   D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8084
8085   /* We only handle certain easy cases so far. */
8086   if ((shCount != 0)
8087    && (shCount < (size * 8))
8088    && (size != 1)
8089    && (size != 2))
8090   {
8091       D(emitcode (";", "genRightShiftLiteral wimping out"););   
8092       return FALSE;
8093   }
8094
8095   freeAsmop (right, NULL, ic, TRUE);
8096
8097   aopOp (left, ic, FALSE, FALSE);
8098   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8099
8100 #if VIEW_SIZE
8101   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8102             AOP_SIZE (left));
8103 #endif
8104
8105   /* test the LEFT size !!! */
8106
8107   /* I suppose that the left size >= result size */
8108   if (shCount == 0)
8109   {
8110       size = getDataSize (result);
8111       _startLazyDPSEvaluation();
8112       while (size--)
8113       {
8114         movLeft2Result (left, size, result, size, 0);
8115       }
8116       _endLazyDPSEvaluation();
8117   }
8118   else if (shCount >= (size * 8))
8119     {
8120       if (sign)
8121       {
8122         /* get sign in acc.7 */
8123         MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
8124       }
8125       addSign (result, LSB, sign);
8126     }
8127   else
8128     {
8129       switch (size)
8130         {
8131         case 1:
8132           genrshOne (result, left, shCount, sign);
8133           break;
8134
8135         case 2:
8136           genrshTwo (result, left, shCount, sign);
8137           break;
8138 #if 0
8139         case 4:
8140           genrshFour (result, left, shCount, sign);
8141           break;
8142 #endif    
8143         default:
8144           break;
8145         }
8146
8147       freeAsmop (left, NULL, ic, TRUE);
8148       freeAsmop (result, NULL, ic, TRUE);
8149     }
8150     return TRUE;
8151 }
8152 #endif
8153
8154 /*-----------------------------------------------------------------*/
8155 /* genSignedRightShift - right shift of signed number              */
8156 /*-----------------------------------------------------------------*/
8157 static void
8158 genSignedRightShift (iCode * ic)
8159 {
8160   operand *right, *left, *result;
8161   int size, offset;
8162   char *l;
8163   symbol *tlbl, *tlbl1;
8164
8165   D (emitcode (";", "genSignedRightShift "););
8166
8167   /* we do it the hard way put the shift count in b
8168      and loop thru preserving the sign */
8169
8170   right = IC_RIGHT (ic);
8171   left = IC_LEFT (ic);
8172   result = IC_RESULT (ic);
8173
8174   aopOp (right, ic, FALSE, FALSE);
8175
8176 #ifdef BETTER_LITERAL_SHIFT
8177   if (AOP_TYPE (right) == AOP_LIT)
8178     {
8179       if (genRightShiftLiteral (left, right, result, ic, 1))
8180       {
8181         return;
8182       }
8183     }
8184 #endif
8185   /* shift count is unknown then we have to form
8186      a loop get the loop count in B : Note: we take
8187      only the lower order byte since shifting
8188      more that 32 bits make no sense anyway, ( the
8189      largest size of an object can be only 32 bits ) */
8190
8191   if (AOP_TYPE (right) == AOP_LIT)
8192   {
8193       /* Really should be handled by genRightShiftLiteral,
8194        * but since I'm too lazy to fix that today, at least we can make
8195        * some small improvement.
8196        */
8197        emitcode("mov", "b,#0x%02x",
8198                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8199   }
8200   else
8201   {
8202         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8203         emitcode ("inc", "b");
8204   }
8205   freeAsmop (right, NULL, ic, TRUE);
8206   aopOp (left, ic, FALSE, FALSE);
8207   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8208
8209   /* now move the left to the result if they are not the
8210      same */
8211   if (!sameRegs (AOP (left), AOP (result)) &&
8212       AOP_SIZE (result) > 1)
8213     {
8214
8215       size = AOP_SIZE (result);
8216       offset = 0;
8217       _startLazyDPSEvaluation ();
8218       while (size--)
8219         {
8220           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8221           if (*l == '@' && IS_AOP_PREG (result))
8222             {
8223
8224               emitcode ("mov", "a,%s", l);
8225               aopPut (AOP (result), "a", offset);
8226             }
8227           else
8228             aopPut (AOP (result), l, offset);
8229           offset++;
8230         }
8231       _endLazyDPSEvaluation ();
8232     }
8233
8234   /* mov the highest order bit to OVR */
8235   tlbl = newiTempLabel (NULL);
8236   tlbl1 = newiTempLabel (NULL);
8237
8238   size = AOP_SIZE (result);
8239   offset = size - 1;
8240   emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
8241   emitcode ("rlc", "a");
8242   emitcode ("mov", "ov,c");
8243   /* if it is only one byte then */
8244   if (size == 1)
8245     {
8246       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8247       MOVA (l);
8248       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8249       emitcode ("", "%05d$:", tlbl->key + 100);
8250       emitcode ("mov", "c,ov");
8251       emitcode ("rrc", "a");
8252       emitcode ("", "%05d$:", tlbl1->key + 100);
8253       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8254       aopPut (AOP (result), "a", 0);
8255       goto release;
8256     }
8257
8258   reAdjustPreg (AOP (result));
8259   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8260   emitcode ("", "%05d$:", tlbl->key + 100);
8261   emitcode ("mov", "c,ov");
8262   _startLazyDPSEvaluation ();
8263   while (size--)
8264     {
8265       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8266       MOVA (l);
8267       emitcode ("rrc", "a");
8268       aopPut (AOP (result), "a", offset--);
8269     }
8270   _endLazyDPSEvaluation ();
8271   reAdjustPreg (AOP (result));
8272   emitcode ("", "%05d$:", tlbl1->key + 100);
8273   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8274
8275 release:
8276   freeAsmop (left, NULL, ic, TRUE);
8277   freeAsmop (result, NULL, ic, TRUE);
8278 }
8279
8280 /*-----------------------------------------------------------------*/
8281 /* genRightShift - generate code for right shifting                */
8282 /*-----------------------------------------------------------------*/
8283 static void
8284 genRightShift (iCode * ic)
8285 {
8286   operand *right, *left, *result;
8287   sym_link *retype;
8288   int size, offset;
8289   char *l;
8290   symbol *tlbl, *tlbl1;
8291
8292   D (emitcode (";", "genRightShift "););
8293
8294   /* if signed then we do it the hard way preserve the
8295      sign bit moving it inwards */
8296   retype = getSpec (operandType (IC_RESULT (ic)));
8297
8298   if (!SPEC_USIGN (retype))
8299     {
8300       genSignedRightShift (ic);
8301       return;
8302     }
8303
8304   /* signed & unsigned types are treated the same : i.e. the
8305      signed is NOT propagated inwards : quoting from the
8306      ANSI - standard : "for E1 >> E2, is equivalent to division
8307      by 2**E2 if unsigned or if it has a non-negative value,
8308      otherwise the result is implementation defined ", MY definition
8309      is that the sign does not get propagated */
8310
8311   right = IC_RIGHT (ic);
8312   left = IC_LEFT (ic);
8313   result = IC_RESULT (ic);
8314
8315   aopOp (right, ic, FALSE, FALSE);
8316
8317 #ifdef BETTER_LITERAL_SHIFT
8318   /* if the shift count is known then do it
8319      as efficiently as possible */
8320   if (AOP_TYPE (right) == AOP_LIT)
8321     {
8322       if (genRightShiftLiteral (left, right, result, ic, 0))
8323       {
8324         return;
8325       }
8326     }
8327 #endif
8328
8329   /* shift count is unknown then we have to form
8330      a loop get the loop count in B : Note: we take
8331      only the lower order byte since shifting
8332      more that 32 bits make no sense anyway, ( the
8333      largest size of an object can be only 32 bits ) */
8334   
8335   if (AOP_TYPE (right) == AOP_LIT)
8336   {
8337       /* Really should be handled by genRightShiftLiteral,
8338        * but since I'm too lazy to fix that today, at least we can make
8339        * some small improvement.
8340        */
8341        emitcode("mov", "b,#0x%02x",
8342                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8343   }
8344   else
8345   {
8346         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8347         emitcode ("inc", "b");
8348   }
8349   freeAsmop (right, NULL, ic, TRUE);
8350   aopOp (left, ic, FALSE, FALSE);
8351   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8352
8353   /* now move the left to the result if they are not the
8354      same */
8355   if (!sameRegs (AOP (left), AOP (result)) &&
8356       AOP_SIZE (result) > 1)
8357     {
8358
8359       size = AOP_SIZE (result);
8360       offset = 0;
8361       _startLazyDPSEvaluation ();
8362       while (size--)
8363         {
8364           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8365           if (*l == '@' && IS_AOP_PREG (result))
8366             {
8367
8368               emitcode ("mov", "a,%s", l);
8369               aopPut (AOP (result), "a", offset);
8370             }
8371           else
8372             aopPut (AOP (result), l, offset);
8373           offset++;
8374         }
8375       _endLazyDPSEvaluation ();
8376     }
8377
8378   tlbl = newiTempLabel (NULL);
8379   tlbl1 = newiTempLabel (NULL);
8380   size = AOP_SIZE (result);
8381   offset = size - 1;
8382
8383   /* if it is only one byte then */
8384   if (size == 1)
8385     {
8386       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8387       MOVA (l);
8388       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8389       emitcode ("", "%05d$:", tlbl->key + 100);
8390       CLRC;
8391       emitcode ("rrc", "a");
8392       emitcode ("", "%05d$:", tlbl1->key + 100);
8393       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8394       aopPut (AOP (result), "a", 0);
8395       goto release;
8396     }
8397
8398   reAdjustPreg (AOP (result));
8399   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8400   emitcode ("", "%05d$:", tlbl->key + 100);
8401   CLRC;
8402   _startLazyDPSEvaluation ();
8403   while (size--)
8404     {
8405       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8406       MOVA (l);
8407       emitcode ("rrc", "a");
8408       aopPut (AOP (result), "a", offset--);
8409     }
8410   _endLazyDPSEvaluation ();
8411   reAdjustPreg (AOP (result));
8412
8413   emitcode ("", "%05d$:", tlbl1->key + 100);
8414   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8415
8416 release:
8417   freeAsmop (left, NULL, ic, TRUE);
8418   freeAsmop (result, NULL, ic, TRUE);
8419 }
8420
8421 /*-----------------------------------------------------------------*/
8422 /* genUnpackBits - generates code for unpacking bits               */
8423 /*-----------------------------------------------------------------*/
8424 static void
8425 genUnpackBits (operand * result, char *rname, int ptype)
8426 {
8427   int shCnt;
8428   int rlen = 0;
8429   sym_link *etype;
8430   int offset = 0;
8431
8432   D (emitcode (";", "genUnpackBits ");
8433     );
8434
8435   etype = getSpec (operandType (result));
8436
8437   /* read the first byte  */
8438   switch (ptype)
8439     {
8440
8441     case POINTER:
8442     case IPOINTER:
8443       emitcode ("mov", "a,@%s", rname);
8444       break;
8445
8446     case PPOINTER:
8447       emitcode ("movx", "a,@%s", rname);
8448       break;
8449
8450     case FPOINTER:
8451       emitcode ("movx", "a,@dptr");
8452       break;
8453
8454     case CPOINTER:
8455       emitcode ("clr", "a");
8456       emitcode ("movc", "a,@a+dptr");
8457       break;
8458
8459     case GPOINTER:
8460       emitcode ("lcall", "__gptrget");
8461       break;
8462     }
8463
8464   /* if we have bitdisplacement then it fits   */
8465   /* into this byte completely or if length is */
8466   /* less than a byte                          */
8467   if ((shCnt = SPEC_BSTR (etype)) ||
8468       (SPEC_BLEN (etype) <= 8))
8469     {
8470
8471       /* shift right acc */
8472       AccRsh (shCnt);
8473
8474       emitcode ("anl", "a,#0x%02x",
8475                 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
8476       aopPut (AOP (result), "a", offset);
8477       return;
8478     }
8479
8480   /* bit field did not fit in a byte  */
8481   rlen = SPEC_BLEN (etype) - 8;
8482   aopPut (AOP (result), "a", offset++);
8483
8484   while (1)
8485     {
8486
8487       switch (ptype)
8488         {
8489         case POINTER:
8490         case IPOINTER:
8491           emitcode ("inc", "%s", rname);
8492           emitcode ("mov", "a,@%s", rname);
8493           break;
8494
8495         case PPOINTER:
8496           emitcode ("inc", "%s", rname);
8497           emitcode ("movx", "a,@%s", rname);
8498           break;
8499
8500         case FPOINTER:
8501           emitcode ("inc", "dptr");
8502           emitcode ("movx", "a,@dptr");
8503           break;
8504
8505         case CPOINTER:
8506           emitcode ("clr", "a");
8507           emitcode ("inc", "dptr");
8508           emitcode ("movc", "a,@a+dptr");
8509           break;
8510
8511         case GPOINTER:
8512           emitcode ("inc", "dptr");
8513           emitcode ("lcall", "__gptrget");
8514           break;
8515         }
8516
8517       rlen -= 8;
8518       /* if we are done */
8519       if (rlen < 8)
8520         break;
8521
8522       aopPut (AOP (result), "a", offset++);
8523
8524     }
8525
8526   if (rlen)
8527     {
8528       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
8529       aopPut (AOP (result), "a", offset);
8530     }
8531
8532   return;
8533 }
8534
8535
8536 /*-----------------------------------------------------------------*/
8537 /* genDataPointerGet - generates code when ptr offset is known     */
8538 /*-----------------------------------------------------------------*/
8539 static void
8540 genDataPointerGet (operand * left,
8541                    operand * result,
8542                    iCode * ic)
8543 {
8544   char *l;
8545   char buffer[256];
8546   int size, offset = 0;
8547   aopOp (result, ic, TRUE, FALSE);
8548
8549   /* get the string representation of the name */
8550   l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
8551   size = AOP_SIZE (result);
8552   _startLazyDPSEvaluation ();
8553   while (size--)
8554     {
8555       if (offset)
8556         sprintf (buffer, "(%s + %d)", l + 1, offset);
8557       else
8558         sprintf (buffer, "%s", l + 1);
8559       aopPut (AOP (result), buffer, offset++);
8560     }
8561   _endLazyDPSEvaluation ();
8562
8563   freeAsmop (left, NULL, ic, TRUE);
8564   freeAsmop (result, NULL, ic, TRUE);
8565 }
8566
8567 /*-----------------------------------------------------------------*/
8568 /* genNearPointerGet - emitcode for near pointer fetch             */
8569 /*-----------------------------------------------------------------*/
8570 static void
8571 genNearPointerGet (operand * left,
8572                    operand * result,
8573                    iCode * ic,
8574                    iCode *pi)
8575 {
8576   asmop *aop = NULL;
8577   regs *preg = NULL;
8578   char *rname;
8579   sym_link *rtype, *retype, *letype;
8580   sym_link *ltype = operandType (left);
8581   char buffer[80];
8582
8583   rtype = operandType (result);
8584   retype = getSpec (rtype);
8585   letype = getSpec (ltype);
8586
8587   aopOp (left, ic, FALSE, FALSE);
8588
8589   /* if left is rematerialisable and
8590      result is not bit variable type and
8591      the left is pointer to data space i.e
8592      lower 128 bytes of space */
8593   if (AOP_TYPE (left) == AOP_IMMD &&
8594       !IS_BITVAR (retype) &&
8595       !IS_BITVAR (letype) &&
8596       DCL_TYPE (ltype) == POINTER)
8597     {
8598       genDataPointerGet (left, result, ic);
8599       return;
8600     }
8601
8602   /* if the value is already in a pointer register
8603      then don't need anything more */
8604   if (!AOP_INPREG (AOP (left)))
8605     {
8606       /* otherwise get a free pointer register */
8607       aop = newAsmop (0);
8608       preg = getFreePtr (ic, &aop, FALSE);
8609       emitcode ("mov", "%s,%s",
8610                 preg->name,
8611                 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8612       rname = preg->name;
8613     }
8614   else
8615     rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8616
8617   freeAsmop (left, NULL, ic, TRUE);
8618   aopOp (result, ic, FALSE, FALSE);
8619
8620   /* if bitfield then unpack the bits */
8621   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8622     genUnpackBits (result, rname, POINTER);
8623   else
8624     {
8625       /* we have can just get the values */
8626       int size = AOP_SIZE (result);
8627       int offset = 0;
8628
8629       while (size--)
8630         {
8631           if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8632             {
8633
8634               emitcode ("mov", "a,@%s", rname);
8635               aopPut (AOP (result), "a", offset);
8636             }
8637           else
8638             {
8639               sprintf (buffer, "@%s", rname);
8640               aopPut (AOP (result), buffer, offset);
8641             }
8642           offset++;
8643           if (size || pi)
8644             emitcode ("inc", "%s", rname);
8645         }
8646     }
8647
8648   /* now some housekeeping stuff */
8649   if (aop)
8650     {
8651       /* we had to allocate for this iCode */
8652       if (pi) { /* post increment present */
8653         aopPut(AOP ( left ),rname,0);
8654       }
8655       freeAsmop (NULL, aop, ic, TRUE);
8656     }
8657   else
8658     {
8659       /* we did not allocate which means left
8660          already in a pointer register, then
8661          if size > 0 && this could be used again
8662          we have to point it back to where it
8663          belongs */
8664       if (AOP_SIZE (result) > 1 &&
8665           !OP_SYMBOL (left)->remat &&
8666           (OP_SYMBOL (left)->liveTo > ic->seq ||
8667            ic->depth) &&
8668           !pi)
8669         {
8670           int size = AOP_SIZE (result) - 1;
8671           while (size--)
8672             emitcode ("dec", "%s", rname);
8673         }
8674     }
8675
8676   /* done */
8677   freeAsmop (result, NULL, ic, TRUE);
8678   if (pi) pi->generated = 1;
8679 }
8680
8681 /*-----------------------------------------------------------------*/
8682 /* genPagedPointerGet - emitcode for paged pointer fetch           */
8683 /*-----------------------------------------------------------------*/
8684 static void
8685 genPagedPointerGet (operand * left,
8686                     operand * result,
8687                     iCode * ic,
8688                     iCode * pi)
8689 {
8690   asmop *aop = NULL;
8691   regs *preg = NULL;
8692   char *rname;
8693   sym_link *rtype, *retype, *letype;
8694
8695   rtype = operandType (result);
8696   retype = getSpec (rtype);
8697   letype = getSpec (operandType (left));
8698   aopOp (left, ic, FALSE, FALSE);
8699
8700   /* if the value is already in a pointer register
8701      then don't need anything more */
8702   if (!AOP_INPREG (AOP (left)))
8703     {
8704       /* otherwise get a free pointer register */
8705       aop = newAsmop (0);
8706       preg = getFreePtr (ic, &aop, FALSE);
8707       emitcode ("mov", "%s,%s",
8708                 preg->name,
8709                 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8710       rname = preg->name;
8711     }
8712   else
8713     rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8714
8715   freeAsmop (left, NULL, ic, TRUE);
8716   aopOp (result, ic, FALSE, FALSE);
8717
8718   /* if bitfield then unpack the bits */
8719   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8720     genUnpackBits (result, rname, PPOINTER);
8721   else
8722     {
8723       /* we have can just get the values */
8724       int size = AOP_SIZE (result);
8725       int offset = 0;
8726
8727       while (size--)
8728         {
8729
8730           emitcode ("movx", "a,@%s", rname);
8731           aopPut (AOP (result), "a", offset);
8732
8733           offset++;
8734
8735           if (size || pi)
8736             emitcode ("inc", "%s", rname);
8737         }
8738     }
8739
8740   /* now some housekeeping stuff */
8741   if (aop)
8742     {
8743       /* we had to allocate for this iCode */
8744       if (pi) aopPut ( AOP (left), rname, 0);
8745       freeAsmop (NULL, aop, ic, TRUE);
8746     }
8747   else
8748     {
8749       /* we did not allocate which means left
8750          already in a pointer register, then
8751          if size > 0 && this could be used again
8752          we have to point it back to where it
8753          belongs */
8754       if (AOP_SIZE (result) > 1 &&
8755           !OP_SYMBOL (left)->remat &&
8756           (OP_SYMBOL (left)->liveTo > ic->seq ||
8757            ic->depth) &&
8758           !pi)
8759         {
8760           int size = AOP_SIZE (result) - 1;
8761           while (size--)
8762             emitcode ("dec", "%s", rname);
8763         }
8764     }
8765
8766   /* done */
8767   freeAsmop (result, NULL, ic, TRUE);
8768   if (pi) pi->generated = 1;
8769 }
8770
8771 /*-----------------------------------------------------------------*/
8772 /* genFarPointerGet - gget value from far space                    */
8773 /*-----------------------------------------------------------------*/
8774 static void
8775 genFarPointerGet (operand * left,
8776                   operand * result, iCode * ic, iCode *pi)
8777 {
8778   int size, offset;
8779   sym_link *retype = getSpec (operandType (result));
8780   sym_link *letype = getSpec (operandType (left));
8781   D (emitcode (";", "genFarPointerGet");
8782     );
8783
8784   aopOp (left, ic, FALSE, FALSE);
8785
8786   /* if the operand is already in dptr
8787      then we do nothing else we move the value to dptr */
8788   if (AOP_TYPE (left) != AOP_STR)
8789     {
8790       /* if this is remateriazable */
8791       if (AOP_TYPE (left) == AOP_IMMD)
8792         {
8793           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8794         }
8795       else
8796         {
8797           /* we need to get it byte by byte */
8798           _startLazyDPSEvaluation ();
8799           if (AOP_TYPE (left) != AOP_DPTR)
8800             {
8801               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8802               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8803               if (options.model == MODEL_FLAT24)
8804                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8805             }
8806           else
8807             {
8808               /* We need to generate a load to DPTR indirect through DPTR. */
8809               D (emitcode (";", "genFarPointerGet -- indirection special case.");
8810                 );
8811               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8812               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8813               if (options.model == MODEL_FLAT24)
8814                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8815               emitcode ("pop", "dph");
8816               emitcode ("pop", "dpl");
8817             }
8818           _endLazyDPSEvaluation ();
8819         }
8820     }
8821   /* so dptr know contains the address */
8822   freeAsmop (left, NULL, ic, TRUE);
8823   aopOp (result, ic, FALSE, TRUE);
8824
8825   /* if bit then unpack */
8826   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8827     genUnpackBits (result, "dptr", FPOINTER);
8828   else
8829     {
8830       size = AOP_SIZE (result);
8831       offset = 0;
8832
8833       _startLazyDPSEvaluation ();
8834       while (size--)
8835         {
8836
8837           genSetDPTR (0);
8838           _flushLazyDPS ();
8839
8840           emitcode ("movx", "a,@dptr");
8841           if (size || pi)
8842             emitcode ("inc", "dptr");
8843
8844           aopPut (AOP (result), "a", offset++);
8845         }
8846       _endLazyDPSEvaluation ();
8847     }
8848   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
8849     aopPut ( AOP (left), "dpl", 0);
8850     aopPut ( AOP (left), "dph", 1);
8851     if (options.model == MODEL_FLAT24)
8852             aopPut ( AOP (left), "dpx", 2);
8853     pi->generated = 1;
8854   }
8855
8856   freeAsmop (result, NULL, ic, TRUE);
8857 }
8858
8859 /*-----------------------------------------------------------------*/
8860 /* emitcodePointerGet - gget value from code space                  */
8861 /*-----------------------------------------------------------------*/
8862 static void
8863 emitcodePointerGet (operand * left,
8864                     operand * result, iCode * ic, iCode *pi)
8865 {
8866   int size, offset;
8867   sym_link *retype = getSpec (operandType (result));
8868
8869   aopOp (left, ic, FALSE, FALSE);
8870
8871   /* if the operand is already in dptr
8872      then we do nothing else we move the value to dptr */
8873   if (AOP_TYPE (left) != AOP_STR)
8874     {
8875       /* if this is remateriazable */
8876       if (AOP_TYPE (left) == AOP_IMMD)
8877         {
8878           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8879         }
8880       else
8881         {                       /* we need to get it byte by byte */
8882           _startLazyDPSEvaluation ();
8883           if (AOP_TYPE (left) != AOP_DPTR)
8884             {
8885               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8886               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8887               if (options.model == MODEL_FLAT24)
8888                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8889             }
8890           else
8891             {
8892               /* We need to generate a load to DPTR indirect through DPTR. */
8893               D (emitcode (";", "gencodePointerGet -- indirection special case.");
8894                 );
8895               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8896               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8897               if (options.model == MODEL_FLAT24)
8898                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8899               emitcode ("pop", "dph");
8900               emitcode ("pop", "dpl");
8901             }
8902           _endLazyDPSEvaluation ();
8903         }
8904     }
8905   /* so dptr know contains the address */
8906   aopOp (result, ic, FALSE, TRUE);
8907
8908   /* if bit then unpack */
8909   if (IS_BITVAR (retype))
8910     genUnpackBits (result, "dptr", CPOINTER);
8911   else
8912     {
8913       size = AOP_SIZE (result);
8914       offset = 0;
8915
8916       _startLazyDPSEvaluation ();
8917       while (size--)
8918         {
8919           genSetDPTR (0);
8920           _flushLazyDPS ();
8921
8922           emitcode ("clr", "a");
8923           emitcode ("movc", "a,@a+dptr");
8924           if (size || pi)
8925             emitcode ("inc", "dptr");
8926           aopPut (AOP (result), "a", offset++);
8927         }
8928       _endLazyDPSEvaluation ();
8929     }
8930   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
8931     aopPut ( AOP (left), "dpl", 0);
8932     aopPut ( AOP (left), "dph", 1);
8933     if (options.model == MODEL_FLAT24)
8934             aopPut ( AOP (left), "dpx", 2);
8935     pi->generated = 1;
8936   }
8937
8938   freeAsmop (left, NULL, ic, TRUE);
8939   freeAsmop (result, NULL, ic, TRUE);
8940 }
8941
8942 /*-----------------------------------------------------------------*/
8943 /* genGenPointerGet - gget value from generic pointer space        */
8944 /*-----------------------------------------------------------------*/
8945 static void
8946 genGenPointerGet (operand * left,
8947                   operand * result, iCode * ic, iCode * pi)
8948 {
8949   int size, offset;
8950   sym_link *retype = getSpec (operandType (result));
8951   sym_link *letype = getSpec (operandType (left));
8952
8953   D (emitcode (";", "genGenPointerGet "); );
8954
8955   aopOp (left, ic, FALSE, TRUE);
8956
8957   /* if the operand is already in dptr
8958      then we do nothing else we move the value to dptr */
8959   if (AOP_TYPE (left) != AOP_STR)
8960     {
8961       /* if this is remateriazable */
8962       if (AOP_TYPE (left) == AOP_IMMD)
8963         {
8964           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8965           if (AOP(left)->aopu.aop_immd.from_cast_remat) 
8966                   emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, FALSE));
8967           else
8968                   emitcode ("mov", "b,#%d", pointerCode (retype));
8969         }
8970       else
8971         {                       /* we need to get it byte by byte */
8972           _startLazyDPSEvaluation ();
8973           if (AOP(left)->type==AOP_DPTR2) {
8974             char *l;
8975             l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
8976             genSetDPTR(0);
8977             _flushLazyDPS();
8978             emitcode ("mov", "dpl,%s", l);
8979             l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
8980             genSetDPTR(0);
8981             _flushLazyDPS();
8982             emitcode ("mov", "dph,%s", l);
8983             if (options.model == MODEL_FLAT24) {
8984               l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
8985               genSetDPTR(0);
8986               _flushLazyDPS();
8987               emitcode ("mov", "dpx,%s", l);
8988               emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8989             } else {
8990               emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8991             }
8992           } else {
8993             emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
8994             emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
8995             if (options.model == MODEL_FLAT24) {
8996               emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8997               emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8998             } else {
8999               emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9000             }
9001           }
9002           _endLazyDPSEvaluation ();
9003         }
9004     }
9005   /* so dptr know contains the address */
9006   aopOp (result, ic, FALSE, TRUE);
9007
9008   /* if bit then unpack */
9009   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9010     genUnpackBits (result, "dptr", GPOINTER);
9011   else
9012     {
9013       size = AOP_SIZE (result);
9014       offset = 0;
9015
9016       while (size--)
9017         {
9018           emitcode ("lcall", "__gptrget");
9019           aopPut (AOP (result), "a", offset++);
9020           if (size || pi)
9021             emitcode ("inc", "dptr");
9022         }
9023     }
9024
9025   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
9026     aopPut ( AOP (left), "dpl", 0);
9027     aopPut ( AOP (left), "dph", 1);
9028     if (options.model == MODEL_FLAT24) {
9029             aopPut ( AOP (left), "dpx", 2);
9030             aopPut ( AOP (left), "b", 3);       
9031     } else  aopPut ( AOP (left), "b", 2);       
9032     pi->generated = 1;
9033   }
9034   freeAsmop (left, NULL, ic, TRUE);
9035   freeAsmop (result, NULL, ic, TRUE);
9036 }
9037
9038 /*-----------------------------------------------------------------*/
9039 /* genPointerGet - generate code for pointer get                   */
9040 /*-----------------------------------------------------------------*/
9041 static void
9042 genPointerGet (iCode * ic, iCode *pi)
9043 {
9044   operand *left, *result;
9045   sym_link *type, *etype;
9046   int p_type;
9047
9048   D (emitcode (";", "genPointerGet ");
9049     );
9050
9051   left = IC_LEFT (ic);
9052   result = IC_RESULT (ic);
9053
9054   /* depending on the type of pointer we need to
9055      move it to the correct pointer register */
9056   type = operandType (left);
9057   etype = getSpec (type);
9058   /* if left is of type of pointer then it is simple */
9059   if (IS_PTR (type) && !IS_FUNC (type->next))
9060     p_type = DCL_TYPE (type);
9061   else
9062     {
9063       /* we have to go by the storage class */
9064       p_type = PTR_TYPE (SPEC_OCLS (etype));
9065     }
9066   /* special case when cast remat */
9067   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9068       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9069           left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9070           type =   type = operandType (left);
9071           p_type = DCL_TYPE (type);
9072   }
9073   /* now that we have the pointer type we assign
9074      the pointer values */
9075   switch (p_type)
9076     {
9077
9078     case POINTER:
9079     case IPOINTER:
9080       genNearPointerGet (left, result, ic, pi);
9081       break;
9082
9083     case PPOINTER:
9084       genPagedPointerGet (left, result, ic, pi);
9085       break;
9086
9087     case FPOINTER:
9088       genFarPointerGet (left, result, ic, pi);
9089       break;
9090
9091     case CPOINTER:
9092       emitcodePointerGet (left, result, ic, pi);
9093       break;
9094
9095     case GPOINTER:
9096       genGenPointerGet (left, result, ic, pi);
9097       break;
9098     }
9099
9100 }
9101
9102 /*-----------------------------------------------------------------*/
9103 /* genPackBits - generates code for packed bit storage             */
9104 /*-----------------------------------------------------------------*/
9105 static void
9106 genPackBits (sym_link * etype,
9107              operand * right,
9108              char *rname, int p_type)
9109 {
9110   int shCount = 0;
9111   int offset = 0;
9112   int rLen = 0;
9113   int blen, bstr;
9114   char *l;
9115
9116   blen = SPEC_BLEN (etype);
9117   bstr = SPEC_BSTR (etype);
9118
9119   l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9120   MOVA (l);
9121
9122   /* if the bit lenth is less than or    */
9123   /* it exactly fits a byte then         */
9124   if (SPEC_BLEN (etype) <= 8)
9125     {
9126       shCount = SPEC_BSTR (etype);
9127
9128       /* shift left acc */
9129       AccLsh (shCount);
9130
9131       if (SPEC_BLEN (etype) < 8)
9132         {                       /* if smaller than a byte */
9133
9134
9135           switch (p_type)
9136             {
9137             case POINTER:
9138               emitcode ("mov", "b,a");
9139               emitcode ("mov", "a,@%s", rname);
9140               break;
9141
9142             case FPOINTER:
9143               emitcode ("mov", "b,a");
9144               emitcode ("movx", "a,@dptr");
9145               break;
9146
9147             case GPOINTER:
9148               emitcode ("push", "b");
9149               emitcode ("push", "acc");
9150               emitcode ("lcall", "__gptrget");
9151               emitcode ("pop", "b");
9152               break;
9153             }
9154
9155           emitcode ("anl", "a,#0x%02x", (unsigned char)
9156                     ((unsigned char) (0xFF << (blen + bstr)) |
9157                      (unsigned char) (0xFF >> (8 - bstr))));
9158           emitcode ("orl", "a,b");
9159           if (p_type == GPOINTER)
9160             emitcode ("pop", "b");
9161         }
9162     }
9163
9164   switch (p_type)
9165     {
9166     case POINTER:
9167       emitcode ("mov", "@%s,a", rname);
9168       break;
9169
9170     case FPOINTER:
9171       emitcode ("movx", "@dptr,a");
9172       break;
9173
9174     case GPOINTER:
9175       emitcode ("lcall", "__gptrput");
9176       break;
9177     }
9178
9179   /* if we r done */
9180   if (SPEC_BLEN (etype) <= 8)
9181     return;
9182
9183   emitcode ("inc", "%s", rname);
9184   rLen = SPEC_BLEN (etype);
9185
9186   /* now generate for lengths greater than one byte */
9187   while (1)
9188     {
9189
9190       l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
9191
9192       rLen -= 8;
9193       if (rLen < 8)
9194         break;
9195
9196       switch (p_type)
9197         {
9198         case POINTER:
9199           if (*l == '@')
9200             {
9201               MOVA (l);
9202               emitcode ("mov", "@%s,a", rname);
9203             }
9204           else
9205             emitcode ("mov", "@%s,%s", rname, l);
9206           break;
9207
9208         case FPOINTER:
9209           MOVA (l);
9210           emitcode ("movx", "@dptr,a");
9211           break;
9212
9213         case GPOINTER:
9214           MOVA (l);
9215           emitcode ("lcall", "__gptrput");
9216           break;
9217         }
9218       emitcode ("inc", "%s", rname);
9219     }
9220
9221   MOVA (l);
9222
9223   /* last last was not complete */
9224   if (rLen)
9225     {
9226       /* save the byte & read byte */
9227       switch (p_type)
9228         {
9229         case POINTER:
9230           emitcode ("mov", "b,a");
9231           emitcode ("mov", "a,@%s", rname);
9232           break;
9233
9234         case FPOINTER:
9235           emitcode ("mov", "b,a");
9236           emitcode ("movx", "a,@dptr");
9237           break;
9238
9239         case GPOINTER:
9240           emitcode ("push", "b");
9241           emitcode ("push", "acc");
9242           emitcode ("lcall", "__gptrget");
9243           emitcode ("pop", "b");
9244           break;
9245         }
9246
9247       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
9248       emitcode ("orl", "a,b");
9249     }
9250
9251   if (p_type == GPOINTER)
9252     emitcode ("pop", "b");
9253
9254   switch (p_type)
9255     {
9256
9257     case POINTER:
9258       emitcode ("mov", "@%s,a", rname);
9259       break;
9260
9261     case FPOINTER:
9262       emitcode ("movx", "@dptr,a");
9263       break;
9264
9265     case GPOINTER:
9266       emitcode ("lcall", "__gptrput");
9267       break;
9268     }
9269 }
9270 /*-----------------------------------------------------------------*/
9271 /* genDataPointerSet - remat pointer to data space                 */
9272 /*-----------------------------------------------------------------*/
9273 static void
9274 genDataPointerSet (operand * right,
9275                    operand * result,
9276                    iCode * ic)
9277 {
9278   int size, offset = 0;
9279   char *l, buffer[256];
9280
9281   aopOp (right, ic, FALSE, FALSE);
9282
9283   l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
9284   size = AOP_SIZE (right);
9285   while (size--)
9286     {
9287       if (offset)
9288         sprintf (buffer, "(%s + %d)", l + 1, offset);
9289       else
9290         sprintf (buffer, "%s", l + 1);
9291       emitcode ("mov", "%s,%s", buffer,
9292                 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
9293     }
9294
9295   freeAsmop (right, NULL, ic, TRUE);
9296   freeAsmop (result, NULL, ic, TRUE);
9297 }
9298
9299 /*-----------------------------------------------------------------*/
9300 /* genNearPointerSet - emitcode for near pointer put                */
9301 /*-----------------------------------------------------------------*/
9302 static void
9303 genNearPointerSet (operand * right,
9304                    operand * result,
9305                    iCode * ic,
9306                    iCode * pi)
9307 {
9308   asmop *aop = NULL;
9309   regs *preg = NULL;
9310   char *rname, *l;
9311   sym_link *retype, *letype;
9312   sym_link *ptype = operandType (result);
9313
9314   retype = getSpec (operandType (right));
9315   letype = getSpec (ptype);
9316
9317   aopOp (result, ic, FALSE, FALSE);
9318
9319   /* if the result is rematerializable &
9320      in data space & not a bit variable */
9321   if (AOP_TYPE (result) == AOP_IMMD &&
9322       DCL_TYPE (ptype) == POINTER &&
9323       !IS_BITVAR (retype) &&
9324       !IS_BITVAR (letype))
9325     {
9326       genDataPointerSet (right, result, ic);
9327       return;
9328     }
9329
9330   /* if the value is already in a pointer register
9331      then don't need anything more */
9332   if (!AOP_INPREG (AOP (result)))
9333     {
9334       /* otherwise get a free pointer register */
9335       aop = newAsmop (0);
9336       preg = getFreePtr (ic, &aop, FALSE);
9337       emitcode ("mov", "%s,%s",
9338                 preg->name,
9339                 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9340       rname = preg->name;
9341     }
9342   else
9343     rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9344
9345   aopOp (right, ic, FALSE, FALSE);
9346
9347   /* if bitfield then unpack the bits */
9348   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9349     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
9350   else
9351     {
9352       /* we have can just get the values */
9353       int size = AOP_SIZE (right);
9354       int offset = 0;
9355
9356       while (size--)
9357         {
9358           l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
9359           if (*l == '@')
9360             {
9361               MOVA (l);
9362               emitcode ("mov", "@%s,a", rname);
9363             }
9364           else
9365             emitcode ("mov", "@%s,%s", rname, l);
9366           if (size || pi)
9367             emitcode ("inc", "%s", rname);
9368           offset++;
9369         }
9370     }
9371
9372   /* now some housekeeping stuff */
9373   if (aop)
9374     {
9375       /* we had to allocate for this iCode */
9376       if (pi) aopPut (AOP (result),rname,0);
9377       freeAsmop (NULL, aop, ic, TRUE);
9378     }
9379   else
9380     {
9381       /* we did not allocate which means left
9382          already in a pointer register, then
9383          if size > 0 && this could be used again
9384          we have to point it back to where it
9385          belongs */
9386       if (AOP_SIZE (right) > 1 &&
9387           !OP_SYMBOL (result)->remat &&
9388           (OP_SYMBOL (result)->liveTo > ic->seq ||
9389            ic->depth) &&
9390           !pi)
9391         {
9392           int size = AOP_SIZE (right) - 1;
9393           while (size--)
9394             emitcode ("dec", "%s", rname);
9395         }
9396     }
9397
9398   /* done */
9399   if (pi) pi->generated = 1;
9400   freeAsmop (result, NULL, ic, TRUE);
9401   freeAsmop (right, NULL, ic, TRUE);
9402
9403
9404 }
9405
9406 /*-----------------------------------------------------------------*/
9407 /* genPagedPointerSet - emitcode for Paged pointer put             */
9408 /*-----------------------------------------------------------------*/
9409 static void
9410 genPagedPointerSet (operand * right,
9411                     operand * result,
9412                     iCode * ic,
9413                     iCode *pi)
9414 {
9415   asmop *aop = NULL;
9416   regs *preg = NULL;
9417   char *rname, *l;
9418   sym_link *retype, *letype;
9419
9420   retype = getSpec (operandType (right));
9421   letype = getSpec (operandType (result));
9422
9423   aopOp (result, ic, FALSE, FALSE);
9424
9425   /* if the value is already in a pointer register
9426      then don't need anything more */
9427   if (!AOP_INPREG (AOP (result)))
9428     {
9429       /* otherwise get a free pointer register */
9430       aop = newAsmop (0);
9431       preg = getFreePtr (ic, &aop, FALSE);
9432       emitcode ("mov", "%s,%s",
9433                 preg->name,
9434                 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9435       rname = preg->name;
9436     }
9437   else
9438     rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9439
9440   aopOp (right, ic, FALSE, FALSE);
9441
9442   /* if bitfield then unpack the bits */
9443   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9444     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
9445   else
9446     {
9447       /* we have can just get the values */
9448       int size = AOP_SIZE (right);
9449       int offset = 0;
9450
9451       while (size--)
9452         {
9453           l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
9454
9455           MOVA (l);
9456           emitcode ("movx", "@%s,a", rname);
9457
9458           if (size || pi)
9459             emitcode ("inc", "%s", rname);
9460
9461           offset++;
9462         }
9463     }
9464
9465   /* now some housekeeping stuff */
9466   if (aop)
9467     {
9468       if (pi) aopPut (AOP (result),rname,0);
9469       /* we had to allocate for this iCode */
9470       freeAsmop (NULL, aop, ic, TRUE);
9471     }
9472   else
9473     {
9474       /* we did not allocate which means left
9475          already in a pointer register, then
9476          if size > 0 && this could be used again
9477          we have to point it back to where it
9478          belongs */
9479       if (AOP_SIZE (right) > 1 &&
9480           !OP_SYMBOL (result)->remat &&
9481           (OP_SYMBOL (result)->liveTo > ic->seq ||
9482            ic->depth) &&
9483           !pi)
9484         {
9485           int size = AOP_SIZE (right) - 1;
9486           while (size--)
9487             emitcode ("dec", "%s", rname);
9488         }
9489     }
9490
9491   /* done */
9492   if (pi) pi->generated = 1;
9493   freeAsmop (result, NULL, ic, TRUE);
9494   freeAsmop (right, NULL, ic, TRUE);
9495
9496
9497 }
9498
9499 /*-----------------------------------------------------------------*/
9500 /* genFarPointerSet - set value from far space                     */
9501 /*-----------------------------------------------------------------*/
9502 static void
9503 genFarPointerSet (operand * right,
9504                   operand * result, iCode * ic, iCode *pi)
9505 {
9506   int size, offset;
9507   sym_link *retype = getSpec (operandType (right));
9508   sym_link *letype = getSpec (operandType (result));
9509
9510   aopOp (result, ic, FALSE, FALSE);
9511
9512   /* if the operand is already in dptr
9513      then we do nothing else we move the value to dptr */
9514   if (AOP_TYPE (result) != AOP_STR)
9515     {
9516       /* if this is remateriazable */
9517       if (AOP_TYPE (result) == AOP_IMMD)
9518         emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9519       else
9520         {
9521           /* we need to get it byte by byte */
9522           _startLazyDPSEvaluation ();
9523           if (AOP_TYPE (result) != AOP_DPTR)
9524             {
9525               emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9526               emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9527               if (options.model == MODEL_FLAT24)
9528                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9529             }
9530           else
9531             {
9532               /* We need to generate a load to DPTR indirect through DPTR. */
9533               D (emitcode (";", "genFarPointerSet -- indirection special case.");
9534                 );
9535               emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
9536               emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
9537               if (options.model == MODEL_FLAT24)
9538                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9539               emitcode ("pop", "dph");
9540               emitcode ("pop", "dpl");
9541             }
9542           _endLazyDPSEvaluation ();
9543         }
9544     }
9545   /* so dptr know contains the address */
9546   aopOp (right, ic, FALSE, TRUE);
9547
9548   /* if bit then unpack */
9549   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9550     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
9551   else
9552     {
9553       size = AOP_SIZE (right);
9554       offset = 0;
9555
9556       _startLazyDPSEvaluation ();
9557       while (size--)
9558         {
9559           char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9560           MOVA (l);
9561
9562           genSetDPTR (0);
9563           _flushLazyDPS ();
9564
9565           emitcode ("movx", "@dptr,a");
9566           if (size || pi)
9567             emitcode ("inc", "dptr");
9568         }
9569       _endLazyDPSEvaluation ();
9570     }
9571
9572   if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
9573     aopPut (AOP(result),"dpl",0);
9574     aopPut (AOP(result),"dph",1);
9575     if (options.model == MODEL_FLAT24)
9576         aopPut (AOP(result),"dpx",2);
9577     pi->generated=1;
9578   }
9579   freeAsmop (result, NULL, ic, TRUE);
9580   freeAsmop (right, NULL, ic, TRUE);
9581 }
9582
9583 /*-----------------------------------------------------------------*/
9584 /* genGenPointerSet - set value from generic pointer space         */
9585 /*-----------------------------------------------------------------*/
9586 static void
9587 genGenPointerSet (operand * right,
9588                   operand * result, iCode * ic, iCode *pi)
9589 {
9590   int size, offset;
9591   sym_link *retype = getSpec (operandType (right));
9592   sym_link *letype = getSpec (operandType (result));
9593
9594   aopOp (result, ic, FALSE, TRUE);
9595
9596   /* if the operand is already in dptr
9597      then we do nothing else we move the value to dptr */
9598   if (AOP_TYPE (result) != AOP_STR)
9599     {
9600       _startLazyDPSEvaluation ();
9601       /* if this is remateriazable */
9602       if (AOP_TYPE (result) == AOP_IMMD)
9603         {
9604           emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9605           if (AOP(result)->aopu.aop_immd.from_cast_remat) 
9606                   emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, FALSE));
9607           else
9608                   emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9609         }
9610       else
9611         {                       /* we need to get it byte by byte */
9612           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9613           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9614           if (options.model == MODEL_FLAT24) {
9615             emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9616             emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
9617           } else {
9618             emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9619           }
9620         }
9621       _endLazyDPSEvaluation ();
9622     }
9623   /* so dptr know contains the address */
9624   aopOp (right, ic, FALSE, TRUE);
9625
9626   /* if bit then unpack */
9627   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9628     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
9629   else
9630     {
9631       size = AOP_SIZE (right);
9632       offset = 0;
9633
9634       _startLazyDPSEvaluation ();
9635       while (size--)
9636         {
9637           char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9638           MOVA (l);
9639
9640           genSetDPTR (0);
9641           _flushLazyDPS ();
9642
9643           emitcode ("lcall", "__gptrput");
9644           if (size || pi)
9645             emitcode ("inc", "dptr");
9646         }
9647       _endLazyDPSEvaluation ();
9648     }
9649
9650   if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
9651     aopPut (AOP(result),"dpl",0);
9652     aopPut (AOP(result),"dph",1);
9653     if (options.model == MODEL_FLAT24) {
9654         aopPut (AOP(result),"dpx",2);
9655         aopPut (AOP(result),"b",3);
9656     } else {
9657         aopPut (AOP(result),"b",2);
9658     }
9659     pi->generated=1;
9660   }
9661   freeAsmop (result, NULL, ic, TRUE);
9662   freeAsmop (right, NULL, ic, TRUE);
9663 }
9664
9665 /*-----------------------------------------------------------------*/
9666 /* genPointerSet - stores the value into a pointer location        */
9667 /*-----------------------------------------------------------------*/
9668 static void
9669 genPointerSet (iCode * ic, iCode *pi)
9670 {
9671   operand *right, *result;
9672   sym_link *type, *etype;
9673   int p_type;
9674
9675   D (emitcode (";", "genPointerSet ");
9676     );
9677
9678   right = IC_RIGHT (ic);
9679   result = IC_RESULT (ic);
9680
9681   /* depending on the type of pointer we need to
9682      move it to the correct pointer register */
9683   type = operandType (result);
9684   etype = getSpec (type);
9685   /* if left is of type of pointer then it is simple */
9686   if (IS_PTR (type) && !IS_FUNC (type->next))
9687     {
9688       p_type = DCL_TYPE (type);
9689     }
9690   else
9691     {
9692       /* we have to go by the storage class */
9693       p_type = PTR_TYPE (SPEC_OCLS (etype));
9694     }
9695   /* special case when cast remat */
9696   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
9697       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
9698           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
9699           type =   type = operandType (result);
9700           p_type = DCL_TYPE (type);
9701   }
9702
9703   /* now that we have the pointer type we assign
9704      the pointer values */
9705   switch (p_type)
9706     {
9707
9708     case POINTER:
9709     case IPOINTER:
9710       genNearPointerSet (right, result, ic, pi);
9711       break;
9712
9713     case PPOINTER:
9714       genPagedPointerSet (right, result, ic, pi);
9715       break;
9716
9717     case FPOINTER:
9718       genFarPointerSet (right, result, ic, pi);
9719       break;
9720
9721     case GPOINTER:
9722       genGenPointerSet (right, result, ic, pi);
9723       break;
9724     }
9725
9726 }
9727
9728 /*-----------------------------------------------------------------*/
9729 /* genIfx - generate code for Ifx statement                        */
9730 /*-----------------------------------------------------------------*/
9731 static void
9732 genIfx (iCode * ic, iCode * popIc)
9733 {
9734   operand *cond = IC_COND (ic);
9735   int isbit = 0;
9736
9737   D (emitcode (";", "genIfx "););
9738
9739   aopOp (cond, ic, FALSE, FALSE);
9740
9741   /* get the value into acc */
9742   if (AOP_TYPE (cond) != AOP_CRY)
9743     toBoolean (cond);
9744   else
9745     isbit = 1;
9746   /* the result is now in the accumulator */
9747   freeAsmop (cond, NULL, ic, TRUE);
9748
9749   /* if there was something to be popped then do it */
9750   if (popIc)
9751     genIpop (popIc);
9752
9753   /* if the condition is  a bit variable */
9754   if (isbit && IS_ITEMP (cond) &&
9755       SPIL_LOC (cond))
9756     genIfxJump (ic, SPIL_LOC (cond)->rname);
9757   else if (isbit && !IS_ITEMP (cond))
9758     genIfxJump (ic, OP_SYMBOL (cond)->rname);
9759   else
9760     genIfxJump (ic, "a");
9761
9762   ic->generated = 1;
9763 }
9764
9765 /*-----------------------------------------------------------------*/
9766 /* genAddrOf - generates code for address of                       */
9767 /*-----------------------------------------------------------------*/
9768 static void
9769 genAddrOf (iCode * ic)
9770 {
9771   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
9772   int size, offset;
9773
9774   D (emitcode (";", "genAddrOf ");
9775     );
9776
9777   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9778
9779   /* if the operand is on the stack then we
9780      need to get the stack offset of this
9781      variable */
9782   if (sym->onStack)
9783     {
9784       /* if it has an offset then we need to compute
9785          it */
9786       if (sym->stack)
9787         {
9788           emitcode ("mov", "a,_bp");
9789           emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
9790           aopPut (AOP (IC_RESULT (ic)), "a", 0);
9791         }
9792       else
9793         {
9794           /* we can just move _bp */
9795           aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
9796         }
9797       /* fill the result with zero */
9798       size = AOP_SIZE (IC_RESULT (ic)) - 1;
9799
9800
9801       if (options.stack10bit && size < (FPTRSIZE - 1))
9802         {
9803           fprintf (stderr,
9804                    "*** warning: pointer to stack var truncated.\n");
9805         }
9806
9807       offset = 1;
9808       while (size--)
9809         {
9810           /* Yuck! */
9811           if (options.stack10bit && offset == 2)
9812             {
9813               aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
9814             }
9815           else
9816             {
9817               aopPut (AOP (IC_RESULT (ic)), zero, offset++);
9818             }
9819         }
9820
9821       goto release;
9822     }
9823
9824   /* object not on stack then we need the name */
9825   size = AOP_SIZE (IC_RESULT (ic));
9826   offset = 0;
9827
9828   while (size--)
9829     {
9830       char s[SDCC_NAME_MAX];
9831       if (offset)
9832         sprintf (s, "#(%s >> %d)",
9833                  sym->rname,
9834                  offset * 8);
9835       else
9836         sprintf (s, "#%s", sym->rname);
9837       aopPut (AOP (IC_RESULT (ic)), s, offset++);
9838     }
9839
9840 release:
9841   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9842
9843 }
9844
9845 /*-----------------------------------------------------------------*/
9846 /* genArrayInit - generates code for address of                       */
9847 /*-----------------------------------------------------------------*/
9848 static void
9849 genArrayInit (iCode * ic)
9850 {
9851     literalList *iLoop;
9852     int         ix, count;
9853     int         elementSize = 0, eIndex;
9854     unsigned    val, lastVal;
9855     sym_link    *type;
9856     operand     *left=IC_LEFT(ic);
9857     
9858     D (emitcode (";", "genArrayInit "););
9859
9860     aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
9861     
9862     if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
9863     {
9864         // Load immediate value into DPTR.
9865         emitcode("mov", "dptr, %s",
9866              aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, TRUE));
9867     }
9868     else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
9869     {
9870 #if 0
9871       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9872               "Unexpected operand to genArrayInit.\n");
9873       exit(1);
9874 #else
9875       // a regression because of SDCCcse.c:1.52
9876       emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9877       emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9878       if (options.model == MODEL_FLAT24)
9879         emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9880 #endif
9881     }
9882     
9883     type = operandType(IC_LEFT(ic));
9884     
9885     if (type && type->next)
9886     {
9887         elementSize = getSize(type->next);
9888     }
9889     else
9890     {
9891         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9892                                 "can't determine element size in genArrayInit.\n");
9893         exit(1);
9894     }
9895     
9896     iLoop = IC_ARRAYILIST(ic);
9897     lastVal = 0xffff;
9898     
9899     while (iLoop)
9900     {
9901         bool firstpass = TRUE;
9902         
9903         emitcode(";", "store %d x 0x%x to DPTR (element size %d)", 
9904                  iLoop->count, (int)iLoop->literalValue, elementSize);
9905         
9906         ix = iLoop->count;
9907         
9908         while (ix)
9909         {
9910             symbol *tlbl = NULL;
9911             
9912             count = ix > 256 ? 256 : ix;
9913             
9914             if (count > 1)
9915             {
9916                 tlbl = newiTempLabel (NULL);
9917                 if (firstpass || (count & 0xff))
9918                 {
9919                     emitcode("mov", "b, #0x%x", count & 0xff);
9920                 }
9921                 
9922                 emitcode ("", "%05d$:", tlbl->key + 100);
9923             }
9924             
9925             firstpass = FALSE;
9926                 
9927             for (eIndex = 0; eIndex < elementSize; eIndex++)
9928             {
9929                 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
9930                 if (val != lastVal)
9931                 {
9932                     emitcode("mov", "a, #0x%x", val);
9933                     lastVal = val;
9934                 }
9935                 
9936                 emitcode("movx", "@dptr, a");
9937                 emitcode("inc", "dptr");
9938             }
9939             
9940             if (count > 1)
9941             {
9942                 emitcode("djnz", "b, %05d$", tlbl->key + 100);
9943             }
9944             
9945             ix -= count;
9946         }
9947         
9948         iLoop = iLoop->next;
9949     }
9950     
9951     freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
9952 }
9953
9954 /*-----------------------------------------------------------------*/
9955 /* genFarFarAssign - assignment when both are in far space         */
9956 /*-----------------------------------------------------------------*/
9957 static void
9958 genFarFarAssign (operand * result, operand * right, iCode * ic)
9959 {
9960   int size = AOP_SIZE (right);
9961   int offset = 0;
9962   symbol *rSym = NULL;
9963
9964   if (size == 1)
9965   {
9966       /* quick & easy case. */
9967       D(emitcode(";","genFarFarAssign (1 byte case)"););      
9968       MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
9969       freeAsmop (right, NULL, ic, FALSE);
9970       /* now assign DPTR to result */
9971       _G.accInUse++;
9972       aopOp(result, ic, FALSE, FALSE);
9973       _G.accInUse--;
9974       aopPut(AOP(result), "a", 0);
9975       freeAsmop(result, NULL, ic, FALSE);
9976       return;
9977   }
9978   
9979   /* See if we've got an underlying symbol to abuse. */
9980   if (IS_SYMOP(result) && OP_SYMBOL(result))
9981   {
9982       if (IS_TRUE_SYMOP(result))
9983       {
9984           rSym = OP_SYMBOL(result);
9985       }
9986       else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
9987       {
9988           rSym = OP_SYMBOL(result)->usl.spillLoc;
9989       }
9990   }
9991              
9992   if (size > 1 && rSym && rSym->rname && !rSym->onStack)
9993   {
9994       /* We can use the '390 auto-toggle feature to good effect here. */
9995       
9996       D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
9997       emitcode("mov", "dps, #0x21");    /* Select DPTR2 & auto-toggle. */
9998       emitcode ("mov", "dptr,#%s", rSym->rname); 
9999       /* DP2 = result, DP1 = right, DP1 is current. */
10000       while (size)
10001       {
10002           emitcode("movx", "a,@dptr");
10003           emitcode("movx", "@dptr,a");
10004           if (--size)
10005           {
10006                emitcode("inc", "dptr");
10007                emitcode("inc", "dptr");
10008           }
10009       }
10010       emitcode("mov", "dps, #0");
10011       freeAsmop (right, NULL, ic, FALSE);
10012 #if 0
10013 some alternative code for processors without auto-toggle
10014 no time to test now, so later well put in...kpb
10015         D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10016         emitcode("mov", "dps, #0x01");  /* Select DPTR2. */
10017         emitcode ("mov", "dptr,#%s", rSym->rname); 
10018         /* DP2 = result, DP1 = right, DP1 is current. */
10019         while (size)
10020         {
10021           --size;
10022           emitcode("movx", "a,@dptr");
10023           if (size)
10024             emitcode("inc", "dptr");
10025           emitcode("inc", "dps");
10026           emitcode("movx", "@dptr,a");
10027           if (size)
10028             emitcode("inc", "dptr");
10029           emitcode("inc", "dps");
10030         }
10031         emitcode("mov", "dps, #0");
10032         freeAsmop (right, NULL, ic, FALSE);
10033 #endif
10034   }
10035   else
10036   {
10037       D (emitcode (";", "genFarFarAssign"););
10038       aopOp (result, ic, TRUE, TRUE);
10039
10040       _startLazyDPSEvaluation ();
10041       
10042       while (size--)
10043         {
10044           aopPut (AOP (result),
10045                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
10046           offset++;
10047         }
10048       _endLazyDPSEvaluation ();
10049       freeAsmop (result, NULL, ic, FALSE);
10050       freeAsmop (right, NULL, ic, FALSE);
10051   }
10052 }
10053
10054 /*-----------------------------------------------------------------*/
10055 /* genAssign - generate code for assignment                        */
10056 /*-----------------------------------------------------------------*/
10057 static void
10058 genAssign (iCode * ic)
10059 {
10060   operand *result, *right;
10061   int size, offset;
10062   unsigned long lit = 0L;
10063
10064   D (emitcode (";", "genAssign ");
10065     );
10066
10067   result = IC_RESULT (ic);
10068   right = IC_RIGHT (ic);
10069
10070   /* if they are the same */
10071   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10072     return;
10073
10074   aopOp (right, ic, FALSE, FALSE);
10075
10076   emitcode (";", "genAssign: resultIsFar = %s",
10077             isOperandInFarSpace (result) ?
10078             "TRUE" : "FALSE");
10079
10080   /* special case both in far space */
10081   if ((AOP_TYPE (right) == AOP_DPTR ||
10082        AOP_TYPE (right) == AOP_DPTR2) &&
10083   /* IS_TRUE_SYMOP(result)       && */
10084       isOperandInFarSpace (result))
10085     {
10086       genFarFarAssign (result, right, ic);
10087       return;
10088     }
10089
10090   aopOp (result, ic, TRUE, FALSE);
10091
10092   /* if they are the same registers */
10093   if (sameRegs (AOP (right), AOP (result)))
10094     goto release;
10095
10096   /* if the result is a bit */
10097   if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10098     {
10099       /* if the right size is a literal then
10100          we know what the value is */
10101       if (AOP_TYPE (right) == AOP_LIT)
10102         {
10103           if (((int) operandLitValue (right)))
10104             aopPut (AOP (result), one, 0);
10105           else
10106             aopPut (AOP (result), zero, 0);
10107           goto release;
10108         }
10109
10110       /* the right is also a bit variable */
10111       if (AOP_TYPE (right) == AOP_CRY)
10112         {
10113           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10114           aopPut (AOP (result), "c", 0);
10115           goto release;
10116         }
10117
10118       /* we need to or */
10119       toBoolean (right);
10120       aopPut (AOP (result), "a", 0);
10121       goto release;
10122     }
10123
10124   /* bit variables done */
10125   /* general case */
10126   size = AOP_SIZE (result);
10127   offset = 0;
10128   if (AOP_TYPE (right) == AOP_LIT)
10129     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10130
10131   if ((size > 1) &&
10132       (AOP_TYPE (result) != AOP_REG) &&
10133       (AOP_TYPE (right) == AOP_LIT) &&
10134       !IS_FLOAT (operandType (right)))
10135     {
10136       _startLazyDPSEvaluation ();
10137       while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10138         {
10139           aopPut (AOP (result),
10140                   aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
10141                   offset);
10142           offset++;
10143           size--;
10144         }
10145       /* And now fill the rest with zeros. */
10146       if (size)
10147         {
10148           emitcode ("clr", "a");
10149         }
10150       while (size--)
10151         {
10152           aopPut (AOP (result), "a", offset++);
10153         }
10154       _endLazyDPSEvaluation ();
10155     }
10156   else
10157     {
10158       _startLazyDPSEvaluation ();
10159       while (size--)
10160         {
10161           aopPut (AOP (result),
10162                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10163                   offset);
10164           offset++;
10165         }
10166       _endLazyDPSEvaluation ();
10167     }
10168
10169 release:
10170   freeAsmop (right, NULL, ic, FALSE);
10171   freeAsmop (result, NULL, ic, TRUE);
10172 }
10173
10174 /*-----------------------------------------------------------------*/
10175 /* genJumpTab - generates code for jump table                      */
10176 /*-----------------------------------------------------------------*/
10177 static void
10178 genJumpTab (iCode * ic)
10179 {
10180   symbol *jtab;
10181   char *l;
10182
10183   D (emitcode (";", "genJumpTab ");
10184     );
10185
10186   aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10187   /* get the condition into accumulator */
10188   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
10189   MOVA (l);
10190   /* multiply by four! */
10191   emitcode ("add", "a,acc");
10192   emitcode ("add", "a,acc");
10193   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10194
10195   jtab = newiTempLabel (NULL);
10196   emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
10197   emitcode ("jmp", "@a+dptr");
10198   emitcode ("", "%05d$:", jtab->key + 100);
10199   /* now generate the jump labels */
10200   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10201        jtab = setNextItem (IC_JTLABELS (ic)))
10202     emitcode ("ljmp", "%05d$", jtab->key + 100);
10203
10204 }
10205
10206 /*-----------------------------------------------------------------*/
10207 /* genCast - gen code for casting                                  */
10208 /*-----------------------------------------------------------------*/
10209 static void
10210 genCast (iCode * ic)
10211 {
10212   operand *result = IC_RESULT (ic);
10213   sym_link *ctype = operandType (IC_LEFT (ic));
10214   sym_link *rtype = operandType (IC_RIGHT (ic));
10215   operand *right = IC_RIGHT (ic);
10216   int size, offset;
10217
10218   D (emitcode (";", "genCast ");
10219     );
10220
10221   /* if they are equivalent then do nothing */
10222   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10223     return;
10224
10225   aopOp (right, ic, FALSE, FALSE);
10226   aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
10227
10228   /* if the result is a bit */
10229   // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10230   if (IS_BITVAR(OP_SYMBOL(result)->type))
10231     {
10232       /* if the right size is a literal then
10233          we know what the value is */
10234       if (AOP_TYPE (right) == AOP_LIT)
10235         {
10236           if (((int) operandLitValue (right)))
10237             aopPut (AOP (result), one, 0);
10238           else
10239             aopPut (AOP (result), zero, 0);
10240
10241           goto release;
10242         }
10243
10244       /* the right is also a bit variable */
10245       if (AOP_TYPE (right) == AOP_CRY)
10246         {
10247           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10248           aopPut (AOP (result), "c", 0);
10249           goto release;
10250         }
10251
10252       /* we need to or */
10253       toBoolean (right);
10254       aopPut (AOP (result), "a", 0);
10255       goto release;
10256     }
10257
10258   /* if they are the same size : or less */
10259   if (AOP_SIZE (result) <= AOP_SIZE (right))
10260     {
10261
10262       /* if they are in the same place */
10263       if (sameRegs (AOP (right), AOP (result)))
10264         goto release;
10265
10266       /* if they in different places then copy */
10267       size = AOP_SIZE (result);
10268       offset = 0;
10269       _startLazyDPSEvaluation ();
10270       while (size--)
10271         {
10272           aopPut (AOP (result),
10273                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10274                   offset);
10275           offset++;
10276         }
10277       _endLazyDPSEvaluation ();
10278       goto release;
10279     }
10280
10281
10282   /* if the result is of type pointer */
10283   if (IS_PTR (ctype))
10284     {
10285
10286       int p_type;
10287       sym_link *type = operandType (right);
10288
10289       /* pointer to generic pointer */
10290       if (IS_GENPTR (ctype))
10291         {
10292           char *l = zero;
10293
10294           if (IS_PTR (type))
10295             {
10296               p_type = DCL_TYPE (type);
10297             }
10298           else
10299             {
10300 #if OLD_CAST_BEHAVIOR
10301               /* KV: we are converting a non-pointer type to
10302                * a generic pointer. This (ifdef'd out) code
10303                * says that the resulting generic pointer
10304                * should have the same class as the storage
10305                * location of the non-pointer variable.
10306                *
10307                * For example, converting an int (which happens
10308                * to be stored in DATA space) to a pointer results
10309                * in a DATA generic pointer; if the original int
10310                * in XDATA space, so will be the resulting pointer.
10311                *
10312                * I don't like that behavior, and thus this change:
10313                * all such conversions will be forced to XDATA and
10314                * throw a warning. If you want some non-XDATA
10315                * type, or you want to suppress the warning, you
10316                * must go through an intermediate cast, like so:
10317                *
10318                * char _generic *gp = (char _xdata *)(intVar);
10319                */
10320               sym_link *etype = getSpec (type);
10321
10322               /* we have to go by the storage class */
10323               if (SPEC_OCLS (etype) != generic)
10324                 {
10325                   p_type = PTR_TYPE (SPEC_OCLS (etype));
10326                 }
10327               else
10328 #endif
10329                 {
10330                   /* Converting unknown class (i.e. register variable)
10331                    * to generic pointer. This is not good, but
10332                    * we'll make a guess (and throw a warning).
10333                    */
10334                   p_type = FPOINTER;
10335                   werror (W_INT_TO_GEN_PTR_CAST);
10336                 }
10337             }
10338
10339           /* the first two bytes are known */
10340           size = GPTRSIZE - 1;
10341           offset = 0;
10342           _startLazyDPSEvaluation ();
10343           while (size--)
10344             {
10345               aopPut (AOP (result),
10346                       aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10347                       offset);
10348               offset++;
10349             }
10350           _endLazyDPSEvaluation ();
10351
10352           /* the last byte depending on type */
10353           switch (p_type)
10354             {
10355             case IPOINTER:
10356             case POINTER:
10357               l = zero;
10358               break;
10359             case FPOINTER:
10360               l = one;
10361               break;
10362             case CPOINTER:
10363               l = "#0x02";
10364               break;
10365             case PPOINTER:
10366               l = "#0x03";
10367               break;
10368
10369             default:
10370               /* this should never happen */
10371               werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10372                       "got unknown pointer type");
10373               exit (1);
10374             }
10375           aopPut (AOP (result), l, GPTRSIZE - 1);
10376           goto release;
10377         }
10378
10379       /* just copy the pointers */
10380       size = AOP_SIZE (result);
10381       offset = 0;
10382       _startLazyDPSEvaluation ();
10383       while (size--)
10384         {
10385           aopPut (AOP (result),
10386                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10387                   offset);
10388           offset++;
10389         }
10390       _endLazyDPSEvaluation ();
10391       goto release;
10392     }
10393
10394   /* so we now know that the size of destination is greater
10395      than the size of the source */
10396   /* we move to result for the size of source */
10397   size = AOP_SIZE (right);
10398   offset = 0;
10399   _startLazyDPSEvaluation ();
10400   while (size--)
10401     {
10402       aopPut (AOP (result),
10403               aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10404               offset);
10405       offset++;
10406     }
10407   _endLazyDPSEvaluation ();
10408
10409   /* now depending on the sign of the source && destination */
10410   size = AOP_SIZE (result) - AOP_SIZE (right);
10411   /* if unsigned or not an integral type */
10412   /* also, if the source is a bit, we don't need to sign extend, because
10413    * it can't possibly have set the sign bit.
10414    */
10415   if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
10416     {
10417       while (size--)
10418         {
10419           aopPut (AOP (result), zero, offset++);
10420         }
10421     }
10422   else
10423     {
10424       /* we need to extend the sign :{ */
10425       char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
10426                         FALSE, FALSE, TRUE);
10427       MOVA (l);
10428       emitcode ("rlc", "a");
10429       emitcode ("subb", "a,acc");
10430       while (size--)
10431         aopPut (AOP (result), "a", offset++);
10432     }
10433
10434   /* we are done hurray !!!! */
10435
10436 release:
10437   freeAsmop (right, NULL, ic, TRUE);
10438   freeAsmop (result, NULL, ic, TRUE);
10439
10440 }
10441
10442 /*-----------------------------------------------------------------*/
10443 /* genDjnz - generate decrement & jump if not zero instrucion      */
10444 /*-----------------------------------------------------------------*/
10445 static int
10446 genDjnz (iCode * ic, iCode * ifx)
10447 {
10448   symbol *lbl, *lbl1;
10449   if (!ifx)
10450     return 0;
10451
10452   /* if the if condition has a false label
10453      then we cannot save */
10454   if (IC_FALSE (ifx))
10455     return 0;
10456
10457   /* if the minus is not of the form
10458      a = a - 1 */
10459   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
10460       !IS_OP_LITERAL (IC_RIGHT (ic)))
10461     return 0;
10462
10463   if (operandLitValue (IC_RIGHT (ic)) != 1)
10464     return 0;
10465
10466   /* if the size of this greater than one then no
10467      saving */
10468   if (getSize (operandType (IC_RESULT (ic))) > 1)
10469     return 0;
10470
10471   /* otherwise we can save BIG */
10472   D(emitcode(";", "genDjnz"););
10473
10474   lbl = newiTempLabel (NULL);
10475   lbl1 = newiTempLabel (NULL);
10476
10477   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10478
10479   if (AOP_NEEDSACC(IC_RESULT(ic)))
10480   {
10481       /* If the result is accessed indirectly via
10482        * the accumulator, we must explicitly write
10483        * it back after the decrement.
10484        */
10485       char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
10486       
10487       if (strcmp(rByte, "a"))
10488       {
10489            /* Something is hopelessly wrong */
10490            fprintf(stderr, "*** warning: internal error at %s:%d\n",
10491                    __FILE__, __LINE__);
10492            /* We can just give up; the generated code will be inefficient,
10493             * but what the hey.
10494             */
10495            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10496            return 0;
10497       }
10498       emitcode ("dec", "%s", rByte);
10499       aopPut(AOP(IC_RESULT(ic)), rByte, 0);
10500       emitcode ("jnz", "%05d$", lbl->key + 100);
10501   }
10502   else if (IS_AOP_PREG (IC_RESULT (ic)))
10503     {
10504       emitcode ("dec", "%s",
10505                 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10506       emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10507       emitcode ("jnz", "%05d$", lbl->key + 100);
10508     }
10509   else
10510     {
10511       emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
10512                 lbl->key + 100);
10513     }
10514   emitcode ("sjmp", "%05d$", lbl1->key + 100);
10515   emitcode ("", "%05d$:", lbl->key + 100);
10516   emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
10517   emitcode ("", "%05d$:", lbl1->key + 100);
10518
10519   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10520   ifx->generated = 1;
10521   return 1;
10522 }
10523
10524 /*-----------------------------------------------------------------*/
10525 /* genReceive - generate code for a receive iCode                  */
10526 /*-----------------------------------------------------------------*/
10527 static void
10528 genReceive (iCode * ic)
10529 {
10530
10531   D (emitcode (";", "genReceive ");
10532     );
10533
10534   if (isOperandInFarSpace (IC_RESULT (ic)) &&
10535       (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
10536        IS_TRUE_SYMOP (IC_RESULT (ic))))
10537     {
10538       int size = getSize (operandType (IC_RESULT (ic)));
10539       int offset = fReturnSizeDS390 - size;
10540       while (size--)
10541         {
10542           emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
10543                             fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
10544           offset++;
10545         }
10546       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10547       size = AOP_SIZE (IC_RESULT (ic));
10548       offset = 0;
10549       while (size--)
10550         {
10551           emitcode ("pop", "acc");
10552           aopPut (AOP (IC_RESULT (ic)), "a", offset++);
10553         }
10554
10555     }
10556   else
10557     {
10558       _G.accInUse++;
10559       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10560       _G.accInUse--;
10561       assignResultValue (IC_RESULT (ic));
10562     }
10563
10564   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10565 }
10566
10567 /*-----------------------------------------------------------------*/
10568 /* gen390Code - generate code for Dallas 390 based controllers     */
10569 /*-----------------------------------------------------------------*/
10570 void
10571 gen390Code (iCode * lic)
10572 {
10573   iCode *ic;
10574   int cln = 0;
10575
10576   lineHead = lineCurr = NULL;
10577
10578   if (options.model == MODEL_FLAT24) {
10579     fReturnSizeDS390 = 5;
10580     fReturn = fReturn24;
10581   } else {
10582     fReturnSizeDS390 = 4;
10583     fReturn = fReturn16;
10584     options.stack10bit=0;
10585   }
10586 #if 0
10587   //REMOVE ME!!!
10588   /* print the allocation information */
10589   if (allocInfo)
10590     printAllocInfo (currFunc, codeOutFile);
10591 #endif
10592   /* if debug information required */
10593   if (options.debug && currFunc)
10594     {
10595       cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
10596       _G.debugLine = 1;
10597       if (IS_STATIC (currFunc->etype))
10598         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
10599       else
10600         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
10601       _G.debugLine = 0;
10602     }
10603   /* stack pointer name */
10604   if (options.useXstack)
10605     spname = "_spx";
10606   else
10607     spname = "sp";
10608
10609
10610   for (ic = lic; ic; ic = ic->next)
10611     {
10612
10613       if (cln != ic->lineno)
10614         {
10615           if (options.debug)
10616             {
10617               _G.debugLine = 1;
10618               emitcode ("", "C$%s$%d$%d$%d ==.",
10619                         FileBaseName (ic->filename), ic->lineno,
10620                         ic->level, ic->block);
10621               _G.debugLine = 0;
10622             }
10623           emitcode (";", "%s %d", ic->filename, ic->lineno);
10624           cln = ic->lineno;
10625         }
10626       /* if the result is marked as
10627          spilt and rematerializable or code for
10628          this has already been generated then
10629          do nothing */
10630       if (resultRemat (ic) || ic->generated)
10631         continue;
10632
10633       /* depending on the operation */
10634       switch (ic->op)
10635         {
10636         case '!':
10637           genNot (ic);
10638           break;
10639
10640         case '~':
10641           genCpl (ic);
10642           break;
10643
10644         case UNARYMINUS:
10645           genUminus (ic);
10646           break;
10647
10648         case IPUSH:
10649           genIpush (ic);
10650           break;
10651
10652         case IPOP:
10653           /* IPOP happens only when trying to restore a
10654              spilt live range, if there is an ifx statement
10655              following this pop then the if statement might
10656              be using some of the registers being popped which
10657              would destory the contents of the register so
10658              we need to check for this condition and handle it */
10659           if (ic->next &&
10660               ic->next->op == IFX &&
10661               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
10662             genIfx (ic->next, ic);
10663           else
10664             genIpop (ic);
10665           break;
10666
10667         case CALL:
10668           genCall (ic);
10669           break;
10670
10671         case PCALL:
10672           genPcall (ic);
10673           break;
10674
10675         case FUNCTION:
10676           genFunction (ic);
10677           break;
10678
10679         case ENDFUNCTION:
10680           genEndFunction (ic);
10681           break;
10682
10683         case RETURN:
10684           genRet (ic);
10685           break;
10686
10687         case LABEL:
10688           genLabel (ic);
10689           break;
10690
10691         case GOTO:
10692           genGoto (ic);
10693           break;
10694
10695         case '+':
10696           genPlus (ic);
10697           break;
10698
10699         case '-':
10700           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
10701             genMinus (ic);
10702           break;
10703
10704         case '*':
10705           genMult (ic);
10706           break;
10707
10708         case '/':
10709           genDiv (ic);
10710           break;
10711
10712         case '%':
10713           genMod (ic);
10714           break;
10715
10716         case '>':
10717           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
10718           break;
10719
10720         case '<':
10721           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
10722           break;
10723
10724         case LE_OP:
10725         case GE_OP:
10726         case NE_OP:
10727
10728           /* note these two are xlated by algebraic equivalence
10729              during parsing SDCC.y */
10730           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10731                   "got '>=' or '<=' shouldn't have come here");
10732           break;
10733
10734         case EQ_OP:
10735           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
10736           break;
10737
10738         case AND_OP:
10739           genAndOp (ic);
10740           break;
10741
10742         case OR_OP:
10743           genOrOp (ic);
10744           break;
10745
10746         case '^':
10747           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
10748           break;
10749
10750         case '|':
10751           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
10752           break;
10753
10754         case BITWISEAND:
10755           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
10756           break;
10757
10758         case INLINEASM:
10759           genInline (ic);
10760           break;
10761
10762         case RRC:
10763           genRRC (ic);
10764           break;
10765
10766         case RLC:
10767           genRLC (ic);
10768           break;
10769
10770         case GETHBIT:
10771           genGetHbit (ic);
10772           break;
10773
10774         case LEFT_OP:
10775           genLeftShift (ic);
10776           break;
10777
10778         case RIGHT_OP:
10779           genRightShift (ic);
10780           break;
10781
10782         case GET_VALUE_AT_ADDRESS:
10783           genPointerGet (ic,hasInc(IC_LEFT(ic),ic));
10784           break;
10785
10786         case '=':
10787           if (POINTER_SET (ic))
10788             genPointerSet (ic,hasInc(IC_RESULT(ic),ic));
10789           else
10790             genAssign (ic);
10791           break;
10792
10793         case IFX:
10794           genIfx (ic, NULL);
10795           break;
10796
10797         case ADDRESS_OF:
10798           genAddrOf (ic);
10799           break;
10800
10801         case JUMPTABLE:
10802           genJumpTab (ic);
10803           break;
10804
10805         case CAST:
10806           genCast (ic);
10807           break;
10808
10809         case RECEIVE:
10810           genReceive (ic);
10811           break;
10812
10813         case SEND:
10814           addSet (&_G.sendSet, ic);
10815           break;
10816
10817         case ARRAYINIT:
10818             genArrayInit(ic);
10819             break;
10820             
10821         default:
10822           ic = ic;
10823         }
10824     }
10825
10826
10827   /* now we are ready to call the
10828      peep hole optimizer */
10829   if (!options.nopeep)
10830     peepHole (&lineHead);
10831
10832   /* now do the actual printing */
10833   printLine (lineHead, codeOutFile);
10834   return;
10835 }