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