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