Arithmetic accelerator: genModTwoBytes loaded MB backwards with literals too.
[fw/sdcc] / src / ds390 / gen.c
1 /*-------------------------------------------------------------------------
2   gen.c - source file for code generation for DS80C390
3
4   Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
5          and -  Jean-Louis VERN.jlvern@writeme.com (1999)
6   Bug Fixes  -  Wojciech Stryjewski  wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7   DS390 adaptation by Kevin Vigor <kevin@vigor.nu>
8
9   This program is free software; you can redistribute it and/or modify it
10   under the terms of the GNU General Public License as published by the
11   Free Software Foundation; either version 2, or (at your option) any
12   later version.
13
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License for more details.
18
19   You should have received a copy of the GNU General Public License
20   along with this program; if not, write to the Free Software
21   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22
23   In other words, you are welcome to use, share and improve this program.
24   You are forbidden to forbid anyone else to use, share and improve
25   what you give them.   Help stamp out software-hoarding!
26 -------------------------------------------------------------------------*/
27
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <ctype.h>
32
33 #include <common.h>
34 #include "ralloc.h"
35 #include "gen.h"
36 #include "SDCCglobl.h"
37 #include "newalloc.h"
38
39 #ifdef HAVE_SYS_ISA_DEFS_H
40 #include <sys/isa_defs.h>
41 #else
42 #ifdef HAVE_MACHINE_ENDIAN_H
43 #include <machine/endian.h>
44 #else
45 #ifdef HAVE_ENDIAN_H
46 #include <endian.h>
47 #else
48 #if !defined(__BORLANDC__) && !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__CYGWIN__)
49 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
50 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
51 #endif
52 #endif
53 #endif
54 #endif
55
56 #define BETTER_LITERAL_SHIFT
57
58 char *aopLiteral (value * val, int offset);
59
60 /* this is the down and dirty file with all kinds of
61    kludgy & hacky stuff. This is what it is all about
62    CODE GENERATION for a specific MCU . some of the
63    routines may be reusable, will have to see */
64
65 static char *zero = "#0x00";
66 static char *one = "#0x01";
67 static char *spname;
68
69 #define D(x) x
70
71 #define TR_DPTR(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_DPTR1 %s ", s); }
72 #define TR_AP(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_AP %s ", s); }
73
74 unsigned fReturnSizeDS390 = 5;  /* shared with ralloc.c */
75 static char *fReturn24[] =
76 {"dpl", "dph", "dpx", "b", "a"};
77 static char *fReturn16[] =
78 {"dpl", "dph", "b", "a"};
79 static char **fReturn = fReturn24;
80 static char *accUse[] =
81 {"a", "b"};
82
83 static short rbank = -1;
84
85 static struct
86   {
87     short r0Pushed;
88     short r1Pushed;
89     short accInUse;
90     short inLine;
91     short debugLine;
92     short nRegsSaved;
93     set *sendSet;
94   }
95 _G;
96
97 static void saveRBank (int, iCode *, bool);
98
99 #define RESULTONSTACK(x) \
100                          (IC_RESULT(x) && IC_RESULT(x)->aop && \
101                          IC_RESULT(x)->aop->type == AOP_STK )
102
103 /* #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x); */
104 #define MOVA(x) { char *_mova_tmp = strdup(x); \
105                  if (strcmp(_mova_tmp,"a") && strcmp(_mova_tmp,"acc")) \
106                  { \
107                     emitcode("mov","a,%s",_mova_tmp); \
108                  } \
109                  free(_mova_tmp); \
110                 }
111 #define CLRC    emitcode("clr","c")
112 #define SETC    emitcode("setb","c")
113
114 // A scratch register which will be used to hold
115 // result bytes from operands in far space via DPTR2.
116 #define DP2_RESULT_REG  "ap"
117
118 static lineNode *lineHead = NULL;
119 static lineNode *lineCurr = NULL;
120
121 static unsigned char SLMask[] =
122 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
123  0xE0, 0xC0, 0x80, 0x00};
124 static unsigned char SRMask[] =
125 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
126  0x07, 0x03, 0x01, 0x00};
127
128 #define LSB     0
129 #define MSB16   1
130 #define MSB24   2
131 #define MSB32   3
132
133 /*-----------------------------------------------------------------*/
134 /* emitcode - writes the code into a file : for now it is simple    */
135 /*-----------------------------------------------------------------*/
136 static void
137 emitcode (char *inst, char *fmt,...)
138 {
139   va_list ap;
140   char lb[INITIAL_INLINEASM];
141   char *lbp = lb;
142
143   va_start (ap, fmt);
144
145   if (inst && *inst)
146     {
147       if (fmt && *fmt)
148         sprintf (lb, "%s\t", inst);
149       else
150         sprintf (lb, "%s", inst);
151       vsprintf (lb + (strlen (lb)), fmt, ap);
152     }
153   else
154     vsprintf (lb, fmt, ap);
155
156   while (isspace (*lbp))
157     lbp++;
158
159   if (lbp && *lbp)
160     lineCurr = (lineCurr ?
161                 connectLine (lineCurr, newLineNode (lb)) :
162                 (lineHead = newLineNode (lb)));
163   lineCurr->isInline = _G.inLine;
164   lineCurr->isDebug = _G.debugLine;
165   va_end (ap);
166 }
167
168 /*-----------------------------------------------------------------*/
169 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
170 /*-----------------------------------------------------------------*/
171 static regs *
172 getFreePtr (iCode * ic, asmop ** aopp, bool result)
173 {
174   bool r0iu = FALSE, r1iu = FALSE;
175   bool r0ou = FALSE, r1ou = FALSE;
176
177   /* the logic: if r0 & r1 used in the instruction
178      then we are in trouble otherwise */
179
180   /* first check if r0 & r1 are used by this
181      instruction, in which case we are in trouble */
182   r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
183   r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
184   if (r0iu && r1iu) {
185       goto endOfWorld;
186     }
187
188   r0ou = bitVectBitValue (ic->rMask, R0_IDX);
189   r1ou = bitVectBitValue (ic->rMask, R1_IDX);
190
191   /* if no usage of r0 then return it */
192   if (!r0iu && !r0ou)
193     {
194       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
195       (*aopp)->type = AOP_R0;
196
197       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
198     }
199
200   /* if no usage of r1 then return it */
201   if (!r1iu && !r1ou)
202     {
203       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
204       (*aopp)->type = AOP_R1;
205
206       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R1_IDX);
207     }
208
209   /* now we know they both have usage */
210   /* if r0 not used in this instruction */
211   if (!r0iu)
212     {
213       /* push it if not already pushed */
214       if (!_G.r0Pushed)
215         {
216           emitcode ("push", "%s",
217                     ds390_regWithIdx (R0_IDX)->dname);
218           _G.r0Pushed++;
219         }
220
221       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
222       (*aopp)->type = AOP_R0;
223
224       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
225     }
226
227   /* if r1 not used then */
228
229   if (!r1iu)
230     {
231       /* push it if not already pushed */
232       if (!_G.r1Pushed)
233         {
234           emitcode ("push", "%s",
235                     ds390_regWithIdx (R1_IDX)->dname);
236           _G.r1Pushed++;
237         }
238
239       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
240       (*aopp)->type = AOP_R1;
241       return ds390_regWithIdx (R1_IDX);
242     }
243
244 endOfWorld:
245   /* I said end of world but not quite end of world yet */
246   /* if this is a result then we can push it on the stack */
247   if (result)
248     {
249       (*aopp)->type = AOP_STK;
250       return NULL;
251     }
252
253   /* other wise this is true end of the world */
254   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
255           "getFreePtr should never reach here");
256   exit (1);
257 }
258
259 /*-----------------------------------------------------------------*/
260 /* newAsmop - creates a new asmOp                                  */
261 /*-----------------------------------------------------------------*/
262 static asmop *
263 newAsmop (short type)
264 {
265   asmop *aop;
266
267   aop = Safe_calloc (1, sizeof (asmop));
268   aop->type = type;
269   return aop;
270 }
271
272 static int _currentDPS;         /* Current processor DPS. */
273 static int _desiredDPS;         /* DPS value compiler thinks we should be using. */
274 static int _lazyDPS = 0;        /* if non-zero, we are doing lazy evaluation of DPS changes. */
275
276 /*-----------------------------------------------------------------*/
277 /* genSetDPTR: generate code to select which DPTR is in use (zero  */
278 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390     */
279 /* alternate DPTR (DPL1/DPH1/DPX1).          */
280 /*-----------------------------------------------------------------*/
281 static void
282 genSetDPTR (int n)
283 {
284
285   /* If we are doing lazy evaluation, simply note the desired
286    * change, but don't emit any code yet.
287    */
288   if (_lazyDPS)
289     {
290       _desiredDPS = n;
291       return;
292     }
293
294   if (!n)
295     {
296       emitcode ("mov", "dps, #0x00");
297     }
298   else
299     {
300       TR_DPTR("#1");
301       emitcode ("mov", "dps, #0x01");
302     }
303 }
304
305 /*-----------------------------------------------------------------*/
306 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
307 /*                   */
308 /* Any code that operates on DPTR (NB: not on the individual     */
309 /* components, like DPH) *must* call _flushLazyDPS() before using  */
310 /* DPTR within a lazy DPS evaluation block.        */
311 /*                   */
312 /* Note that aopPut and aopGet already contain the proper calls to */
313 /* _flushLazyDPS, so it is safe to use these calls within a lazy   */
314 /* DPS evaluation block.             */
315 /*                   */
316 /* Also, _flushLazyDPS must be called before any flow control      */
317 /* operations that could potentially branch out of the block.    */
318 /*                         */
319 /* Lazy DPS evaluation is simply an optimization (though an      */
320 /* important one), so if in doubt, leave it out.       */
321 /*-----------------------------------------------------------------*/
322 static void
323 _startLazyDPSEvaluation (void)
324 {
325   _currentDPS = 0;
326   _desiredDPS = 0;
327 #ifdef BETTER_LITERAL_SHIFT  
328   _lazyDPS++;
329 #else
330   _lazyDPS = 1;
331 #endif  
332 }
333
334 /*-----------------------------------------------------------------*/
335 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
336 /* desired one. Call before using DPTR within a lazy DPS evaluation */
337 /* block.                */
338 /*-----------------------------------------------------------------*/
339 static void
340 _flushLazyDPS (void)
341 {
342   if (!_lazyDPS)
343     {
344       /* nothing to do. */
345       return;
346     }
347
348   if (_desiredDPS != _currentDPS)
349     {
350       if (_desiredDPS)
351         {
352           emitcode ("inc", "dps");
353         }
354       else
355         {
356           emitcode ("dec", "dps");
357         }
358       _currentDPS = _desiredDPS;
359     }
360 }
361
362 /*-----------------------------------------------------------------*/
363 /* _endLazyDPSEvaluation: end lazy DPS evaluation block.     */
364 /*                   */
365 /* Forces us back to the safe state (standard DPTR selected).    */
366 /*-----------------------------------------------------------------*/
367 static void
368 _endLazyDPSEvaluation (void)
369 {
370 #ifdef BETTER_LITERAL_SHIFT  
371   _lazyDPS--;
372 #else
373   _lazyDPS = 0;
374 #endif    
375   if (!_lazyDPS)
376   {
377     if (_currentDPS)
378     {
379       genSetDPTR (0);
380       _flushLazyDPS ();
381     }
382     _currentDPS = 0;
383     _desiredDPS = 0;
384   }
385 }
386
387
388
389 /*-----------------------------------------------------------------*/
390 /* pointerCode - returns the code for a pointer type               */
391 /*-----------------------------------------------------------------*/
392 static int
393 pointerCode (sym_link * etype)
394 {
395
396   return PTR_TYPE (SPEC_OCLS (etype));
397
398 }
399
400 /*-----------------------------------------------------------------*/
401 /* aopForSym - for a true symbol                                   */
402 /*-----------------------------------------------------------------*/
403 static asmop *
404 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
405 {
406   asmop *aop;
407   memmap *space = SPEC_OCLS (sym->etype);
408
409   /* if already has one */
410   if (sym->aop)
411     return sym->aop;
412
413   /* assign depending on the storage class */
414   /* if it is on the stack or indirectly addressable */
415   /* space we need to assign either r0 or r1 to it   */
416   if ((sym->onStack && !options.stack10bit) || sym->iaccess)
417     {
418       sym->aop = aop = newAsmop (0);
419       aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
420       aop->size = getSize (sym->type);
421
422       /* now assign the address of the variable to
423          the pointer register */
424       if (aop->type != AOP_STK)
425         {
426
427           if (sym->onStack)
428             {
429               if (_G.accInUse)
430                 emitcode ("push", "acc");
431
432               emitcode ("mov", "a,_bp");
433               emitcode ("add", "a,#0x%02x",
434                         ((sym->stack < 0) ?
435                          ((char) (sym->stack - _G.nRegsSaved)) :
436                          ((char) sym->stack)) & 0xff);
437               emitcode ("mov", "%s,a",
438                         aop->aopu.aop_ptr->name);
439
440               if (_G.accInUse)
441                 emitcode ("pop", "acc");
442             }
443           else
444             emitcode ("mov", "%s,#%s",
445                       aop->aopu.aop_ptr->name,
446                       sym->rname);
447           aop->paged = space->paged;
448         }
449       else
450         aop->aopu.aop_stk = sym->stack;
451       return aop;
452     }
453
454   if (sym->onStack && options.stack10bit)
455     {
456       /* It's on the 10 bit stack, which is located in
457        * far data space.
458        */
459
460       if (_G.accInUse)
461         emitcode ("push", "acc");
462
463       emitcode ("mov", "a,_bp");
464       emitcode ("add", "a,#0x%02x",
465                 ((sym->stack < 0) ?
466                  ((char) (sym->stack - _G.nRegsSaved)) :
467                  ((char) sym->stack)) & 0xff);
468
469       if (useDP2)
470         {
471           if (options.model == MODEL_FLAT24)
472             emitcode ("mov", "dpx1,#0x40");
473           TR_DPTR("#2");
474           emitcode ("mov", "dph1,#0x00");
475           emitcode ("mov", "dpl1, a");
476         }
477       else
478         {
479           if (options.model == MODEL_FLAT24)
480             emitcode ("mov", "dpx,#0x40");
481           emitcode ("mov", "dph,#0x00");
482           emitcode ("mov", "dpl, a");
483         }
484
485       if (_G.accInUse)
486         emitcode ("pop", "acc");
487
488       sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
489       aop->size = getSize (sym->type);
490       return aop;
491     }
492
493   /* if in bit space */
494   if (IN_BITSPACE (space))
495     {
496       sym->aop = aop = newAsmop (AOP_CRY);
497       aop->aopu.aop_dir = sym->rname;
498       aop->size = getSize (sym->type);
499       return aop;
500     }
501   /* if it is in direct space */
502   if (IN_DIRSPACE (space))
503     {
504       sym->aop = aop = newAsmop (AOP_DIR);
505       aop->aopu.aop_dir = sym->rname;
506       aop->size = getSize (sym->type);
507       return aop;
508     }
509
510   /* special case for a function */
511   if (IS_FUNC (sym->type))
512     {
513       sym->aop = aop = newAsmop (AOP_IMMD);
514       aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
515       strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
516       aop->size = FPTRSIZE;
517       return aop;
518     }
519
520   /* only remaining is far space */
521   /* in which case DPTR gets the address */
522   sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
523   if (useDP2)
524     {
525       genSetDPTR (1);
526       _flushLazyDPS ();
527       emitcode ("mov", "dptr,#%s", sym->rname);
528       genSetDPTR (0);
529     }
530   else
531     {
532       emitcode ("mov", "dptr,#%s", sym->rname);
533     }
534   aop->size = getSize (sym->type);
535
536   /* if it is in code space */
537   if (IN_CODESPACE (space))
538     aop->code = 1;
539
540   return aop;
541 }
542
543 /*-----------------------------------------------------------------*/
544 /* aopForRemat - rematerialzes an object                           */
545 /*-----------------------------------------------------------------*/
546 static asmop *
547 aopForRemat (symbol * sym)
548 {
549   iCode *ic = sym->rematiCode;
550   asmop *aop = newAsmop (AOP_IMMD);
551   int ptr_type ;
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 & 0xff);
4100                         emitcode ("mov","mb,#0x%02x",(val >> 8) & 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                 if (AOP_TYPE(result) == AOP_ACC)
4173                 {
4174                     D(emitcode(";", "ACC special case."););
4175                     /* We know result is the only live aop, and 
4176                      * it's obviously not a DPTR2, so AP is available.
4177                      */
4178                     emitcode("mov", "%s,acc", DP2_RESULT_REG);
4179                 }
4180                 else
4181                 {
4182                     aopPut(AOP(result),"a",0);
4183                 }
4184             
4185                 emitcode("pop","acc");
4186                 lbl = newiTempLabel(NULL);      
4187                 emitcode("jnb","F0,%05d$",lbl->key+100);
4188                 emitcode("cpl","a");
4189                 emitcode("addc","a,#0");
4190                 emitcode("","%05d$:", lbl->key+100);
4191                 aopPut(AOP(result),"a",1);
4192                 emitcode("pop","acc");
4193                 if (AOP_SIZE(result) >= 3) {
4194                         lbl = newiTempLabel(NULL);      
4195                         emitcode("jnb","F0,%05d$",lbl->key+100);
4196                         emitcode("cpl","a");
4197                         emitcode("addc","a,#0");                        
4198                         emitcode("","%05d$:", lbl->key+100);
4199                         aopPut(AOP(result),"a",2);
4200                 }
4201                 emitcode("pop","acc");
4202                 if (AOP_SIZE(result) >= 4) {
4203                         lbl = newiTempLabel(NULL);      
4204                         emitcode("jnb","F0,%05d$",lbl->key+100);
4205                         emitcode("cpl","a");
4206                         emitcode("addc","a,#0");                        
4207                         emitcode("","%05d$:", lbl->key+100);
4208                         aopPut(AOP(result),"a",3);
4209                 }
4210                 if (AOP_TYPE(result) == AOP_ACC)
4211                 {
4212                     /* We stashed the result away above. */
4213                     emitcode("mov", "acc,%s", DP2_RESULT_REG);
4214                 }           
4215                 
4216         }
4217         freeAsmop (result, NULL, ic, TRUE);
4218         return ;
4219 }
4220
4221 /*-----------------------------------------------------------------*/
4222 /* genMult - generates code for multiplication                     */
4223 /*-----------------------------------------------------------------*/
4224 static void
4225 genMult (iCode * ic)
4226 {
4227   operand *left = IC_LEFT (ic);
4228   operand *right = IC_RIGHT (ic);
4229   operand *result = IC_RESULT (ic);
4230
4231   D (emitcode (";", "genMult "););
4232
4233   /* assign the amsops */
4234   AOP_OP_2 (ic);
4235
4236   /* special cases first */
4237   /* both are bits */
4238   if (AOP_TYPE (left) == AOP_CRY &&
4239       AOP_TYPE (right) == AOP_CRY)
4240     {
4241       genMultbits (left, right, result, ic);
4242       goto release;
4243     }
4244
4245   /* if both are of size == 1 */
4246   if (AOP_SIZE (left) == 1 &&
4247       AOP_SIZE (right) == 1)
4248     {
4249       genMultOneByte (left, right, result, ic);
4250       goto release;
4251     }
4252
4253   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4254           /* use the ds390 ARITHMETIC accel UNIT */
4255           genMultTwoByte (left, right, result, ic);
4256           return ;
4257   }
4258   /* should have been converted to function call */
4259   assert (0);
4260
4261 release:
4262   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4263   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4264   freeAsmop (result, NULL, ic, TRUE);
4265 }
4266
4267 /*-----------------------------------------------------------------*/
4268 /* genDivbits :- division of bits                                  */
4269 /*-----------------------------------------------------------------*/
4270 static void
4271 genDivbits (operand * left,
4272             operand * right,
4273             operand * result,
4274             iCode   * ic)
4275 {
4276
4277   char *l;
4278
4279   /* the result must be bit */
4280   LOAD_AB_FOR_DIV (left, right, l);
4281   emitcode ("div", "ab");
4282   emitcode ("rrc", "a");
4283   aopOp(result, ic, TRUE, FALSE);
4284     
4285   aopPut (AOP (result), "c", 0);
4286 }
4287
4288 /*-----------------------------------------------------------------*/
4289 /* genDivOneByte : 8 bit division                                  */
4290 /*-----------------------------------------------------------------*/
4291 static void
4292 genDivOneByte (operand * left,
4293                operand * right,
4294                operand * result,
4295                iCode   * ic)
4296 {
4297   sym_link *opetype = operandType (result);
4298   char *l;
4299   symbol *lbl;
4300   int size, offset;
4301
4302   offset = 1;
4303   /* signed or unsigned */
4304   if (SPEC_USIGN (opetype))
4305     {
4306         /* unsigned is easy */
4307         LOAD_AB_FOR_DIV (left, right, l);
4308         emitcode ("div", "ab");
4309
4310         _G.accInUse++;
4311         aopOp(result, ic, TRUE, FALSE);
4312         aopPut (AOP (result), "a", 0);
4313         _G.accInUse--;
4314
4315         size = AOP_SIZE (result) - 1;
4316         
4317         while (size--)
4318         {
4319             aopPut (AOP (result), zero, offset++);
4320         }
4321       return;
4322     }
4323
4324   /* signed is a little bit more difficult */
4325
4326   /* save the signs of the operands */
4327   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4328   MOVA (l);
4329   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4330   emitcode ("push", "acc");     /* save it on the stack */
4331
4332   /* now sign adjust for both left & right */
4333   l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4334   MOVA (l);
4335   lbl = newiTempLabel (NULL);
4336   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4337   emitcode ("cpl", "a");
4338   emitcode ("inc", "a");
4339   emitcode ("", "%05d$:", (lbl->key + 100));
4340   emitcode ("mov", "b,a");
4341
4342   /* sign adjust left side */
4343   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4344   MOVA (l);
4345
4346   lbl = newiTempLabel (NULL);
4347   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4348   emitcode ("cpl", "a");
4349   emitcode ("inc", "a");
4350   emitcode ("", "%05d$:", (lbl->key + 100));
4351
4352   /* now the division */
4353   emitcode ("nop", "; workaround for DS80C390 div bug.");
4354   emitcode ("div", "ab");
4355   /* we are interested in the lower order
4356      only */
4357   emitcode ("mov", "b,a");
4358   lbl = newiTempLabel (NULL);
4359   emitcode ("pop", "acc");
4360   /* if there was an over flow we don't
4361      adjust the sign of the result */
4362   emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4363   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4364   CLRC;
4365   emitcode ("clr", "a");
4366   emitcode ("subb", "a,b");
4367   emitcode ("mov", "b,a");
4368   emitcode ("", "%05d$:", (lbl->key + 100));
4369
4370   /* now we are done */
4371     _G.accInUse++;
4372     aopOp(result, ic, TRUE, FALSE);
4373     
4374     aopPut (AOP (result), "b", 0);
4375     
4376     size = AOP_SIZE (result) - 1;
4377     
4378     if (size > 0)
4379     {
4380       emitcode ("mov", "c,b.7");
4381       emitcode ("subb", "a,acc");
4382     }
4383     while (size--)
4384     {
4385         aopPut (AOP (result), "a", offset++);
4386     }
4387     _G.accInUse--;
4388
4389 }
4390
4391 /*-----------------------------------------------------------------*/
4392 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide       */
4393 /*-----------------------------------------------------------------*/
4394 static void genDivTwoByte (operand *left, operand *right, 
4395                             operand *result, iCode *ic)
4396 {
4397         sym_link *retype = getSpec(operandType(right));
4398         sym_link *letype = getSpec(operandType(left));
4399         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4400         symbol *lbl;
4401
4402         /* load up MA with left */
4403         if (!umult) {
4404                 emitcode("clr","F0");
4405                 lbl = newiTempLabel(NULL);
4406                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4407                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4408                 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4409                 emitcode ("xch", "a,b");
4410                 emitcode ("cpl","a");
4411                 emitcode ("add", "a,#1");
4412                 emitcode ("xch", "a,b");
4413                 emitcode ("cpl", "a"); // msb
4414                 emitcode ("addc","a,#0");
4415                 emitcode ("setb","F0");
4416                 emitcode ("","%05d$:",lbl->key+100);
4417                 emitcode ("mov","ma,b");
4418                 emitcode ("mov","ma,a");
4419         } else {
4420                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4421                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4422         }
4423
4424         /* load up MB with right */
4425         if (!umult) {
4426                 if (AOP_TYPE(right) == AOP_LIT) {
4427                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
4428                         if (val < 0) {
4429                                 lbl = newiTempLabel(NULL);
4430                                 emitcode ("jbc","F0,%05d$",lbl->key+100);
4431                                 emitcode("setb","F0");
4432                                 emitcode ("","%05d$:",lbl->key+100);
4433                                 val = -val;
4434                         } 
4435                         emitcode ("mov","mb,#0x%02x",val & 0xff);                   
4436                         emitcode ("mov","mb,#0x%02x",(val >> 8) & 0xff);
4437                 } else {
4438                         lbl = newiTempLabel(NULL);
4439                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4440                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4441                         emitcode ("jnb","acc.7,%05d$",lbl->key+100);            
4442                         emitcode ("xch", "a,b");
4443                         emitcode ("cpl","a");
4444                         emitcode ("add", "a,#1");
4445                         emitcode ("xch", "a,b");
4446                         emitcode ("cpl", "a"); // msb
4447                         emitcode ("addc", "a,#0");
4448                         emitcode ("jbc","F0,%05d$",lbl->key+100);
4449                         emitcode ("setb","F0");
4450                         emitcode ("","%05d$:",lbl->key+100);
4451                         emitcode ("mov","mb,b");
4452                         emitcode ("mov","mb,a");
4453                 }
4454         } else {
4455                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4456                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4457         }
4458
4459         /* wait for multiplication to finish */
4460         lbl = newiTempLabel(NULL);
4461         emitcode("","%05d$:", lbl->key+100);
4462         emitcode("mov","a,mcnt1");
4463         emitcode("anl","a,#0x80");
4464         emitcode("jnz","%05d$",lbl->key+100);
4465         
4466         freeAsmop (left, NULL, ic, TRUE);
4467         freeAsmop (right, NULL, ic,TRUE);
4468         aopOp(result, ic, TRUE, FALSE);
4469
4470         /* if unsigned then simple */   
4471         if (umult) {
4472                 aopPut(AOP(result),"ma",1);
4473                 aopPut(AOP(result),"ma",0);
4474         } else {
4475                 emitcode("push","ma");
4476                 MOVA("ma");
4477                 /* negate result if needed */
4478                 lbl = newiTempLabel(NULL);      
4479                 emitcode("jnb","F0,%05d$",lbl->key+100);
4480                 emitcode("cpl","a");
4481                 emitcode("add","a,#1");
4482                 emitcode("","%05d$:", lbl->key+100);
4483                 aopPut(AOP(result),"a",0);
4484                 emitcode("pop","acc");
4485                 lbl = newiTempLabel(NULL);      
4486                 emitcode("jnb","F0,%05d$",lbl->key+100);
4487                 emitcode("cpl","a");
4488                 emitcode("addc","a,#0");
4489                 emitcode("","%05d$:", lbl->key+100);
4490                 aopPut(AOP(result),"a",1);
4491         }
4492         freeAsmop (result, NULL, ic, TRUE);
4493         return ;
4494 }
4495
4496 /*-----------------------------------------------------------------*/
4497 /* genDiv - generates code for division                            */
4498 /*-----------------------------------------------------------------*/
4499 static void
4500 genDiv (iCode * ic)
4501 {
4502   operand *left = IC_LEFT (ic);
4503   operand *right = IC_RIGHT (ic);
4504   operand *result = IC_RESULT (ic);
4505
4506   D (emitcode (";", "genDiv "););
4507
4508   /* assign the amsops */
4509   AOP_OP_2 (ic);
4510
4511   /* special cases first */
4512   /* both are bits */
4513   if (AOP_TYPE (left) == AOP_CRY &&
4514       AOP_TYPE (right) == AOP_CRY)
4515     {
4516       genDivbits (left, right, result, ic);
4517       goto release;
4518     }
4519
4520   /* if both are of size == 1 */
4521   if (AOP_SIZE (left) == 1 &&
4522       AOP_SIZE (right) == 1)
4523     {
4524       genDivOneByte (left, right, result, ic);
4525       goto release;
4526     }
4527
4528   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4529           /* use the ds390 ARITHMETIC accel UNIT */
4530           genDivTwoByte (left, right, result, ic);
4531           return ;
4532   }
4533   /* should have been converted to function call */
4534   assert (0);
4535 release:
4536   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4537   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4538   freeAsmop (result, NULL, ic, TRUE);
4539 }
4540
4541 /*-----------------------------------------------------------------*/
4542 /* genModbits :- modulus of bits                                   */
4543 /*-----------------------------------------------------------------*/
4544 static void
4545 genModbits (operand * left,
4546             operand * right,
4547             operand * result,
4548             iCode   * ic)
4549 {
4550
4551   char *l;
4552
4553   /* the result must be bit */
4554   LOAD_AB_FOR_DIV (left, right, l);
4555   emitcode ("div", "ab");
4556   emitcode ("mov", "a,b");
4557   emitcode ("rrc", "a");
4558   aopOp(result, ic, TRUE, FALSE);
4559   aopPut (AOP (result), "c", 0);
4560 }
4561
4562 /*-----------------------------------------------------------------*/
4563 /* genModOneByte : 8 bit modulus                                   */
4564 /*-----------------------------------------------------------------*/
4565 static void
4566 genModOneByte (operand * left,
4567                operand * right,
4568                operand * result,
4569                iCode   * ic)
4570 {
4571   sym_link *opetype = operandType (result);
4572   char *l;
4573   symbol *lbl;
4574
4575   /* signed or unsigned */
4576   if (SPEC_USIGN (opetype))
4577     {
4578       /* unsigned is easy */
4579       LOAD_AB_FOR_DIV (left, right, l);
4580       emitcode ("div", "ab");
4581       aopOp(result, ic, TRUE, FALSE);   
4582       aopPut (AOP (result), "b", 0);
4583       return;
4584     }
4585
4586   /* signed is a little bit more difficult */
4587
4588   /* save the signs of the operands */
4589   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4590   MOVA (l);
4591
4592   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4593   emitcode ("push", "acc");     /* save it on the stack */
4594
4595   /* now sign adjust for both left & right */
4596   l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4597   MOVA (l);
4598
4599   lbl = newiTempLabel (NULL);
4600   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4601   emitcode ("cpl", "a");
4602   emitcode ("inc", "a");
4603   emitcode ("", "%05d$:", (lbl->key + 100));
4604   emitcode ("mov", "b,a");
4605
4606   /* sign adjust left side */
4607   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4608   MOVA (l);
4609
4610   lbl = newiTempLabel (NULL);
4611   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4612   emitcode ("cpl", "a");
4613   emitcode ("inc", "a");
4614   emitcode ("", "%05d$:", (lbl->key + 100));
4615
4616   /* now the multiplication */
4617   emitcode ("nop", "; workaround for DS80C390 div bug.");
4618   emitcode ("div", "ab");
4619   /* we are interested in the lower order
4620      only */
4621   lbl = newiTempLabel (NULL);
4622   emitcode ("pop", "acc");
4623   /* if there was an over flow we don't
4624      adjust the sign of the result */
4625   emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4626   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4627   CLRC;
4628   emitcode ("clr", "a");
4629   emitcode ("subb", "a,b");
4630   emitcode ("mov", "b,a");
4631   emitcode ("", "%05d$:", (lbl->key + 100));
4632
4633   /* now we are done */
4634   aopOp(result, ic, TRUE, FALSE);    
4635   aopPut (AOP (result), "b", 0);
4636
4637 }
4638
4639 /*-----------------------------------------------------------------*/
4640 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus      */
4641 /*-----------------------------------------------------------------*/
4642 static void genModTwoByte (operand *left, operand *right, 
4643                             operand *result, iCode *ic)
4644 {
4645         sym_link *retype = getSpec(operandType(right));
4646         sym_link *letype = getSpec(operandType(left));
4647         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4648         symbol *lbl;
4649
4650         /* load up MA with left */
4651         if (!umult) {
4652                 lbl = newiTempLabel(NULL);
4653                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4654                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4655                 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4656                 emitcode ("xch", "a,b");
4657                 emitcode ("cpl","a");
4658                 emitcode ("add", "a,#1");
4659                 emitcode ("xch", "a,b");
4660                 emitcode ("cpl", "a"); // msb
4661                 emitcode ("addc","a,#0");
4662                 emitcode ("","%05d$:",lbl->key+100);
4663                 emitcode ("mov","ma,b");
4664                 emitcode ("mov","ma,a");
4665         } else {
4666                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4667                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4668         }
4669
4670         /* load up MB with right */
4671         if (!umult) {
4672                 if (AOP_TYPE(right) == AOP_LIT) {
4673                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
4674                         if (val < 0) {
4675                                 val = -val;
4676                         } 
4677                         emitcode ("mov","mb,#0x%02x",val & 0xff);
4678                         emitcode ("mov","mb,#0x%02x",(val >> 8) & 0xff);                    
4679                 } else {
4680                         lbl = newiTempLabel(NULL);
4681                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4682                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4683                         emitcode ("jnb","acc.7,%05d$",lbl->key+100);            
4684                         emitcode ("xch", "a,b");
4685                         emitcode ("cpl","a");
4686                         emitcode ("add", "a,#1");
4687                         emitcode ("xch", "a,b");
4688                         emitcode ("cpl", "a"); // msb
4689                         emitcode ("addc", "a,#0");
4690                         emitcode ("","%05d$:",lbl->key+100);
4691                         emitcode ("mov","mb,b");
4692                         emitcode ("mov","mb,a");
4693                 }
4694         } else {
4695                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4696                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4697         }
4698
4699         /* wait for multiplication to finish */
4700         lbl = newiTempLabel(NULL);
4701         emitcode("","%05d$:", lbl->key+100);
4702         emitcode("mov","a,mcnt1");
4703         emitcode("anl","a,#0x80");
4704         emitcode("jnz","%05d$",lbl->key+100);
4705         
4706         freeAsmop (left, NULL, ic, TRUE);
4707         freeAsmop (right, NULL, ic,TRUE);
4708         aopOp(result, ic, TRUE, FALSE);
4709
4710         aopPut(AOP(result),"mb",1);
4711         aopPut(AOP(result),"mb",0);
4712         freeAsmop (result, NULL, ic, TRUE);
4713         return ;
4714 }
4715
4716 /*-----------------------------------------------------------------*/
4717 /* genMod - generates code for division                            */
4718 /*-----------------------------------------------------------------*/
4719 static void
4720 genMod (iCode * ic)
4721 {
4722   operand *left = IC_LEFT (ic);
4723   operand *right = IC_RIGHT (ic);
4724   operand *result = IC_RESULT (ic);
4725
4726   D (emitcode (";", "genMod "); );
4727
4728   /* assign the amsops */
4729   AOP_OP_2 (ic);
4730
4731   /* special cases first */
4732   /* both are bits */
4733   if (AOP_TYPE (left) == AOP_CRY &&
4734       AOP_TYPE (right) == AOP_CRY)
4735     {
4736       genModbits (left, right, result, ic);
4737       goto release;
4738     }
4739
4740   /* if both are of size == 1 */
4741   if (AOP_SIZE (left) == 1 &&
4742       AOP_SIZE (right) == 1)
4743     {
4744       genModOneByte (left, right, result, ic);
4745       goto release;
4746     }
4747
4748   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4749           /* use the ds390 ARITHMETIC accel UNIT */
4750           genModTwoByte (left, right, result, ic);
4751           return ;
4752   }
4753
4754   /* should have been converted to function call */
4755   assert (0);
4756
4757 release:
4758   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4759   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4760   freeAsmop (result, NULL, ic, TRUE);
4761 }
4762
4763 /*-----------------------------------------------------------------*/
4764 /* genIfxJump :- will create a jump depending on the ifx           */
4765 /*-----------------------------------------------------------------*/
4766 static void
4767 genIfxJump (iCode * ic, char *jval)
4768 {
4769   symbol *jlbl;
4770   symbol *tlbl = newiTempLabel (NULL);
4771   char *inst;
4772
4773   D (emitcode (";", "genIfxJump ");
4774     );
4775
4776   /* if true label then we jump if condition
4777      supplied is true */
4778   if (IC_TRUE (ic))
4779     {
4780       jlbl = IC_TRUE (ic);
4781       inst = ((strcmp (jval, "a") == 0 ? "jz" :
4782                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4783     }
4784   else
4785     {
4786       /* false label is present */
4787       jlbl = IC_FALSE (ic);
4788       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4789                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4790     }
4791   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4792     emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4793   else
4794     emitcode (inst, "%05d$", tlbl->key + 100);
4795   emitcode ("ljmp", "%05d$", jlbl->key + 100);
4796   emitcode ("", "%05d$:", tlbl->key + 100);
4797
4798   /* mark the icode as generated */
4799   ic->generated = 1;
4800 }
4801
4802 /*-----------------------------------------------------------------*/
4803 /* genCmp :- greater or less than comparison                       */
4804 /*-----------------------------------------------------------------*/
4805 static void
4806 genCmp (operand * left, operand * right,
4807         iCode * ic, iCode * ifx, int sign)
4808 {
4809   int size, offset = 0;
4810   unsigned long lit = 0L;
4811   operand *result;
4812
4813   D (emitcode (";", "genCmp");
4814     );
4815
4816   result = IC_RESULT (ic);
4817
4818   /* if left & right are bit variables */
4819   if (AOP_TYPE (left) == AOP_CRY &&
4820       AOP_TYPE (right) == AOP_CRY)
4821     {
4822       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4823       emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
4824     }
4825   else
4826     {
4827       /* subtract right from left if at the
4828          end the carry flag is set then we know that
4829          left is greater than right */
4830       size = max (AOP_SIZE (left), AOP_SIZE (right));
4831
4832       /* if unsigned char cmp with lit, do cjne left,#right,zz */
4833       if ((size == 1) && !sign &&
4834           (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4835         {
4836           symbol *lbl = newiTempLabel (NULL);
4837           emitcode ("cjne", "%s,%s,%05d$",
4838                     aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
4839                     aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4840                     lbl->key + 100);
4841           emitcode ("", "%05d$:", lbl->key + 100);
4842         }
4843       else
4844         {
4845           if (AOP_TYPE (right) == AOP_LIT)
4846             {
4847               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4848               /* optimize if(x < 0) or if(x >= 0) */
4849               if (lit == 0L)
4850                 {
4851                   if (!sign)
4852                     {
4853                       CLRC;
4854                     }
4855                   else
4856                     {
4857                       MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
4858
4859                       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4860                       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4861
4862                       aopOp (result, ic, FALSE, FALSE);
4863
4864                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4865                         {
4866                           freeAsmop (result, NULL, ic, TRUE);
4867                           genIfxJump (ifx, "acc.7");
4868                           return;
4869                         }
4870                       else
4871                         {
4872                           emitcode ("rlc", "a");
4873                         }
4874                       goto release_freedLR;
4875                     }
4876                   goto release;
4877                 }
4878             }
4879           CLRC;
4880           while (size--)
4881             {
4882               emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
4883               MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4884               emitcode (";", "genCmp #2");
4885               if (sign && (size == 0))
4886                 {
4887                   emitcode (";", "genCmp #3");
4888                   emitcode ("xrl", "a,#0x80");
4889                   if (AOP_TYPE (right) == AOP_LIT)
4890                     {
4891                       unsigned long lit = (unsigned long)
4892                       floatFromVal (AOP (right)->aopu.aop_lit);
4893                       emitcode (";", "genCmp #3.1");
4894                       emitcode ("subb", "a,#0x%02x",
4895                                 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4896                     }
4897                   else
4898                     {
4899                       emitcode (";", "genCmp #3.2");
4900                       if (AOP_NEEDSACC (right))
4901                         {
4902                           emitcode ("push", "acc");
4903                         }
4904                       emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
4905                                                        FALSE, FALSE, FALSE));
4906                       emitcode ("xrl", "b,#0x80");
4907                       if (AOP_NEEDSACC (right))
4908                         {
4909                           emitcode ("pop", "acc");
4910                         }
4911                       emitcode ("subb", "a,b");
4912                     }
4913                 }
4914               else
4915                 {
4916                   const char *s;
4917
4918                   emitcode (";", "genCmp #4");
4919                   if (AOP_NEEDSACC (right))
4920                     {
4921                       /* Yuck!! */
4922                       emitcode (";", "genCmp #4.1");
4923                       emitcode ("xch", "a, b");
4924                       MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
4925                       emitcode ("xch", "a, b");
4926                       s = "b";
4927                     }
4928                   else
4929                     {
4930                       emitcode (";", "genCmp #4.2");
4931                       s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
4932                     }
4933
4934                   emitcode ("subb", "a,%s", s);
4935                 }
4936             }
4937         }
4938     }
4939
4940 release:
4941 /* Don't need the left & right operands any more; do need the result. */
4942   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4943   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4944
4945   aopOp (result, ic, FALSE, FALSE);
4946
4947 release_freedLR:
4948
4949   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4950     {
4951       outBitC (result);
4952     }
4953   else
4954     {
4955       /* if the result is used in the next
4956          ifx conditional branch then generate
4957          code a little differently */
4958       if (ifx)
4959         {
4960           genIfxJump (ifx, "c");
4961         }
4962       else
4963         {
4964           outBitC (result);
4965         }
4966       /* leave the result in acc */
4967     }
4968   freeAsmop (result, NULL, ic, TRUE);
4969 }
4970
4971 /*-----------------------------------------------------------------*/
4972 /* genCmpGt :- greater than comparison                             */
4973 /*-----------------------------------------------------------------*/
4974 static void
4975 genCmpGt (iCode * ic, iCode * ifx)
4976 {
4977   operand *left, *right;
4978   sym_link *letype, *retype;
4979   int sign;
4980
4981   D (emitcode (";", "genCmpGt ");
4982     );
4983
4984   left = IC_LEFT (ic);
4985   right = IC_RIGHT (ic);
4986
4987   letype = getSpec (operandType (left));
4988   retype = getSpec (operandType (right));
4989   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4990
4991   /* assign the left & right amsops */
4992   AOP_OP_2 (ic);
4993
4994   genCmp (right, left, ic, ifx, sign);
4995 }
4996
4997 /*-----------------------------------------------------------------*/
4998 /* genCmpLt - less than comparisons                                */
4999 /*-----------------------------------------------------------------*/
5000 static void
5001 genCmpLt (iCode * ic, iCode * ifx)
5002 {
5003   operand *left, *right;
5004   sym_link *letype, *retype;
5005   int sign;
5006
5007   D (emitcode (";", "genCmpLt "););
5008
5009   left = IC_LEFT (ic);
5010   right = IC_RIGHT (ic);
5011
5012   letype = getSpec (operandType (left));
5013   retype = getSpec (operandType (right));
5014   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5015
5016   /* assign the left & right amsops */
5017   AOP_OP_2 (ic);
5018
5019   genCmp (left, right, ic, ifx, sign);
5020 }
5021
5022 /*-----------------------------------------------------------------*/
5023 /* gencjneshort - compare and jump if not equal                    */
5024 /*-----------------------------------------------------------------*/
5025 static void
5026 gencjneshort (operand * left, operand * right, symbol * lbl)
5027 {
5028   int size = max (AOP_SIZE (left), AOP_SIZE (right));
5029   int offset = 0;
5030   unsigned long lit = 0L;
5031
5032   D (emitcode (";", "gencjneshort");
5033     );
5034
5035   /* if the left side is a literal or
5036      if the right is in a pointer register and left
5037      is not */
5038   if ((AOP_TYPE (left) == AOP_LIT) ||
5039       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5040     {
5041       operand *t = right;
5042       right = left;
5043       left = t;
5044     }
5045
5046   if (AOP_TYPE (right) == AOP_LIT)
5047     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5048
5049   if (opIsGptr (left) || opIsGptr (right))
5050     {
5051       /* We are comparing a generic pointer to something.
5052        * Exclude the generic type byte from the comparison.
5053        */
5054       size--;
5055       D (emitcode (";", "cjneshort: generic ptr special case.");
5056         )
5057     }
5058
5059
5060   /* if the right side is a literal then anything goes */
5061   if (AOP_TYPE (right) == AOP_LIT &&
5062       AOP_TYPE (left) != AOP_DIR)
5063     {
5064       while (size--)
5065         {
5066           char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5067           MOVA (l);
5068           emitcode ("cjne", "a,%s,%05d$",
5069                     aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
5070                     lbl->key + 100);
5071           offset++;
5072         }
5073     }
5074
5075   /* if the right side is in a register or in direct space or
5076      if the left is a pointer register & right is not */
5077   else if (AOP_TYPE (right) == AOP_REG ||
5078            AOP_TYPE (right) == AOP_DIR ||
5079            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5080            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5081     {
5082       while (size--)
5083         {
5084           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5085           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5086               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5087             emitcode ("jnz", "%05d$", lbl->key + 100);
5088           else
5089             emitcode ("cjne", "a,%s,%05d$",
5090                       aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
5091                       lbl->key + 100);
5092           offset++;
5093         }
5094     }
5095   else
5096     {
5097       /* right is a pointer reg need both a & b */
5098       while (size--)
5099         {
5100           char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5101           if (strcmp (l, "b"))
5102             emitcode ("mov", "b,%s", l);
5103           MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5104           emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
5105           offset++;
5106         }
5107     }
5108 }
5109
5110 /*-----------------------------------------------------------------*/
5111 /* gencjne - compare and jump if not equal                         */
5112 /*-----------------------------------------------------------------*/
5113 static void
5114 gencjne (operand * left, operand * right, symbol * lbl)
5115 {
5116   symbol *tlbl = newiTempLabel (NULL);
5117
5118   D (emitcode (";", "gencjne");
5119     );
5120
5121   gencjneshort (left, right, lbl);
5122
5123   emitcode ("mov", "a,%s", one);
5124   emitcode ("sjmp", "%05d$", tlbl->key + 100);
5125   emitcode ("", "%05d$:", lbl->key + 100);
5126   emitcode ("clr", "a");
5127   emitcode ("", "%05d$:", tlbl->key + 100);
5128 }
5129
5130 /*-----------------------------------------------------------------*/
5131 /* genCmpEq - generates code for equal to                          */
5132 /*-----------------------------------------------------------------*/
5133 static void
5134 genCmpEq (iCode * ic, iCode * ifx)
5135 {
5136   operand *left, *right, *result;
5137
5138   D (emitcode (";", "genCmpEq ");
5139     );
5140
5141   AOP_OP_2 (ic);
5142   AOP_SET_LOCALS (ic);
5143
5144   /* if literal, literal on the right or
5145      if the right is in a pointer register and left
5146      is not */
5147   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5148       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5149     {
5150       operand *t = IC_RIGHT (ic);
5151       IC_RIGHT (ic) = IC_LEFT (ic);
5152       IC_LEFT (ic) = t;
5153     }
5154
5155   if (ifx &&                    /* !AOP_SIZE(result) */
5156       OP_SYMBOL (result) &&
5157       OP_SYMBOL (result)->regType == REG_CND)
5158     {
5159       symbol *tlbl;
5160       /* if they are both bit variables */
5161       if (AOP_TYPE (left) == AOP_CRY &&
5162           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5163         {
5164           if (AOP_TYPE (right) == AOP_LIT)
5165             {
5166               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5167               if (lit == 0L)
5168                 {
5169                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5170                   emitcode ("cpl", "c");
5171                 }
5172               else if (lit == 1L)
5173                 {
5174                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5175                 }
5176               else
5177                 {
5178                   emitcode ("clr", "c");
5179                 }
5180               /* AOP_TYPE(right) == AOP_CRY */
5181             }
5182           else
5183             {
5184               symbol *lbl = newiTempLabel (NULL);
5185               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5186               emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5187               emitcode ("cpl", "c");
5188               emitcode ("", "%05d$:", (lbl->key + 100));
5189             }
5190           /* if true label then we jump if condition
5191              supplied is true */
5192           tlbl = newiTempLabel (NULL);
5193           if (IC_TRUE (ifx))
5194             {
5195               emitcode ("jnc", "%05d$", tlbl->key + 100);
5196               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5197             }
5198           else
5199             {
5200               emitcode ("jc", "%05d$", tlbl->key + 100);
5201               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5202             }
5203           emitcode ("", "%05d$:", tlbl->key + 100);
5204         }
5205       else
5206         {
5207           tlbl = newiTempLabel (NULL);
5208           gencjneshort (left, right, tlbl);
5209           if (IC_TRUE (ifx))
5210             {
5211               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5212               emitcode ("", "%05d$:", tlbl->key + 100);
5213             }
5214           else
5215             {
5216               symbol *lbl = newiTempLabel (NULL);
5217               emitcode ("sjmp", "%05d$", lbl->key + 100);
5218               emitcode ("", "%05d$:", tlbl->key + 100);
5219               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5220               emitcode ("", "%05d$:", lbl->key + 100);
5221             }
5222         }
5223       /* mark the icode as generated */
5224       ifx->generated = 1;
5225
5226       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5227       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5228       return;
5229     }
5230
5231   /* if they are both bit variables */
5232   if (AOP_TYPE (left) == AOP_CRY &&
5233       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5234     {
5235       if (AOP_TYPE (right) == AOP_LIT)
5236         {
5237           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5238           if (lit == 0L)
5239             {
5240               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5241               emitcode ("cpl", "c");
5242             }
5243           else if (lit == 1L)
5244             {
5245               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5246             }
5247           else
5248             {
5249               emitcode ("clr", "c");
5250             }
5251           /* AOP_TYPE(right) == AOP_CRY */
5252         }
5253       else
5254         {
5255           symbol *lbl = newiTempLabel (NULL);
5256           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5257           emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5258           emitcode ("cpl", "c");
5259           emitcode ("", "%05d$:", (lbl->key + 100));
5260         }
5261
5262       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5263       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5264
5265       aopOp (result, ic, TRUE, FALSE);
5266
5267       /* c = 1 if egal */
5268       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5269         {
5270           outBitC (result);
5271           goto release;
5272         }
5273       if (ifx)
5274         {
5275           genIfxJump (ifx, "c");
5276           goto release;
5277         }
5278       /* if the result is used in an arithmetic operation
5279          then put the result in place */
5280       outBitC (result);
5281     }
5282   else
5283     {
5284       gencjne (left, right, newiTempLabel (NULL));
5285
5286       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5287       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5288
5289       aopOp (result, ic, TRUE, FALSE);
5290
5291       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5292         {
5293           aopPut (AOP (result), "a", 0);
5294           goto release;
5295         }
5296       if (ifx)
5297         {
5298           genIfxJump (ifx, "a");
5299           goto release;
5300         }
5301       /* if the result is used in an arithmetic operation
5302          then put the result in place */
5303       if (AOP_TYPE (result) != AOP_CRY)
5304         outAcc (result);
5305       /* leave the result in acc */
5306     }
5307
5308 release:
5309   freeAsmop (result, NULL, ic, TRUE);
5310 }
5311
5312 /*-----------------------------------------------------------------*/
5313 /* ifxForOp - returns the icode containing the ifx for operand     */
5314 /*-----------------------------------------------------------------*/
5315 static iCode *
5316 ifxForOp (operand * op, iCode * ic)
5317 {
5318   /* if true symbol then needs to be assigned */
5319   if (IS_TRUE_SYMOP (op))
5320     return NULL;
5321
5322   /* if this has register type condition and
5323      the next instruction is ifx with the same operand
5324      and live to of the operand is upto the ifx only then */
5325   if (ic->next &&
5326       ic->next->op == IFX &&
5327       IC_COND (ic->next)->key == op->key &&
5328       OP_SYMBOL (op)->liveTo <= ic->next->seq)
5329     return ic->next;
5330
5331   return NULL;
5332 }
5333 /*-----------------------------------------------------------------*/
5334 /* genAndOp - for && operation                                     */
5335 /*-----------------------------------------------------------------*/
5336 static void
5337 genAndOp (iCode * ic)
5338 {
5339   operand *left, *right, *result;
5340   symbol *tlbl;
5341
5342   D (emitcode (";", "genAndOp "););
5343
5344   /* note here that && operations that are in an
5345      if statement are taken away by backPatchLabels
5346      only those used in arthmetic operations remain */
5347   AOP_OP_2 (ic);
5348   AOP_SET_LOCALS (ic);
5349
5350   /* if both are bit variables */
5351   if (AOP_TYPE (left) == AOP_CRY &&
5352       AOP_TYPE (right) == AOP_CRY)
5353     {
5354       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5355       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5356       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5357       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5358   
5359       aopOp (result,ic,FALSE, FALSE);
5360       outBitC (result);
5361     }
5362   else
5363     {
5364       tlbl = newiTempLabel (NULL);
5365       toBoolean (left);
5366       emitcode ("jz", "%05d$", tlbl->key + 100);
5367       toBoolean (right);
5368       emitcode ("", "%05d$:", tlbl->key + 100);
5369       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5370       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5371   
5372       aopOp (result,ic,FALSE, FALSE);
5373       outBitAcc (result);
5374     }
5375     freeAsmop (result, NULL, ic, TRUE);
5376 }
5377
5378
5379 /*-----------------------------------------------------------------*/
5380 /* genOrOp - for || operation                                      */
5381 /*-----------------------------------------------------------------*/
5382 static void
5383 genOrOp (iCode * ic)
5384 {
5385   operand *left, *right, *result;
5386   symbol *tlbl;
5387
5388   D (emitcode (";", "genOrOp "););
5389
5390   /* note here that || operations that are in an
5391      if statement are taken away by backPatchLabels
5392      only those used in arthmetic operations remain */
5393   AOP_OP_2 (ic);
5394   AOP_SET_LOCALS (ic);
5395
5396   /* if both are bit variables */
5397   if (AOP_TYPE (left) == AOP_CRY &&
5398       AOP_TYPE (right) == AOP_CRY)
5399     {
5400       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5401       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5402       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5403       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5404   
5405       aopOp (result,ic,FALSE, FALSE);
5406       
5407       outBitC (result);
5408     }
5409   else
5410     {
5411       tlbl = newiTempLabel (NULL);
5412       toBoolean (left);
5413       emitcode ("jnz", "%05d$", tlbl->key + 100);
5414       toBoolean (right);
5415       emitcode ("", "%05d$:", tlbl->key + 100);
5416       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5417       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5418   
5419       aopOp (result,ic,FALSE, FALSE);
5420       
5421       outBitAcc (result);
5422     }
5423
5424   freeAsmop (result, NULL, ic, TRUE);
5425 }
5426
5427 /*-----------------------------------------------------------------*/
5428 /* isLiteralBit - test if lit == 2^n                               */
5429 /*-----------------------------------------------------------------*/
5430 static int
5431 isLiteralBit (unsigned long lit)
5432 {
5433   unsigned long pw[32] =
5434   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5435    0x100L, 0x200L, 0x400L, 0x800L,
5436    0x1000L, 0x2000L, 0x4000L, 0x8000L,
5437    0x10000L, 0x20000L, 0x40000L, 0x80000L,
5438    0x100000L, 0x200000L, 0x400000L, 0x800000L,
5439    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5440    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5441   int idx;
5442
5443   for (idx = 0; idx < 32; idx++)
5444     if (lit == pw[idx])
5445       return idx + 1;
5446   return 0;
5447 }
5448
5449 /*-----------------------------------------------------------------*/
5450 /* continueIfTrue -                                                */
5451 /*-----------------------------------------------------------------*/
5452 static void
5453 continueIfTrue (iCode * ic)
5454 {
5455   if (IC_TRUE (ic))
5456     emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5457   ic->generated = 1;
5458 }
5459
5460 /*-----------------------------------------------------------------*/
5461 /* jmpIfTrue -                                                     */
5462 /*-----------------------------------------------------------------*/
5463 static void
5464 jumpIfTrue (iCode * ic)
5465 {
5466   if (!IC_TRUE (ic))
5467     emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5468   ic->generated = 1;
5469 }
5470
5471 /*-----------------------------------------------------------------*/
5472 /* jmpTrueOrFalse -                                                */
5473 /*-----------------------------------------------------------------*/
5474 static void
5475 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
5476 {
5477   // ugly but optimized by peephole
5478   if (IC_TRUE (ic))
5479     {
5480       symbol *nlbl = newiTempLabel (NULL);
5481       emitcode ("sjmp", "%05d$", nlbl->key + 100);
5482       emitcode ("", "%05d$:", tlbl->key + 100);
5483       emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5484       emitcode ("", "%05d$:", nlbl->key + 100);
5485     }
5486   else
5487     {
5488       emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5489       emitcode ("", "%05d$:", tlbl->key + 100);
5490     }
5491   ic->generated = 1;
5492 }
5493
5494 // Generate code to perform a bit-wise logic operation
5495 // on two operands in far space (assumed to already have been 
5496 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
5497 // in far space. This requires pushing the result on the stack
5498 // then popping it into the result.
5499 static void
5500 genFarFarLogicOp(iCode *ic, char *logicOp)
5501 {
5502       int size, resultSize, compSize;
5503       int offset = 0;
5504       
5505       TR_AP("#5");
5506       D(emitcode(";", "%s special case for 3 far operands.", logicOp););
5507       compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ? 
5508                   AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
5509       
5510       _startLazyDPSEvaluation();
5511       for (size = compSize; (size--); offset++)
5512       {
5513           MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
5514           emitcode ("mov", "%s, acc", DP2_RESULT_REG);
5515           MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
5516           
5517           emitcode (logicOp, "a,%s", DP2_RESULT_REG);
5518           emitcode ("push", "acc");
5519       }
5520       _endLazyDPSEvaluation();
5521      
5522       freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5523       freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5524       aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
5525      
5526       resultSize = AOP_SIZE(IC_RESULT(ic));
5527
5528       ADJUST_PUSHED_RESULT(compSize, resultSize);
5529
5530       _startLazyDPSEvaluation();
5531       while (compSize--)
5532       {
5533           emitcode ("pop", "acc");
5534           aopPut (AOP (IC_RESULT (ic)), "a", compSize);
5535       }
5536       _endLazyDPSEvaluation();
5537       freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
5538 }
5539
5540
5541 /*-----------------------------------------------------------------*/
5542 /* genAnd  - code for and                                          */
5543 /*-----------------------------------------------------------------*/
5544 static void
5545 genAnd (iCode * ic, iCode * ifx)
5546 {
5547   operand *left, *right, *result;
5548   int size, offset = 0;
5549   unsigned long lit = 0L;
5550   int bytelit = 0;
5551   char buffer[10];
5552   bool pushResult;
5553
5554   D (emitcode (";", "genAnd "););
5555
5556   AOP_OP_3_NOFATAL (ic, pushResult);
5557   AOP_SET_LOCALS (ic);
5558
5559   if (pushResult)
5560   {
5561       genFarFarLogicOp(ic, "anl");
5562       return;
5563   }  
5564
5565 #ifdef DEBUG_TYPE
5566   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5567             AOP_TYPE (result),
5568             AOP_TYPE (left), AOP_TYPE (right));
5569   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5570             AOP_SIZE (result),
5571             AOP_SIZE (left), AOP_SIZE (right));
5572 #endif
5573
5574   /* if left is a literal & right is not then exchange them */
5575   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5576 #ifdef LOGIC_OPS_BROKEN      
5577     ||  AOP_NEEDSACC (left)
5578 #endif
5579     )
5580     {
5581       operand *tmp = right;
5582       right = left;
5583       left = tmp;
5584     }
5585
5586   /* if result = right then exchange them */
5587   if (sameRegs (AOP (result), AOP (right)))
5588     {
5589       operand *tmp = right;
5590       right = left;
5591       left = tmp;
5592     }
5593
5594   /* if right is bit then exchange them */
5595   if (AOP_TYPE (right) == AOP_CRY &&
5596       AOP_TYPE (left) != AOP_CRY)
5597     {
5598       operand *tmp = right;
5599       right = left;
5600       left = tmp;
5601     }
5602   if (AOP_TYPE (right) == AOP_LIT)
5603     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5604
5605   size = AOP_SIZE (result);
5606
5607   // if(bit & yy)
5608   // result = bit & yy;
5609   if (AOP_TYPE (left) == AOP_CRY)
5610     {
5611       // c = bit & literal;
5612       if (AOP_TYPE (right) == AOP_LIT)
5613         {
5614           if (lit & 1)
5615             {
5616               if (size && sameRegs (AOP (result), AOP (left)))
5617                 // no change
5618                 goto release;
5619               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5620             }
5621           else
5622             {
5623               // bit(result) = 0;
5624               if (size && (AOP_TYPE (result) == AOP_CRY))
5625                 {
5626                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5627                   goto release;
5628                 }
5629               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5630                 {
5631                   jumpIfTrue (ifx);
5632                   goto release;
5633                 }
5634               emitcode ("clr", "c");
5635             }
5636         }
5637       else
5638         {
5639           if (AOP_TYPE (right) == AOP_CRY)
5640             {
5641               // c = bit & bit;
5642               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5643               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5644             }
5645           else
5646             {
5647               // c = bit & val;
5648               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
5649               // c = lsb
5650               emitcode ("rrc", "a");
5651               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5652             }
5653         }
5654       // bit = c
5655       // val = c
5656       if (size)
5657         outBitC (result);
5658       // if(bit & ...)
5659       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5660         genIfxJump (ifx, "c");
5661       goto release;
5662     }
5663
5664   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5665   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5666   if ((AOP_TYPE (right) == AOP_LIT) &&
5667       (AOP_TYPE (result) == AOP_CRY) &&
5668       (AOP_TYPE (left) != AOP_CRY))
5669     {
5670       int posbit = isLiteralBit (lit);
5671       /* left &  2^n */
5672       if (posbit)
5673         {
5674           posbit--;
5675           MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
5676           // bit = left & 2^n
5677           if (size)
5678             emitcode ("mov", "c,acc.%d", posbit & 0x07);
5679           // if(left &  2^n)
5680           else
5681             {
5682               if (ifx)
5683                 {
5684                   sprintf (buffer, "acc.%d", posbit & 0x07);
5685                   genIfxJump (ifx, buffer);
5686                 }
5687               goto release;
5688             }
5689         }
5690       else
5691         {
5692           symbol *tlbl = newiTempLabel (NULL);
5693           int sizel = AOP_SIZE (left);
5694           if (size)
5695             emitcode ("setb", "c");
5696           while (sizel--)
5697             {
5698               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5699                 {
5700                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5701                   // byte ==  2^n ?
5702                   if ((posbit = isLiteralBit (bytelit)) != 0)
5703                     emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5704                   else
5705                     {
5706                       if (bytelit != 0x0FFL)
5707                         emitcode ("anl", "a,%s",
5708                           aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
5709                       emitcode ("jnz", "%05d$", tlbl->key + 100);
5710                     }
5711                 }
5712               offset++;
5713             }
5714           // bit = left & literal
5715           if (size)
5716             {
5717               emitcode ("clr", "c");
5718               emitcode ("", "%05d$:", tlbl->key + 100);
5719             }
5720           // if(left & literal)
5721           else
5722             {
5723               if (ifx)
5724                 jmpTrueOrFalse (ifx, tlbl);
5725               goto release;
5726             }
5727         }
5728       outBitC (result);
5729       goto release;
5730     }
5731
5732   /* if left is same as result */
5733   if (sameRegs (AOP (result), AOP (left)))
5734     {
5735       for (; size--; offset++)
5736         {
5737           if (AOP_TYPE (right) == AOP_LIT)
5738             {
5739               if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5740                 continue;
5741               else if (bytelit == 0)
5742                 aopPut (AOP (result), zero, offset);
5743               else if (IS_AOP_PREG (result))
5744                 {
5745                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5746                   emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5747                   aopPut (AOP (result), "a", offset);
5748                 }
5749               else
5750                 emitcode ("anl", "%s,%s",
5751                           aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5752                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5753             }
5754           else
5755             {
5756               if (AOP_TYPE (left) == AOP_ACC)
5757                 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5758               else
5759                 {
5760                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5761                   if (IS_AOP_PREG (result))
5762                     {
5763                       emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5764                       aopPut (AOP (result), "a", offset);
5765
5766                     }
5767                   else
5768                     emitcode ("anl", "%s,a",
5769                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5770                 }
5771             }
5772         }
5773     }
5774   else
5775     {
5776       // left & result in different registers
5777       if (AOP_TYPE (result) == AOP_CRY)
5778         {
5779           // result = bit
5780           // if(size), result in bit
5781           // if(!size && ifx), conditional oper: if(left & right)
5782           symbol *tlbl = newiTempLabel (NULL);
5783           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5784           if (size)
5785             emitcode ("setb", "c");
5786           while (sizer--)
5787             {
5788               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5789                 emitcode ("anl", "a,%s",
5790                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5791               } else {
5792                 if (AOP_TYPE(left)==AOP_ACC) {
5793                   emitcode("mov", "b,a");
5794                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5795                   emitcode("anl", "a,b");
5796                 }else {
5797                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5798                   emitcode ("anl", "a,%s",
5799                             aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5800                 }
5801               }
5802               emitcode ("jnz", "%05d$", tlbl->key + 100);
5803               offset++;
5804             }
5805           if (size)
5806             {
5807               CLRC;
5808               emitcode ("", "%05d$:", tlbl->key + 100);
5809               outBitC (result);
5810             }
5811           else if (ifx)
5812             jmpTrueOrFalse (ifx, tlbl);
5813         }
5814       else
5815         {
5816           for (; (size--); offset++)
5817             {
5818               // normal case
5819               // result = left & right
5820               if (AOP_TYPE (right) == AOP_LIT)
5821                 {
5822                   if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5823                     {
5824                       aopPut (AOP (result),
5825                            aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5826                               offset);
5827                       continue;
5828                     }
5829                   else if (bytelit == 0)
5830                     {
5831                       aopPut (AOP (result), zero, offset);
5832                       continue;
5833                     }
5834                   D (emitcode (";", "better literal AND."););
5835                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5836                   emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
5837                                                     FALSE, FALSE, FALSE));
5838
5839                 }
5840               else
5841                 {
5842                   // faster than result <- left, anl result,right
5843                   // and better if result is SFR
5844                   if (AOP_TYPE (left) == AOP_ACC)
5845                     {
5846                       emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
5847                                                        FALSE, FALSE, FALSE));
5848                     }
5849                   else
5850                     {
5851                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
5852                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
5853                       {
5854                           emitcode("mov", "b,a");
5855                           rOp = "b";
5856                       }
5857                         
5858                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5859                       emitcode ("anl", "a,%s", rOp);
5860                     }                   
5861                 }
5862               aopPut (AOP (result), "a", offset);
5863             }
5864         }
5865     }
5866
5867 release:
5868   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5869   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5870   freeAsmop (result, NULL, ic, TRUE);
5871 }
5872
5873
5874 /*-----------------------------------------------------------------*/
5875 /* genOr  - code for or                                            */
5876 /*-----------------------------------------------------------------*/
5877 static void
5878 genOr (iCode * ic, iCode * ifx)
5879 {
5880   operand *left, *right, *result;
5881   int size, offset = 0;
5882   unsigned long lit = 0L;
5883   bool     pushResult;
5884
5885   D (emitcode (";", "genOr "););
5886
5887   AOP_OP_3_NOFATAL (ic, pushResult);
5888   AOP_SET_LOCALS (ic);
5889
5890   if (pushResult)
5891   {
5892       genFarFarLogicOp(ic, "orl");
5893       return;
5894   }
5895
5896
5897 #ifdef DEBUG_TYPE
5898   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5899             AOP_TYPE (result),
5900             AOP_TYPE (left), AOP_TYPE (right));
5901   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5902             AOP_SIZE (result),
5903             AOP_SIZE (left), AOP_SIZE (right));
5904 #endif
5905
5906   /* if left is a literal & right is not then exchange them */
5907   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5908 #ifdef LOGIC_OPS_BROKEN
5909    || AOP_NEEDSACC (left) // I think this is a net loss now.
5910 #endif      
5911       )
5912     {
5913       operand *tmp = right;
5914       right = left;
5915       left = tmp;
5916     }
5917
5918   /* if result = right then exchange them */
5919   if (sameRegs (AOP (result), AOP (right)))
5920     {
5921       operand *tmp = right;
5922       right = left;
5923       left = tmp;
5924     }
5925
5926   /* if right is bit then exchange them */
5927   if (AOP_TYPE (right) == AOP_CRY &&
5928       AOP_TYPE (left) != AOP_CRY)
5929     {
5930       operand *tmp = right;
5931       right = left;
5932       left = tmp;
5933     }
5934   if (AOP_TYPE (right) == AOP_LIT)
5935     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5936
5937   size = AOP_SIZE (result);
5938
5939   // if(bit | yy)
5940   // xx = bit | yy;
5941   if (AOP_TYPE (left) == AOP_CRY)
5942     {
5943       if (AOP_TYPE (right) == AOP_LIT)
5944         {
5945           // c = bit & literal;
5946           if (lit)
5947             {
5948               // lit != 0 => result = 1
5949               if (AOP_TYPE (result) == AOP_CRY)
5950                 {
5951                   if (size)
5952                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5953                   else if (ifx)
5954                     continueIfTrue (ifx);
5955                   goto release;
5956                 }
5957               emitcode ("setb", "c");
5958             }
5959           else
5960             {
5961               // lit == 0 => result = left
5962               if (size && sameRegs (AOP (result), AOP (left)))
5963                 goto release;
5964               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5965             }
5966         }
5967       else
5968         {
5969           if (AOP_TYPE (right) == AOP_CRY)
5970             {
5971               // c = bit | bit;
5972               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5973               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5974             }
5975           else
5976             {
5977               // c = bit | val;
5978               symbol *tlbl = newiTempLabel (NULL);
5979               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5980                 emitcode ("setb", "c");
5981               emitcode ("jb", "%s,%05d$",
5982                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
5983               toBoolean (right);
5984               emitcode ("jnz", "%05d$", tlbl->key + 100);
5985               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5986                 {
5987                   jmpTrueOrFalse (ifx, tlbl);
5988                   goto release;
5989                 }
5990               else
5991                 {
5992                   CLRC;
5993                   emitcode ("", "%05d$:", tlbl->key + 100);
5994                 }
5995             }
5996         }
5997       // bit = c
5998       // val = c
5999       if (size)
6000         outBitC (result);
6001       // if(bit | ...)
6002       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6003         genIfxJump (ifx, "c");
6004       goto release;
6005     }
6006
6007   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6008   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6009   if ((AOP_TYPE (right) == AOP_LIT) &&
6010       (AOP_TYPE (result) == AOP_CRY) &&
6011       (AOP_TYPE (left) != AOP_CRY))
6012     {
6013       if (lit)
6014         {
6015           // result = 1
6016           if (size)
6017             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6018           else
6019             continueIfTrue (ifx);
6020           goto release;
6021         }
6022       else
6023         {
6024           // lit = 0, result = boolean(left)
6025           if (size)
6026             emitcode ("setb", "c");
6027           toBoolean (right);
6028           if (size)
6029             {
6030               symbol *tlbl = newiTempLabel (NULL);
6031               emitcode ("jnz", "%05d$", tlbl->key + 100);
6032               CLRC;
6033               emitcode ("", "%05d$:", tlbl->key + 100);
6034             }
6035           else
6036             {
6037               genIfxJump (ifx, "a");
6038               goto release;
6039             }
6040         }
6041       outBitC (result);
6042       goto release;
6043     }
6044
6045   /* if left is same as result */
6046   if (sameRegs (AOP (result), AOP (left)))
6047     {
6048       for (; size--; offset++)
6049         {
6050           if (AOP_TYPE (right) == AOP_LIT)
6051             {
6052               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6053                 {
6054                   continue;
6055                 }
6056               else
6057                 {
6058                   if (IS_AOP_PREG (left))
6059                     {
6060                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6061                       emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6062                       aopPut (AOP (result), "a", offset);
6063                     }
6064                   else
6065                     {
6066                       emitcode ("orl", "%s,%s",
6067                             aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6068                          aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6069                     }
6070                 }
6071             }
6072           else
6073             {
6074               if (AOP_TYPE (left) == AOP_ACC)
6075                 {
6076                   emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6077                 }
6078               else
6079                 {
6080                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6081                   if (IS_AOP_PREG (left))
6082                     {
6083                       emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6084                       aopPut (AOP (result), "a", offset);
6085                     }
6086                   else
6087                     {
6088                       emitcode ("orl", "%s,a",
6089                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6090                     }
6091                 }
6092             }
6093         }
6094     }
6095   else
6096     {
6097       // left & result in different registers
6098       if (AOP_TYPE (result) == AOP_CRY)
6099         {
6100           // result = bit
6101           // if(size), result in bit
6102           // if(!size && ifx), conditional oper: if(left | right)
6103           symbol *tlbl = newiTempLabel (NULL);
6104           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6105           if (size)
6106             emitcode ("setb", "c");
6107           while (sizer--)
6108             {
6109               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6110                 emitcode ("orl", "a,%s",
6111                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6112               } else {
6113                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6114                 emitcode ("orl", "a,%s",
6115                           aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6116               }
6117               emitcode ("jnz", "%05d$", tlbl->key + 100);
6118               offset++;
6119             }
6120           if (size)
6121             {
6122               CLRC;
6123               emitcode ("", "%05d$:", tlbl->key + 100);
6124               outBitC (result);
6125             }
6126           else if (ifx)
6127             jmpTrueOrFalse (ifx, tlbl);
6128         }
6129       else
6130         {
6131             _startLazyDPSEvaluation();
6132           for (; (size--); offset++)
6133             {
6134               // normal case
6135               // result = left & right
6136               if (AOP_TYPE (right) == AOP_LIT)
6137                 {
6138                   if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6139                     {
6140                       aopPut (AOP (result),
6141                            aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6142                               offset);
6143                       continue;
6144                     }
6145                   D (emitcode (";", "better literal OR."););
6146                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6147                   emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
6148                                                     FALSE, FALSE, FALSE));
6149
6150                 }
6151               else
6152                 {
6153                   // faster than result <- left, anl result,right
6154                   // and better if result is SFR
6155                   if (AOP_TYPE (left) == AOP_ACC)
6156                     {
6157                       emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
6158                                                        FALSE, FALSE, FALSE));
6159                     }
6160                   else
6161                     {
6162                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6163                         
6164                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6165                       {
6166                           emitcode("mov", "b,a");
6167                           rOp = "b";
6168                       }
6169                         
6170                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6171                       emitcode ("orl", "a,%s", rOp);
6172                     }
6173                 }
6174               aopPut (AOP (result), "a", offset);
6175             }
6176             _endLazyDPSEvaluation();
6177         }
6178     }
6179
6180 release:
6181   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6182   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6183   freeAsmop (result, NULL, ic, TRUE);
6184 }
6185
6186 /*-----------------------------------------------------------------*/
6187 /* genXor - code for xclusive or                                   */
6188 /*-----------------------------------------------------------------*/
6189 static void
6190 genXor (iCode * ic, iCode * ifx)
6191 {
6192   operand *left, *right, *result;
6193   int size, offset = 0;
6194   unsigned long lit = 0L;
6195   bool pushResult;
6196
6197   D (emitcode (";", "genXor "););
6198
6199   AOP_OP_3_NOFATAL (ic, pushResult);
6200   AOP_SET_LOCALS (ic);
6201
6202   if (pushResult)
6203   {
6204       genFarFarLogicOp(ic, "xrl");
6205       return;
6206   }  
6207
6208 #ifdef DEBUG_TYPE
6209   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6210             AOP_TYPE (result),
6211             AOP_TYPE (left), AOP_TYPE (right));
6212   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6213             AOP_SIZE (result),
6214             AOP_SIZE (left), AOP_SIZE (right));
6215 #endif
6216
6217   /* if left is a literal & right is not ||
6218      if left needs acc & right does not */
6219   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) 
6220 #ifdef LOGIC_OPS_BROKEN      
6221       || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6222 #endif
6223      )
6224     {
6225       operand *tmp = right;
6226       right = left;
6227       left = tmp;
6228     }
6229
6230   /* if result = right then exchange them */
6231   if (sameRegs (AOP (result), AOP (right)))
6232     {
6233       operand *tmp = right;
6234       right = left;
6235       left = tmp;
6236     }
6237
6238   /* if right is bit then exchange them */
6239   if (AOP_TYPE (right) == AOP_CRY &&
6240       AOP_TYPE (left) != AOP_CRY)
6241     {
6242       operand *tmp = right;
6243       right = left;
6244       left = tmp;
6245     }
6246   if (AOP_TYPE (right) == AOP_LIT)
6247     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6248
6249   size = AOP_SIZE (result);
6250
6251   // if(bit ^ yy)
6252   // xx = bit ^ yy;
6253   if (AOP_TYPE (left) == AOP_CRY)
6254     {
6255       if (AOP_TYPE (right) == AOP_LIT)
6256         {
6257           // c = bit & literal;
6258           if (lit >> 1)
6259             {
6260               // lit>>1  != 0 => result = 1
6261               if (AOP_TYPE (result) == AOP_CRY)
6262                 {
6263                   if (size)
6264                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6265                   else if (ifx)
6266                     continueIfTrue (ifx);
6267                   goto release;
6268                 }
6269               emitcode ("setb", "c");
6270             }
6271           else
6272             {
6273               // lit == (0 or 1)
6274               if (lit == 0)
6275                 {
6276                   // lit == 0, result = left
6277                   if (size && sameRegs (AOP (result), AOP (left)))
6278                     goto release;
6279                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6280                 }
6281               else
6282                 {
6283                   // lit == 1, result = not(left)
6284                   if (size && sameRegs (AOP (result), AOP (left)))
6285                     {
6286                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6287                       goto release;
6288                     }
6289                   else
6290                     {
6291                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6292                       emitcode ("cpl", "c");
6293                     }
6294                 }
6295             }
6296
6297         }
6298       else
6299         {
6300           // right != literal
6301           symbol *tlbl = newiTempLabel (NULL);
6302           if (AOP_TYPE (right) == AOP_CRY)
6303             {
6304               // c = bit ^ bit;
6305               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6306             }
6307           else
6308             {
6309               int sizer = AOP_SIZE (right);
6310               // c = bit ^ val
6311               // if val>>1 != 0, result = 1
6312               emitcode ("setb", "c");
6313               while (sizer)
6314                 {
6315                   MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
6316                   if (sizer == 1)
6317                     // test the msb of the lsb
6318                     emitcode ("anl", "a,#0xfe");
6319                   emitcode ("jnz", "%05d$", tlbl->key + 100);
6320                   sizer--;
6321                 }
6322               // val = (0,1)
6323               emitcode ("rrc", "a");
6324             }
6325           emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6326           emitcode ("cpl", "c");
6327           emitcode ("", "%05d$:", (tlbl->key + 100));
6328         }
6329       // bit = c
6330       // val = c
6331       if (size)
6332         outBitC (result);
6333       // if(bit | ...)
6334       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6335         genIfxJump (ifx, "c");
6336       goto release;
6337     }
6338
6339   if (sameRegs (AOP (result), AOP (left)))
6340     {
6341       /* if left is same as result */
6342       for (; size--; offset++)
6343         {
6344           if (AOP_TYPE (right) == AOP_LIT)
6345             {
6346               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6347                 continue;
6348               else if (IS_AOP_PREG (left))
6349                 {
6350                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
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,%s",
6356                           aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6357                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6358             }
6359           else
6360             {
6361               if (AOP_TYPE (left) == AOP_ACC)
6362                 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6363               else
6364                 {
6365                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6366                   if (IS_AOP_PREG (left))
6367                     {
6368                       emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6369                       aopPut (AOP (result), "a", offset);
6370                     }
6371                   else
6372                     emitcode ("xrl", "%s,a",
6373                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6374                 }
6375             }
6376         }
6377     }
6378   else
6379     {
6380       // left & result in different registers
6381       if (AOP_TYPE (result) == AOP_CRY)
6382         {
6383           // result = bit
6384           // if(size), result in bit
6385           // if(!size && ifx), conditional oper: if(left ^ right)
6386           symbol *tlbl = newiTempLabel (NULL);
6387           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6388           if (size)
6389             emitcode ("setb", "c");
6390           while (sizer--)
6391             {
6392               if ((AOP_TYPE (right) == AOP_LIT) &&
6393                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6394                 {
6395                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6396                 }
6397               else
6398                 {
6399                   if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6400                     emitcode ("xrl", "a,%s",
6401                               aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6402                   } else {
6403                     MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6404                     emitcode ("xrl", "a,%s",
6405                               aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6406                   }
6407                 }
6408               emitcode ("jnz", "%05d$", tlbl->key + 100);
6409               offset++;
6410             }
6411           if (size)
6412             {
6413               CLRC;
6414               emitcode ("", "%05d$:", tlbl->key + 100);
6415               outBitC (result);
6416             }
6417           else if (ifx)
6418             jmpTrueOrFalse (ifx, tlbl);
6419         }
6420       else
6421         for (; (size--); offset++)
6422           {
6423             // normal case
6424             // result = left & right
6425             if (AOP_TYPE (right) == AOP_LIT)
6426               {
6427                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6428                   {
6429                     aopPut (AOP (result),
6430                             aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6431                             offset);
6432                     continue;
6433                   }
6434                 D (emitcode (";", "better literal XOR.");
6435                   );
6436                 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6437                 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
6438                                                   FALSE, FALSE, FALSE));
6439               }
6440             else
6441               {
6442                 // faster than result <- left, anl result,right
6443                 // and better if result is SFR
6444                 if (AOP_TYPE (left) == AOP_ACC)
6445                   {
6446                     emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
6447                                                      FALSE, FALSE, FALSE));
6448                   }
6449                 else
6450                   {
6451                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6452                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6453                       {
6454                           emitcode("mov", "b,a");
6455                           rOp = "b";
6456                       }
6457                         
6458                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6459                       emitcode ("xrl", "a,%s", rOp);
6460                   }
6461               }
6462             aopPut (AOP (result), "a", offset);
6463           }
6464     }
6465
6466 release:
6467   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6468   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6469   freeAsmop (result, NULL, ic, TRUE);
6470 }
6471
6472 /*-----------------------------------------------------------------*/
6473 /* genInline - write the inline code out                           */
6474 /*-----------------------------------------------------------------*/
6475 static void
6476 genInline (iCode * ic)
6477 {
6478   char *buffer, *bp, *bp1;
6479
6480   D (emitcode (";", "genInline ");
6481     );
6482
6483   _G.inLine += (!options.asmpeep);
6484
6485   buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6486   strcpy (buffer, IC_INLINE (ic));
6487
6488   /* emit each line as a code */
6489   while (*bp)
6490     {
6491       if (*bp == '\n')
6492         {
6493           *bp++ = '\0';
6494           emitcode (bp1, "");
6495           bp1 = bp;
6496         }
6497       else
6498         {
6499           if (*bp == ':')
6500             {
6501               bp++;
6502               *bp = '\0';
6503               bp++;
6504               emitcode (bp1, "");
6505               bp1 = bp;
6506             }
6507           else
6508             bp++;
6509         }
6510     }
6511   if (bp1 != bp)
6512     emitcode (bp1, "");
6513   /*     emitcode("",buffer); */
6514   _G.inLine -= (!options.asmpeep);
6515 }
6516
6517 /*-----------------------------------------------------------------*/
6518 /* genRRC - rotate right with carry                                */
6519 /*-----------------------------------------------------------------*/
6520 static void
6521 genRRC (iCode * ic)
6522 {
6523   operand *left, *result;
6524   int size, offset = 0;
6525   char *l;
6526
6527   D (emitcode (";", "genRRC ");
6528     );
6529
6530   /* rotate right with carry */
6531   left = IC_LEFT (ic);
6532   result = IC_RESULT (ic);
6533   aopOp (left, ic, FALSE, FALSE);
6534   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6535
6536   /* move it to the result */
6537   size = AOP_SIZE (result);
6538   offset = size - 1;
6539   CLRC;
6540
6541   _startLazyDPSEvaluation ();
6542   while (size--)
6543     {
6544       l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6545       MOVA (l);
6546       emitcode ("rrc", "a");
6547       if (AOP_SIZE (result) > 1)
6548         aopPut (AOP (result), "a", offset--);
6549     }
6550   _endLazyDPSEvaluation ();
6551
6552   /* now we need to put the carry into the
6553      highest order byte of the result */
6554   if (AOP_SIZE (result) > 1)
6555     {
6556       l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
6557       MOVA (l);
6558     }
6559   emitcode ("mov", "acc.7,c");
6560   aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
6561   freeAsmop (left, NULL, ic, TRUE);
6562   freeAsmop (result, NULL, ic, TRUE);
6563 }
6564
6565 /*-----------------------------------------------------------------*/
6566 /* genRLC - generate code for rotate left with carry               */
6567 /*-----------------------------------------------------------------*/
6568 static void
6569 genRLC (iCode * ic)
6570 {
6571   operand *left, *result;
6572   int size, offset = 0;
6573   char *l;
6574
6575   D (emitcode (";", "genRLC ");
6576     );
6577
6578   /* rotate right with carry */
6579   left = IC_LEFT (ic);
6580   result = IC_RESULT (ic);
6581   aopOp (left, ic, FALSE, FALSE);
6582   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6583
6584   /* move it to the result */
6585   size = AOP_SIZE (result);
6586   offset = 0;
6587   if (size--)
6588     {
6589       l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6590       MOVA (l);
6591       emitcode ("add", "a,acc");
6592       if (AOP_SIZE (result) > 1)
6593         {
6594           aopPut (AOP (result), "a", offset++);
6595         }
6596
6597       _startLazyDPSEvaluation ();
6598       while (size--)
6599         {
6600           l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6601           MOVA (l);
6602           emitcode ("rlc", "a");
6603           if (AOP_SIZE (result) > 1)
6604             aopPut (AOP (result), "a", offset++);
6605         }
6606       _endLazyDPSEvaluation ();
6607     }
6608   /* now we need to put the carry into the
6609      highest order byte of the result */
6610   if (AOP_SIZE (result) > 1)
6611     {
6612       l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
6613       MOVA (l);
6614     }
6615   emitcode ("mov", "acc.0,c");
6616   aopPut (AOP (result), "a", 0);
6617   freeAsmop (left, NULL, ic, TRUE);
6618   freeAsmop (result, NULL, ic, TRUE);
6619 }
6620
6621 /*-----------------------------------------------------------------*/
6622 /* genGetHbit - generates code get highest order bit               */
6623 /*-----------------------------------------------------------------*/
6624 static void
6625 genGetHbit (iCode * ic)
6626 {
6627   operand *left, *result;
6628   left = IC_LEFT (ic);
6629   result = IC_RESULT (ic);
6630   aopOp (left, ic, FALSE, FALSE);
6631   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6632
6633   D (emitcode (";", "genGetHbit ");
6634     );
6635
6636   /* get the highest order byte into a */
6637   MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
6638   if (AOP_TYPE (result) == AOP_CRY)
6639     {
6640       emitcode ("rlc", "a");
6641       outBitC (result);
6642     }
6643   else
6644     {
6645       emitcode ("rl", "a");
6646       emitcode ("anl", "a,#0x01");
6647       outAcc (result);
6648     }
6649
6650
6651   freeAsmop (left, NULL, ic, TRUE);
6652   freeAsmop (result, NULL, ic, TRUE);
6653 }
6654
6655 /*-----------------------------------------------------------------*/
6656 /* AccRol - rotate left accumulator by known count                 */
6657 /*-----------------------------------------------------------------*/
6658 static void
6659 AccRol (int shCount)
6660 {
6661   shCount &= 0x0007;            // shCount : 0..7
6662
6663   switch (shCount)
6664     {
6665     case 0:
6666       break;
6667     case 1:
6668       emitcode ("rl", "a");
6669       break;
6670     case 2:
6671       emitcode ("rl", "a");
6672       emitcode ("rl", "a");
6673       break;
6674     case 3:
6675       emitcode ("swap", "a");
6676       emitcode ("rr", "a");
6677       break;
6678     case 4:
6679       emitcode ("swap", "a");
6680       break;
6681     case 5:
6682       emitcode ("swap", "a");
6683       emitcode ("rl", "a");
6684       break;
6685     case 6:
6686       emitcode ("rr", "a");
6687       emitcode ("rr", "a");
6688       break;
6689     case 7:
6690       emitcode ("rr", "a");
6691       break;
6692     }
6693 }
6694
6695 /*-----------------------------------------------------------------*/
6696 /* AccLsh - left shift accumulator by known count                  */
6697 /*-----------------------------------------------------------------*/
6698 static void
6699 AccLsh (int shCount)
6700 {
6701   if (shCount != 0)
6702     {
6703       if (shCount == 1)
6704         emitcode ("add", "a,acc");
6705       else if (shCount == 2)
6706         {
6707           emitcode ("add", "a,acc");
6708           emitcode ("add", "a,acc");
6709         }
6710       else
6711         {
6712           /* rotate left accumulator */
6713           AccRol (shCount);
6714           /* and kill the lower order bits */
6715           emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6716         }
6717     }
6718 }
6719
6720 /*-----------------------------------------------------------------*/
6721 /* AccRsh - right shift accumulator by known count                 */
6722 /*-----------------------------------------------------------------*/
6723 static void
6724 AccRsh (int shCount)
6725 {
6726   if (shCount != 0)
6727     {
6728       if (shCount == 1)
6729         {
6730           CLRC;
6731           emitcode ("rrc", "a");
6732         }
6733       else
6734         {
6735           /* rotate right accumulator */
6736           AccRol (8 - shCount);
6737           /* and kill the higher order bits */
6738           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6739         }
6740     }
6741 }
6742
6743 #ifdef BETTER_LITERAL_SHIFT
6744 /*-----------------------------------------------------------------*/
6745 /* AccSRsh - signed right shift accumulator by known count                 */
6746 /*-----------------------------------------------------------------*/
6747 static void
6748 AccSRsh (int shCount)
6749 {
6750   symbol *tlbl;
6751   if (shCount != 0)
6752     {
6753       if (shCount == 1)
6754         {
6755           emitcode ("mov", "c,acc.7");
6756           emitcode ("rrc", "a");
6757         }
6758       else if (shCount == 2)
6759         {
6760           emitcode ("mov", "c,acc.7");
6761           emitcode ("rrc", "a");
6762           emitcode ("mov", "c,acc.7");
6763           emitcode ("rrc", "a");
6764         }
6765       else
6766         {
6767           tlbl = newiTempLabel (NULL);
6768           /* rotate right accumulator */
6769           AccRol (8 - shCount);
6770           /* and kill the higher order bits */
6771           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6772           emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6773           emitcode ("orl", "a,#0x%02x",
6774                     (unsigned char) ~SRMask[shCount]);
6775           emitcode ("", "%05d$:", tlbl->key + 100);
6776         }
6777     }
6778 }
6779 #endif
6780
6781 #ifdef BETTER_LITERAL_SHIFT
6782 /*-----------------------------------------------------------------*/
6783 /* shiftR1Left2Result - shift right one byte from left to result   */
6784 /*-----------------------------------------------------------------*/
6785 static void
6786 shiftR1Left2Result (operand * left, int offl,
6787                     operand * result, int offr,
6788                     int shCount, int sign)
6789 {
6790   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6791   /* shift right accumulator */
6792   if (sign)
6793     AccSRsh (shCount);
6794   else
6795     AccRsh (shCount);
6796   aopPut (AOP (result), "a", offr);
6797 }
6798 #endif
6799
6800 #ifdef BETTER_LITERAL_SHIFT
6801 /*-----------------------------------------------------------------*/
6802 /* shiftL1Left2Result - shift left one byte from left to result    */
6803 /*-----------------------------------------------------------------*/
6804 static void
6805 shiftL1Left2Result (operand * left, int offl,
6806                     operand * result, int offr, int shCount)
6807 {
6808   MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6809   /* shift left accumulator */
6810   AccLsh (shCount);
6811   aopPut (AOP (result), "a", offr);
6812 }
6813 #endif
6814
6815 #ifdef BETTER_LITERAL_SHIFT
6816 /*-----------------------------------------------------------------*/
6817 /* movLeft2Result - move byte from left to result                  */
6818 /*-----------------------------------------------------------------*/
6819 static void
6820 movLeft2Result (operand * left, int offl,
6821                 operand * result, int offr, int sign)
6822 {
6823   char *l;
6824   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6825   {
6826       l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
6827
6828       if (*l == '@' && (IS_AOP_PREG (result)))
6829       {
6830           emitcode ("mov", "a,%s", l);
6831           aopPut (AOP (result), "a", offr);
6832       }
6833       else
6834       {
6835           if (!sign)
6836           {
6837             aopPut (AOP (result), l, offr);
6838           }
6839           else
6840             {
6841               /* MSB sign in acc.7 ! */
6842               if (getDataSize (left) == offl + 1)
6843                 {
6844                   emitcode ("mov", "a,%s", l);
6845                   aopPut (AOP (result), "a", offr);
6846                 }
6847             }
6848       }
6849   }
6850 }
6851 #endif
6852
6853 #ifdef BETTER_LITERAL_SHIFT
6854 /*-----------------------------------------------------------------*/
6855 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
6856 /*-----------------------------------------------------------------*/
6857 static void
6858 AccAXRrl1 (char *x)
6859 {
6860   emitcode ("rrc", "a");
6861   emitcode ("xch", "a,%s", x);
6862   emitcode ("rrc", "a");
6863   emitcode ("xch", "a,%s", x);
6864 }
6865 #endif
6866
6867 #ifdef BETTER_LITERAL_SHIFT
6868 //REMOVE ME!!!
6869 /*-----------------------------------------------------------------*/
6870 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
6871 /*-----------------------------------------------------------------*/
6872 static void
6873 AccAXLrl1 (char *x)
6874 {
6875   emitcode ("xch", "a,%s", x);
6876   emitcode ("rlc", "a");
6877   emitcode ("xch", "a,%s", x);
6878   emitcode ("rlc", "a");
6879 }
6880 #endif
6881
6882 #ifdef BETTER_LITERAL_SHIFT
6883 /*-----------------------------------------------------------------*/
6884 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
6885 /*-----------------------------------------------------------------*/
6886 static void
6887 AccAXLsh1 (char *x)
6888 {
6889   emitcode ("xch", "a,%s", x);
6890   emitcode ("add", "a,acc");
6891   emitcode ("xch", "a,%s", x);
6892   emitcode ("rlc", "a");
6893 }
6894 #endif
6895
6896 #ifdef BETTER_LITERAL_SHIFT
6897 /*-----------------------------------------------------------------*/
6898 /* AccAXLsh - left shift a:x by known count (0..7)                 */
6899 /*-----------------------------------------------------------------*/
6900 static void
6901 AccAXLsh (char *x, int shCount)
6902 {
6903   switch (shCount)
6904     {
6905     case 0:
6906       break;
6907     case 1:
6908       AccAXLsh1 (x);
6909       break;
6910     case 2:
6911       AccAXLsh1 (x);
6912       AccAXLsh1 (x);
6913       break;
6914     case 3:
6915     case 4:
6916     case 5:                     // AAAAABBB:CCCCCDDD
6917
6918       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
6919
6920       emitcode ("anl", "a,#0x%02x",
6921                 SLMask[shCount]);       // BBB00000:CCCCCDDD
6922
6923       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
6924
6925       AccRol (shCount);         // DDDCCCCC:BBB00000
6926
6927       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
6928
6929       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
6930
6931       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
6932
6933       emitcode ("anl", "a,#0x%02x",
6934                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
6935
6936       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
6937
6938       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
6939
6940       break;
6941     case 6:                     // AAAAAABB:CCCCCCDD
6942       emitcode ("anl", "a,#0x%02x",
6943                 SRMask[shCount]);       // 000000BB:CCCCCCDD
6944       emitcode ("mov", "c,acc.0");      // c = B
6945       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
6946 #if 0
6947       AccAXRrl1 (x);            // BCCCCCCD:D000000B
6948       AccAXRrl1 (x);            // BBCCCCCC:DD000000
6949 #else
6950       emitcode("rrc","a"); 
6951       emitcode("xch","a,%s", x); 
6952       emitcode("rrc","a"); 
6953       emitcode("mov","c,acc.0"); //<< get correct bit 
6954       emitcode("xch","a,%s", x); 
6955
6956       emitcode("rrc","a"); 
6957       emitcode("xch","a,%s", x); 
6958       emitcode("rrc","a"); 
6959       emitcode("xch","a,%s", x); 
6960 #endif
6961       break;
6962     case 7:                     // a:x <<= 7
6963
6964       emitcode ("anl", "a,#0x%02x",
6965                 SRMask[shCount]);       // 0000000B:CCCCCCCD
6966
6967       emitcode ("mov", "c,acc.0");      // c = B
6968
6969       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
6970
6971       AccAXRrl1 (x);            // BCCCCCCC:D0000000
6972
6973       break;
6974     default:
6975       break;
6976     }
6977 }
6978 #endif
6979
6980 #ifdef BETTER_LITERAL_SHIFT
6981 //REMOVE ME!!!
6982 /*-----------------------------------------------------------------*/
6983 /* AccAXRsh - right shift a:x known count (0..7)                   */
6984 /*-----------------------------------------------------------------*/
6985 static void
6986 AccAXRsh (char *x, int shCount)
6987 {
6988   switch (shCount)
6989     {
6990     case 0:
6991       break;
6992     case 1:
6993       CLRC;
6994       AccAXRrl1 (x);            // 0->a:x
6995
6996       break;
6997     case 2:
6998       CLRC;
6999       AccAXRrl1 (x);            // 0->a:x
7000
7001       CLRC;
7002       AccAXRrl1 (x);            // 0->a:x
7003
7004       break;
7005     case 3:
7006     case 4:
7007     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7008
7009       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
7010
7011       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7012
7013       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7014
7015       emitcode ("anl", "a,#0x%02x",
7016                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7017
7018       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7019
7020       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7021
7022       emitcode ("anl", "a,#0x%02x",
7023                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7024
7025       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7026
7027       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7028
7029       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
7030
7031       break;
7032     case 6:                     // AABBBBBB:CCDDDDDD
7033
7034       emitcode ("mov", "c,acc.7");
7035       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7036
7037       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7038
7039       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7040
7041       emitcode ("anl", "a,#0x%02x",
7042                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7043
7044       break;
7045     case 7:                     // ABBBBBBB:CDDDDDDD
7046
7047       emitcode ("mov", "c,acc.7");      // c = A
7048
7049       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7050
7051       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7052
7053       emitcode ("anl", "a,#0x%02x",
7054                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7055
7056       break;
7057     default:
7058       break;
7059     }
7060 }
7061 #endif
7062
7063 #ifdef BETTER_LITERAL_SHIFT
7064 /*-----------------------------------------------------------------*/
7065 /* AccAXRshS - right shift signed a:x known count (0..7)           */
7066 /*-----------------------------------------------------------------*/
7067 static void
7068 AccAXRshS (char *x, int shCount)
7069 {
7070   symbol *tlbl;
7071   switch (shCount)
7072     {
7073     case 0:
7074       break;
7075     case 1:
7076       emitcode ("mov", "c,acc.7");
7077       AccAXRrl1 (x);            // s->a:x
7078
7079       break;
7080     case 2:
7081       emitcode ("mov", "c,acc.7");
7082       AccAXRrl1 (x);            // s->a:x
7083
7084       emitcode ("mov", "c,acc.7");
7085       AccAXRrl1 (x);            // s->a:x
7086
7087       break;
7088     case 3:
7089     case 4:
7090     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7091
7092       tlbl = newiTempLabel (NULL);
7093       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
7094
7095       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7096
7097       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7098
7099       emitcode ("anl", "a,#0x%02x",
7100                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7101
7102       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7103
7104       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7105
7106       emitcode ("anl", "a,#0x%02x",
7107                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7108
7109       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7110
7111       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7112
7113       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
7114
7115       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7116       emitcode ("orl", "a,#0x%02x",
7117                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
7118
7119       emitcode ("", "%05d$:", tlbl->key + 100);
7120       break;                    // SSSSAAAA:BBBCCCCC
7121
7122     case 6:                     // AABBBBBB:CCDDDDDD
7123
7124       tlbl = newiTempLabel (NULL);
7125       emitcode ("mov", "c,acc.7");
7126       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7127
7128       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7129
7130       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7131
7132       emitcode ("anl", "a,#0x%02x",
7133                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7134
7135       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7136       emitcode ("orl", "a,#0x%02x",
7137                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
7138
7139       emitcode ("", "%05d$:", tlbl->key + 100);
7140       break;
7141     case 7:                     // ABBBBBBB:CDDDDDDD
7142
7143       tlbl = newiTempLabel (NULL);
7144       emitcode ("mov", "c,acc.7");      // c = A
7145
7146       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7147
7148       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7149
7150       emitcode ("anl", "a,#0x%02x",
7151                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7152
7153       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7154       emitcode ("orl", "a,#0x%02x",
7155                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
7156
7157       emitcode ("", "%05d$:", tlbl->key + 100);
7158       break;
7159     default:
7160       break;
7161     }
7162 }
7163 #endif
7164
7165 #ifdef BETTER_LITERAL_SHIFT
7166 static void
7167 _loadLeftIntoAx(char    **lsb, 
7168                 operand *left, 
7169                 operand *result,
7170                 int     offl,
7171                 int     offr)
7172 {
7173   // Get the initial value from left into a pair of registers.
7174   // MSB must be in A, LSB can be any register.
7175   //
7176   // If the result is held in registers, it is an optimization
7177   // if the LSB can be held in the register which will hold the,
7178   // result LSB since this saves us from having to copy it into
7179   // the result following AccAXLsh.
7180   //
7181   // If the result is addressed indirectly, this is not a gain.
7182   if (AOP_NEEDSACC(result))
7183   {
7184        char *leftByte;
7185        
7186        _startLazyDPSEvaluation();
7187       if (AOP_TYPE(left) == AOP_DPTR2)
7188        {
7189            // Get MSB in A.
7190            MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
7191            // get LSB in DP2_RESULT_REG.
7192            leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
7193            assert(!strcmp(leftByte, DP2_RESULT_REG));
7194        }
7195        else
7196        {
7197            // get LSB into DP2_RESULT_REG
7198            leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
7199            if (strcmp(leftByte, DP2_RESULT_REG))
7200            {
7201                TR_AP("#7");
7202                emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7203            }
7204            // And MSB in A.
7205            leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
7206            assert(strcmp(leftByte, DP2_RESULT_REG));
7207            MOVA(leftByte);
7208        }
7209        _endLazyDPSEvaluation();
7210        *lsb = DP2_RESULT_REG;
7211   }
7212   else
7213   {
7214       if (sameRegs (AOP (result), AOP (left)) &&
7215         ((offl + MSB16) == offr))
7216       {
7217           /* don't crash result[offr] */
7218           MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
7219           emitcode ("xch", "a,%s", 
7220                     aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
7221       }
7222       else
7223       {
7224           movLeft2Result (left, offl, result, offr, 0);
7225           MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
7226       }
7227       *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
7228       assert(strcmp(*lsb,"a"));      
7229   }
7230 }
7231
7232 static void
7233 _storeAxResults(char    *lsb,
7234                 operand *result,
7235                 int     offr)
7236 {
7237   _startLazyDPSEvaluation();
7238   if (AOP_NEEDSACC(result))
7239   {
7240       /* We have to explicitly update the result LSB.
7241        */
7242       emitcode("xch","a,%s", lsb);
7243       aopPut(AOP(result), "a", offr);
7244       emitcode("mov","a,%s", lsb);
7245   }
7246   if (getDataSize (result) > 1)
7247   {
7248       aopPut (AOP (result), "a", offr + MSB16);
7249   }
7250   _endLazyDPSEvaluation();
7251 }
7252
7253 /*-----------------------------------------------------------------*/
7254 /* shiftL2Left2Result - shift left two bytes from left to result   */
7255 /*-----------------------------------------------------------------*/
7256 static void
7257 shiftL2Left2Result (operand * left, int offl,
7258                     operand * result, int offr, int shCount)
7259 {
7260   char *lsb;
7261
7262   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7263   
7264   AccAXLsh (lsb, shCount);
7265   
7266   _storeAxResults(lsb, result, offr);
7267 }
7268 #endif
7269
7270 #ifdef BETTER_LITERAL_SHIFT
7271 /*-----------------------------------------------------------------*/
7272 /* shiftR2Left2Result - shift right two bytes from left to result  */
7273 /*-----------------------------------------------------------------*/
7274 static void
7275 shiftR2Left2Result (operand * left, int offl,
7276                     operand * result, int offr,
7277                     int shCount, int sign)
7278 {
7279   char *lsb;
7280   
7281   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7282   
7283   /* a:x >> shCount (x = lsb(result)) */
7284   if (sign)
7285   {
7286      AccAXRshS(lsb, shCount);
7287   }
7288   else
7289   {
7290     AccAXRsh(lsb, shCount);
7291   }
7292   
7293   _storeAxResults(lsb, result, offr);
7294 }
7295 #endif
7296
7297 #if 0
7298 //REMOVE ME!!!
7299 /*-----------------------------------------------------------------*/
7300 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7301 /*-----------------------------------------------------------------*/
7302 static void
7303 shiftLLeftOrResult (operand * left, int offl,
7304                     operand * result, int offr, int shCount)
7305 {
7306   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7307   /* shift left accumulator */
7308   AccLsh (shCount);
7309   /* or with result */
7310   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7311   /* back to result */
7312   aopPut (AOP (result), "a", offr);
7313 }
7314 #endif
7315
7316 #if 0
7317 //REMOVE ME!!!
7318 /*-----------------------------------------------------------------*/
7319 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7320 /*-----------------------------------------------------------------*/
7321 static void
7322 shiftRLeftOrResult (operand * left, int offl,
7323                     operand * result, int offr, int shCount)
7324 {
7325   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7326   /* shift right accumulator */
7327   AccRsh (shCount);
7328   /* or with result */
7329   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7330   /* back to result */
7331   aopPut (AOP (result), "a", offr);
7332 }
7333 #endif
7334
7335 #ifdef BETTER_LITERAL_SHIFT
7336 /*-----------------------------------------------------------------*/
7337 /* genlshOne - left shift a one byte quantity by known count       */
7338 /*-----------------------------------------------------------------*/
7339 static void
7340 genlshOne (operand * result, operand * left, int shCount)
7341 {
7342   D (emitcode (";", "genlshOne "););
7343   shiftL1Left2Result (left, LSB, result, LSB, shCount);
7344 }
7345 #endif
7346
7347 #ifdef BETTER_LITERAL_SHIFT
7348 /*-----------------------------------------------------------------*/
7349 /* genlshTwo - left shift two bytes by known amount != 0           */
7350 /*-----------------------------------------------------------------*/
7351 static void
7352 genlshTwo (operand * result, operand * left, int shCount)
7353 {
7354   int size;
7355
7356   D (emitcode (";", "genlshTwo "););
7357
7358   size = getDataSize (result);
7359
7360   /* if shCount >= 8 */
7361   if (shCount >= 8)
7362   {
7363       shCount -= 8;
7364
7365       _startLazyDPSEvaluation();
7366
7367       if (size > 1)
7368         {
7369           if (shCount)
7370           {
7371             _endLazyDPSEvaluation();
7372             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7373             aopPut (AOP (result), zero, LSB);       
7374           }
7375           else
7376           {
7377             movLeft2Result (left, LSB, result, MSB16, 0);
7378             aopPut (AOP (result), zero, LSB);
7379             _endLazyDPSEvaluation();
7380           }
7381         }
7382         else
7383         {
7384           aopPut (AOP (result), zero, LSB);
7385           _endLazyDPSEvaluation();
7386         }
7387   }
7388
7389   /*  1 <= shCount <= 7 */
7390   else
7391     {
7392       if (size == 1)
7393       {
7394         shiftL1Left2Result (left, LSB, result, LSB, shCount);
7395       }
7396       else
7397       {
7398         shiftL2Left2Result (left, LSB, result, LSB, shCount);
7399       }
7400     }
7401 }
7402 #endif
7403
7404 #if 0
7405 //REMOVE ME!!!
7406 /*-----------------------------------------------------------------*/
7407 /* shiftLLong - shift left one long from left to result            */
7408 /* offl = LSB or MSB16                                             */
7409 /*-----------------------------------------------------------------*/
7410 static void
7411 shiftLLong (operand * left, operand * result, int offr)
7412 {
7413   char *l;
7414   int size = AOP_SIZE (result);
7415
7416   if (size >= LSB + offr)
7417     {
7418       l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
7419       MOVA (l);
7420       emitcode ("add", "a,acc");
7421       if (sameRegs (AOP (left), AOP (result)) &&
7422           size >= MSB16 + offr && offr != LSB)
7423         emitcode ("xch", "a,%s",
7424                   aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
7425       else
7426         aopPut (AOP (result), "a", LSB + offr);
7427     }
7428
7429   if (size >= MSB16 + offr)
7430     {
7431       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7432         {
7433           l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
7434           MOVA (l);
7435         }
7436       emitcode ("rlc", "a");
7437       if (sameRegs (AOP (left), AOP (result)) &&
7438           size >= MSB24 + offr && offr != LSB)
7439         emitcode ("xch", "a,%s",
7440                   aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
7441       else
7442         aopPut (AOP (result), "a", MSB16 + offr);
7443     }
7444
7445   if (size >= MSB24 + offr)
7446     {
7447       if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7448         {
7449           l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
7450           MOVA (l);
7451         }
7452       emitcode ("rlc", "a");
7453       if (sameRegs (AOP (left), AOP (result)) &&
7454           size >= MSB32 + offr && offr != LSB)
7455         emitcode ("xch", "a,%s",
7456                   aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
7457       else
7458         aopPut (AOP (result), "a", MSB24 + offr);
7459     }
7460
7461   if (size > MSB32 + offr)
7462     {
7463       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7464         {
7465           l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
7466           MOVA (l);
7467         }
7468       emitcode ("rlc", "a");
7469       aopPut (AOP (result), "a", MSB32 + offr);
7470     }
7471   if (offr != LSB)
7472     aopPut (AOP (result), zero, LSB);
7473 }
7474 #endif
7475
7476 #if 0
7477 //REMOVE ME!!!
7478 /*-----------------------------------------------------------------*/
7479 /* genlshFour - shift four byte by a known amount != 0             */
7480 /*-----------------------------------------------------------------*/
7481 static void
7482 genlshFour (operand * result, operand * left, int shCount)
7483 {
7484   int size;
7485
7486   D (emitcode (";", "genlshFour ");
7487     );
7488
7489   size = AOP_SIZE (result);
7490
7491   /* if shifting more that 3 bytes */
7492   if (shCount >= 24)
7493     {
7494       shCount -= 24;
7495       if (shCount)
7496         /* lowest order of left goes to the highest
7497            order of the destination */
7498         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7499       else
7500         movLeft2Result (left, LSB, result, MSB32, 0);
7501       aopPut (AOP (result), zero, LSB);
7502       aopPut (AOP (result), zero, MSB16);
7503       aopPut (AOP (result), zero, MSB24);
7504       return;
7505     }
7506
7507   /* more than two bytes */
7508   else if (shCount >= 16)
7509     {
7510       /* lower order two bytes goes to higher order two bytes */
7511       shCount -= 16;
7512       /* if some more remaining */
7513       if (shCount)
7514         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7515       else
7516         {
7517           movLeft2Result (left, MSB16, result, MSB32, 0);
7518           movLeft2Result (left, LSB, result, MSB24, 0);
7519         }
7520       aopPut (AOP (result), zero, MSB16);
7521       aopPut (AOP (result), zero, LSB);
7522       return;
7523     }
7524
7525   /* if more than 1 byte */
7526   else if (shCount >= 8)
7527     {
7528       /* lower order three bytes goes to higher order  three bytes */
7529       shCount -= 8;
7530       if (size == 2)
7531         {
7532           if (shCount)
7533             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7534           else
7535             movLeft2Result (left, LSB, result, MSB16, 0);
7536         }
7537       else
7538         {                       /* size = 4 */
7539           if (shCount == 0)
7540             {
7541               movLeft2Result (left, MSB24, result, MSB32, 0);
7542               movLeft2Result (left, MSB16, result, MSB24, 0);
7543               movLeft2Result (left, LSB, result, MSB16, 0);
7544               aopPut (AOP (result), zero, LSB);
7545             }
7546           else if (shCount == 1)
7547             shiftLLong (left, result, MSB16);
7548           else
7549             {
7550               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7551               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7552               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7553               aopPut (AOP (result), zero, LSB);
7554             }
7555         }
7556     }
7557
7558   /* 1 <= shCount <= 7 */
7559   else if (shCount <= 2)
7560     {
7561       shiftLLong (left, result, LSB);
7562       if (shCount == 2)
7563         shiftLLong (result, result, LSB);
7564     }
7565   /* 3 <= shCount <= 7, optimize */
7566   else
7567     {
7568       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7569       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7570       shiftL2Left2Result (left, LSB, result, LSB, shCount);
7571     }
7572 }
7573 #endif
7574
7575 #ifdef BETTER_LITERAL_SHIFT
7576 /*-----------------------------------------------------------------*/
7577 /* genLeftShiftLiteral - left shifting by known count              */
7578 /*-----------------------------------------------------------------*/
7579 static bool
7580 genLeftShiftLiteral (operand * left,
7581                      operand * right,
7582                      operand * result,
7583                      iCode * ic)
7584 {
7585   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7586   int size;
7587
7588   size = getSize (operandType (result));
7589
7590   D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
7591
7592   /* We only handle certain easy cases so far. */
7593   if ((shCount != 0)
7594    && (shCount < (size * 8))
7595    && (size != 1)
7596    && (size != 2))
7597   {
7598       D(emitcode (";", "genLeftShiftLiteral wimping out"););    
7599       return FALSE;
7600   }
7601
7602   freeAsmop (right, NULL, ic, TRUE);
7603
7604   aopOp(left, ic, FALSE, FALSE);
7605   aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
7606
7607 #if 1 // debug spew
7608   if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
7609   {
7610         emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
7611         if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
7612         {
7613            emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
7614         }
7615   }
7616   if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
7617   {
7618         emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
7619         if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
7620         {
7621            emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
7622         }       
7623   }  
7624 #endif
7625   
7626 #if VIEW_SIZE
7627   emitcode ("; shift left ", "result %d, left %d", size,
7628             AOP_SIZE (left));
7629 #endif
7630
7631   /* I suppose that the left size >= result size */
7632   if (shCount == 0)
7633   {
7634         _startLazyDPSEvaluation();
7635         while (size--)
7636         {
7637           movLeft2Result (left, size, result, size, 0);
7638         }
7639         _endLazyDPSEvaluation();
7640   }
7641   else if (shCount >= (size * 8))
7642   {
7643     _startLazyDPSEvaluation();
7644     while (size--)
7645     {
7646       aopPut (AOP (result), zero, size);
7647     }
7648     _endLazyDPSEvaluation();
7649   }
7650   else
7651   {
7652       switch (size)
7653         {
7654         case 1:
7655           genlshOne (result, left, shCount);
7656           break;
7657
7658         case 2:
7659           genlshTwo (result, left, shCount);
7660           break;
7661 #if 0
7662         case 4:
7663           genlshFour (result, left, shCount);
7664           break;
7665 #endif
7666         default:
7667           fprintf(stderr, "*** ack! mystery literal shift!\n");   
7668           break;
7669         }
7670     }
7671   freeAsmop (left, NULL, ic, TRUE);
7672   freeAsmop (result, NULL, ic, TRUE);
7673   return TRUE;
7674 }
7675 #endif
7676
7677 /*-----------------------------------------------------------------*/
7678 /* genLeftShift - generates code for left shifting                 */
7679 /*-----------------------------------------------------------------*/
7680 static void
7681 genLeftShift (iCode * ic)
7682 {
7683   operand *left, *right, *result;
7684   int size, offset;
7685   char *l;
7686   symbol *tlbl, *tlbl1;
7687
7688   D (emitcode (";", "genLeftShift "););
7689
7690   right = IC_RIGHT (ic);
7691   left = IC_LEFT (ic);
7692   result = IC_RESULT (ic);
7693
7694   aopOp (right, ic, FALSE, FALSE);
7695
7696
7697 #ifdef BETTER_LITERAL_SHIFT
7698   /* if the shift count is known then do it
7699      as efficiently as possible */
7700   if (AOP_TYPE (right) == AOP_LIT)
7701     {
7702       if (genLeftShiftLiteral (left, right, result, ic))
7703       {
7704         return;
7705       }
7706     }
7707 #endif
7708
7709   /* shift count is unknown then we have to form
7710      a loop get the loop count in B : Note: we take
7711      only the lower order byte since shifting
7712      more that 32 bits make no sense anyway, ( the
7713      largest size of an object can be only 32 bits ) */
7714
7715   if (AOP_TYPE (right) == AOP_LIT)
7716   {
7717       /* Really should be handled by genLeftShiftLiteral,
7718        * but since I'm too lazy to fix that today, at least we can make
7719        * some small improvement.
7720        */
7721        emitcode("mov", "b,#0x%02x",
7722                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7723   }
7724   else
7725   {
7726         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7727         emitcode ("inc", "b");
7728   }
7729   freeAsmop (right, NULL, ic, TRUE);
7730   aopOp (left, ic, FALSE, FALSE);
7731   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7732
7733   /* now move the left to the result if they are not the
7734      same */
7735   if (!sameRegs (AOP (left), AOP (result)) &&
7736       AOP_SIZE (result) > 1)
7737     {
7738
7739       size = AOP_SIZE (result);
7740       offset = 0;
7741       _startLazyDPSEvaluation ();
7742       while (size--)
7743         {
7744           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7745           if (*l == '@' && (IS_AOP_PREG (result)))
7746             {
7747
7748               emitcode ("mov", "a,%s", l);
7749               aopPut (AOP (result), "a", offset);
7750             }
7751           else
7752             aopPut (AOP (result), l, offset);
7753           offset++;
7754         }
7755       _endLazyDPSEvaluation ();
7756     }
7757
7758   tlbl = newiTempLabel (NULL);
7759   size = AOP_SIZE (result);
7760   offset = 0;
7761   tlbl1 = newiTempLabel (NULL);
7762
7763   /* if it is only one byte then */
7764   if (size == 1)
7765     {
7766       symbol *tlbl1 = newiTempLabel (NULL);
7767
7768       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7769       MOVA (l);
7770       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7771       emitcode ("", "%05d$:", tlbl->key + 100);
7772       emitcode ("add", "a,acc");
7773       emitcode ("", "%05d$:", tlbl1->key + 100);
7774       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7775       aopPut (AOP (result), "a", 0);
7776       goto release;
7777     }
7778
7779   reAdjustPreg (AOP (result));
7780
7781   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7782   emitcode ("", "%05d$:", tlbl->key + 100);
7783   l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7784   MOVA (l);
7785   emitcode ("add", "a,acc");
7786   aopPut (AOP (result), "a", offset++);
7787   _startLazyDPSEvaluation ();
7788   while (--size)
7789     {
7790       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7791       MOVA (l);
7792       emitcode ("rlc", "a");
7793       aopPut (AOP (result), "a", offset++);
7794     }
7795   _endLazyDPSEvaluation ();
7796   reAdjustPreg (AOP (result));
7797
7798   emitcode ("", "%05d$:", tlbl1->key + 100);
7799   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7800 release:
7801   freeAsmop (left, NULL, ic, TRUE);
7802   freeAsmop (result, NULL, ic, TRUE);
7803 }
7804
7805 #ifdef BETTER_LITERAL_SHIFT
7806 /*-----------------------------------------------------------------*/
7807 /* genrshOne - right shift a one byte quantity by known count      */
7808 /*-----------------------------------------------------------------*/
7809 static void
7810 genrshOne (operand * result, operand * left,
7811            int shCount, int sign)
7812 {
7813   D (emitcode (";", "genrshOne"););
7814   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7815 }
7816 #endif
7817
7818 #ifdef BETTER_LITERAL_SHIFT
7819 /*-----------------------------------------------------------------*/
7820 /* genrshTwo - right shift two bytes by known amount != 0          */
7821 /*-----------------------------------------------------------------*/
7822 static void
7823 genrshTwo (operand * result, operand * left,
7824            int shCount, int sign)
7825 {
7826   D (emitcode (";", "genrshTwo"););
7827
7828   /* if shCount >= 8 */
7829   if (shCount >= 8)
7830     {
7831       shCount -= 8;
7832       _startLazyDPSEvaluation();
7833       if (shCount)
7834       {
7835         shiftR1Left2Result (left, MSB16, result, LSB,
7836                             shCount, sign);
7837       }                     
7838       else
7839       {
7840         movLeft2Result (left, MSB16, result, LSB, sign);
7841       }
7842       addSign (result, MSB16, sign);
7843       _endLazyDPSEvaluation();
7844     }
7845
7846   /*  1 <= shCount <= 7 */
7847   else
7848   {
7849     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7850   }
7851 }
7852 #endif
7853
7854 #if 0
7855 //REMOVE ME!!!
7856 /*-----------------------------------------------------------------*/
7857 /* shiftRLong - shift right one long from left to result           */
7858 /* offl = LSB or MSB16                                             */
7859 /*-----------------------------------------------------------------*/
7860 static void
7861 shiftRLong (operand * left, int offl,
7862             operand * result, int sign)
7863 {
7864   int isSameRegs=sameRegs(AOP(left),AOP(result));
7865
7866   if (isSameRegs && offl>1) {
7867     // we are in big trouble, but this shouldn't happen
7868     werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
7869   }
7870
7871   MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7872   
7873   if (offl==MSB16) {
7874     // shift is > 8
7875     if (sign) {
7876       emitcode ("rlc", "a");
7877       emitcode ("subb", "a,acc");
7878       emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
7879     } else {
7880       aopPut (AOP(result), zero, MSB32);
7881     }
7882   }
7883
7884   if (!sign) {
7885     emitcode ("clr", "c");
7886   } else {
7887     emitcode ("mov", "c,acc.7");
7888   }
7889
7890   emitcode ("rrc", "a");
7891
7892   if (isSameRegs && offl==MSB16) {
7893     emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
7894   } else {
7895     aopPut (AOP (result), "a", MSB32);
7896     MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
7897   }
7898
7899   emitcode ("rrc", "a");
7900   if (isSameRegs && offl==1) {
7901     emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
7902   } else {
7903     aopPut (AOP (result), "a", MSB24);
7904     MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
7905   }
7906   emitcode ("rrc", "a");
7907   aopPut (AOP (result), "a", MSB16 - offl);
7908
7909   if (offl == LSB)
7910     {
7911       MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
7912       emitcode ("rrc", "a");
7913       aopPut (AOP (result), "a", LSB);
7914     }
7915 }
7916 #endif
7917
7918 #if 0
7919 //REMOVE ME!!!
7920 /*-----------------------------------------------------------------*/
7921 /* genrshFour - shift four byte by a known amount != 0             */
7922 /*-----------------------------------------------------------------*/
7923 static void
7924 genrshFour (operand * result, operand * left,
7925             int shCount, int sign)
7926 {
7927   D (emitcode (";", "genrshFour");
7928     );
7929
7930   /* if shifting more that 3 bytes */
7931   if (shCount >= 24)
7932     {
7933       shCount -= 24;
7934       if (shCount)
7935         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7936       else
7937         movLeft2Result (left, MSB32, result, LSB, sign);
7938       addSign (result, MSB16, sign);
7939     }
7940   else if (shCount >= 16)
7941     {
7942       shCount -= 16;
7943       if (shCount)
7944         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7945       else
7946         {
7947           movLeft2Result (left, MSB24, result, LSB, 0);
7948           movLeft2Result (left, MSB32, result, MSB16, sign);
7949         }
7950       addSign (result, MSB24, sign);
7951     }
7952   else if (shCount >= 8)
7953     {
7954       shCount -= 8;
7955       if (shCount == 1)
7956         shiftRLong (left, MSB16, result, sign);
7957       else if (shCount == 0)
7958         {
7959           movLeft2Result (left, MSB16, result, LSB, 0);
7960           movLeft2Result (left, MSB24, result, MSB16, 0);
7961           movLeft2Result (left, MSB32, result, MSB24, sign);
7962           addSign (result, MSB32, sign);
7963         }
7964       else
7965         {
7966           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7967           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7968           /* the last shift is signed */
7969           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7970           addSign (result, MSB32, sign);
7971         }
7972     }
7973   else
7974     {                           /* 1 <= shCount <= 7 */
7975       if (shCount <= 2)
7976         {
7977           shiftRLong (left, LSB, result, sign);
7978           if (shCount == 2)
7979             shiftRLong (result, LSB, result, sign);
7980         }
7981       else
7982         {
7983           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7984           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7985           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7986         }
7987     }
7988 }
7989 #endif
7990
7991 #ifdef BETTER_LITERAL_SHIFT
7992 /*-----------------------------------------------------------------*/
7993 /* genRightShiftLiteral - right shifting by known count            */
7994 /*-----------------------------------------------------------------*/
7995 static bool
7996 genRightShiftLiteral (operand * left,
7997                       operand * right,
7998                       operand * result,
7999                       iCode * ic,
8000                       int sign)
8001 {
8002   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8003   int size;
8004
8005   size = getSize (operandType (result));
8006
8007   D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8008
8009   /* We only handle certain easy cases so far. */
8010   if ((shCount != 0)
8011    && (shCount < (size * 8))
8012    && (size != 1)
8013    && (size != 2))
8014   {
8015       D(emitcode (";", "genRightShiftLiteral wimping out"););   
8016       return FALSE;
8017   }
8018
8019   freeAsmop (right, NULL, ic, TRUE);
8020
8021   aopOp (left, ic, FALSE, FALSE);
8022   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8023
8024 #if VIEW_SIZE
8025   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8026             AOP_SIZE (left));
8027 #endif
8028
8029   /* test the LEFT size !!! */
8030
8031   /* I suppose that the left size >= result size */
8032   if (shCount == 0)
8033   {
8034       size = getDataSize (result);
8035       _startLazyDPSEvaluation();
8036       while (size--)
8037       {
8038         movLeft2Result (left, size, result, size, 0);
8039       }
8040       _endLazyDPSEvaluation();
8041   }
8042   else if (shCount >= (size * 8))
8043     {
8044       if (sign)
8045       {
8046         /* get sign in acc.7 */
8047         MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
8048       }
8049       addSign (result, LSB, sign);
8050     }
8051   else
8052     {
8053       switch (size)
8054         {
8055         case 1:
8056           genrshOne (result, left, shCount, sign);
8057           break;
8058
8059         case 2:
8060           genrshTwo (result, left, shCount, sign);
8061           break;
8062 #if 0
8063         case 4:
8064           genrshFour (result, left, shCount, sign);
8065           break;
8066 #endif    
8067         default:
8068           break;
8069         }
8070
8071       freeAsmop (left, NULL, ic, TRUE);
8072       freeAsmop (result, NULL, ic, TRUE);
8073     }
8074     return TRUE;
8075 }
8076 #endif
8077
8078 /*-----------------------------------------------------------------*/
8079 /* genSignedRightShift - right shift of signed number              */
8080 /*-----------------------------------------------------------------*/
8081 static void
8082 genSignedRightShift (iCode * ic)
8083 {
8084   operand *right, *left, *result;
8085   int size, offset;
8086   char *l;
8087   symbol *tlbl, *tlbl1;
8088
8089   D (emitcode (";", "genSignedRightShift "););
8090
8091   /* we do it the hard way put the shift count in b
8092      and loop thru preserving the sign */
8093
8094   right = IC_RIGHT (ic);
8095   left = IC_LEFT (ic);
8096   result = IC_RESULT (ic);
8097
8098   aopOp (right, ic, FALSE, FALSE);
8099
8100 #ifdef BETTER_LITERAL_SHIFT
8101   if (AOP_TYPE (right) == AOP_LIT)
8102     {
8103       if (genRightShiftLiteral (left, right, result, ic, 1))
8104       {
8105         return;
8106       }
8107     }
8108 #endif
8109   /* shift count is unknown then we have to form
8110      a loop get the loop count in B : Note: we take
8111      only the lower order byte since shifting
8112      more that 32 bits make no sense anyway, ( the
8113      largest size of an object can be only 32 bits ) */
8114
8115   if (AOP_TYPE (right) == AOP_LIT)
8116   {
8117       /* Really should be handled by genRightShiftLiteral,
8118        * but since I'm too lazy to fix that today, at least we can make
8119        * some small improvement.
8120        */
8121        emitcode("mov", "b,#0x%02x",
8122                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8123   }
8124   else
8125   {
8126         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8127         emitcode ("inc", "b");
8128   }
8129   freeAsmop (right, NULL, ic, TRUE);
8130   aopOp (left, ic, FALSE, FALSE);
8131   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8132
8133   /* now move the left to the result if they are not the
8134      same */
8135   if (!sameRegs (AOP (left), AOP (result)) &&
8136       AOP_SIZE (result) > 1)
8137     {
8138
8139       size = AOP_SIZE (result);
8140       offset = 0;
8141       _startLazyDPSEvaluation ();
8142       while (size--)
8143         {
8144           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8145           if (*l == '@' && IS_AOP_PREG (result))
8146             {
8147
8148               emitcode ("mov", "a,%s", l);
8149               aopPut (AOP (result), "a", offset);
8150             }
8151           else
8152             aopPut (AOP (result), l, offset);
8153           offset++;
8154         }
8155       _endLazyDPSEvaluation ();
8156     }
8157
8158   /* mov the highest order bit to OVR */
8159   tlbl = newiTempLabel (NULL);
8160   tlbl1 = newiTempLabel (NULL);
8161
8162   size = AOP_SIZE (result);
8163   offset = size - 1;
8164   emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
8165   emitcode ("rlc", "a");
8166   emitcode ("mov", "ov,c");
8167   /* if it is only one byte then */
8168   if (size == 1)
8169     {
8170       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8171       MOVA (l);
8172       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8173       emitcode ("", "%05d$:", tlbl->key + 100);
8174       emitcode ("mov", "c,ov");
8175       emitcode ("rrc", "a");
8176       emitcode ("", "%05d$:", tlbl1->key + 100);
8177       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8178       aopPut (AOP (result), "a", 0);
8179       goto release;
8180     }
8181
8182   reAdjustPreg (AOP (result));
8183   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8184   emitcode ("", "%05d$:", tlbl->key + 100);
8185   emitcode ("mov", "c,ov");
8186   _startLazyDPSEvaluation ();
8187   while (size--)
8188     {
8189       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8190       MOVA (l);
8191       emitcode ("rrc", "a");
8192       aopPut (AOP (result), "a", offset--);
8193     }
8194   _endLazyDPSEvaluation ();
8195   reAdjustPreg (AOP (result));
8196   emitcode ("", "%05d$:", tlbl1->key + 100);
8197   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8198
8199 release:
8200   freeAsmop (left, NULL, ic, TRUE);
8201   freeAsmop (result, NULL, ic, TRUE);
8202 }
8203
8204 /*-----------------------------------------------------------------*/
8205 /* genRightShift - generate code for right shifting                */
8206 /*-----------------------------------------------------------------*/
8207 static void
8208 genRightShift (iCode * ic)
8209 {
8210   operand *right, *left, *result;
8211   sym_link *retype;
8212   int size, offset;
8213   char *l;
8214   symbol *tlbl, *tlbl1;
8215
8216   D (emitcode (";", "genRightShift "););
8217
8218   /* if signed then we do it the hard way preserve the
8219      sign bit moving it inwards */
8220   retype = getSpec (operandType (IC_RESULT (ic)));
8221
8222   if (!SPEC_USIGN (retype))
8223     {
8224       genSignedRightShift (ic);
8225       return;
8226     }
8227
8228   /* signed & unsigned types are treated the same : i.e. the
8229      signed is NOT propagated inwards : quoting from the
8230      ANSI - standard : "for E1 >> E2, is equivalent to division
8231      by 2**E2 if unsigned or if it has a non-negative value,
8232      otherwise the result is implementation defined ", MY definition
8233      is that the sign does not get propagated */
8234
8235   right = IC_RIGHT (ic);
8236   left = IC_LEFT (ic);
8237   result = IC_RESULT (ic);
8238
8239   aopOp (right, ic, FALSE, FALSE);
8240
8241 #ifdef BETTER_LITERAL_SHIFT
8242   /* if the shift count is known then do it
8243      as efficiently as possible */
8244   if (AOP_TYPE (right) == AOP_LIT)
8245     {
8246       if (genRightShiftLiteral (left, right, result, ic, 0))
8247       {
8248         return;
8249       }
8250     }
8251 #endif
8252
8253   /* shift count is unknown then we have to form
8254      a loop get the loop count in B : Note: we take
8255      only the lower order byte since shifting
8256      more that 32 bits make no sense anyway, ( the
8257      largest size of an object can be only 32 bits ) */
8258   
8259   if (AOP_TYPE (right) == AOP_LIT)
8260   {
8261       /* Really should be handled by genRightShiftLiteral,
8262        * but since I'm too lazy to fix that today, at least we can make
8263        * some small improvement.
8264        */
8265        emitcode("mov", "b,#0x%02x",
8266                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8267   }
8268   else
8269   {
8270         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8271         emitcode ("inc", "b");
8272   }
8273   freeAsmop (right, NULL, ic, TRUE);
8274   aopOp (left, ic, FALSE, FALSE);
8275   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8276
8277   /* now move the left to the result if they are not the
8278      same */
8279   if (!sameRegs (AOP (left), AOP (result)) &&
8280       AOP_SIZE (result) > 1)
8281     {
8282
8283       size = AOP_SIZE (result);
8284       offset = 0;
8285       _startLazyDPSEvaluation ();
8286       while (size--)
8287         {
8288           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8289           if (*l == '@' && IS_AOP_PREG (result))
8290             {
8291
8292               emitcode ("mov", "a,%s", l);
8293               aopPut (AOP (result), "a", offset);
8294             }
8295           else
8296             aopPut (AOP (result), l, offset);
8297           offset++;
8298         }
8299       _endLazyDPSEvaluation ();
8300     }
8301
8302   tlbl = newiTempLabel (NULL);
8303   tlbl1 = newiTempLabel (NULL);
8304   size = AOP_SIZE (result);
8305   offset = size - 1;
8306
8307   /* if it is only one byte then */
8308   if (size == 1)
8309     {
8310       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8311       MOVA (l);
8312       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8313       emitcode ("", "%05d$:", tlbl->key + 100);
8314       CLRC;
8315       emitcode ("rrc", "a");
8316       emitcode ("", "%05d$:", tlbl1->key + 100);
8317       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8318       aopPut (AOP (result), "a", 0);
8319       goto release;
8320     }
8321
8322   reAdjustPreg (AOP (result));
8323   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8324   emitcode ("", "%05d$:", tlbl->key + 100);
8325   CLRC;
8326   _startLazyDPSEvaluation ();
8327   while (size--)
8328     {
8329       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8330       MOVA (l);
8331       emitcode ("rrc", "a");
8332       aopPut (AOP (result), "a", offset--);
8333     }
8334   _endLazyDPSEvaluation ();
8335   reAdjustPreg (AOP (result));
8336
8337   emitcode ("", "%05d$:", tlbl1->key + 100);
8338   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8339
8340 release:
8341   freeAsmop (left, NULL, ic, TRUE);
8342   freeAsmop (result, NULL, ic, TRUE);
8343 }
8344
8345 /*-----------------------------------------------------------------*/
8346 /* genUnpackBits - generates code for unpacking bits               */
8347 /*-----------------------------------------------------------------*/
8348 static void
8349 genUnpackBits (operand * result, char *rname, int ptype)
8350 {
8351   int shCnt;
8352   int rlen = 0;
8353   sym_link *etype;
8354   int offset = 0;
8355
8356   D (emitcode (";", "genUnpackBits ");
8357     );
8358
8359   etype = getSpec (operandType (result));
8360
8361   /* read the first byte  */
8362   switch (ptype)
8363     {
8364
8365     case POINTER:
8366     case IPOINTER:
8367       emitcode ("mov", "a,@%s", rname);
8368       break;
8369
8370     case PPOINTER:
8371       emitcode ("movx", "a,@%s", rname);
8372       break;
8373
8374     case FPOINTER:
8375       emitcode ("movx", "a,@dptr");
8376       break;
8377
8378     case CPOINTER:
8379       emitcode ("clr", "a");
8380       emitcode ("movc", "a,@a+dptr");
8381       break;
8382
8383     case GPOINTER:
8384       emitcode ("lcall", "__gptrget");
8385       break;
8386     }
8387
8388   /* if we have bitdisplacement then it fits   */
8389   /* into this byte completely or if length is */
8390   /* less than a byte                          */
8391   if ((shCnt = SPEC_BSTR (etype)) ||
8392       (SPEC_BLEN (etype) <= 8))
8393     {
8394
8395       /* shift right acc */
8396       AccRsh (shCnt);
8397
8398       emitcode ("anl", "a,#0x%02x",
8399                 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
8400       aopPut (AOP (result), "a", offset);
8401       return;
8402     }
8403
8404   /* bit field did not fit in a byte  */
8405   rlen = SPEC_BLEN (etype) - 8;
8406   aopPut (AOP (result), "a", offset++);
8407
8408   while (1)
8409     {
8410
8411       switch (ptype)
8412         {
8413         case POINTER:
8414         case IPOINTER:
8415           emitcode ("inc", "%s", rname);
8416           emitcode ("mov", "a,@%s", rname);
8417           break;
8418
8419         case PPOINTER:
8420           emitcode ("inc", "%s", rname);
8421           emitcode ("movx", "a,@%s", rname);
8422           break;
8423
8424         case FPOINTER:
8425           emitcode ("inc", "dptr");
8426           emitcode ("movx", "a,@dptr");
8427           break;
8428
8429         case CPOINTER:
8430           emitcode ("clr", "a");
8431           emitcode ("inc", "dptr");
8432           emitcode ("movc", "a,@a+dptr");
8433           break;
8434
8435         case GPOINTER:
8436           emitcode ("inc", "dptr");
8437           emitcode ("lcall", "__gptrget");
8438           break;
8439         }
8440
8441       rlen -= 8;
8442       /* if we are done */
8443       if (rlen < 8)
8444         break;
8445
8446       aopPut (AOP (result), "a", offset++);
8447
8448     }
8449
8450   if (rlen)
8451     {
8452       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
8453       aopPut (AOP (result), "a", offset);
8454     }
8455
8456   return;
8457 }
8458
8459
8460 /*-----------------------------------------------------------------*/
8461 /* genDataPointerGet - generates code when ptr offset is known     */
8462 /*-----------------------------------------------------------------*/
8463 static void
8464 genDataPointerGet (operand * left,
8465                    operand * result,
8466                    iCode * ic)
8467 {
8468   char *l;
8469   char buffer[256];
8470   int size, offset = 0;
8471   aopOp (result, ic, TRUE, FALSE);
8472
8473   /* get the string representation of the name */
8474   l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
8475   size = AOP_SIZE (result);
8476   _startLazyDPSEvaluation ();
8477   while (size--)
8478     {
8479       if (offset)
8480         sprintf (buffer, "(%s + %d)", l + 1, offset);
8481       else
8482         sprintf (buffer, "%s", l + 1);
8483       aopPut (AOP (result), buffer, offset++);
8484     }
8485   _endLazyDPSEvaluation ();
8486
8487   freeAsmop (left, NULL, ic, TRUE);
8488   freeAsmop (result, NULL, ic, TRUE);
8489 }
8490
8491 /*-----------------------------------------------------------------*/
8492 /* genNearPointerGet - emitcode for near pointer fetch             */
8493 /*-----------------------------------------------------------------*/
8494 static void
8495 genNearPointerGet (operand * left,
8496                    operand * result,
8497                    iCode * ic)
8498 {
8499   asmop *aop = NULL;
8500   regs *preg = NULL;
8501   char *rname;
8502   sym_link *rtype, *retype, *letype;
8503   sym_link *ltype = operandType (left);
8504   char buffer[80];
8505
8506   rtype = operandType (result);
8507   retype = getSpec (rtype);
8508   letype = getSpec (ltype);
8509
8510   aopOp (left, ic, FALSE, FALSE);
8511
8512   /* if left is rematerialisable and
8513      result is not bit variable type and
8514      the left is pointer to data space i.e
8515      lower 128 bytes of space */
8516   if (AOP_TYPE (left) == AOP_IMMD &&
8517       !IS_BITVAR (retype) &&
8518       !IS_BITVAR (letype) &&
8519       DCL_TYPE (ltype) == POINTER)
8520     {
8521       genDataPointerGet (left, result, ic);
8522       return;
8523     }
8524
8525   /* if the value is already in a pointer register
8526      then don't need anything more */
8527   if (!AOP_INPREG (AOP (left)))
8528     {
8529       /* otherwise get a free pointer register */
8530       aop = newAsmop (0);
8531       preg = getFreePtr (ic, &aop, FALSE);
8532       emitcode ("mov", "%s,%s",
8533                 preg->name,
8534                 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8535       rname = preg->name;
8536     }
8537   else
8538     rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8539
8540   freeAsmop (left, NULL, ic, TRUE);
8541   aopOp (result, ic, FALSE, FALSE);
8542
8543   /* if bitfield then unpack the bits */
8544   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8545     genUnpackBits (result, rname, POINTER);
8546   else
8547     {
8548       /* we have can just get the values */
8549       int size = AOP_SIZE (result);
8550       int offset = 0;
8551
8552       while (size--)
8553         {
8554           if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8555             {
8556
8557               emitcode ("mov", "a,@%s", rname);
8558               aopPut (AOP (result), "a", offset);
8559             }
8560           else
8561             {
8562               sprintf (buffer, "@%s", rname);
8563               aopPut (AOP (result), buffer, offset);
8564             }
8565           offset++;
8566           if (size)
8567             emitcode ("inc", "%s", rname);
8568         }
8569     }
8570
8571   /* now some housekeeping stuff */
8572   if (aop)
8573     {
8574       /* we had to allocate for this iCode */
8575       freeAsmop (NULL, aop, ic, TRUE);
8576     }
8577   else
8578     {
8579       /* we did not allocate which means left
8580          already in a pointer register, then
8581          if size > 0 && this could be used again
8582          we have to point it back to where it
8583          belongs */
8584       if (AOP_SIZE (result) > 1 &&
8585           !OP_SYMBOL (left)->remat &&
8586           (OP_SYMBOL (left)->liveTo > ic->seq ||
8587            ic->depth))
8588         {
8589           int size = AOP_SIZE (result) - 1;
8590           while (size--)
8591             emitcode ("dec", "%s", rname);
8592         }
8593     }
8594
8595   /* done */
8596   freeAsmop (result, NULL, ic, TRUE);
8597
8598 }
8599
8600 /*-----------------------------------------------------------------*/
8601 /* genPagedPointerGet - emitcode for paged pointer fetch           */
8602 /*-----------------------------------------------------------------*/
8603 static void
8604 genPagedPointerGet (operand * left,
8605                     operand * result,
8606                     iCode * ic)
8607 {
8608   asmop *aop = NULL;
8609   regs *preg = NULL;
8610   char *rname;
8611   sym_link *rtype, *retype, *letype;
8612
8613   rtype = operandType (result);
8614   retype = getSpec (rtype);
8615   letype = getSpec (operandType (left));
8616   aopOp (left, ic, FALSE, FALSE);
8617
8618   /* if the value is already in a pointer register
8619      then don't need anything more */
8620   if (!AOP_INPREG (AOP (left)))
8621     {
8622       /* otherwise get a free pointer register */
8623       aop = newAsmop (0);
8624       preg = getFreePtr (ic, &aop, FALSE);
8625       emitcode ("mov", "%s,%s",
8626                 preg->name,
8627                 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8628       rname = preg->name;
8629     }
8630   else
8631     rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8632
8633   freeAsmop (left, NULL, ic, TRUE);
8634   aopOp (result, ic, FALSE, FALSE);
8635
8636   /* if bitfield then unpack the bits */
8637   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8638     genUnpackBits (result, rname, PPOINTER);
8639   else
8640     {
8641       /* we have can just get the values */
8642       int size = AOP_SIZE (result);
8643       int offset = 0;
8644
8645       while (size--)
8646         {
8647
8648           emitcode ("movx", "a,@%s", rname);
8649           aopPut (AOP (result), "a", offset);
8650
8651           offset++;
8652
8653           if (size)
8654             emitcode ("inc", "%s", rname);
8655         }
8656     }
8657
8658   /* now some housekeeping stuff */
8659   if (aop)
8660     {
8661       /* we had to allocate for this iCode */
8662       freeAsmop (NULL, aop, ic, TRUE);
8663     }
8664   else
8665     {
8666       /* we did not allocate which means left
8667          already in a pointer register, then
8668          if size > 0 && this could be used again
8669          we have to point it back to where it
8670          belongs */
8671       if (AOP_SIZE (result) > 1 &&
8672           !OP_SYMBOL (left)->remat &&
8673           (OP_SYMBOL (left)->liveTo > ic->seq ||
8674            ic->depth))
8675         {
8676           int size = AOP_SIZE (result) - 1;
8677           while (size--)
8678             emitcode ("dec", "%s", rname);
8679         }
8680     }
8681
8682   /* done */
8683   freeAsmop (result, NULL, ic, TRUE);
8684
8685
8686 }
8687
8688 /*-----------------------------------------------------------------*/
8689 /* genFarPointerGet - gget value from far space                    */
8690 /*-----------------------------------------------------------------*/
8691 static void
8692 genFarPointerGet (operand * left,
8693                   operand * result, iCode * ic)
8694 {
8695   int size, offset;
8696   sym_link *retype = getSpec (operandType (result));
8697   sym_link *letype = getSpec (operandType (left));
8698   D (emitcode (";", "genFarPointerGet");
8699     );
8700
8701   aopOp (left, ic, FALSE, FALSE);
8702
8703   /* if the operand is already in dptr
8704      then we do nothing else we move the value to dptr */
8705   if (AOP_TYPE (left) != AOP_STR)
8706     {
8707       /* if this is remateriazable */
8708       if (AOP_TYPE (left) == AOP_IMMD)
8709         {
8710           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8711         }
8712       else
8713         {
8714           /* we need to get it byte by byte */
8715           _startLazyDPSEvaluation ();
8716           if (AOP_TYPE (left) != AOP_DPTR)
8717             {
8718               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8719               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8720               if (options.model == MODEL_FLAT24)
8721                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8722             }
8723           else
8724             {
8725               /* We need to generate a load to DPTR indirect through DPTR. */
8726               D (emitcode (";", "genFarPointerGet -- indirection special case.");
8727                 );
8728               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8729               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8730               if (options.model == MODEL_FLAT24)
8731                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8732               emitcode ("pop", "dph");
8733               emitcode ("pop", "dpl");
8734             }
8735           _endLazyDPSEvaluation ();
8736         }
8737     }
8738   /* so dptr know contains the address */
8739   freeAsmop (left, NULL, ic, TRUE);
8740   aopOp (result, ic, FALSE, TRUE);
8741
8742   /* if bit then unpack */
8743   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8744     genUnpackBits (result, "dptr", FPOINTER);
8745   else
8746     {
8747       size = AOP_SIZE (result);
8748       offset = 0;
8749
8750       _startLazyDPSEvaluation ();
8751       while (size--)
8752         {
8753
8754           genSetDPTR (0);
8755           _flushLazyDPS ();
8756
8757           emitcode ("movx", "a,@dptr");
8758           if (size)
8759             emitcode ("inc", "dptr");
8760
8761           aopPut (AOP (result), "a", offset++);
8762         }
8763       _endLazyDPSEvaluation ();
8764     }
8765
8766   freeAsmop (result, NULL, ic, TRUE);
8767 }
8768
8769 /*-----------------------------------------------------------------*/
8770 /* emitcodePointerGet - gget value from code space                  */
8771 /*-----------------------------------------------------------------*/
8772 static void
8773 emitcodePointerGet (operand * left,
8774                     operand * result, iCode * ic)
8775 {
8776   int size, offset;
8777   sym_link *retype = getSpec (operandType (result));
8778
8779   aopOp (left, ic, FALSE, FALSE);
8780
8781   /* if the operand is already in dptr
8782      then we do nothing else we move the value to dptr */
8783   if (AOP_TYPE (left) != AOP_STR)
8784     {
8785       /* if this is remateriazable */
8786       if (AOP_TYPE (left) == AOP_IMMD)
8787         {
8788           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8789         }
8790       else
8791         {                       /* we need to get it byte by byte */
8792           _startLazyDPSEvaluation ();
8793           if (AOP_TYPE (left) != AOP_DPTR)
8794             {
8795               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8796               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8797               if (options.model == MODEL_FLAT24)
8798                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8799             }
8800           else
8801             {
8802               /* We need to generate a load to DPTR indirect through DPTR. */
8803               D (emitcode (";", "gencodePointerGet -- indirection special case.");
8804                 );
8805               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8806               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8807               if (options.model == MODEL_FLAT24)
8808                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8809               emitcode ("pop", "dph");
8810               emitcode ("pop", "dpl");
8811             }
8812           _endLazyDPSEvaluation ();
8813         }
8814     }
8815   /* so dptr know contains the address */
8816   freeAsmop (left, NULL, ic, TRUE);
8817   aopOp (result, ic, FALSE, TRUE);
8818
8819   /* if bit then unpack */
8820   if (IS_BITVAR (retype))
8821     genUnpackBits (result, "dptr", CPOINTER);
8822   else
8823     {
8824       size = AOP_SIZE (result);
8825       offset = 0;
8826
8827       _startLazyDPSEvaluation ();
8828       while (size--)
8829         {
8830           genSetDPTR (0);
8831           _flushLazyDPS ();
8832
8833           emitcode ("clr", "a");
8834           emitcode ("movc", "a,@a+dptr");
8835           if (size)
8836             emitcode ("inc", "dptr");
8837           aopPut (AOP (result), "a", offset++);
8838         }
8839       _endLazyDPSEvaluation ();
8840     }
8841
8842   freeAsmop (result, NULL, ic, TRUE);
8843 }
8844
8845 /*-----------------------------------------------------------------*/
8846 /* genGenPointerGet - gget value from generic pointer space        */
8847 /*-----------------------------------------------------------------*/
8848 static void
8849 genGenPointerGet (operand * left,
8850                   operand * result, iCode * ic)
8851 {
8852   int size, offset;
8853   sym_link *retype = getSpec (operandType (result));
8854   sym_link *letype = getSpec (operandType (left));
8855
8856   D (emitcode (";", "genGenPointerGet "); );
8857
8858   aopOp (left, ic, FALSE, TRUE);
8859
8860   /* if the operand is already in dptr
8861      then we do nothing else we move the value to dptr */
8862   if (AOP_TYPE (left) != AOP_STR)
8863     {
8864       /* if this is remateriazable */
8865       if (AOP_TYPE (left) == AOP_IMMD)
8866         {
8867           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8868           emitcode ("mov", "b,#%d", pointerCode (retype));
8869         }
8870       else
8871         {                       /* we need to get it byte by byte */
8872           _startLazyDPSEvaluation ();
8873           if (AOP(left)->type==AOP_DPTR2) {
8874             char *l;
8875             l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
8876             genSetDPTR(0);
8877             _flushLazyDPS();
8878             emitcode ("mov", "dpl,%s", l);
8879             l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
8880             genSetDPTR(0);
8881             _flushLazyDPS();
8882             emitcode ("mov", "dph,%s", l);
8883             if (options.model == MODEL_FLAT24) {
8884               l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
8885               genSetDPTR(0);
8886               _flushLazyDPS();
8887               emitcode ("mov", "dpx,%s", l);
8888               emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8889             } else {
8890               emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8891             }
8892           } else {
8893             emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
8894             emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
8895             if (options.model == MODEL_FLAT24) {
8896               emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8897               emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8898             } else {
8899               emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8900             }
8901           }
8902           _endLazyDPSEvaluation ();
8903         }
8904     }
8905   /* so dptr know contains the address */
8906   freeAsmop (left, NULL, ic, TRUE);
8907   aopOp (result, ic, FALSE, TRUE);
8908
8909   /* if bit then unpack */
8910   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8911     genUnpackBits (result, "dptr", GPOINTER);
8912   else
8913     {
8914       size = AOP_SIZE (result);
8915       offset = 0;
8916
8917       while (size--)
8918         {
8919           emitcode ("lcall", "__gptrget");
8920           aopPut (AOP (result), "a", offset++);
8921           if (size)
8922             emitcode ("inc", "dptr");
8923         }
8924     }
8925
8926   freeAsmop (result, NULL, ic, TRUE);
8927 }
8928
8929 /*-----------------------------------------------------------------*/
8930 /* genPointerGet - generate code for pointer get                   */
8931 /*-----------------------------------------------------------------*/
8932 static void
8933 genPointerGet (iCode * ic)
8934 {
8935   operand *left, *result;
8936   sym_link *type, *etype;
8937   int p_type;
8938
8939   D (emitcode (";", "genPointerGet ");
8940     );
8941
8942   left = IC_LEFT (ic);
8943   result = IC_RESULT (ic);
8944
8945   /* depending on the type of pointer we need to
8946      move it to the correct pointer register */
8947   type = operandType (left);
8948   etype = getSpec (type);
8949   /* if left is of type of pointer then it is simple */
8950   if (IS_PTR (type) && !IS_FUNC (type->next))
8951     p_type = DCL_TYPE (type);
8952   else
8953     {
8954       /* we have to go by the storage class */
8955       p_type = PTR_TYPE (SPEC_OCLS (etype));
8956     }
8957
8958   /* now that we have the pointer type we assign
8959      the pointer values */
8960   switch (p_type)
8961     {
8962
8963     case POINTER:
8964     case IPOINTER:
8965       genNearPointerGet (left, result, ic);
8966       break;
8967
8968     case PPOINTER:
8969       genPagedPointerGet (left, result, ic);
8970       break;
8971
8972     case FPOINTER:
8973       genFarPointerGet (left, result, ic);
8974       break;
8975
8976     case CPOINTER:
8977       emitcodePointerGet (left, result, ic);
8978       break;
8979
8980     case GPOINTER:
8981       genGenPointerGet (left, result, ic);
8982       break;
8983     }
8984
8985 }
8986
8987 /*-----------------------------------------------------------------*/
8988 /* genPackBits - generates code for packed bit storage             */
8989 /*-----------------------------------------------------------------*/
8990 static void
8991 genPackBits (sym_link * etype,
8992              operand * right,
8993              char *rname, int p_type)
8994 {
8995   int shCount = 0;
8996   int offset = 0;
8997   int rLen = 0;
8998   int blen, bstr;
8999   char *l;
9000
9001   blen = SPEC_BLEN (etype);
9002   bstr = SPEC_BSTR (etype);
9003
9004   l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9005   MOVA (l);
9006
9007   /* if the bit lenth is less than or    */
9008   /* it exactly fits a byte then         */
9009   if (SPEC_BLEN (etype) <= 8)
9010     {
9011       shCount = SPEC_BSTR (etype);
9012
9013       /* shift left acc */
9014       AccLsh (shCount);
9015
9016       if (SPEC_BLEN (etype) < 8)
9017         {                       /* if smaller than a byte */
9018
9019
9020           switch (p_type)
9021             {
9022             case POINTER:
9023               emitcode ("mov", "b,a");
9024               emitcode ("mov", "a,@%s", rname);
9025               break;
9026
9027             case FPOINTER:
9028               emitcode ("mov", "b,a");
9029               emitcode ("movx", "a,@dptr");
9030               break;
9031
9032             case GPOINTER:
9033               emitcode ("push", "b");
9034               emitcode ("push", "acc");
9035               emitcode ("lcall", "__gptrget");
9036               emitcode ("pop", "b");
9037               break;
9038             }
9039
9040           emitcode ("anl", "a,#0x%02x", (unsigned char)
9041                     ((unsigned char) (0xFF << (blen + bstr)) |
9042                      (unsigned char) (0xFF >> (8 - bstr))));
9043           emitcode ("orl", "a,b");
9044           if (p_type == GPOINTER)
9045             emitcode ("pop", "b");
9046         }
9047     }
9048
9049   switch (p_type)
9050     {
9051     case POINTER:
9052       emitcode ("mov", "@%s,a", rname);
9053       break;
9054
9055     case FPOINTER:
9056       emitcode ("movx", "@dptr,a");
9057       break;
9058
9059     case GPOINTER:
9060       emitcode ("lcall", "__gptrput");
9061       break;
9062     }
9063
9064   /* if we r done */
9065   if (SPEC_BLEN (etype) <= 8)
9066     return;
9067
9068   emitcode ("inc", "%s", rname);
9069   rLen = SPEC_BLEN (etype);
9070
9071   /* now generate for lengths greater than one byte */
9072   while (1)
9073     {
9074
9075       l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
9076
9077       rLen -= 8;
9078       if (rLen < 8)
9079         break;
9080
9081       switch (p_type)
9082         {
9083         case POINTER:
9084           if (*l == '@')
9085             {
9086               MOVA (l);
9087               emitcode ("mov", "@%s,a", rname);
9088             }
9089           else
9090             emitcode ("mov", "@%s,%s", rname, l);
9091           break;
9092
9093         case FPOINTER:
9094           MOVA (l);
9095           emitcode ("movx", "@dptr,a");
9096           break;
9097
9098         case GPOINTER:
9099           MOVA (l);
9100           emitcode ("lcall", "__gptrput");
9101           break;
9102         }
9103       emitcode ("inc", "%s", rname);
9104     }
9105
9106   MOVA (l);
9107
9108   /* last last was not complete */
9109   if (rLen)
9110     {
9111       /* save the byte & read byte */
9112       switch (p_type)
9113         {
9114         case POINTER:
9115           emitcode ("mov", "b,a");
9116           emitcode ("mov", "a,@%s", rname);
9117           break;
9118
9119         case FPOINTER:
9120           emitcode ("mov", "b,a");
9121           emitcode ("movx", "a,@dptr");
9122           break;
9123
9124         case GPOINTER:
9125           emitcode ("push", "b");
9126           emitcode ("push", "acc");
9127           emitcode ("lcall", "__gptrget");
9128           emitcode ("pop", "b");
9129           break;
9130         }
9131
9132       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
9133       emitcode ("orl", "a,b");
9134     }
9135
9136   if (p_type == GPOINTER)
9137     emitcode ("pop", "b");
9138
9139   switch (p_type)
9140     {
9141
9142     case POINTER:
9143       emitcode ("mov", "@%s,a", rname);
9144       break;
9145
9146     case FPOINTER:
9147       emitcode ("movx", "@dptr,a");
9148       break;
9149
9150     case GPOINTER:
9151       emitcode ("lcall", "__gptrput");
9152       break;
9153     }
9154 }
9155 /*-----------------------------------------------------------------*/
9156 /* genDataPointerSet - remat pointer to data space                 */
9157 /*-----------------------------------------------------------------*/
9158 static void
9159 genDataPointerSet (operand * right,
9160                    operand * result,
9161                    iCode * ic)
9162 {
9163   int size, offset = 0;
9164   char *l, buffer[256];
9165
9166   aopOp (right, ic, FALSE, FALSE);
9167
9168   l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
9169   size = AOP_SIZE (right);
9170   while (size--)
9171     {
9172       if (offset)
9173         sprintf (buffer, "(%s + %d)", l + 1, offset);
9174       else
9175         sprintf (buffer, "%s", l + 1);
9176       emitcode ("mov", "%s,%s", buffer,
9177                 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
9178     }
9179
9180   freeAsmop (right, NULL, ic, TRUE);
9181   freeAsmop (result, NULL, ic, TRUE);
9182 }
9183
9184 /*-----------------------------------------------------------------*/
9185 /* genNearPointerSet - emitcode for near pointer put                */
9186 /*-----------------------------------------------------------------*/
9187 static void
9188 genNearPointerSet (operand * right,
9189                    operand * result,
9190                    iCode * ic)
9191 {
9192   asmop *aop = NULL;
9193   regs *preg = NULL;
9194   char *rname, *l;
9195   sym_link *retype, *letype;
9196   sym_link *ptype = operandType (result);
9197
9198   retype = getSpec (operandType (right));
9199   letype = getSpec (ptype);
9200
9201   aopOp (result, ic, FALSE, FALSE);
9202
9203   /* if the result is rematerializable &
9204      in data space & not a bit variable */
9205   if (AOP_TYPE (result) == AOP_IMMD &&
9206       DCL_TYPE (ptype) == POINTER &&
9207       !IS_BITVAR (retype) &&
9208       !IS_BITVAR (letype))
9209     {
9210       genDataPointerSet (right, result, ic);
9211       return;
9212     }
9213
9214   /* if the value is already in a pointer register
9215      then don't need anything more */
9216   if (!AOP_INPREG (AOP (result)))
9217     {
9218       /* otherwise get a free pointer register */
9219       aop = newAsmop (0);
9220       preg = getFreePtr (ic, &aop, FALSE);
9221       emitcode ("mov", "%s,%s",
9222                 preg->name,
9223                 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9224       rname = preg->name;
9225     }
9226   else
9227     rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9228
9229   freeAsmop (result, NULL, ic, TRUE);
9230   aopOp (right, ic, FALSE, FALSE);
9231
9232   /* if bitfield then unpack the bits */
9233   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9234     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
9235   else
9236     {
9237       /* we have can just get the values */
9238       int size = AOP_SIZE (right);
9239       int offset = 0;
9240
9241       while (size--)
9242         {
9243           l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
9244           if (*l == '@')
9245             {
9246               MOVA (l);
9247               emitcode ("mov", "@%s,a", rname);
9248             }
9249           else
9250             emitcode ("mov", "@%s,%s", rname, l);
9251           if (size)
9252             emitcode ("inc", "%s", rname);
9253           offset++;
9254         }
9255     }
9256
9257   /* now some housekeeping stuff */
9258   if (aop)
9259     {
9260       /* we had to allocate for this iCode */
9261       freeAsmop (NULL, aop, ic, TRUE);
9262     }
9263   else
9264     {
9265       /* we did not allocate which means left
9266          already in a pointer register, then
9267          if size > 0 && this could be used again
9268          we have to point it back to where it
9269          belongs */
9270       if (AOP_SIZE (right) > 1 &&
9271           !OP_SYMBOL (result)->remat &&
9272           (OP_SYMBOL (result)->liveTo > ic->seq ||
9273            ic->depth))
9274         {
9275           int size = AOP_SIZE (right) - 1;
9276           while (size--)
9277             emitcode ("dec", "%s", rname);
9278         }
9279     }
9280
9281   /* done */
9282   freeAsmop (right, NULL, ic, TRUE);
9283
9284
9285 }
9286
9287 /*-----------------------------------------------------------------*/
9288 /* genPagedPointerSet - emitcode for Paged pointer put             */
9289 /*-----------------------------------------------------------------*/
9290 static void
9291 genPagedPointerSet (operand * right,
9292                     operand * result,
9293                     iCode * ic)
9294 {
9295   asmop *aop = NULL;
9296   regs *preg = NULL;
9297   char *rname, *l;
9298   sym_link *retype, *letype;
9299
9300   retype = getSpec (operandType (right));
9301   letype = getSpec (operandType (result));
9302
9303   aopOp (result, ic, FALSE, FALSE);
9304
9305   /* if the value is already in a pointer register
9306      then don't need anything more */
9307   if (!AOP_INPREG (AOP (result)))
9308     {
9309       /* otherwise get a free pointer register */
9310       aop = newAsmop (0);
9311       preg = getFreePtr (ic, &aop, FALSE);
9312       emitcode ("mov", "%s,%s",
9313                 preg->name,
9314                 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9315       rname = preg->name;
9316     }
9317   else
9318     rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9319
9320   freeAsmop (result, NULL, ic, TRUE);
9321   aopOp (right, ic, FALSE, FALSE);
9322
9323   /* if bitfield then unpack the bits */
9324   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9325     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
9326   else
9327     {
9328       /* we have can just get the values */
9329       int size = AOP_SIZE (right);
9330       int offset = 0;
9331
9332       while (size--)
9333         {
9334           l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
9335
9336           MOVA (l);
9337           emitcode ("movx", "@%s,a", rname);
9338
9339           if (size)
9340             emitcode ("inc", "%s", rname);
9341
9342           offset++;
9343         }
9344     }
9345
9346   /* now some housekeeping stuff */
9347   if (aop)
9348     {
9349       /* we had to allocate for this iCode */
9350       freeAsmop (NULL, aop, ic, TRUE);
9351     }
9352   else
9353     {
9354       /* we did not allocate which means left
9355          already in a pointer register, then
9356          if size > 0 && this could be used again
9357          we have to point it back to where it
9358          belongs */
9359       if (AOP_SIZE (right) > 1 &&
9360           !OP_SYMBOL (result)->remat &&
9361           (OP_SYMBOL (result)->liveTo > ic->seq ||
9362            ic->depth))
9363         {
9364           int size = AOP_SIZE (right) - 1;
9365           while (size--)
9366             emitcode ("dec", "%s", rname);
9367         }
9368     }
9369
9370   /* done */
9371   freeAsmop (right, NULL, ic, TRUE);
9372
9373
9374 }
9375
9376 /*-----------------------------------------------------------------*/
9377 /* genFarPointerSet - set value from far space                     */
9378 /*-----------------------------------------------------------------*/
9379 static void
9380 genFarPointerSet (operand * right,
9381                   operand * result, iCode * ic)
9382 {
9383   int size, offset;
9384   sym_link *retype = getSpec (operandType (right));
9385   sym_link *letype = getSpec (operandType (result));
9386
9387   aopOp (result, ic, FALSE, FALSE);
9388
9389   /* if the operand is already in dptr
9390      then we do nothing else we move the value to dptr */
9391   if (AOP_TYPE (result) != AOP_STR)
9392     {
9393       /* if this is remateriazable */
9394       if (AOP_TYPE (result) == AOP_IMMD)
9395         emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9396       else
9397         {
9398           /* we need to get it byte by byte */
9399           _startLazyDPSEvaluation ();
9400           if (AOP_TYPE (result) != AOP_DPTR)
9401             {
9402               emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9403               emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9404               if (options.model == MODEL_FLAT24)
9405                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9406             }
9407           else
9408             {
9409               /* We need to generate a load to DPTR indirect through DPTR. */
9410               D (emitcode (";", "genFarPointerSet -- indirection special case.");
9411                 );
9412               emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
9413               emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
9414               if (options.model == MODEL_FLAT24)
9415                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9416               emitcode ("pop", "dph");
9417               emitcode ("pop", "dpl");
9418             }
9419           _endLazyDPSEvaluation ();
9420         }
9421     }
9422   /* so dptr know contains the address */
9423   freeAsmop (result, NULL, ic, TRUE);
9424   aopOp (right, ic, FALSE, TRUE);
9425
9426   /* if bit then unpack */
9427   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9428     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
9429   else
9430     {
9431       size = AOP_SIZE (right);
9432       offset = 0;
9433
9434       _startLazyDPSEvaluation ();
9435       while (size--)
9436         {
9437           char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9438           MOVA (l);
9439
9440           genSetDPTR (0);
9441           _flushLazyDPS ();
9442
9443           emitcode ("movx", "@dptr,a");
9444           if (size)
9445             emitcode ("inc", "dptr");
9446         }
9447       _endLazyDPSEvaluation ();
9448     }
9449
9450   freeAsmop (right, NULL, ic, TRUE);
9451 }
9452
9453 /*-----------------------------------------------------------------*/
9454 /* genGenPointerSet - set value from generic pointer space         */
9455 /*-----------------------------------------------------------------*/
9456 static void
9457 genGenPointerSet (operand * right,
9458                   operand * result, iCode * ic)
9459 {
9460   int size, offset;
9461   sym_link *retype = getSpec (operandType (right));
9462   sym_link *letype = getSpec (operandType (result));
9463
9464   aopOp (result, ic, FALSE, TRUE);
9465
9466   /* if the operand is already in dptr
9467      then we do nothing else we move the value to dptr */
9468   if (AOP_TYPE (result) != AOP_STR)
9469     {
9470       _startLazyDPSEvaluation ();
9471       /* if this is remateriazable */
9472       if (AOP_TYPE (result) == AOP_IMMD)
9473         {
9474           emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9475           emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9476         }
9477       else
9478         {                       /* we need to get it byte by byte */
9479           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9480           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9481           if (options.model == MODEL_FLAT24) {
9482             emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9483             emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
9484           } else {
9485             emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9486           }
9487         }
9488       _endLazyDPSEvaluation ();
9489     }
9490   /* so dptr know contains the address */
9491   freeAsmop (result, NULL, ic, TRUE);
9492   aopOp (right, ic, FALSE, TRUE);
9493
9494   /* if bit then unpack */
9495   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9496     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
9497   else
9498     {
9499       size = AOP_SIZE (right);
9500       offset = 0;
9501
9502       _startLazyDPSEvaluation ();
9503       while (size--)
9504         {
9505           char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9506           MOVA (l);
9507
9508           genSetDPTR (0);
9509           _flushLazyDPS ();
9510
9511           emitcode ("lcall", "__gptrput");
9512           if (size)
9513             emitcode ("inc", "dptr");
9514         }
9515       _endLazyDPSEvaluation ();
9516     }
9517
9518   freeAsmop (right, NULL, ic, TRUE);
9519 }
9520
9521 /*-----------------------------------------------------------------*/
9522 /* genPointerSet - stores the value into a pointer location        */
9523 /*-----------------------------------------------------------------*/
9524 static void
9525 genPointerSet (iCode * ic)
9526 {
9527   operand *right, *result;
9528   sym_link *type, *etype;
9529   int p_type;
9530
9531   D (emitcode (";", "genPointerSet ");
9532     );
9533
9534   right = IC_RIGHT (ic);
9535   result = IC_RESULT (ic);
9536
9537   /* depending on the type of pointer we need to
9538      move it to the correct pointer register */
9539   type = operandType (result);
9540   etype = getSpec (type);
9541   /* if left is of type of pointer then it is simple */
9542   if (IS_PTR (type) && !IS_FUNC (type->next))
9543     {
9544       p_type = DCL_TYPE (type);
9545     }
9546   else
9547     {
9548       /* we have to go by the storage class */
9549       p_type = PTR_TYPE (SPEC_OCLS (etype));
9550     }
9551
9552   /* now that we have the pointer type we assign
9553      the pointer values */
9554   switch (p_type)
9555     {
9556
9557     case POINTER:
9558     case IPOINTER:
9559       genNearPointerSet (right, result, ic);
9560       break;
9561
9562     case PPOINTER:
9563       genPagedPointerSet (right, result, ic);
9564       break;
9565
9566     case FPOINTER:
9567       genFarPointerSet (right, result, ic);
9568       break;
9569
9570     case GPOINTER:
9571       genGenPointerSet (right, result, ic);
9572       break;
9573     }
9574
9575 }
9576
9577 /*-----------------------------------------------------------------*/
9578 /* genIfx - generate code for Ifx statement                        */
9579 /*-----------------------------------------------------------------*/
9580 static void
9581 genIfx (iCode * ic, iCode * popIc)
9582 {
9583   operand *cond = IC_COND (ic);
9584   int isbit = 0;
9585
9586   D (emitcode (";", "genIfx "););
9587
9588   aopOp (cond, ic, FALSE, FALSE);
9589
9590   /* get the value into acc */
9591   if (AOP_TYPE (cond) != AOP_CRY)
9592     toBoolean (cond);
9593   else
9594     isbit = 1;
9595   /* the result is now in the accumulator */
9596   freeAsmop (cond, NULL, ic, TRUE);
9597
9598   /* if there was something to be popped then do it */
9599   if (popIc)
9600     genIpop (popIc);
9601
9602   /* if the condition is  a bit variable */
9603   if (isbit && IS_ITEMP (cond) &&
9604       SPIL_LOC (cond))
9605     genIfxJump (ic, SPIL_LOC (cond)->rname);
9606   else if (isbit && !IS_ITEMP (cond))
9607     genIfxJump (ic, OP_SYMBOL (cond)->rname);
9608   else
9609     genIfxJump (ic, "a");
9610
9611   ic->generated = 1;
9612 }
9613
9614 /*-----------------------------------------------------------------*/
9615 /* genAddrOf - generates code for address of                       */
9616 /*-----------------------------------------------------------------*/
9617 static void
9618 genAddrOf (iCode * ic)
9619 {
9620   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
9621   int size, offset;
9622
9623   D (emitcode (";", "genAddrOf ");
9624     );
9625
9626   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9627
9628   /* if the operand is on the stack then we
9629      need to get the stack offset of this
9630      variable */
9631   if (sym->onStack)
9632     {
9633       /* if it has an offset then we need to compute
9634          it */
9635       if (sym->stack)
9636         {
9637           emitcode ("mov", "a,_bp");
9638           emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
9639           aopPut (AOP (IC_RESULT (ic)), "a", 0);
9640         }
9641       else
9642         {
9643           /* we can just move _bp */
9644           aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
9645         }
9646       /* fill the result with zero */
9647       size = AOP_SIZE (IC_RESULT (ic)) - 1;
9648
9649
9650       if (options.stack10bit && size < (FPTRSIZE - 1))
9651         {
9652           fprintf (stderr,
9653                    "*** warning: pointer to stack var truncated.\n");
9654         }
9655
9656       offset = 1;
9657       while (size--)
9658         {
9659           /* Yuck! */
9660           if (options.stack10bit && offset == 2)
9661             {
9662               aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
9663             }
9664           else
9665             {
9666               aopPut (AOP (IC_RESULT (ic)), zero, offset++);
9667             }
9668         }
9669
9670       goto release;
9671     }
9672
9673   /* object not on stack then we need the name */
9674   size = AOP_SIZE (IC_RESULT (ic));
9675   offset = 0;
9676
9677   while (size--)
9678     {
9679       char s[SDCC_NAME_MAX];
9680       if (offset)
9681         sprintf (s, "#(%s >> %d)",
9682                  sym->rname,
9683                  offset * 8);
9684       else
9685         sprintf (s, "#%s", sym->rname);
9686       aopPut (AOP (IC_RESULT (ic)), s, offset++);
9687     }
9688
9689 release:
9690   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9691
9692 }
9693
9694 /*-----------------------------------------------------------------*/
9695 /* genArrayInit - generates code for address of                       */
9696 /*-----------------------------------------------------------------*/
9697 static void
9698 genArrayInit (iCode * ic)
9699 {
9700     literalList *iLoop;
9701     int         ix, count;
9702     int         elementSize = 0, eIndex;
9703     unsigned    val, lastVal;
9704     sym_link    *type;
9705     operand     *left=IC_LEFT(ic);
9706     
9707     D (emitcode (";", "genArrayInit "););
9708
9709     aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
9710     
9711     if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
9712     {
9713         // Load immediate value into DPTR.
9714         emitcode("mov", "dptr, %s",
9715              aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, TRUE));
9716     }
9717     else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
9718     {
9719 #if 0
9720       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9721               "Unexpected operand to genArrayInit.\n");
9722       exit(1);
9723 #else
9724       // a regression because of SDCCcse.c:1.52
9725       emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9726       emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9727       if (options.model == MODEL_FLAT24)
9728         emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9729 #endif
9730     }
9731     
9732     type = operandType(IC_LEFT(ic));
9733     
9734     if (type && type->next)
9735     {
9736         elementSize = getSize(type->next);
9737     }
9738     else
9739     {
9740         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9741                                 "can't determine element size in genArrayInit.\n");
9742         exit(1);
9743     }
9744     
9745     iLoop = IC_ARRAYILIST(ic);
9746     lastVal = 0xffff;
9747     
9748     while (iLoop)
9749     {
9750         bool firstpass = TRUE;
9751         
9752         emitcode(";", "store %d x 0x%x to DPTR (element size %d)", 
9753                  iLoop->count, (int)iLoop->literalValue, elementSize);
9754         
9755         ix = iLoop->count;
9756         
9757         while (ix)
9758         {
9759             symbol *tlbl = NULL;
9760             
9761             count = ix > 256 ? 256 : ix;
9762             
9763             if (count > 1)
9764             {
9765                 tlbl = newiTempLabel (NULL);
9766                 if (firstpass || (count & 0xff))
9767                 {
9768                     emitcode("mov", "b, #0x%x", count & 0xff);
9769                 }
9770                 
9771                 emitcode ("", "%05d$:", tlbl->key + 100);
9772             }
9773             
9774             firstpass = FALSE;
9775                 
9776             for (eIndex = 0; eIndex < elementSize; eIndex++)
9777             {
9778                 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
9779                 if (val != lastVal)
9780                 {
9781                     emitcode("mov", "a, #0x%x", val);
9782                     lastVal = val;
9783                 }
9784                 
9785                 emitcode("movx", "@dptr, a");
9786                 emitcode("inc", "dptr");
9787             }
9788             
9789             if (count > 1)
9790             {
9791                 emitcode("djnz", "b, %05d$", tlbl->key + 100);
9792             }
9793             
9794             ix -= count;
9795         }
9796         
9797         iLoop = iLoop->next;
9798     }
9799     
9800     freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
9801 }
9802
9803 /*-----------------------------------------------------------------*/
9804 /* genFarFarAssign - assignment when both are in far space         */
9805 /*-----------------------------------------------------------------*/
9806 static void
9807 genFarFarAssign (operand * result, operand * right, iCode * ic)
9808 {
9809   int size = AOP_SIZE (right);
9810   int offset = 0;
9811   symbol *rSym = NULL;
9812
9813   if (size == 1)
9814   {
9815       /* quick & easy case. */
9816       D(emitcode(";","genFarFarAssign (1 byte case)"););      
9817       MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
9818       freeAsmop (right, NULL, ic, FALSE);
9819       /* now assign DPTR to result */
9820       _G.accInUse++;
9821       aopOp(result, ic, FALSE, FALSE);
9822       _G.accInUse--;
9823       aopPut(AOP(result), "a", 0);
9824       freeAsmop(result, NULL, ic, FALSE);
9825       return;
9826   }
9827   
9828   /* See if we've got an underlying symbol to abuse. */
9829   if (IS_SYMOP(result) && OP_SYMBOL(result))
9830   {
9831       if (IS_TRUE_SYMOP(result))
9832       {
9833           rSym = OP_SYMBOL(result);
9834       }
9835       else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
9836       {
9837           rSym = OP_SYMBOL(result)->usl.spillLoc;
9838       }
9839   }
9840              
9841   if (size > 1 && rSym && rSym->rname && !rSym->onStack)
9842   {
9843       /* We can use the '390 auto-toggle feature to good effect here. */
9844       
9845       D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
9846       emitcode("mov", "dps, #0x21");    /* Select DPTR2 & auto-toggle. */
9847       emitcode ("mov", "dptr,#%s", rSym->rname); 
9848       /* DP2 = result, DP1 = right, DP1 is current. */
9849       while (size)
9850       {
9851           emitcode("movx", "a,@dptr");
9852           emitcode("movx", "@dptr,a");
9853           if (--size)
9854           {
9855                emitcode("inc", "dptr");
9856                emitcode("inc", "dptr");
9857           }
9858       }
9859       emitcode("mov", "dps, #0");
9860       freeAsmop (right, NULL, ic, FALSE);
9861 #if 0
9862 some alternative code for processors without auto-toggle
9863 no time to test now, so later well put in...kpb
9864         D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
9865         emitcode("mov", "dps, #0x01");  /* Select DPTR2. */
9866         emitcode ("mov", "dptr,#%s", rSym->rname); 
9867         /* DP2 = result, DP1 = right, DP1 is current. */
9868         while (size)
9869         {
9870           --size;
9871           emitcode("movx", "a,@dptr");
9872           if (size)
9873             emitcode("inc", "dptr");
9874           emitcode("inc", "dps");
9875           emitcode("movx", "@dptr,a");
9876           if (size)
9877             emitcode("inc", "dptr");
9878           emitcode("inc", "dps");
9879         }
9880         emitcode("mov", "dps, #0");
9881         freeAsmop (right, NULL, ic, FALSE);
9882 #endif
9883   }
9884   else
9885   {
9886       D (emitcode (";", "genFarFarAssign"););
9887       aopOp (result, ic, TRUE, TRUE);
9888
9889       _startLazyDPSEvaluation ();
9890       
9891       while (size--)
9892         {
9893           aopPut (AOP (result),
9894                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
9895           offset++;
9896         }
9897       _endLazyDPSEvaluation ();
9898       freeAsmop (result, NULL, ic, FALSE);
9899       freeAsmop (right, NULL, ic, FALSE);
9900   }
9901 }
9902
9903 /*-----------------------------------------------------------------*/
9904 /* genAssign - generate code for assignment                        */
9905 /*-----------------------------------------------------------------*/
9906 static void
9907 genAssign (iCode * ic)
9908 {
9909   operand *result, *right;
9910   int size, offset;
9911   unsigned long lit = 0L;
9912
9913   D (emitcode (";", "genAssign ");
9914     );
9915
9916   result = IC_RESULT (ic);
9917   right = IC_RIGHT (ic);
9918
9919   /* if they are the same */
9920   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9921     return;
9922
9923   aopOp (right, ic, FALSE, FALSE);
9924
9925   emitcode (";", "genAssign: resultIsFar = %s",
9926             isOperandInFarSpace (result) ?
9927             "TRUE" : "FALSE");
9928
9929   /* special case both in far space */
9930   if ((AOP_TYPE (right) == AOP_DPTR ||
9931        AOP_TYPE (right) == AOP_DPTR2) &&
9932   /* IS_TRUE_SYMOP(result)       && */
9933       isOperandInFarSpace (result))
9934     {
9935       genFarFarAssign (result, right, ic);
9936       return;
9937     }
9938
9939   aopOp (result, ic, TRUE, FALSE);
9940
9941   /* if they are the same registers */
9942   if (sameRegs (AOP (right), AOP (result)))
9943     goto release;
9944
9945   /* if the result is a bit */
9946   if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
9947     {
9948       /* if the right size is a literal then
9949          we know what the value is */
9950       if (AOP_TYPE (right) == AOP_LIT)
9951         {
9952           if (((int) operandLitValue (right)))
9953             aopPut (AOP (result), one, 0);
9954           else
9955             aopPut (AOP (result), zero, 0);
9956           goto release;
9957         }
9958
9959       /* the right is also a bit variable */
9960       if (AOP_TYPE (right) == AOP_CRY)
9961         {
9962           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9963           aopPut (AOP (result), "c", 0);
9964           goto release;
9965         }
9966
9967       /* we need to or */
9968       toBoolean (right);
9969       aopPut (AOP (result), "a", 0);
9970       goto release;
9971     }
9972
9973   /* bit variables done */
9974   /* general case */
9975   size = AOP_SIZE (result);
9976   offset = 0;
9977   if (AOP_TYPE (right) == AOP_LIT)
9978     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
9979
9980   if ((size > 1) &&
9981       (AOP_TYPE (result) != AOP_REG) &&
9982       (AOP_TYPE (right) == AOP_LIT) &&
9983       !IS_FLOAT (operandType (right)))
9984     {
9985       _startLazyDPSEvaluation ();
9986       while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
9987         {
9988           aopPut (AOP (result),
9989                   aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
9990                   offset);
9991           offset++;
9992           size--;
9993         }
9994       /* And now fill the rest with zeros. */
9995       if (size)
9996         {
9997           emitcode ("clr", "a");
9998         }
9999       while (size--)
10000         {
10001           aopPut (AOP (result), "a", offset++);
10002         }
10003       _endLazyDPSEvaluation ();
10004     }
10005   else
10006     {
10007       _startLazyDPSEvaluation ();
10008       while (size--)
10009         {
10010           aopPut (AOP (result),
10011                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10012                   offset);
10013           offset++;
10014         }
10015       _endLazyDPSEvaluation ();
10016     }
10017
10018 release:
10019   freeAsmop (right, NULL, ic, FALSE);
10020   freeAsmop (result, NULL, ic, TRUE);
10021 }
10022
10023 /*-----------------------------------------------------------------*/
10024 /* genJumpTab - generates code for jump table                      */
10025 /*-----------------------------------------------------------------*/
10026 static void
10027 genJumpTab (iCode * ic)
10028 {
10029   symbol *jtab;
10030   char *l;
10031
10032   D (emitcode (";", "genJumpTab ");
10033     );
10034
10035   aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10036   /* get the condition into accumulator */
10037   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
10038   MOVA (l);
10039   /* multiply by four! */
10040   emitcode ("add", "a,acc");
10041   emitcode ("add", "a,acc");
10042   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10043
10044   jtab = newiTempLabel (NULL);
10045   emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
10046   emitcode ("jmp", "@a+dptr");
10047   emitcode ("", "%05d$:", jtab->key + 100);
10048   /* now generate the jump labels */
10049   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10050        jtab = setNextItem (IC_JTLABELS (ic)))
10051     emitcode ("ljmp", "%05d$", jtab->key + 100);
10052
10053 }
10054
10055 /*-----------------------------------------------------------------*/
10056 /* genCast - gen code for casting                                  */
10057 /*-----------------------------------------------------------------*/
10058 static void
10059 genCast (iCode * ic)
10060 {
10061   operand *result = IC_RESULT (ic);
10062   sym_link *ctype = operandType (IC_LEFT (ic));
10063   sym_link *rtype = operandType (IC_RIGHT (ic));
10064   operand *right = IC_RIGHT (ic);
10065   int size, offset;
10066
10067   D (emitcode (";", "genCast ");
10068     );
10069
10070   /* if they are equivalent then do nothing */
10071   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10072     return;
10073
10074   aopOp (right, ic, FALSE, FALSE);
10075   aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
10076
10077   /* if the result is a bit */
10078   // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10079   if (IS_BITVAR(OP_SYMBOL(result)->type))
10080     {
10081       /* if the right size is a literal then
10082          we know what the value is */
10083       if (AOP_TYPE (right) == AOP_LIT)
10084         {
10085           if (((int) operandLitValue (right)))
10086             aopPut (AOP (result), one, 0);
10087           else
10088             aopPut (AOP (result), zero, 0);
10089
10090           goto release;
10091         }
10092
10093       /* the right is also a bit variable */
10094       if (AOP_TYPE (right) == AOP_CRY)
10095         {
10096           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10097           aopPut (AOP (result), "c", 0);
10098           goto release;
10099         }
10100
10101       /* we need to or */
10102       toBoolean (right);
10103       aopPut (AOP (result), "a", 0);
10104       goto release;
10105     }
10106
10107   /* if they are the same size : or less */
10108   if (AOP_SIZE (result) <= AOP_SIZE (right))
10109     {
10110
10111       /* if they are in the same place */
10112       if (sameRegs (AOP (right), AOP (result)))
10113         goto release;
10114
10115       /* if they in different places then copy */
10116       size = AOP_SIZE (result);
10117       offset = 0;
10118       _startLazyDPSEvaluation ();
10119       while (size--)
10120         {
10121           aopPut (AOP (result),
10122                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10123                   offset);
10124           offset++;
10125         }
10126       _endLazyDPSEvaluation ();
10127       goto release;
10128     }
10129
10130
10131   /* if the result is of type pointer */
10132   if (IS_PTR (ctype))
10133     {
10134
10135       int p_type;
10136       sym_link *type = operandType (right);
10137
10138       /* pointer to generic pointer */
10139       if (IS_GENPTR (ctype))
10140         {
10141           char *l = zero;
10142
10143           if (IS_PTR (type))
10144             {
10145               p_type = DCL_TYPE (type);
10146             }
10147           else
10148             {
10149 #if OLD_CAST_BEHAVIOR
10150               /* KV: we are converting a non-pointer type to
10151                * a generic pointer. This (ifdef'd out) code
10152                * says that the resulting generic pointer
10153                * should have the same class as the storage
10154                * location of the non-pointer variable.
10155                *
10156                * For example, converting an int (which happens
10157                * to be stored in DATA space) to a pointer results
10158                * in a DATA generic pointer; if the original int
10159                * in XDATA space, so will be the resulting pointer.
10160                *
10161                * I don't like that behavior, and thus this change:
10162                * all such conversions will be forced to XDATA and
10163                * throw a warning. If you want some non-XDATA
10164                * type, or you want to suppress the warning, you
10165                * must go through an intermediate cast, like so:
10166                *
10167                * char _generic *gp = (char _xdata *)(intVar);
10168                */
10169               sym_link *etype = getSpec (type);
10170
10171               /* we have to go by the storage class */
10172               if (SPEC_OCLS (etype) != generic)
10173                 {
10174                   p_type = PTR_TYPE (SPEC_OCLS (etype));
10175                 }
10176               else
10177 #endif
10178                 {
10179                   /* Converting unknown class (i.e. register variable)
10180                    * to generic pointer. This is not good, but
10181                    * we'll make a guess (and throw a warning).
10182                    */
10183                   p_type = FPOINTER;
10184                   werror (W_INT_TO_GEN_PTR_CAST);
10185                 }
10186             }
10187
10188           /* the first two bytes are known */
10189           size = GPTRSIZE - 1;
10190           offset = 0;
10191           _startLazyDPSEvaluation ();
10192           while (size--)
10193             {
10194               aopPut (AOP (result),
10195                       aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10196                       offset);
10197               offset++;
10198             }
10199           _endLazyDPSEvaluation ();
10200
10201           /* the last byte depending on type */
10202           switch (p_type)
10203             {
10204             case IPOINTER:
10205             case POINTER:
10206               l = zero;
10207               break;
10208             case FPOINTER:
10209               l = one;
10210               break;
10211             case CPOINTER:
10212               l = "#0x02";
10213               break;
10214             case PPOINTER:
10215               l = "#0x03";
10216               break;
10217
10218             default:
10219               /* this should never happen */
10220               werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10221                       "got unknown pointer type");
10222               exit (1);
10223             }
10224           aopPut (AOP (result), l, GPTRSIZE - 1);
10225           goto release;
10226         }
10227
10228       /* just copy the pointers */
10229       size = AOP_SIZE (result);
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       goto release;
10241     }
10242
10243   /* so we now know that the size of destination is greater
10244      than the size of the source */
10245   /* we move to result for the size of source */
10246   size = AOP_SIZE (right);
10247   offset = 0;
10248   _startLazyDPSEvaluation ();
10249   while (size--)
10250     {
10251       aopPut (AOP (result),
10252               aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10253               offset);
10254       offset++;
10255     }
10256   _endLazyDPSEvaluation ();
10257
10258   /* now depending on the sign of the source && destination */
10259   size = AOP_SIZE (result) - AOP_SIZE (right);
10260   /* if unsigned or not an integral type */
10261   /* also, if the source is a bit, we don't need to sign extend, because
10262    * it can't possibly have set the sign bit.
10263    */
10264   if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
10265     {
10266       while (size--)
10267         {
10268           aopPut (AOP (result), zero, offset++);
10269         }
10270     }
10271   else
10272     {
10273       /* we need to extend the sign :{ */
10274       char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
10275                         FALSE, FALSE, TRUE);
10276       MOVA (l);
10277       emitcode ("rlc", "a");
10278       emitcode ("subb", "a,acc");
10279       while (size--)
10280         aopPut (AOP (result), "a", offset++);
10281     }
10282
10283   /* we are done hurray !!!! */
10284
10285 release:
10286   freeAsmop (right, NULL, ic, TRUE);
10287   freeAsmop (result, NULL, ic, TRUE);
10288
10289 }
10290
10291 /*-----------------------------------------------------------------*/
10292 /* genDjnz - generate decrement & jump if not zero instrucion      */
10293 /*-----------------------------------------------------------------*/
10294 static int
10295 genDjnz (iCode * ic, iCode * ifx)
10296 {
10297   symbol *lbl, *lbl1;
10298   if (!ifx)
10299     return 0;
10300
10301   /* if the if condition has a false label
10302      then we cannot save */
10303   if (IC_FALSE (ifx))
10304     return 0;
10305
10306   /* if the minus is not of the form
10307      a = a - 1 */
10308   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
10309       !IS_OP_LITERAL (IC_RIGHT (ic)))
10310     return 0;
10311
10312   if (operandLitValue (IC_RIGHT (ic)) != 1)
10313     return 0;
10314
10315   /* if the size of this greater than one then no
10316      saving */
10317   if (getSize (operandType (IC_RESULT (ic))) > 1)
10318     return 0;
10319
10320   /* otherwise we can save BIG */
10321   D(emitcode(";", "genDjnz"););
10322
10323   lbl = newiTempLabel (NULL);
10324   lbl1 = newiTempLabel (NULL);
10325
10326   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10327
10328   if (AOP_NEEDSACC(IC_RESULT(ic)))
10329   {
10330       /* If the result is accessed indirectly via
10331        * the accumulator, we must explicitly write
10332        * it back after the decrement.
10333        */
10334       char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
10335       
10336       if (strcmp(rByte, "a"))
10337       {
10338            /* Something is hopelessly wrong */
10339            fprintf(stderr, "*** warning: internal error at %s:%d\n",
10340                    __FILE__, __LINE__);
10341            /* We can just give up; the generated code will be inefficient,
10342             * but what the hey.
10343             */
10344            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10345            return 0;
10346       }
10347       emitcode ("dec", "%s", rByte);
10348       aopPut(AOP(IC_RESULT(ic)), rByte, 0);
10349       emitcode ("jnz", "%05d$", lbl->key + 100);
10350   }
10351   else if (IS_AOP_PREG (IC_RESULT (ic)))
10352     {
10353       emitcode ("dec", "%s",
10354                 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10355       emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10356       emitcode ("jnz", "%05d$", lbl->key + 100);
10357     }
10358   else
10359     {
10360       emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
10361                 lbl->key + 100);
10362     }
10363   emitcode ("sjmp", "%05d$", lbl1->key + 100);
10364   emitcode ("", "%05d$:", lbl->key + 100);
10365   emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
10366   emitcode ("", "%05d$:", lbl1->key + 100);
10367
10368   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10369   ifx->generated = 1;
10370   return 1;
10371 }
10372
10373 /*-----------------------------------------------------------------*/
10374 /* genReceive - generate code for a receive iCode                  */
10375 /*-----------------------------------------------------------------*/
10376 static void
10377 genReceive (iCode * ic)
10378 {
10379
10380   D (emitcode (";", "genReceive ");
10381     );
10382
10383   if (isOperandInFarSpace (IC_RESULT (ic)) &&
10384       (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
10385        IS_TRUE_SYMOP (IC_RESULT (ic))))
10386     {
10387       int size = getSize (operandType (IC_RESULT (ic)));
10388       int offset = fReturnSizeDS390 - size;
10389       while (size--)
10390         {
10391           emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
10392                             fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
10393           offset++;
10394         }
10395       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10396       size = AOP_SIZE (IC_RESULT (ic));
10397       offset = 0;
10398       while (size--)
10399         {
10400           emitcode ("pop", "acc");
10401           aopPut (AOP (IC_RESULT (ic)), "a", offset++);
10402         }
10403
10404     }
10405   else
10406     {
10407       _G.accInUse++;
10408       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10409       _G.accInUse--;
10410       assignResultValue (IC_RESULT (ic));
10411     }
10412
10413   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10414 }
10415
10416 /*-----------------------------------------------------------------*/
10417 /* gen390Code - generate code for Dallas 390 based controllers     */
10418 /*-----------------------------------------------------------------*/
10419 void
10420 gen390Code (iCode * lic)
10421 {
10422   iCode *ic;
10423   int cln = 0;
10424
10425   lineHead = lineCurr = NULL;
10426
10427   if (options.model == MODEL_FLAT24) {
10428     fReturnSizeDS390 = 5;
10429     fReturn = fReturn24;
10430   } else {
10431     fReturnSizeDS390 = 4;
10432     fReturn = fReturn16;
10433     options.stack10bit=0;
10434   }
10435 #if 0
10436   //REMOVE ME!!!
10437   /* print the allocation information */
10438   if (allocInfo)
10439     printAllocInfo (currFunc, codeOutFile);
10440 #endif
10441   /* if debug information required */
10442   if (options.debug && currFunc)
10443     {
10444       cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
10445       _G.debugLine = 1;
10446       if (IS_STATIC (currFunc->etype))
10447         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
10448       else
10449         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
10450       _G.debugLine = 0;
10451     }
10452   /* stack pointer name */
10453   if (options.useXstack)
10454     spname = "_spx";
10455   else
10456     spname = "sp";
10457
10458
10459   for (ic = lic; ic; ic = ic->next)
10460     {
10461
10462       if (cln != ic->lineno)
10463         {
10464           if (options.debug)
10465             {
10466               _G.debugLine = 1;
10467               emitcode ("", "C$%s$%d$%d$%d ==.",
10468                         FileBaseName (ic->filename), ic->lineno,
10469                         ic->level, ic->block);
10470               _G.debugLine = 0;
10471             }
10472           emitcode (";", "%s %d", ic->filename, ic->lineno);
10473           cln = ic->lineno;
10474         }
10475       /* if the result is marked as
10476          spilt and rematerializable or code for
10477          this has already been generated then
10478          do nothing */
10479       if (resultRemat (ic) || ic->generated)
10480         continue;
10481
10482       /* depending on the operation */
10483       switch (ic->op)
10484         {
10485         case '!':
10486           genNot (ic);
10487           break;
10488
10489         case '~':
10490           genCpl (ic);
10491           break;
10492
10493         case UNARYMINUS:
10494           genUminus (ic);
10495           break;
10496
10497         case IPUSH:
10498           genIpush (ic);
10499           break;
10500
10501         case IPOP:
10502           /* IPOP happens only when trying to restore a
10503              spilt live range, if there is an ifx statement
10504              following this pop then the if statement might
10505              be using some of the registers being popped which
10506              would destory the contents of the register so
10507              we need to check for this condition and handle it */
10508           if (ic->next &&
10509               ic->next->op == IFX &&
10510               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
10511             genIfx (ic->next, ic);
10512           else
10513             genIpop (ic);
10514           break;
10515
10516         case CALL:
10517           genCall (ic);
10518           break;
10519
10520         case PCALL:
10521           genPcall (ic);
10522           break;
10523
10524         case FUNCTION:
10525           genFunction (ic);
10526           break;
10527
10528         case ENDFUNCTION:
10529           genEndFunction (ic);
10530           break;
10531
10532         case RETURN:
10533           genRet (ic);
10534           break;
10535
10536         case LABEL:
10537           genLabel (ic);
10538           break;
10539
10540         case GOTO:
10541           genGoto (ic);
10542           break;
10543
10544         case '+':
10545           genPlus (ic);
10546           break;
10547
10548         case '-':
10549           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
10550             genMinus (ic);
10551           break;
10552
10553         case '*':
10554           genMult (ic);
10555           break;
10556
10557         case '/':
10558           genDiv (ic);
10559           break;
10560
10561         case '%':
10562           genMod (ic);
10563           break;
10564
10565         case '>':
10566           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
10567           break;
10568
10569         case '<':
10570           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
10571           break;
10572
10573         case LE_OP:
10574         case GE_OP:
10575         case NE_OP:
10576
10577           /* note these two are xlated by algebraic equivalence
10578              during parsing SDCC.y */
10579           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10580                   "got '>=' or '<=' shouldn't have come here");
10581           break;
10582
10583         case EQ_OP:
10584           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
10585           break;
10586
10587         case AND_OP:
10588           genAndOp (ic);
10589           break;
10590
10591         case OR_OP:
10592           genOrOp (ic);
10593           break;
10594
10595         case '^':
10596           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
10597           break;
10598
10599         case '|':
10600           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
10601           break;
10602
10603         case BITWISEAND:
10604           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
10605           break;
10606
10607         case INLINEASM:
10608           genInline (ic);
10609           break;
10610
10611         case RRC:
10612           genRRC (ic);
10613           break;
10614
10615         case RLC:
10616           genRLC (ic);
10617           break;
10618
10619         case GETHBIT:
10620           genGetHbit (ic);
10621           break;
10622
10623         case LEFT_OP:
10624           genLeftShift (ic);
10625           break;
10626
10627         case RIGHT_OP:
10628           genRightShift (ic);
10629           break;
10630
10631         case GET_VALUE_AT_ADDRESS:
10632           genPointerGet (ic);
10633           break;
10634
10635         case '=':
10636           if (POINTER_SET (ic))
10637             genPointerSet (ic);
10638           else
10639             genAssign (ic);
10640           break;
10641
10642         case IFX:
10643           genIfx (ic, NULL);
10644           break;
10645
10646         case ADDRESS_OF:
10647           genAddrOf (ic);
10648           break;
10649
10650         case JUMPTABLE:
10651           genJumpTab (ic);
10652           break;
10653
10654         case CAST:
10655           genCast (ic);
10656           break;
10657
10658         case RECEIVE:
10659           genReceive (ic);
10660           break;
10661
10662         case SEND:
10663           addSet (&_G.sendSet, ic);
10664           break;
10665
10666         case ARRAYINIT:
10667             genArrayInit(ic);
10668             break;
10669             
10670         default:
10671           ic = ic;
10672         }
10673     }
10674
10675
10676   /* now we are ready to call the
10677      peep hole optimizer */
10678   if (!options.nopeep)
10679     peepHole (&lineHead);
10680
10681   /* now do the actual printing */
10682   printLine (lineHead, codeOutFile);
10683   return;
10684 }