fixed bug #481053
[fw/sdcc] / src / ds390 / gen.c
1 /*-------------------------------------------------------------------------
2   gen.c - source file for code generation for DS80C390
3
4   Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
5          and -  Jean-Louis VERN.jlvern@writeme.com (1999)
6   Bug Fixes  -  Wojciech Stryjewski  wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7   DS390 adaptation by Kevin Vigor <kevin@vigor.nu>
8
9   This program is free software; you can redistribute it and/or modify it
10   under the terms of the GNU General Public License as published by the
11   Free Software Foundation; either version 2, or (at your option) any
12   later version.
13
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License for more details.
18
19   You should have received a copy of the GNU General Public License
20   along with this program; if not, write to the Free Software
21   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22
23   In other words, you are welcome to use, share and improve this program.
24   You are forbidden to forbid anyone else to use, share and improve
25   what you give them.   Help stamp out software-hoarding!
26 -------------------------------------------------------------------------*/
27
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <ctype.h>
32
33 #include <common.h>
34 #include "ralloc.h"
35 #include "gen.h"
36 #include "SDCCglobl.h"
37 #include "newalloc.h"
38
39 #ifdef HAVE_SYS_ISA_DEFS_H
40 #include <sys/isa_defs.h>
41 #else
42 #ifdef HAVE_MACHINE_ENDIAN_H
43 #include <machine/endian.h>
44 #else
45 #ifdef HAVE_ENDIAN_H
46 #include <endian.h>
47 #else
48 #if !defined(__BORLANDC__) && !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__CYGWIN__)
49 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
50 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
51 #endif
52 #endif
53 #endif
54 #endif
55
56 #define BETTER_LITERAL_SHIFT
57
58 char *aopLiteral (value * val, int offset);
59
60 /* this is the down and dirty file with all kinds of
61    kludgy & hacky stuff. This is what it is all about
62    CODE GENERATION for a specific MCU . some of the
63    routines may be reusable, will have to see */
64
65 static char *zero = "#0x00";
66 static char *one = "#0x01";
67 static char *spname;
68
69 #define D(x) x
70
71 #define TR_DPTR(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_DPTR1 %s ", s); }
72 #define TR_AP(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_AP %s ", s); }
73
74 unsigned fReturnSizeDS390 = 5;  /* shared with ralloc.c */
75 static char *fReturn24[] =
76 {"dpl", "dph", "dpx", "b", "a"};
77 static char *fReturn16[] =
78 {"dpl", "dph", "b", "a"};
79 static char **fReturn = fReturn24;
80 static char *accUse[] =
81 {"a", "b"};
82
83 static short rbank = -1;
84
85 static struct
86   {
87     short r0Pushed;
88     short r1Pushed;
89     short accInUse;
90     short inLine;
91     short debugLine;
92     short nRegsSaved;
93     set *sendSet;
94   }
95 _G;
96
97 static void saveRBank (int, iCode *, bool);
98
99 #define RESULTONSTACK(x) \
100                          (IC_RESULT(x) && IC_RESULT(x)->aop && \
101                          IC_RESULT(x)->aop->type == AOP_STK )
102
103 /* #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x); */
104 #define MOVA(x) { char *_mova_tmp = strdup(x); \
105                  if (strcmp(_mova_tmp,"a") && strcmp(_mova_tmp,"acc")) \
106                  { \
107                     emitcode("mov","a,%s",_mova_tmp); \
108                  } \
109                  free(_mova_tmp); \
110                 }
111 #define CLRC    emitcode("clr","c")
112 #define SETC    emitcode("setb","c")
113
114 // A scratch register which will be used to hold
115 // result bytes from operands in far space via DPTR2.
116 #define DP2_RESULT_REG  "ap"
117
118 static lineNode *lineHead = NULL;
119 static lineNode *lineCurr = NULL;
120
121 static unsigned char SLMask[] =
122 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
123  0xE0, 0xC0, 0x80, 0x00};
124 static unsigned char SRMask[] =
125 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
126  0x07, 0x03, 0x01, 0x00};
127
128 #define LSB     0
129 #define MSB16   1
130 #define MSB24   2
131 #define MSB32   3
132
133 /*-----------------------------------------------------------------*/
134 /* emitcode - writes the code into a file : for now it is simple    */
135 /*-----------------------------------------------------------------*/
136 static void
137 emitcode (char *inst, char *fmt,...)
138 {
139   va_list ap;
140   char lb[INITIAL_INLINEASM];
141   char *lbp = lb;
142
143   va_start (ap, fmt);
144
145   if (inst && *inst)
146     {
147       if (fmt && *fmt)
148         sprintf (lb, "%s\t", inst);
149       else
150         sprintf (lb, "%s", inst);
151       vsprintf (lb + (strlen (lb)), fmt, ap);
152     }
153   else
154     vsprintf (lb, fmt, ap);
155
156   while (isspace (*lbp))
157     lbp++;
158
159   if (lbp && *lbp)
160     lineCurr = (lineCurr ?
161                 connectLine (lineCurr, newLineNode (lb)) :
162                 (lineHead = newLineNode (lb)));
163   lineCurr->isInline = _G.inLine;
164   lineCurr->isDebug = _G.debugLine;
165   va_end (ap);
166 }
167
168 /*-----------------------------------------------------------------*/
169 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
170 /*-----------------------------------------------------------------*/
171 static regs *
172 getFreePtr (iCode * ic, asmop ** aopp, bool result)
173 {
174   bool r0iu = FALSE, r1iu = FALSE;
175   bool r0ou = FALSE, r1ou = FALSE;
176
177   /* the logic: if r0 & r1 used in the instruction
178      then we are in trouble otherwise */
179
180   /* first check if r0 & r1 are used by this
181      instruction, in which case we are in trouble */
182   r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
183   r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
184   if (r0iu && r1iu) {
185       goto endOfWorld;
186     }
187
188   r0ou = bitVectBitValue (ic->rMask, R0_IDX);
189   r1ou = bitVectBitValue (ic->rMask, R1_IDX);
190
191   /* if no usage of r0 then return it */
192   if (!r0iu && !r0ou)
193     {
194       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
195       (*aopp)->type = AOP_R0;
196
197       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
198     }
199
200   /* if no usage of r1 then return it */
201   if (!r1iu && !r1ou)
202     {
203       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
204       (*aopp)->type = AOP_R1;
205
206       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R1_IDX);
207     }
208
209   /* now we know they both have usage */
210   /* if r0 not used in this instruction */
211   if (!r0iu)
212     {
213       /* push it if not already pushed */
214       if (!_G.r0Pushed)
215         {
216           emitcode ("push", "%s",
217                     ds390_regWithIdx (R0_IDX)->dname);
218           _G.r0Pushed++;
219         }
220
221       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
222       (*aopp)->type = AOP_R0;
223
224       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
225     }
226
227   /* if r1 not used then */
228
229   if (!r1iu)
230     {
231       /* push it if not already pushed */
232       if (!_G.r1Pushed)
233         {
234           emitcode ("push", "%s",
235                     ds390_regWithIdx (R1_IDX)->dname);
236           _G.r1Pushed++;
237         }
238
239       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
240       (*aopp)->type = AOP_R1;
241       return ds390_regWithIdx (R1_IDX);
242     }
243
244 endOfWorld:
245   /* I said end of world but not quite end of world yet */
246   /* if this is a result then we can push it on the stack */
247   if (result)
248     {
249       (*aopp)->type = AOP_STK;
250       return NULL;
251     }
252
253   /* other wise this is true end of the world */
254   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
255           "getFreePtr should never reach here");
256   exit (1);
257 }
258
259 /*-----------------------------------------------------------------*/
260 /* newAsmop - creates a new asmOp                                  */
261 /*-----------------------------------------------------------------*/
262 static asmop *
263 newAsmop (short type)
264 {
265   asmop *aop;
266
267   aop = Safe_calloc (1, sizeof (asmop));
268   aop->type = type;
269   return aop;
270 }
271
272 static int _currentDPS;         /* Current processor DPS. */
273 static int _desiredDPS;         /* DPS value compiler thinks we should be using. */
274 static int _lazyDPS = 0;        /* if non-zero, we are doing lazy evaluation of DPS changes. */
275
276 /*-----------------------------------------------------------------*/
277 /* genSetDPTR: generate code to select which DPTR is in use (zero  */
278 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390     */
279 /* alternate DPTR (DPL1/DPH1/DPX1).          */
280 /*-----------------------------------------------------------------*/
281 static void
282 genSetDPTR (int n)
283 {
284
285   /* If we are doing lazy evaluation, simply note the desired
286    * change, but don't emit any code yet.
287    */
288   if (_lazyDPS)
289     {
290       _desiredDPS = n;
291       return;
292     }
293
294   if (!n)
295     {
296       emitcode ("mov", "dps, #0x00");
297     }
298   else
299     {
300       TR_DPTR("#1");
301       emitcode ("mov", "dps, #0x01");
302     }
303 }
304
305 /*-----------------------------------------------------------------*/
306 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
307 /*                   */
308 /* Any code that operates on DPTR (NB: not on the individual     */
309 /* components, like DPH) *must* call _flushLazyDPS() before using  */
310 /* DPTR within a lazy DPS evaluation block.        */
311 /*                   */
312 /* Note that aopPut and aopGet already contain the proper calls to */
313 /* _flushLazyDPS, so it is safe to use these calls within a lazy   */
314 /* DPS evaluation block.             */
315 /*                   */
316 /* Also, _flushLazyDPS must be called before any flow control      */
317 /* operations that could potentially branch out of the block.    */
318 /*                         */
319 /* Lazy DPS evaluation is simply an optimization (though an      */
320 /* important one), so if in doubt, leave it out.       */
321 /*-----------------------------------------------------------------*/
322 static void
323 _startLazyDPSEvaluation (void)
324 {
325   _currentDPS = 0;
326   _desiredDPS = 0;
327 #ifdef BETTER_LITERAL_SHIFT  
328   _lazyDPS++;
329 #else
330   _lazyDPS = 1;
331 #endif  
332 }
333
334 /*-----------------------------------------------------------------*/
335 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
336 /* desired one. Call before using DPTR within a lazy DPS evaluation */
337 /* block.                */
338 /*-----------------------------------------------------------------*/
339 static void
340 _flushLazyDPS (void)
341 {
342   if (!_lazyDPS)
343     {
344       /* nothing to do. */
345       return;
346     }
347
348   if (_desiredDPS != _currentDPS)
349     {
350       if (_desiredDPS)
351         {
352           emitcode ("inc", "dps");
353         }
354       else
355         {
356           emitcode ("dec", "dps");
357         }
358       _currentDPS = _desiredDPS;
359     }
360 }
361
362 /*-----------------------------------------------------------------*/
363 /* _endLazyDPSEvaluation: end lazy DPS evaluation block.     */
364 /*                   */
365 /* Forces us back to the safe state (standard DPTR selected).    */
366 /*-----------------------------------------------------------------*/
367 static void
368 _endLazyDPSEvaluation (void)
369 {
370 #ifdef BETTER_LITERAL_SHIFT  
371   _lazyDPS--;
372 #else
373   _lazyDPS = 0;
374 #endif    
375   if (!_lazyDPS)
376   {
377     if (_currentDPS)
378     {
379       genSetDPTR (0);
380       _flushLazyDPS ();
381     }
382     _currentDPS = 0;
383     _desiredDPS = 0;
384   }
385 }
386
387
388
389 /*-----------------------------------------------------------------*/
390 /* pointerCode - returns the code for a pointer type               */
391 /*-----------------------------------------------------------------*/
392 static int
393 pointerCode (sym_link * etype)
394 {
395
396   return PTR_TYPE (SPEC_OCLS (etype));
397
398 }
399
400 /*-----------------------------------------------------------------*/
401 /* aopForSym - for a true symbol                                   */
402 /*-----------------------------------------------------------------*/
403 static asmop *
404 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
405 {
406   asmop *aop;
407   memmap *space = SPEC_OCLS (sym->etype);
408
409   /* if already has one */
410   if (sym->aop)
411     return sym->aop;
412
413   /* assign depending on the storage class */
414   /* if it is on the stack or indirectly addressable */
415   /* space we need to assign either r0 or r1 to it   */
416   if ((sym->onStack && !options.stack10bit) || sym->iaccess)
417     {
418       sym->aop = aop = newAsmop (0);
419       aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
420       aop->size = getSize (sym->type);
421
422       /* now assign the address of the variable to
423          the pointer register */
424       if (aop->type != AOP_STK)
425         {
426
427           if (sym->onStack)
428             {
429               if (_G.accInUse)
430                 emitcode ("push", "acc");
431
432               emitcode ("mov", "a,_bp");
433               emitcode ("add", "a,#0x%02x",
434                         ((sym->stack < 0) ?
435                          ((char) (sym->stack - _G.nRegsSaved)) :
436                          ((char) sym->stack)) & 0xff);
437               emitcode ("mov", "%s,a",
438                         aop->aopu.aop_ptr->name);
439
440               if (_G.accInUse)
441                 emitcode ("pop", "acc");
442             }
443           else
444             emitcode ("mov", "%s,#%s",
445                       aop->aopu.aop_ptr->name,
446                       sym->rname);
447           aop->paged = space->paged;
448         }
449       else
450         aop->aopu.aop_stk = sym->stack;
451       return aop;
452     }
453
454   if (sym->onStack && options.stack10bit)
455     {
456       /* It's on the 10 bit stack, which is located in
457        * far data space.
458        */
459
460       if (_G.accInUse)
461         emitcode ("push", "acc");
462
463       emitcode ("mov", "a,_bp");
464       emitcode ("add", "a,#0x%02x",
465                 ((sym->stack < 0) ?
466                  ((char) (sym->stack - _G.nRegsSaved)) :
467                  ((char) sym->stack)) & 0xff);
468
469       if (useDP2)
470         {
471           if (options.model == MODEL_FLAT24)
472             emitcode ("mov", "dpx1,#0x40");
473           TR_DPTR("#2");
474           emitcode ("mov", "dph1,#0x00");
475           emitcode ("mov", "dpl1, a");
476         }
477       else
478         {
479           if (options.model == MODEL_FLAT24)
480             emitcode ("mov", "dpx,#0x40");
481           emitcode ("mov", "dph,#0x00");
482           emitcode ("mov", "dpl, a");
483         }
484
485       if (_G.accInUse)
486         emitcode ("pop", "acc");
487
488       sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
489       aop->size = getSize (sym->type);
490       return aop;
491     }
492
493   /* if in bit space */
494   if (IN_BITSPACE (space))
495     {
496       sym->aop = aop = newAsmop (AOP_CRY);
497       aop->aopu.aop_dir = sym->rname;
498       aop->size = getSize (sym->type);
499       return aop;
500     }
501   /* if it is in direct space */
502   if (IN_DIRSPACE (space))
503     {
504       sym->aop = aop = newAsmop (AOP_DIR);
505       aop->aopu.aop_dir = sym->rname;
506       aop->size = getSize (sym->type);
507       return aop;
508     }
509
510   /* special case for a function */
511   if (IS_FUNC (sym->type))
512     {
513       sym->aop = aop = newAsmop (AOP_IMMD);
514       aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
515       strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
516       aop->size = FPTRSIZE;
517       return aop;
518     }
519
520   /* only remaining is far space */
521   /* in which case DPTR gets the address */
522   sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
523   if (useDP2)
524     {
525       genSetDPTR (1);
526       _flushLazyDPS ();
527       emitcode ("mov", "dptr,#%s", sym->rname);
528       genSetDPTR (0);
529     }
530   else
531     {
532       emitcode ("mov", "dptr,#%s", sym->rname);
533     }
534   aop->size = getSize (sym->type);
535
536   /* if it is in code space */
537   if (IN_CODESPACE (space))
538     aop->code = 1;
539
540   return aop;
541 }
542
543 /*-----------------------------------------------------------------*/
544 /* aopForRemat - rematerialzes an object                           */
545 /*-----------------------------------------------------------------*/
546 static asmop *
547 aopForRemat (symbol * sym)
548 {
549   iCode *ic = sym->rematiCode;
550   asmop *aop = newAsmop (AOP_IMMD);
551   int ptr_type =0;
552   int val = 0;
553
554   for (;;)
555     {
556       if (ic->op == '+')
557         val += (int) operandLitValue (IC_RIGHT (ic));
558       else if (ic->op == '-')
559         val -= (int) operandLitValue (IC_RIGHT (ic));
560       else if (IS_CAST_ICODE(ic)) {
561               sym_link *from_type = operandType(IC_RIGHT(ic));
562               aop->aopu.aop_immd.from_cast_remat = 1;
563               ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
564               ptr_type = DCL_TYPE(from_type);
565               if (ptr_type == IPOINTER) {
566                 // bug #481053
567                 ptr_type = POINTER;
568               }
569               continue ;
570       } else break;
571       
572       ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
573     }
574
575   if (val)
576     sprintf (buffer, "(%s %c 0x%04x)",
577              OP_SYMBOL (IC_LEFT (ic))->rname,
578              val >= 0 ? '+' : '-',
579              abs (val) & 0xffff);
580   else
581     strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
582
583   aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
584   strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
585   /* set immd2 field if required */
586   if (aop->aopu.aop_immd.from_cast_remat) {
587           sprintf(buffer,"#0x%02x",ptr_type);
588           aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
589           strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
590   }
591
592   return aop;
593 }
594
595 /*-----------------------------------------------------------------*/
596 /* regsInCommon - two operands have some registers in common       */
597 /*-----------------------------------------------------------------*/
598 static bool
599 regsInCommon (operand * op1, operand * op2)
600 {
601   symbol *sym1, *sym2;
602   int i;
603
604   /* if they have registers in common */
605   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
606     return FALSE;
607
608   sym1 = OP_SYMBOL (op1);
609   sym2 = OP_SYMBOL (op2);
610
611   if (sym1->nRegs == 0 || sym2->nRegs == 0)
612     return FALSE;
613
614   for (i = 0; i < sym1->nRegs; i++)
615     {
616       int j;
617       if (!sym1->regs[i])
618         continue;
619
620       for (j = 0; j < sym2->nRegs; j++)
621         {
622           if (!sym2->regs[j])
623             continue;
624
625           if (sym2->regs[j] == sym1->regs[i])
626             return TRUE;
627         }
628     }
629
630   return FALSE;
631 }
632
633 /*-----------------------------------------------------------------*/
634 /* operandsEqu - equivalent                                        */
635 /*-----------------------------------------------------------------*/
636 static bool
637 operandsEqu (operand * op1, operand * op2)
638 {
639   symbol *sym1, *sym2;
640
641   /* if they not symbols */
642   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
643     return FALSE;
644
645   sym1 = OP_SYMBOL (op1);
646   sym2 = OP_SYMBOL (op2);
647
648   /* if both are itemps & one is spilt
649      and the other is not then false */
650   if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
651       sym1->isspilt != sym2->isspilt)
652     return FALSE;
653
654   /* if they are the same */
655   if (sym1 == sym2)
656     return TRUE;
657
658   if (strcmp (sym1->rname, sym2->rname) == 0)
659     return TRUE;
660
661
662   /* if left is a tmp & right is not */
663   if (IS_ITEMP (op1) &&
664       !IS_ITEMP (op2) &&
665       sym1->isspilt &&
666       (sym1->usl.spillLoc == sym2))
667     return TRUE;
668
669   if (IS_ITEMP (op2) &&
670       !IS_ITEMP (op1) &&
671       sym2->isspilt &&
672       sym1->level > 0 &&
673       (sym2->usl.spillLoc == sym1))
674     return TRUE;
675
676   return FALSE;
677 }
678
679 /*-----------------------------------------------------------------*/
680 /* sameRegs - two asmops have the same registers                   */
681 /*-----------------------------------------------------------------*/
682 static bool
683 sameRegs (asmop * aop1, asmop * aop2)
684 {
685   int i;
686
687   if (aop1 == aop2)
688     {
689       if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
690         {
691           return FALSE;
692         }
693       return TRUE;
694     }
695
696   if (aop1->type != AOP_REG ||
697       aop2->type != AOP_REG)
698     return FALSE;
699
700   if (aop1->size != aop2->size)
701     return FALSE;
702
703   for (i = 0; i < aop1->size; i++)
704     if (aop1->aopu.aop_reg[i] !=
705         aop2->aopu.aop_reg[i])
706       return FALSE;
707
708   return TRUE;
709 }
710
711 /*-----------------------------------------------------------------*/
712 /* aopOp - allocates an asmop for an operand  :                    */
713 /*-----------------------------------------------------------------*/
714 static void
715 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
716 {
717   asmop *aop;
718   symbol *sym;
719   int i;
720
721   if (!op)
722     return;
723
724   /* if this a literal */
725   if (IS_OP_LITERAL (op))
726     {
727       op->aop = aop = newAsmop (AOP_LIT);
728       aop->aopu.aop_lit = op->operand.valOperand;
729       aop->size = getSize (operandType (op));
730       return;
731     }
732
733   /* if already has a asmop then continue */
734   if (op->aop)
735     return;
736
737   /* if the underlying symbol has a aop */
738   if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
739     {
740       op->aop = OP_SYMBOL (op)->aop;
741       return;
742     }
743
744   /* if this is a true symbol */
745   if (IS_TRUE_SYMOP (op))
746     {
747       op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
748       return;
749     }
750
751   /* this is a temporary : this has
752      only four choices :
753      a) register
754      b) spillocation
755      c) rematerialize
756      d) conditional
757      e) can be a return use only */
758
759   sym = OP_SYMBOL (op);
760
761
762   /* if the type is a conditional */
763   if (sym->regType == REG_CND)
764     {
765       aop = op->aop = sym->aop = newAsmop (AOP_CRY);
766       aop->size = 0;
767       return;
768     }
769
770   /* if it is spilt then two situations
771      a) is rematerialize
772      b) has a spill location */
773   if (sym->isspilt || sym->nRegs == 0)
774     {
775
776       /* rematerialize it NOW */
777       if (sym->remat)
778         {
779           sym->aop = op->aop = aop =
780             aopForRemat (sym);
781           aop->size = getSize (sym->type);
782           return;
783         }
784
785       if (sym->accuse)
786         {
787           int i;
788           aop = op->aop = sym->aop = newAsmop (AOP_ACC);
789           aop->size = getSize (sym->type);
790           for (i = 0; i < 2; i++)
791             aop->aopu.aop_str[i] = accUse[i];
792           return;
793         }
794
795       if (sym->ruonly)
796         {
797           int i;
798
799           if (useDP2)
800             {
801               /* a AOP_STR uses DPTR, but DPTR is already in use;
802                * we're just hosed.
803                */
804               fprintf (stderr, "*** Internal error: AOP_STR with DPTR in use! for operand %s\n",sym->name);
805             }
806
807           aop = op->aop = sym->aop = newAsmop (AOP_STR);
808           aop->size = getSize (sym->type);
809           for (i = 0; i < (int) fReturnSizeDS390; i++)
810             aop->aopu.aop_str[i] = fReturn[i];
811           return;
812         }
813
814       /* else spill location  */
815       sym->aop = op->aop = aop =
816         aopForSym (ic, sym->usl.spillLoc, result, useDP2);
817       aop->size = getSize (sym->type);
818       return;
819     }
820
821   /* must be in a register */
822   sym->aop = op->aop = aop = newAsmop (AOP_REG);
823   aop->size = sym->nRegs;
824   for (i = 0; i < sym->nRegs; i++)
825     aop->aopu.aop_reg[i] = sym->regs[i];
826 }
827
828 /*-----------------------------------------------------------------*/
829 /* freeAsmop - free up the asmop given to an operand               */
830 /*----------------------------------------------------------------*/
831 static void
832 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
833 {
834   asmop *aop;
835
836   if (!op)
837     aop = aaop;
838   else
839     aop = op->aop;
840
841   if (!aop)
842     return;
843
844   if (aop->freed)
845     goto dealloc;
846
847   aop->freed = 1;
848
849   /* depending on the asmop type only three cases need work AOP_RO
850      , AOP_R1 && AOP_STK */
851   switch (aop->type)
852     {
853     case AOP_R0:
854       if (_G.r0Pushed)
855         {
856           if (pop)
857             {
858               emitcode ("pop", "ar0");
859               _G.r0Pushed--;
860             }
861         }
862       bitVectUnSetBit (ic->rUsed, R0_IDX);
863       break;
864
865     case AOP_R1:
866       if (_G.r1Pushed)
867         {
868           if (pop)
869             {
870               emitcode ("pop", "ar1");
871               _G.r1Pushed--;
872             }
873         }
874       bitVectUnSetBit (ic->rUsed, R1_IDX);
875       break;
876
877     case AOP_STK:
878       {
879         int sz = aop->size;
880         int stk = aop->aopu.aop_stk + aop->size;
881         bitVectUnSetBit (ic->rUsed, R0_IDX);
882         bitVectUnSetBit (ic->rUsed, R1_IDX);
883
884         getFreePtr (ic, &aop, FALSE);
885
886         if (options.stack10bit)
887           {
888             /* I'm not sure what to do here yet... */
889             /* #STUB */
890             fprintf (stderr,
891                      "*** Warning: probably generating bad code for "
892                      "10 bit stack mode.\n");
893           }
894
895         if (stk)
896           {
897             emitcode ("mov", "a,_bp");
898             emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
899             emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
900           }
901         else
902           {
903             emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
904           }
905
906         while (sz--)
907           {
908             emitcode ("pop", "acc");
909             emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
910             if (!sz)
911               break;
912             emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
913           }
914         op->aop = aop;
915         freeAsmop (op, NULL, ic, TRUE);
916         if (_G.r0Pushed)
917           {
918             emitcode ("pop", "ar0");
919             _G.r0Pushed--;
920           }
921
922         if (_G.r1Pushed)
923           {
924             emitcode ("pop", "ar1");
925             _G.r1Pushed--;
926           }
927       }
928     }
929
930 dealloc:
931   /* all other cases just dealloc */
932   if (op)
933     {
934       op->aop = NULL;
935       if (IS_SYMOP (op))
936         {
937           OP_SYMBOL (op)->aop = NULL;
938           /* if the symbol has a spill */
939           if (SPIL_LOC (op))
940             SPIL_LOC (op)->aop = NULL;
941         }
942     }
943 }
944
945 /*------------------------------------------------------------------*/
946 /* aopGet - for fetching value of the aop                           */
947 /*                    */
948 /* Set canClobberACC if you are sure it is OK to clobber the value  */
949 /* in the accumulator. Set it FALSE otherwise; FALSE is always safe, */
950 /* just less efficient.               */
951 /*------------------------------------------------------------------*/
952
953 static char *
954 aopGet (asmop * aop,
955         int offset,
956         bool bit16,
957         bool dname,
958         bool canClobberACC)
959 {
960   char *s = buffer;
961   char *rs;
962
963   /* offset is greater than
964      size then zero */
965   if (offset > (aop->size - 1) &&
966       aop->type != AOP_LIT)
967     return zero;
968
969   /* depending on type */
970   switch (aop->type)
971     {
972
973     case AOP_R0:
974     case AOP_R1:
975       /* if we need to increment it */
976       while (offset > aop->coff)
977         {
978           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
979           aop->coff++;
980         }
981
982       while (offset < aop->coff)
983         {
984           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
985           aop->coff--;
986         }
987
988       aop->coff = offset;
989       if (aop->paged)
990         {
991           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
992           return (dname ? "acc" : "a");
993         }
994       sprintf (s, "@%s", aop->aopu.aop_ptr->name);
995       rs = Safe_calloc (1, strlen (s) + 1);
996       strcpy (rs, s);
997       return rs;
998
999     case AOP_DPTR:
1000     case AOP_DPTR2:
1001
1002       if (aop->type == AOP_DPTR2)
1003         {
1004           genSetDPTR (1);
1005           if (!canClobberACC)
1006             {
1007                     TR_AP("#1");
1008                     emitcode ("xch", "a, %s", DP2_RESULT_REG);
1009             }
1010         }
1011
1012       _flushLazyDPS ();
1013
1014       while (offset > aop->coff)
1015         {
1016           emitcode ("inc", "dptr");
1017           aop->coff++;
1018         }
1019
1020       while (offset < aop->coff)
1021         {
1022           emitcode ("lcall", "__decdptr");
1023           aop->coff--;
1024         }
1025
1026       aop->coff = offset;
1027       if (aop->code)
1028         {
1029           emitcode ("clr", "a");
1030           emitcode ("movc", "a,@a+dptr");
1031         }
1032       else
1033         {
1034           emitcode ("movx", "a,@dptr");
1035         }
1036
1037       if (aop->type == AOP_DPTR2)
1038         {
1039           genSetDPTR (0);
1040           if (!canClobberACC)
1041             {
1042        TR_AP("#2");
1043               emitcode ("xch", "a, %s", DP2_RESULT_REG);
1044               return DP2_RESULT_REG;
1045             }
1046         }
1047       return (dname ? "acc" : "a");
1048
1049     case AOP_IMMD:
1050       if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
1051               sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
1052       } else if (bit16)
1053         sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
1054       else if (offset)
1055         sprintf (s, "#(%s >> %d)",
1056                  aop->aopu.aop_immd.aop_immd1,
1057                  offset * 8);
1058       else
1059         sprintf (s, "#%s",
1060                  aop->aopu.aop_immd.aop_immd1);
1061       rs = Safe_calloc (1, strlen (s) + 1);
1062       strcpy (rs, s);
1063       return rs;
1064
1065     case AOP_DIR:
1066       if (offset)
1067         sprintf (s, "(%s + %d)",
1068                  aop->aopu.aop_dir,
1069                  offset);
1070       else
1071         sprintf (s, "%s", aop->aopu.aop_dir);
1072       rs = Safe_calloc (1, strlen (s) + 1);
1073       strcpy (rs, s);
1074       return rs;
1075
1076     case AOP_REG:
1077       if (dname)
1078         return aop->aopu.aop_reg[offset]->dname;
1079       else
1080         return aop->aopu.aop_reg[offset]->name;
1081
1082     case AOP_CRY:
1083       emitcode ("clr", "a");
1084       emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1085       emitcode ("rlc", "a");
1086       return (dname ? "acc" : "a");
1087
1088     case AOP_ACC:
1089       if (!offset && dname)
1090         return "acc";
1091       return aop->aopu.aop_str[offset];
1092
1093     case AOP_LIT:
1094       return aopLiteral (aop->aopu.aop_lit, offset);
1095
1096     case AOP_STR:
1097       aop->coff = offset;
1098       if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1099           dname)
1100         return "acc";
1101
1102       return aop->aopu.aop_str[offset];
1103
1104     }
1105
1106   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1107           "aopget got unsupported aop->type");
1108   exit (1);
1109 }
1110 /*-----------------------------------------------------------------*/
1111 /* aopPut - puts a string for a aop                                */
1112 /*-----------------------------------------------------------------*/
1113 static void
1114 aopPut (asmop * aop, char *s, int offset)
1115 {
1116   char *d = buffer;
1117
1118   if (aop->size && offset > (aop->size - 1))
1119     {
1120       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1121               "aopPut got offset > aop->size");
1122       exit (1);
1123     }
1124
1125   /* will assign value to value */
1126   /* depending on where it is ofcourse */
1127   switch (aop->type)
1128     {
1129     case AOP_DIR:
1130       if (offset)
1131         sprintf (d, "(%s + %d)",
1132                  aop->aopu.aop_dir, offset);
1133       else
1134         sprintf (d, "%s", aop->aopu.aop_dir);
1135
1136       if (strcmp (d, s))
1137         emitcode ("mov", "%s,%s", d, s);
1138
1139       break;
1140
1141     case AOP_REG:
1142       if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1143           strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1144         {
1145           if (*s == '@' ||
1146               strcmp (s, "r0") == 0 ||
1147               strcmp (s, "r1") == 0 ||
1148               strcmp (s, "r2") == 0 ||
1149               strcmp (s, "r3") == 0 ||
1150               strcmp (s, "r4") == 0 ||
1151               strcmp (s, "r5") == 0 ||
1152               strcmp (s, "r6") == 0 ||
1153               strcmp (s, "r7") == 0)
1154             emitcode ("mov", "%s,%s",
1155                       aop->aopu.aop_reg[offset]->dname, s);
1156           else
1157             emitcode ("mov", "%s,%s",
1158                       aop->aopu.aop_reg[offset]->name, s);
1159         }
1160       break;
1161
1162     case AOP_DPTR:
1163     case AOP_DPTR2:
1164
1165       if (aop->type == AOP_DPTR2)
1166         {
1167           genSetDPTR (1);
1168         }
1169       _flushLazyDPS ();
1170
1171       if (aop->code)
1172         {
1173           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1174                   "aopPut writting to code space");
1175           exit (1);
1176         }
1177
1178       while (offset > aop->coff)
1179         {
1180           aop->coff++;
1181           emitcode ("inc", "dptr");
1182         }
1183
1184       while (offset < aop->coff)
1185         {
1186           aop->coff--;
1187           emitcode ("lcall", "__decdptr");
1188         }
1189
1190       aop->coff = offset;
1191
1192       /* if not in accumulater */
1193       MOVA (s);
1194
1195       emitcode ("movx", "@dptr,a");
1196
1197       if (aop->type == AOP_DPTR2)
1198         {
1199           genSetDPTR (0);
1200         }
1201       break;
1202
1203     case AOP_R0:
1204     case AOP_R1:
1205       while (offset > aop->coff)
1206         {
1207           aop->coff++;
1208           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1209         }
1210       while (offset < aop->coff)
1211         {
1212           aop->coff--;
1213           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1214         }
1215       aop->coff = offset;
1216
1217       if (aop->paged)
1218         {
1219           MOVA (s);
1220           emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1221
1222         }
1223       else if (*s == '@')
1224         {
1225           MOVA (s);
1226           emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1227         }
1228       else if (strcmp (s, "r0") == 0 ||
1229                strcmp (s, "r1") == 0 ||
1230                strcmp (s, "r2") == 0 ||
1231                strcmp (s, "r3") == 0 ||
1232                strcmp (s, "r4") == 0 ||
1233                strcmp (s, "r5") == 0 ||
1234                strcmp (s, "r6") == 0 ||
1235                strcmp (s, "r7") == 0)
1236         {
1237           char buffer[10];
1238           sprintf (buffer, "a%s", s);
1239           emitcode ("mov", "@%s,%s",
1240                     aop->aopu.aop_ptr->name, buffer);
1241         }
1242       else
1243         emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1244
1245       break;
1246
1247     case AOP_STK:
1248       if (strcmp (s, "a") == 0)
1249         emitcode ("push", "acc");
1250       else
1251         if (*s=='@') {
1252           MOVA(s);
1253           emitcode ("push", "acc");
1254         } else {
1255           emitcode ("push", s);
1256         }
1257
1258       break;
1259
1260     case AOP_CRY:
1261       /* if bit variable */
1262       if (!aop->aopu.aop_dir)
1263         {
1264           emitcode ("clr", "a");
1265           emitcode ("rlc", "a");
1266         }
1267       else
1268         {
1269           if (s == zero)
1270             emitcode ("clr", "%s", aop->aopu.aop_dir);
1271           else if (s == one)
1272             emitcode ("setb", "%s", aop->aopu.aop_dir);
1273           else if (!strcmp (s, "c"))
1274             emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1275           else
1276             {
1277               if (strcmp (s, "a"))
1278                 {
1279                   MOVA (s);
1280                 }
1281               {
1282                 symbol *lbl = newiTempLabel (NULL);
1283                 emitcode ("clr", "c");
1284                 emitcode ("jz", "%05d$", lbl->key + 100);
1285                 emitcode ("cpl", "c");
1286                 emitcode ("", "%05d$:", lbl->key + 100);
1287                 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1288               }
1289             }
1290         }
1291       break;
1292
1293     case AOP_STR:
1294       aop->coff = offset;
1295       if (strcmp (aop->aopu.aop_str[offset], s))
1296         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1297       break;
1298
1299     case AOP_ACC:
1300       aop->coff = offset;
1301       if (!offset && (strcmp (s, "acc") == 0))
1302         break;
1303
1304       if (strcmp (aop->aopu.aop_str[offset], s))
1305         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1306       break;
1307
1308     default:
1309       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1310               "aopPut got unsupported aop->type");
1311       exit (1);
1312     }
1313
1314 }
1315
1316
1317 /*--------------------------------------------------------------------*/
1318 /* reAdjustPreg - points a register back to where it should (coff==0) */
1319 /*--------------------------------------------------------------------*/
1320 static void
1321 reAdjustPreg (asmop * aop)
1322 {
1323   if ((aop->coff==0) || (aop->size <= 1)) {
1324     return;
1325   }
1326
1327   switch (aop->type)
1328     {
1329     case AOP_R0:
1330     case AOP_R1:
1331       while (aop->coff--)
1332         emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1333       break;
1334     case AOP_DPTR:
1335     case AOP_DPTR2:
1336       if (aop->type == AOP_DPTR2)
1337         {
1338           genSetDPTR (1);
1339           _flushLazyDPS ();
1340         }
1341       while (aop->coff--)
1342         {
1343           emitcode ("lcall", "__decdptr");
1344         }
1345
1346       if (aop->type == AOP_DPTR2)
1347         {
1348           genSetDPTR (0);
1349         }
1350       break;
1351
1352     }
1353   aop->coff=0;
1354 }
1355
1356 #define AOP(op) op->aop
1357 #define AOP_TYPE(op) AOP(op)->type
1358 #define AOP_SIZE(op) AOP(op)->size
1359 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1360                        AOP_TYPE(x) == AOP_R0))
1361
1362 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
1363                         AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1364                          AOP(x)->paged))
1365
1366 #define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
1367                       (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1368                       x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1369
1370 /* Workaround for DS80C390 bug: div ab may return bogus results
1371  * if A is accessed in instruction immediately before the div.
1372  *
1373  * Will be fixed in B4 rev of processor, Dallas claims.
1374  */
1375
1376 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L)       \
1377     if (!AOP_NEEDSACC(RIGHT))         \
1378     {               \
1379       /* We can load A first, then B, since     \
1380        * B (the RIGHT operand) won't clobber A,   \
1381        * thus avoiding touching A right before the div. \
1382        */             \
1383       D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1384       L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE);     \
1385       MOVA(L);            \
1386       emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1387     }               \
1388     else              \
1389     {               \
1390       /* Just stuff in a nop after loading A. */    \
1391       emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1392       L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE);   \
1393       MOVA(L);            \
1394       emitcode("nop", "; workaround for DS80C390 div bug.");  \
1395     }
1396
1397 /*-----------------------------------------------------------------*/
1398 /* genNotFloat - generates not for float operations              */
1399 /*-----------------------------------------------------------------*/
1400 static void
1401 genNotFloat (operand * op, operand * res)
1402 {
1403   int size, offset;
1404   char *l;
1405   symbol *tlbl;
1406
1407   D (emitcode (";", "genNotFloat ");
1408     );
1409
1410   /* we will put 127 in the first byte of
1411      the result */
1412   aopPut (AOP (res), "#127", 0);
1413   size = AOP_SIZE (op) - 1;
1414   offset = 1;
1415
1416   _startLazyDPSEvaluation ();
1417   l = aopGet (op->aop, offset++, FALSE, FALSE, TRUE);
1418   MOVA (l);
1419
1420   while (size--)
1421     {
1422       emitcode ("orl", "a,%s",
1423                 aopGet (op->aop,
1424                         offset++, FALSE, FALSE, FALSE));
1425     }
1426   _endLazyDPSEvaluation ();
1427
1428   tlbl = newiTempLabel (NULL);
1429   aopPut (res->aop, one, 1);
1430   emitcode ("jz", "%05d$", (tlbl->key + 100));
1431   aopPut (res->aop, zero, 1);
1432   emitcode ("", "%05d$:", (tlbl->key + 100));
1433
1434   size = res->aop->size - 2;
1435   offset = 2;
1436   /* put zeros in the rest */
1437   while (size--)
1438     aopPut (res->aop, zero, offset++);
1439 }
1440
1441 /*-----------------------------------------------------------------*/
1442 /* opIsGptr: returns non-zero if the passed operand is       */
1443 /* a generic pointer type.             */
1444 /*-----------------------------------------------------------------*/
1445 static int
1446 opIsGptr (operand * op)
1447 {
1448   sym_link *type = operandType (op);
1449
1450   if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1451     {
1452       return 1;
1453     }
1454   return 0;
1455 }
1456
1457 /*-----------------------------------------------------------------*/
1458 /* getDataSize - get the operand data size                         */
1459 /*-----------------------------------------------------------------*/
1460 static int
1461 getDataSize (operand * op)
1462 {
1463   int size;
1464   size = AOP_SIZE (op);
1465   if (size == GPTRSIZE)
1466     {
1467       sym_link *type = operandType (op);
1468       if (IS_GENPTR (type))
1469         {
1470           /* generic pointer; arithmetic operations
1471            * should ignore the high byte (pointer type).
1472            */
1473           size--;
1474         }
1475     }
1476   return size;
1477 }
1478
1479 /*-----------------------------------------------------------------*/
1480 /* outAcc - output Acc                                             */
1481 /*-----------------------------------------------------------------*/
1482 static void
1483 outAcc (operand * result)
1484 {
1485   int size, offset;
1486   size = getDataSize (result);
1487   if (size)
1488     {
1489       aopPut (AOP (result), "a", 0);
1490       size--;
1491       offset = 1;
1492       /* unsigned or positive */
1493       while (size--)
1494         {
1495           aopPut (AOP (result), zero, offset++);
1496         }
1497     }
1498 }
1499
1500 /*-----------------------------------------------------------------*/
1501 /* outBitC - output a bit C                                        */
1502 /*-----------------------------------------------------------------*/
1503 static void
1504 outBitC (operand * result)
1505 {
1506   /* if the result is bit */
1507   if (AOP_TYPE (result) == AOP_CRY)
1508     {
1509       aopPut (AOP (result), "c", 0);
1510     }
1511   else
1512     {
1513       emitcode ("clr", "a");
1514       emitcode ("rlc", "a");
1515       outAcc (result);
1516     }
1517 }
1518
1519 /*-----------------------------------------------------------------*/
1520 /* toBoolean - emit code for orl a,operator(sizeop)                */
1521 /*-----------------------------------------------------------------*/
1522 static void
1523 toBoolean (operand * oper)
1524 {
1525   int   size = AOP_SIZE (oper) - 1;
1526   int   offset = 1;
1527   bool usedB = FALSE;
1528
1529   /* The generic part of a generic pointer should
1530    * not participate in it's truth value.
1531    *
1532    * i.e. 0x10000000 is zero.
1533    */
1534   if (opIsGptr (oper))
1535     {
1536       D (emitcode (";", "toBoolean: generic ptr special case.");
1537         );
1538       size--;
1539     }
1540
1541   _startLazyDPSEvaluation ();
1542   if (AOP_NEEDSACC (oper) && size)
1543     {
1544       usedB = TRUE;
1545       emitcode ("push", "b");
1546       emitcode ("mov", "b, %s", aopGet (AOP (oper), 0, FALSE, FALSE, FALSE));
1547     }
1548   else
1549     {
1550       MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, TRUE));
1551     }
1552   while (size--)
1553     {
1554       if (usedB)
1555         {
1556           emitcode ("orl", "b,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1557         }
1558       else
1559         {
1560           emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1561         }
1562     }
1563   _endLazyDPSEvaluation ();
1564
1565   if (usedB)
1566     {
1567       emitcode ("mov", "a,b");
1568       emitcode ("pop", "b");
1569     }
1570 }
1571
1572
1573 /*-----------------------------------------------------------------*/
1574 /* genNot - generate code for ! operation                          */
1575 /*-----------------------------------------------------------------*/
1576 static void
1577 genNot (iCode * ic)
1578 {
1579   symbol *tlbl;
1580   sym_link *optype = operandType (IC_LEFT (ic));
1581
1582   D (emitcode (";", "genNot ");
1583     );
1584
1585   /* assign asmOps to operand & result */
1586   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1587   aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1588
1589   /* if in bit space then a special case */
1590   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1591     {
1592       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1593       emitcode ("cpl", "c");
1594       outBitC (IC_RESULT (ic));
1595       goto release;
1596     }
1597
1598   /* if type float then do float */
1599   if (IS_FLOAT (optype))
1600     {
1601       genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1602       goto release;
1603     }
1604
1605   toBoolean (IC_LEFT (ic));
1606
1607   tlbl = newiTempLabel (NULL);
1608   emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1609   emitcode ("", "%05d$:", tlbl->key + 100);
1610   outBitC (IC_RESULT (ic));
1611
1612 release:
1613   /* release the aops */
1614   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1615   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1616 }
1617
1618
1619 /*-----------------------------------------------------------------*/
1620 /* genCpl - generate code for complement                           */
1621 /*-----------------------------------------------------------------*/
1622 static void
1623 genCpl (iCode * ic)
1624 {
1625   int offset = 0;
1626   int size;
1627
1628   D (emitcode (";", "genCpl ");
1629     );
1630
1631
1632   /* assign asmOps to operand & result */
1633   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1634   aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1635
1636   /* if both are in bit space then
1637      a special case */
1638   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1639       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1640     {
1641
1642       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1643       emitcode ("cpl", "c");
1644       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1645       goto release;
1646     }
1647
1648   size = AOP_SIZE (IC_RESULT (ic));
1649   _startLazyDPSEvaluation ();
1650   while (size--)
1651     {
1652       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1653       MOVA (l);
1654       emitcode ("cpl", "a");
1655       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1656     }
1657   _endLazyDPSEvaluation ();
1658
1659
1660 release:
1661   /* release the aops */
1662   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1663   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1664 }
1665
1666 /*-----------------------------------------------------------------*/
1667 /* genUminusFloat - unary minus for floating points                */
1668 /*-----------------------------------------------------------------*/
1669 static void
1670 genUminusFloat (operand * op, operand * result)
1671 {
1672   int size, offset = 0;
1673   char *l;
1674   /* for this we just need to flip the
1675      first it then copy the rest in place */
1676   D (emitcode (";", "genUminusFloat");
1677     );
1678
1679   _startLazyDPSEvaluation ();
1680   size = AOP_SIZE (op) - 1;
1681   l = aopGet (AOP (op), 3, FALSE, FALSE, TRUE);
1682   MOVA (l);
1683
1684   emitcode ("cpl", "acc.7");
1685   aopPut (AOP (result), "a", 3);
1686
1687   while (size--)
1688     {
1689       aopPut (AOP (result),
1690               aopGet (AOP (op), offset, FALSE, FALSE, FALSE),
1691               offset);
1692       offset++;
1693     }
1694   _endLazyDPSEvaluation ();
1695 }
1696
1697 /*-----------------------------------------------------------------*/
1698 /* genUminus - unary minus code generation                         */
1699 /*-----------------------------------------------------------------*/
1700 static void
1701 genUminus (iCode * ic)
1702 {
1703   int offset, size;
1704   sym_link *optype, *rtype;
1705
1706   D (emitcode (";", "genUminus ");
1707     );
1708
1709
1710   /* assign asmops */
1711   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1712   aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1713
1714   /* if both in bit space then special
1715      case */
1716   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1717       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1718     {
1719
1720       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1721       emitcode ("cpl", "c");
1722       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1723       goto release;
1724     }
1725
1726   optype = operandType (IC_LEFT (ic));
1727   rtype = operandType (IC_RESULT (ic));
1728
1729   /* if float then do float stuff */
1730   if (IS_FLOAT (optype))
1731     {
1732       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1733       goto release;
1734     }
1735
1736   /* otherwise subtract from zero */
1737   size = AOP_SIZE (IC_LEFT (ic));
1738   offset = 0;
1739   _startLazyDPSEvaluation ();
1740   while (size--)
1741     {
1742       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1743       if (!strcmp (l, "a"))
1744         {
1745           if (offset == 0)
1746             SETC;
1747           emitcode ("cpl", "a");
1748           emitcode ("addc", "a,#0");
1749         }
1750       else
1751         {
1752           if (offset == 0)
1753             CLRC;
1754           emitcode ("clr", "a");
1755           emitcode ("subb", "a,%s", l);
1756         }
1757       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1758     }
1759   _endLazyDPSEvaluation ();
1760
1761   /* if any remaining bytes in the result */
1762   /* we just need to propagate the sign   */
1763   if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1764     {
1765       emitcode ("rlc", "a");
1766       emitcode ("subb", "a,acc");
1767       while (size--)
1768         aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1769     }
1770
1771 release:
1772   /* release the aops */
1773   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1774   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1775 }
1776
1777 /*-----------------------------------------------------------------*/
1778 /* saveRegisters - will look for a call and save the registers     */
1779 /*-----------------------------------------------------------------*/
1780 static void
1781 saveRegisters (iCode * lic)
1782 {
1783   int i;
1784   iCode *ic;
1785   bitVect *rsave;
1786   sym_link *detype;
1787
1788   /* look for call */
1789   for (ic = lic; ic; ic = ic->next)
1790     if (ic->op == CALL || ic->op == PCALL)
1791       break;
1792
1793   if (!ic)
1794     {
1795       fprintf (stderr, "found parameter push with no function call\n");
1796       return;
1797     }
1798
1799   /* if the registers have been saved already then
1800      do nothing */
1801   if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type) ||
1802       IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic))))
1803     return;
1804
1805   /* find the registers in use at this time
1806      and push them away to safety */
1807   rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1808                          ic->rUsed);
1809
1810   ic->regsSaved = 1;
1811   if (options.useXstack)
1812     {
1813       if (bitVectBitValue (rsave, R0_IDX))
1814         emitcode ("mov", "b,r0");
1815       emitcode ("mov", "r0,%s", spname);
1816       for (i = 0; i < ds390_nRegs; i++)
1817         {
1818           if (bitVectBitValue (rsave, i))
1819             {
1820               if (i == R0_IDX)
1821                 emitcode ("mov", "a,b");
1822               else
1823                 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
1824               emitcode ("movx", "@r0,a");
1825               emitcode ("inc", "r0");
1826             }
1827         }
1828       emitcode ("mov", "%s,r0", spname);
1829       if (bitVectBitValue (rsave, R0_IDX))
1830         emitcode ("mov", "r0,b");
1831     }
1832   else
1833     for (i = 0; i < ds390_nRegs; i++)
1834       {
1835         if (bitVectBitValue (rsave, i))
1836           emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
1837       }
1838
1839   detype = getSpec (operandType (IC_LEFT (ic)));
1840 }
1841
1842 /*-----------------------------------------------------------------*/
1843 /* unsaveRegisters - pop the pushed registers                      */
1844 /*-----------------------------------------------------------------*/
1845 static void
1846 unsaveRegisters (iCode * ic)
1847 {
1848   int i;
1849   bitVect *rsave;
1850   /* find the registers in use at this time
1851      and push them away to safety */
1852   rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1853                          ic->rUsed);
1854
1855   if (options.useXstack)
1856     {
1857       emitcode ("mov", "r0,%s", spname);
1858       for (i = ds390_nRegs; i >= 0; i--)
1859         {
1860           if (bitVectBitValue (rsave, i))
1861             {
1862               emitcode ("dec", "r0");
1863               emitcode ("movx", "a,@r0");
1864               if (i == R0_IDX)
1865                 emitcode ("mov", "b,a");
1866               else
1867                 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
1868             }
1869
1870         }
1871       emitcode ("mov", "%s,r0", spname);
1872       if (bitVectBitValue (rsave, R0_IDX))
1873         emitcode ("mov", "r0,b");
1874     }
1875   else
1876     for (i = ds390_nRegs; i >= 0; i--)
1877       {
1878         if (bitVectBitValue (rsave, i))
1879           emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
1880       }
1881
1882 }
1883
1884
1885 /*-----------------------------------------------------------------*/
1886 /* pushSide -                */
1887 /*-----------------------------------------------------------------*/
1888 static void
1889 pushSide (operand * oper, int size)
1890 {
1891   int offset = 0;
1892   _startLazyDPSEvaluation ();
1893   while (size--)
1894     {
1895       char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, FALSE);
1896       if (AOP_TYPE (oper) != AOP_REG &&
1897           AOP_TYPE (oper) != AOP_DIR &&
1898           strcmp (l, "a"))
1899         {
1900           emitcode ("mov", "a,%s", l);
1901           emitcode ("push", "acc");
1902         }
1903       else
1904         emitcode ("push", "%s", l);
1905     }
1906   _endLazyDPSEvaluation ();
1907 }
1908
1909 /*-----------------------------------------------------------------*/
1910 /* assignResultValue -               */
1911 /*-----------------------------------------------------------------*/
1912 static void
1913 assignResultValue (operand * oper)
1914 {
1915   int offset = 0;
1916   int size = AOP_SIZE (oper);
1917
1918   _startLazyDPSEvaluation ();
1919   while (size--)
1920     {
1921       aopPut (AOP (oper), fReturn[offset], offset);
1922       offset++;
1923     }
1924   _endLazyDPSEvaluation ();
1925 }
1926
1927
1928 /*-----------------------------------------------------------------*/
1929 /* genXpush - pushes onto the external stack                       */
1930 /*-----------------------------------------------------------------*/
1931 static void
1932 genXpush (iCode * ic)
1933 {
1934   asmop *aop = newAsmop (0);
1935   regs *r;
1936   int size, offset = 0;
1937
1938   D (emitcode (";", "genXpush ");
1939     );
1940
1941   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1942   r = getFreePtr (ic, &aop, FALSE);
1943
1944
1945   emitcode ("mov", "%s,_spx", r->name);
1946
1947   size = AOP_SIZE (IC_LEFT (ic));
1948   _startLazyDPSEvaluation ();
1949   while (size--)
1950     {
1951
1952       char *l = aopGet (AOP (IC_LEFT (ic)),
1953                         offset++, FALSE, FALSE, TRUE);
1954       MOVA (l);
1955       emitcode ("movx", "@%s,a", r->name);
1956       emitcode ("inc", "%s", r->name);
1957
1958     }
1959   _endLazyDPSEvaluation ();
1960
1961
1962   emitcode ("mov", "_spx,%s", r->name);
1963
1964   freeAsmop (NULL, aop, ic, TRUE);
1965   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1966 }
1967
1968 /*-----------------------------------------------------------------*/
1969 /* genIpush - genrate code for pushing this gets a little complex  */
1970 /*-----------------------------------------------------------------*/
1971 static void
1972 genIpush (iCode * ic)
1973 {
1974   int size, offset = 0;
1975   char *l;
1976
1977   D (emitcode (";", "genIpush ");
1978     );
1979
1980   /* if this is not a parm push : ie. it is spill push
1981      and spill push is always done on the local stack */
1982   if (!ic->parmPush)
1983     {
1984
1985       /* and the item is spilt then do nothing */
1986       if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1987         return;
1988
1989       aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1990       size = AOP_SIZE (IC_LEFT (ic));
1991       /* push it on the stack */
1992       _startLazyDPSEvaluation ();
1993       while (size--)
1994         {
1995           l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, TRUE);
1996           if (*l == '#')
1997             {
1998               MOVA (l);
1999               l = "acc";
2000             }
2001           emitcode ("push", "%s", l);
2002         }
2003       _endLazyDPSEvaluation ();
2004       return;
2005     }
2006
2007   /* this is a paramter push: in this case we call
2008      the routine to find the call and save those
2009      registers that need to be saved */
2010   saveRegisters (ic);
2011
2012   /* if use external stack then call the external
2013      stack pushing routine */
2014   if (options.useXstack)
2015     {
2016       genXpush (ic);
2017       return;
2018     }
2019
2020   /* then do the push */
2021   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2022
2023   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2024   size = AOP_SIZE (IC_LEFT (ic));
2025
2026   _startLazyDPSEvaluation ();
2027   while (size--)
2028     {
2029       l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, FALSE);
2030       if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2031           AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2032           strcmp (l, "a"))
2033         {
2034           emitcode ("mov", "a,%s", l);
2035           emitcode ("push", "acc");
2036         }
2037       else
2038         emitcode ("push", "%s", l);
2039     }
2040   _endLazyDPSEvaluation ();
2041
2042   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2043 }
2044
2045 /*-----------------------------------------------------------------*/
2046 /* genIpop - recover the registers: can happen only for spilling   */
2047 /*-----------------------------------------------------------------*/
2048 static void
2049 genIpop (iCode * ic)
2050 {
2051   int size, offset;
2052
2053   D (emitcode (";", "genIpop ");
2054     );
2055
2056
2057   /* if the temp was not pushed then */
2058   if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2059     return;
2060
2061   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2062   size = AOP_SIZE (IC_LEFT (ic));
2063   offset = (size - 1);
2064   _startLazyDPSEvaluation ();
2065   while (size--)
2066     {
2067       emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2068                                      FALSE, TRUE, TRUE));
2069     }
2070   _endLazyDPSEvaluation ();
2071
2072   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2073 }
2074
2075 /*-----------------------------------------------------------------*/
2076 /* unsaveRBank - restores the resgister bank from stack            */
2077 /*-----------------------------------------------------------------*/
2078 static void
2079 unsaveRBank (int bank, iCode * ic, bool popPsw)
2080 {
2081   int i;
2082   asmop *aop = NULL;
2083   regs *r = NULL;
2084
2085   if (options.useXstack)
2086   {
2087       if (!ic)
2088       {
2089           /* Assume r0 is available for use. */
2090           r = ds390_regWithIdx (R0_IDX);;          
2091       } 
2092       else
2093       {
2094           aop = newAsmop (0);
2095           r = getFreePtr (ic, &aop, FALSE);
2096       }
2097       emitcode ("mov", "%s,_spx", r->name);      
2098   }
2099   
2100   if (popPsw)
2101     {
2102       if (options.useXstack)
2103       {
2104           emitcode ("movx", "a,@%s", r->name);
2105           emitcode ("mov", "psw,a");
2106           emitcode ("dec", "%s", r->name);
2107         }
2108       else
2109       {
2110         emitcode ("pop", "psw");
2111       }
2112     }
2113
2114   for (i = (ds390_nRegs - 1); i >= 0; i--)
2115     {
2116       if (options.useXstack)
2117         {
2118           emitcode ("movx", "a,@%s", r->name);
2119           emitcode ("mov", "(%s+%d),a",
2120                     regs390[i].base, 8 * bank + regs390[i].offset);
2121           emitcode ("dec", "%s", r->name);
2122
2123         }
2124       else
2125         emitcode ("pop", "(%s+%d)",
2126                   regs390[i].base, 8 * bank + regs390[i].offset);
2127     }
2128
2129   if (options.useXstack)
2130     {
2131       emitcode ("mov", "_spx,%s", r->name);
2132     }
2133     
2134   if (aop)
2135   {
2136       freeAsmop (NULL, aop, ic, TRUE);  
2137   }    
2138 }
2139
2140 /*-----------------------------------------------------------------*/
2141 /* saveRBank - saves an entire register bank on the stack          */
2142 /*-----------------------------------------------------------------*/
2143 static void
2144 saveRBank (int bank, iCode * ic, bool pushPsw)
2145 {
2146   int i;
2147   asmop *aop = NULL;
2148   regs *r = NULL;
2149
2150   if (options.useXstack)
2151     {
2152         if (!ic)
2153         {
2154           /* Assume r0 is available for use. */
2155                   r = ds390_regWithIdx (R0_IDX);;
2156         }
2157         else
2158         {
2159           aop = newAsmop (0);
2160           r = getFreePtr (ic, &aop, FALSE);
2161         }
2162         emitcode ("mov", "%s,_spx", r->name);    
2163     }
2164
2165   for (i = 0; i < ds390_nRegs; i++)
2166     {
2167       if (options.useXstack)
2168         {
2169           emitcode ("inc", "%s", r->name);
2170           emitcode ("mov", "a,(%s+%d)",
2171                     regs390[i].base, 8 * bank + regs390[i].offset);
2172           emitcode ("movx", "@%s,a", r->name);
2173         }
2174       else
2175         emitcode ("push", "(%s+%d)",
2176                   regs390[i].base, 8 * bank + regs390[i].offset);
2177     }
2178
2179   if (pushPsw)
2180     {
2181       if (options.useXstack)
2182         {
2183           emitcode ("mov", "a,psw");
2184           emitcode ("movx", "@%s,a", r->name);
2185           emitcode ("inc", "%s", r->name);
2186           emitcode ("mov", "_spx,%s", r->name);
2187         }
2188       else
2189       {
2190         emitcode ("push", "psw");
2191       }
2192
2193       emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2194     }
2195   
2196   if (aop)
2197   {
2198        freeAsmop (NULL, aop, ic, TRUE);
2199   }    
2200     
2201   if (ic)
2202   {  
2203       ic->bankSaved = 1;
2204   }
2205 }
2206
2207 /*-----------------------------------------------------------------*/
2208 /* genCall - generates a call statement                            */
2209 /*-----------------------------------------------------------------*/
2210 static void
2211 genCall (iCode * ic)
2212 {
2213   sym_link *dtype;
2214   bool restoreBank = FALSE;
2215   bool swapBanks = FALSE;
2216
2217   D (emitcode (";", "genCall "););
2218
2219   /* if we are calling a not _naked function that is not using
2220      the same register bank then we need to save the
2221      destination registers on the stack */
2222   dtype = operandType (IC_LEFT (ic));
2223   if (dtype && !IFFUNC_ISNAKED(dtype) &&
2224       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2225       IFFUNC_ISISR (currFunc->type))
2226   {
2227       if (!ic->bankSaved) 
2228       {
2229            /* This is unexpected; the bank should have been saved in
2230             * genFunction.
2231             */
2232            saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2233            restoreBank = TRUE;
2234       }
2235       swapBanks = TRUE;
2236   }
2237   
2238     /* if caller saves & we have not saved then */
2239     if (!ic->regsSaved)
2240       saveRegisters (ic);
2241   
2242   /* if send set is not empty the assign */
2243   /* We've saved all the registers we care about;
2244   * therefore, we may clobber any register not used
2245   * in the calling convention (i.e. anything not in
2246   * fReturn.
2247   */
2248   if (_G.sendSet)
2249     {
2250       iCode *sic;
2251
2252       for (sic = setFirstItem (_G.sendSet); sic;
2253            sic = setNextItem (_G.sendSet))
2254         {
2255           int size, offset = 0;
2256
2257           aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2258           size = AOP_SIZE (IC_LEFT (sic));
2259
2260           _startLazyDPSEvaluation ();
2261           while (size--)
2262             {
2263               char *l = aopGet (AOP(IC_LEFT(sic)), offset,
2264                                 FALSE, FALSE, TRUE);
2265                 if ((AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR) && size)
2266                 {
2267                     emitcode("mov", "%s,%s", regs390[offset].name, l);
2268                 }
2269                 else if (strcmp (l, fReturn[offset]))
2270                 {
2271                     emitcode ("mov", "%s,%s",
2272                               fReturn[offset],
2273                               l);
2274                 }
2275               offset++;
2276             }
2277           _endLazyDPSEvaluation ();
2278           if (AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR)
2279           {
2280               size = AOP_SIZE (IC_LEFT (sic));
2281               if (size)
2282               {
2283                  size--;
2284               }
2285               while (size)
2286               {
2287                    size--;
2288                    emitcode("mov", "%s,%s",
2289                                     fReturn[size], regs390[size].name);
2290               }
2291           }
2292           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2293         }
2294       _G.sendSet = NULL;
2295     }  
2296     
2297   if (swapBanks)
2298   {
2299         emitcode ("mov", "psw,#0x%02x", 
2300            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2301   }
2302
2303   /* make the call */
2304   emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2305                             OP_SYMBOL (IC_LEFT (ic))->rname :
2306                             OP_SYMBOL (IC_LEFT (ic))->name));
2307
2308   if (swapBanks)
2309   {
2310        emitcode ("mov", "psw,#0x%02x", 
2311           ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2312   }
2313
2314   /* if we need assign a result value */
2315   if ((IS_ITEMP (IC_RESULT (ic)) &&
2316        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2317         OP_SYMBOL (IC_RESULT (ic))->accuse ||
2318         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2319       IS_TRUE_SYMOP (IC_RESULT (ic)))
2320     {
2321       if (isOperandInFarSpace (IC_RESULT (ic))
2322           && getSize (operandType (IC_RESULT (ic))) <= 2)
2323         {
2324           int size = getSize (operandType (IC_RESULT (ic)));
2325
2326           /* Special case for 1 or 2 byte return in far space. */
2327           MOVA (fReturn[0]);
2328           if (size > 1)
2329             {
2330               emitcode ("mov", "b,%s", fReturn[1]);
2331             }
2332
2333           aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2334           aopPut (AOP (IC_RESULT (ic)), "a", 0);
2335
2336           if (size > 1)
2337             {
2338               aopPut (AOP (IC_RESULT (ic)), "b", 1);
2339             }
2340           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2341         }
2342       else
2343         {
2344           _G.accInUse++;
2345           aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2346           _G.accInUse--;
2347
2348           assignResultValue (IC_RESULT (ic));
2349
2350           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2351         }
2352     }
2353
2354   /* adjust the stack for parameters if
2355      required */
2356   if (ic->parmBytes)
2357     {
2358       int i;
2359       if (ic->parmBytes > 3)
2360         {
2361           emitcode ("mov", "a,%s", spname);
2362           emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2363           emitcode ("mov", "%s,a", spname);
2364         }
2365       else
2366         for (i = 0; i < ic->parmBytes; i++)
2367           emitcode ("dec", "%s", spname);
2368     }
2369
2370   /* if we hade saved some registers then unsave them */
2371   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2372     unsaveRegisters (ic);
2373
2374   /* if register bank was saved then pop them */
2375   if (restoreBank)
2376     unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2377 }
2378
2379 /*-----------------------------------------------------------------*/
2380 /* genPcall - generates a call by pointer statement                */
2381 /*-----------------------------------------------------------------*/
2382 static void
2383 genPcall (iCode * ic)
2384 {
2385   sym_link *dtype;
2386   symbol *rlbl = newiTempLabel (NULL);
2387   bool restoreBank=FALSE;
2388
2389   D (emitcode (";", "genPcall ");
2390     );
2391
2392
2393   /* if caller saves & we have not saved then */
2394   if (!ic->regsSaved)
2395     saveRegisters (ic);
2396
2397   /* if we are calling a function that is not using
2398      the same register bank then we need to save the
2399      destination registers on the stack */
2400   dtype = operandType (IC_LEFT (ic));
2401   if (dtype && !IFFUNC_ISNAKED(dtype) &&
2402       IFFUNC_ISISR (currFunc->type) &&
2403       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2404     saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2405     restoreBank=TRUE;
2406   }
2407
2408   /* push the return address on to the stack */
2409   emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2410   emitcode ("push", "acc");
2411   emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2412   emitcode ("push", "acc");
2413
2414   if (options.model == MODEL_FLAT24)
2415     {
2416       emitcode ("mov", "a,#(%05d$ >> 16)", (rlbl->key + 100));
2417       emitcode ("push", "acc");
2418     }
2419
2420   /* now push the calling address */
2421   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2422
2423   pushSide (IC_LEFT (ic), FPTRSIZE);
2424
2425   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2426
2427   /* if send set is not empty the assign */
2428   if (_G.sendSet)
2429     {
2430       iCode *sic;
2431
2432       for (sic = setFirstItem (_G.sendSet); sic;
2433            sic = setNextItem (_G.sendSet))
2434         {
2435           int size, offset = 0;
2436
2437           aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2438           size = AOP_SIZE (IC_LEFT (sic));
2439           _startLazyDPSEvaluation ();
2440           while (size--)
2441             {
2442               char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2443                                 FALSE, FALSE, TRUE);
2444               if (strcmp (l, fReturn[offset]))
2445                 {
2446                   emitcode ("mov", "%s,%s",
2447                             fReturn[offset],
2448                             l);
2449                 }
2450               offset++;
2451             }
2452           _endLazyDPSEvaluation ();
2453           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2454         }
2455       _G.sendSet = NULL;
2456     }
2457
2458   emitcode ("ret", "");
2459   emitcode ("", "%05d$:", (rlbl->key + 100));
2460
2461
2462   /* if we need assign a result value */
2463   if ((IS_ITEMP (IC_RESULT (ic)) &&
2464        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2465         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2466       IS_TRUE_SYMOP (IC_RESULT (ic)))
2467     {
2468
2469       _G.accInUse++;
2470       aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2471       _G.accInUse--;
2472
2473       assignResultValue (IC_RESULT (ic));
2474
2475       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2476     }
2477
2478   /* adjust the stack for parameters if
2479      required */
2480   if (ic->parmBytes)
2481     {
2482       int i;
2483       if (ic->parmBytes > 3)
2484         {
2485           emitcode ("mov", "a,%s", spname);
2486           emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2487           emitcode ("mov", "%s,a", spname);
2488         }
2489       else
2490         for (i = 0; i < ic->parmBytes; i++)
2491           emitcode ("dec", "%s", spname);
2492
2493     }
2494
2495   /* if register bank was saved then unsave them */
2496   if (restoreBank)
2497     unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2498   
2499   /* if we hade saved some registers then
2500      unsave them */
2501   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2502     unsaveRegisters (ic);
2503
2504 }
2505
2506 /*-----------------------------------------------------------------*/
2507 /* resultRemat - result  is rematerializable                       */
2508 /*-----------------------------------------------------------------*/
2509 static int
2510 resultRemat (iCode * ic)
2511 {
2512   if (SKIP_IC (ic) || ic->op == IFX)
2513     return 0;
2514
2515   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2516     {
2517       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2518       if (sym->remat && !POINTER_SET (ic))
2519         return 1;
2520     }
2521
2522   return 0;
2523 }
2524
2525 #if defined(__BORLANDC__) || defined(_MSC_VER)
2526 #define STRCASECMP stricmp
2527 #else
2528 #define STRCASECMP strcasecmp
2529 #endif
2530
2531 /*-----------------------------------------------------------------*/
2532 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2533 /*-----------------------------------------------------------------*/
2534 static bool
2535 inExcludeList (char *s)
2536 {
2537   int i = 0;
2538
2539   if (options.excludeRegs[i] &&
2540       STRCASECMP (options.excludeRegs[i], "none") == 0)
2541     return FALSE;
2542
2543   for (i = 0; options.excludeRegs[i]; i++)
2544     {
2545       if (options.excludeRegs[i] &&
2546           STRCASECMP (s, options.excludeRegs[i]) == 0)
2547         return TRUE;
2548     }
2549   return FALSE;
2550 }
2551
2552 /*-----------------------------------------------------------------*/
2553 /* genFunction - generated code for function entry                 */
2554 /*-----------------------------------------------------------------*/
2555 static void
2556 genFunction (iCode * ic)
2557 {
2558   symbol *sym;
2559   sym_link *ftype;
2560   bool   switchedPSW = FALSE;
2561
2562   D (emitcode (";", "genFunction "););
2563
2564   _G.nRegsSaved = 0;
2565   /* create the function header */
2566   emitcode (";", "-----------------------------------------");
2567   emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2568   emitcode (";", "-----------------------------------------");
2569
2570   emitcode ("", "%s:", sym->rname);
2571   ftype = operandType (IC_LEFT (ic));
2572
2573   if (IFFUNC_ISNAKED(ftype))
2574   {
2575       emitcode(";", "naked function: no prologue.");
2576       return;
2577   }
2578
2579   /* if critical function then turn interrupts off */
2580   if (IFFUNC_ISCRITICAL (ftype))
2581     emitcode ("clr", "ea");
2582
2583   /* here we need to generate the equates for the
2584      register bank if required */
2585   if (FUNC_REGBANK (ftype) != rbank)
2586     {
2587       int i;
2588
2589       rbank = FUNC_REGBANK (ftype);
2590       for (i = 0; i < ds390_nRegs; i++)
2591         {
2592           if (regs390[i].print) {
2593               if (strcmp (regs390[i].base, "0") == 0)
2594                   emitcode ("", "%s = 0x%02x",
2595                             regs390[i].dname,
2596                             8 * rbank + regs390[i].offset);
2597               else
2598                   emitcode ("", "%s = %s + 0x%02x",
2599                             regs390[i].dname,
2600                             regs390[i].base,
2601                             8 * rbank + regs390[i].offset);
2602           }
2603         }
2604     }
2605
2606   /* if this is an interrupt service routine then
2607      save acc, b, dpl, dph  */
2608   if (IFFUNC_ISISR (sym->type))
2609     {
2610
2611       if (!inExcludeList ("acc"))
2612         emitcode ("push", "acc");
2613       if (!inExcludeList ("b"))
2614         emitcode ("push", "b");
2615       if (!inExcludeList ("dpl"))
2616         emitcode ("push", "dpl");
2617       if (!inExcludeList ("dph"))
2618         emitcode ("push", "dph");
2619       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2620         {
2621           emitcode ("push", "dpx");
2622           /* Make sure we're using standard DPTR */
2623           emitcode ("push", "dps");
2624           emitcode ("mov", "dps, #0x00");
2625           if (options.stack10bit)
2626             {
2627               /* This ISR could conceivably use DPTR2. Better save it. */
2628               emitcode ("push", "dpl1");
2629               emitcode ("push", "dph1");
2630               emitcode ("push", "dpx1");
2631               emitcode ("push",  DP2_RESULT_REG);
2632             }
2633         }
2634       /* if this isr has no bank i.e. is going to
2635          run with bank 0 , then we need to save more
2636          registers :-) */
2637       if (!FUNC_REGBANK (sym->type))
2638         {
2639
2640           /* if this function does not call any other
2641              function then we can be economical and
2642              save only those registers that are used */
2643           if (!IFFUNC_HASFCALL(sym->type))
2644             {
2645               int i;
2646
2647               /* if any registers used */
2648               if (sym->regsUsed)
2649                 {
2650                   /* save the registers used */
2651                   for (i = 0; i < sym->regsUsed->size; i++)
2652                     {
2653                       if (bitVectBitValue (sym->regsUsed, i) ||
2654                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2655                         emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2656                     }
2657                 }
2658
2659             }
2660           else
2661             {
2662               /* this function has  a function call cannot
2663                  determines register usage so we will have to push the
2664                  entire bank */
2665               saveRBank (0, ic, FALSE);
2666             }
2667         }
2668         else
2669         {
2670             /* This ISR uses a non-zero bank.
2671              *
2672              * We assume that the bank is available for our
2673              * exclusive use.
2674              *
2675              * However, if this ISR calls a function which uses some
2676              * other bank, we must save that bank entirely.
2677              */
2678             unsigned long banksToSave = 0;
2679             
2680             if (IFFUNC_HASFCALL(sym->type))
2681             {
2682
2683 #define MAX_REGISTER_BANKS 4
2684
2685                 iCode *i;
2686                 int ix;
2687
2688                 for (i = ic; i; i = i->next)
2689                 {
2690                     if (i->op == ENDFUNCTION)
2691                     {
2692                         /* we got to the end OK. */
2693                         break;
2694                     }
2695                     
2696                     if (i->op == CALL)
2697                     {
2698                         sym_link *dtype;
2699                         
2700                         dtype = operandType (IC_LEFT(i));
2701                         if (dtype 
2702                          && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2703                         {
2704                              /* Mark this bank for saving. */
2705                              if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2706                              {
2707                                  werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2708                              }
2709                              else
2710                              {
2711                                  banksToSave |= (1 << FUNC_REGBANK(dtype));
2712                              }
2713                              
2714                              /* And note that we don't need to do it in 
2715                               * genCall.
2716                               */
2717                              i->bankSaved = 1;
2718                         }
2719                     }
2720                     if (i->op == PCALL)
2721                     {
2722                         /* This is a mess; we have no idea what
2723                          * register bank the called function might
2724                          * use.
2725                          *
2726                          * The only thing I can think of to do is
2727                          * throw a warning and hope.
2728                          */
2729                         werror(W_FUNCPTR_IN_USING_ISR);   
2730                     }
2731                 }
2732
2733                 if (banksToSave && options.useXstack)
2734                 {
2735                     /* Since we aren't passing it an ic, 
2736                      * saveRBank will assume r0 is available to abuse.
2737                      *
2738                      * So switch to our (trashable) bank now, so
2739                      * the caller's R0 isn't trashed.
2740                      */
2741                     emitcode ("push", "psw");
2742                     emitcode ("mov", "psw,#0x%02x", 
2743                               (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2744                     switchedPSW = TRUE;
2745                 }
2746                 
2747                 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2748                 {
2749                      if (banksToSave & (1 << ix))
2750                      {
2751                          saveRBank(ix, NULL, FALSE);
2752                      }
2753                 }
2754             }
2755             // jwk: this needs a closer look
2756             SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2757         }
2758     }
2759   else
2760     {
2761       /* if callee-save to be used for this function
2762          then save the registers being used in this function */
2763       if (IFFUNC_CALLEESAVES(sym->type))
2764         {
2765           int i;
2766
2767           /* if any registers used */
2768           if (sym->regsUsed)
2769             {
2770               /* save the registers used */
2771               for (i = 0; i < sym->regsUsed->size; i++)
2772                 {
2773                   if (bitVectBitValue (sym->regsUsed, i) ||
2774                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2775                     {
2776                       emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2777                       _G.nRegsSaved++;
2778                     }
2779                 }
2780             }
2781         }
2782     }
2783
2784   /* set the register bank to the desired value */
2785   if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
2786    && !switchedPSW)
2787     {
2788       emitcode ("push", "psw");
2789       emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2790     }
2791
2792   if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2793     {
2794
2795       if (options.useXstack)
2796         {
2797           emitcode ("mov", "r0,%s", spname);
2798           emitcode ("mov", "a,_bp");
2799           emitcode ("movx", "@r0,a");
2800           emitcode ("inc", "%s", spname);
2801         }
2802       else
2803         {
2804           /* set up the stack */
2805           emitcode ("push", "_bp");     /* save the callers stack  */
2806         }
2807       emitcode ("mov", "_bp,%s", spname);
2808     }
2809
2810   /* adjust the stack for the function */
2811   if (sym->stack)
2812     {
2813
2814       int i = sym->stack;
2815       if (i > 256)
2816         werror (W_STACK_OVERFLOW, sym->name);
2817
2818       if (i > 3 && sym->recvSize < 4)
2819         {
2820
2821           emitcode ("mov", "a,sp");
2822           emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2823           emitcode ("mov", "sp,a");
2824
2825         }
2826       else
2827         while (i--)
2828           emitcode ("inc", "sp");
2829     }
2830
2831   if (sym->xstack)
2832     {
2833
2834       emitcode ("mov", "a,_spx");
2835       emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2836       emitcode ("mov", "_spx,a");
2837     }
2838
2839 }
2840
2841 /*-----------------------------------------------------------------*/
2842 /* genEndFunction - generates epilogue for functions               */
2843 /*-----------------------------------------------------------------*/
2844 static void
2845 genEndFunction (iCode * ic)
2846 {
2847   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2848
2849   D (emitcode (";", "genEndFunction "););
2850
2851   if (IFFUNC_ISNAKED(sym->type))
2852   {
2853       emitcode(";", "naked function: no epilogue.");
2854       return;
2855   }
2856
2857   if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2858     {
2859       emitcode ("mov", "%s,_bp", spname);
2860     }
2861
2862   /* if use external stack but some variables were
2863      added to the local stack then decrement the
2864      local stack */
2865   if (options.useXstack && sym->stack)
2866     {
2867       emitcode ("mov", "a,sp");
2868       emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2869       emitcode ("mov", "sp,a");
2870     }
2871
2872
2873   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2874     {
2875       if (options.useXstack)
2876         {
2877           emitcode ("mov", "r0,%s", spname);
2878           emitcode ("movx", "a,@r0");
2879           emitcode ("mov", "_bp,a");
2880           emitcode ("dec", "%s", spname);
2881         }
2882       else
2883         {
2884           emitcode ("pop", "_bp");
2885         }
2886     }
2887
2888   /* restore the register bank  */
2889   if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
2890   {
2891     if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
2892      || !options.useXstack)
2893     {
2894         /* Special case of ISR using non-zero bank with useXstack
2895          * is handled below.
2896          */
2897         emitcode ("pop", "psw");
2898     }
2899   }
2900
2901   if (IFFUNC_ISISR (sym->type))
2902     {
2903
2904       /* now we need to restore the registers */
2905       /* if this isr has no bank i.e. is going to
2906          run with bank 0 , then we need to save more
2907          registers :-) */
2908       if (!FUNC_REGBANK (sym->type))
2909         {
2910           /* if this function does not call any other
2911              function then we can be economical and
2912              save only those registers that are used */
2913           if (!IFFUNC_HASFCALL(sym->type))
2914             {
2915               int i;
2916
2917               /* if any registers used */
2918               if (sym->regsUsed)
2919                 {
2920                   /* save the registers used */
2921                   for (i = sym->regsUsed->size; i >= 0; i--)
2922                     {
2923                       if (bitVectBitValue (sym->regsUsed, i) ||
2924                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2925                         emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2926                     }
2927                 }
2928
2929             }
2930           else
2931             {
2932               /* this function has  a function call cannot
2933                  determines register usage so we will have to pop the
2934                  entire bank */
2935               unsaveRBank (0, ic, FALSE);
2936             }
2937         }
2938         else
2939         {
2940             /* This ISR uses a non-zero bank.
2941              *
2942              * Restore any register banks saved by genFunction
2943              * in reverse order.
2944              */
2945           // jwk: this needs a closer look
2946             unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2947             int ix;
2948           
2949             for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2950             {
2951                 if (savedBanks & (1 << ix))
2952                 {
2953                     unsaveRBank(ix, NULL, FALSE);
2954                 }
2955             }
2956             
2957             if (options.useXstack)
2958             {
2959                 /* Restore bank AFTER calling unsaveRBank,
2960                  * since it can trash r0.
2961                  */
2962                 emitcode ("pop", "psw");
2963             }
2964         }
2965
2966       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2967         {
2968           if (options.stack10bit)
2969             {
2970               emitcode ("pop", DP2_RESULT_REG);
2971               emitcode ("pop", "dpx1");
2972               emitcode ("pop", "dph1");
2973               emitcode ("pop", "dpl1");
2974             }
2975           emitcode ("pop", "dps");
2976           emitcode ("pop", "dpx");
2977         }
2978       if (!inExcludeList ("dph"))
2979         emitcode ("pop", "dph");
2980       if (!inExcludeList ("dpl"))
2981         emitcode ("pop", "dpl");
2982       if (!inExcludeList ("b"))
2983         emitcode ("pop", "b");
2984       if (!inExcludeList ("acc"))
2985         emitcode ("pop", "acc");
2986
2987       if (IFFUNC_ISCRITICAL (sym->type))
2988         emitcode ("setb", "ea");
2989
2990       /* if debug then send end of function */
2991       if (options.debug && currFunc) {
2992           _G.debugLine = 1;
2993           emitcode ("", "C$%s$%d$%d$%d ==.",
2994                     FileBaseName (ic->filename), currFunc->lastLine,
2995                     ic->level, ic->block);
2996           if (IS_STATIC (currFunc->etype))
2997             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2998           else
2999             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3000           _G.debugLine = 0;
3001         }
3002
3003       emitcode ("reti", "");
3004     }
3005   else
3006     {
3007       if (IFFUNC_ISCRITICAL (sym->type))
3008         emitcode ("setb", "ea");
3009
3010       if (IFFUNC_CALLEESAVES(sym->type))
3011         {
3012           int i;
3013
3014           /* if any registers used */
3015           if (sym->regsUsed)
3016             {
3017               /* save the registers used */
3018               for (i = sym->regsUsed->size; i >= 0; i--)
3019                 {
3020                   if (bitVectBitValue (sym->regsUsed, i) ||
3021                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3022                     emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3023                 }
3024             }
3025
3026         }
3027
3028       /* if debug then send end of function */
3029       if (options.debug && currFunc)
3030         {
3031           _G.debugLine = 1;
3032           emitcode ("", "C$%s$%d$%d$%d ==.",
3033                     FileBaseName (ic->filename), currFunc->lastLine,
3034                     ic->level, ic->block);
3035           if (IS_STATIC (currFunc->etype))
3036             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3037           else
3038             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3039           _G.debugLine = 0;
3040         }
3041
3042       emitcode ("ret", "");
3043     }
3044
3045 }
3046
3047 /*-----------------------------------------------------------------*/
3048 /* genRet - generate code for return statement                     */
3049 /*-----------------------------------------------------------------*/
3050 static void
3051 genRet (iCode * ic)
3052 {
3053   int size, offset = 0, pushed = 0;
3054
3055   D (emitcode (";", "genRet ");
3056     );
3057
3058   /* if we have no return value then
3059      just generate the "ret" */
3060   if (!IC_LEFT (ic))
3061     goto jumpret;
3062
3063   /* we have something to return then
3064      move the return value into place */
3065   aopOp (IC_LEFT (ic), ic, FALSE, TRUE);
3066   size = AOP_SIZE (IC_LEFT (ic));
3067
3068   _startLazyDPSEvaluation ();
3069   while (size--)
3070     {
3071       char *l;
3072       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3073         {
3074           l = aopGet (AOP (IC_LEFT (ic)), offset++,
3075                       FALSE, TRUE, FALSE);
3076           emitcode ("push", "%s", l);
3077           pushed++;
3078         }
3079       else
3080         {
3081           /* Since A is the last element of fReturn,
3082            * is is OK to clobber it in the aopGet.
3083            */
3084           l = aopGet (AOP (IC_LEFT (ic)), offset,
3085                       FALSE, FALSE, TRUE);
3086           if (strcmp (fReturn[offset], l))
3087             emitcode ("mov", "%s,%s", fReturn[offset++], l);
3088         }
3089     }
3090   _endLazyDPSEvaluation ();
3091
3092   if (pushed)
3093     {
3094       while (pushed)
3095         {
3096           pushed--;
3097           if (strcmp (fReturn[pushed], "a"))
3098             emitcode ("pop", fReturn[pushed]);
3099           else
3100             emitcode ("pop", "acc");
3101         }
3102     }
3103   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3104
3105 jumpret:
3106   /* generate a jump to the return label
3107      if the next is not the return statement */
3108   if (!(ic->next && ic->next->op == LABEL &&
3109         IC_LABEL (ic->next) == returnLabel))
3110
3111     emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3112
3113 }
3114
3115 /*-----------------------------------------------------------------*/
3116 /* genLabel - generates a label                                    */
3117 /*-----------------------------------------------------------------*/
3118 static void
3119 genLabel (iCode * ic)
3120 {
3121   /* special case never generate */
3122   if (IC_LABEL (ic) == entryLabel)
3123     return;
3124
3125   D (emitcode (";", "genLabel ");
3126     );
3127
3128   emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3129 }
3130
3131 /*-----------------------------------------------------------------*/
3132 /* genGoto - generates a ljmp                                      */
3133 /*-----------------------------------------------------------------*/
3134 static void
3135 genGoto (iCode * ic)
3136 {
3137   D (emitcode (";", "genGoto ");
3138     );
3139   emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
3140 }
3141
3142 /*-----------------------------------------------------------------*/
3143 /* findLabelBackwards: walks back through the iCode chain looking  */
3144 /* for the given label. Returns number of iCode instructions     */
3145 /* between that label and given ic.          */
3146 /* Returns zero if label not found.          */
3147 /*-----------------------------------------------------------------*/
3148 static int
3149 findLabelBackwards (iCode * ic, int key)
3150 {
3151   int count = 0;
3152
3153   while (ic->prev)
3154     {
3155       ic = ic->prev;
3156       count++;
3157
3158       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3159         {
3160           /* printf("findLabelBackwards = %d\n", count); */
3161           return count;
3162         }
3163     }
3164
3165   return 0;
3166 }
3167
3168 /*-----------------------------------------------------------------*/
3169 /* genPlusIncr :- does addition with increment if possible         */
3170 /*-----------------------------------------------------------------*/
3171 static bool
3172 genPlusIncr (iCode * ic)
3173 {
3174   unsigned int icount;
3175   unsigned int size = getDataSize (IC_RESULT (ic));
3176
3177   /* will try to generate an increment */
3178   /* if the right side is not a literal
3179      we cannot */
3180   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3181     return FALSE;
3182
3183   /* if the literal value of the right hand side
3184      is greater than 4 then it is not worth it */
3185   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3186     return FALSE;
3187
3188   /* if increment 16 bits in register */
3189   if (
3190        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3191        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3192        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3193        (size > 1) &&
3194        (icount == 1))
3195     {
3196       symbol *tlbl;
3197       int emitTlbl;
3198       int labelRange;
3199
3200       /* If the next instruction is a goto and the goto target
3201        * is <= 5 instructions previous to this, we can generate
3202        * jumps straight to that target.
3203        */
3204       if (ic->next && ic->next->op == GOTO
3205           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3206           && labelRange <= 5)
3207         {
3208           emitcode (";", "tail increment optimized (range %d)", labelRange);
3209           tlbl = IC_LABEL (ic->next);
3210           emitTlbl = 0;
3211         }
3212       else
3213         {
3214           tlbl = newiTempLabel (NULL);
3215           emitTlbl = 1;
3216         }
3217       emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3218       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3219           IS_AOP_PREG (IC_RESULT (ic)))
3220         emitcode ("cjne", "%s,#0x00,%05d$"
3221                   ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3222                   ,tlbl->key + 100);
3223       else
3224         {
3225           emitcode ("clr", "a");
3226           emitcode ("cjne", "a,%s,%05d$"
3227                     ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3228                     ,tlbl->key + 100);
3229         }
3230
3231       emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3232       if (size > 2)
3233         {
3234           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3235               IS_AOP_PREG (IC_RESULT (ic)))
3236             emitcode ("cjne", "%s,#0x00,%05d$"
3237                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3238                       ,tlbl->key + 100);
3239           else
3240             emitcode ("cjne", "a,%s,%05d$"
3241                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3242                       ,tlbl->key + 100);
3243
3244           emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3245         }
3246       if (size > 3)
3247         {
3248           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3249               IS_AOP_PREG (IC_RESULT (ic)))
3250             emitcode ("cjne", "%s,#0x00,%05d$"
3251                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3252                       ,tlbl->key + 100);
3253           else
3254             {
3255               emitcode ("cjne", "a,%s,%05d$"
3256                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3257                         ,tlbl->key + 100);
3258             }
3259           emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3260         }
3261
3262       if (emitTlbl)
3263         {
3264           emitcode ("", "%05d$:", tlbl->key + 100);
3265         }
3266       return TRUE;
3267     }
3268
3269   /* if the sizes are greater than 1 then we cannot */
3270   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3271       AOP_SIZE (IC_LEFT (ic)) > 1)
3272     return FALSE;
3273
3274   /* we can if the aops of the left & result match or
3275      if they are in registers and the registers are the
3276      same */
3277   if (
3278        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3279        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3280        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3281     {
3282
3283       if (icount > 3)
3284         {
3285           MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3286           emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3287           aopPut (AOP (IC_RESULT (ic)), "a", 0);
3288         }
3289       else
3290         {
3291
3292           _startLazyDPSEvaluation ();
3293           while (icount--)
3294             {
3295               emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3296             }
3297           _endLazyDPSEvaluation ();
3298         }
3299
3300       return TRUE;
3301     }
3302
3303   return FALSE;
3304 }
3305
3306 /*-----------------------------------------------------------------*/
3307 /* outBitAcc - output a bit in acc                                 */
3308 /*-----------------------------------------------------------------*/
3309 static void
3310 outBitAcc (operand * result)
3311 {
3312   symbol *tlbl = newiTempLabel (NULL);
3313   /* if the result is a bit */
3314   if (AOP_TYPE (result) == AOP_CRY)
3315     {
3316       aopPut (AOP (result), "a", 0);
3317     }
3318   else
3319     {
3320       emitcode ("jz", "%05d$", tlbl->key + 100);
3321       emitcode ("mov", "a,%s", one);
3322       emitcode ("", "%05d$:", tlbl->key + 100);
3323       outAcc (result);
3324     }
3325 }
3326
3327 /*-----------------------------------------------------------------*/
3328 /* genPlusBits - generates code for addition of two bits           */
3329 /*-----------------------------------------------------------------*/
3330 static void
3331 genPlusBits (iCode * ic)
3332 {
3333   D (emitcode (";", "genPlusBits ");
3334     );
3335   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3336     {
3337       symbol *lbl = newiTempLabel (NULL);
3338       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3339       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3340       emitcode ("cpl", "c");
3341       emitcode ("", "%05d$:", (lbl->key + 100));
3342       outBitC (IC_RESULT (ic));
3343     }
3344   else
3345     {
3346       emitcode ("clr", "a");
3347       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3348       emitcode ("rlc", "a");
3349       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3350       emitcode ("addc", "a,#0x00");
3351       outAcc (IC_RESULT (ic));
3352     }
3353 }
3354
3355 static void
3356 adjustArithmeticResult (iCode * ic)
3357 {
3358   if (opIsGptr (IC_RESULT (ic)) &&
3359       opIsGptr (IC_LEFT (ic)) &&
3360       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3361     {
3362       aopPut (AOP (IC_RESULT (ic)),
3363               aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3364               GPTRSIZE - 1);
3365     }
3366
3367   if (opIsGptr (IC_RESULT (ic)) &&
3368       opIsGptr (IC_RIGHT (ic)) &&
3369       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3370     {
3371       aopPut (AOP (IC_RESULT (ic)),
3372             aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3373               GPTRSIZE - 1);
3374     }
3375
3376   if (opIsGptr (IC_RESULT (ic)) &&
3377       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3378       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3379       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3380       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3381     {
3382       char buffer[5];
3383       sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3384       aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3385     }
3386 }
3387
3388 #if 0 // AOP_OP_3 is deprecated; nobody likes Ack errors.
3389       // Please don't bring it back without a really good reason.
3390 // Macro to aopOp all three operands of an ic. Will fatal if this cannot be done
3391 // (because all three operands are in far space).
3392 #define AOP_OP_3(ic) \
3393     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3394     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3395     aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3396               (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3397     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3398         AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3399     { \
3400         /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3401         fprintf(stderr,                                  \
3402                "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno);   \
3403     }
3404 #endif
3405
3406 // Macro to aopOp all three operands of an ic. If this cannot be done, 
3407 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3408 // will be set TRUE. The caller must then handle the case specially, noting
3409 // that the IC_RESULT operand is not aopOp'd.
3410 #define AOP_OP_3_NOFATAL(ic, rc) \
3411     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3412     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3413     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3414         isOperandInFarSpace(IC_RESULT(ic))) \
3415     { \
3416        /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3417        rc = TRUE; \
3418     }  \
3419     else \
3420     { \
3421        aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3422                                      (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3423        rc = FALSE; \
3424        if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3425            AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3426        { \
3427             /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3428             fprintf(stderr,                                  \
3429                     "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno);   \
3430        } \
3431     }
3432
3433 // aopOp the left & right operands of an ic.
3434 #define AOP_OP_2(ic) \
3435     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3436     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3437
3438 // convienience macro.
3439 #define AOP_SET_LOCALS(ic) \
3440     left = IC_LEFT(ic); \
3441     right = IC_RIGHT(ic); \
3442     result = IC_RESULT(ic);
3443
3444
3445 // Given an integer value of pushedSize bytes on the stack,
3446 // adjust it to be resultSize bytes, either by discarding
3447 // the most significant bytes or by zero-padding.
3448 //
3449 // On exit from this macro, pushedSize will have been adjusted to
3450 // equal resultSize, and ACC may be trashed.
3451 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize)            \
3452       /* If the pushed data is bigger than the result,          \
3453        * simply discard unused bytes. Icky, but works.          \
3454        */                                                       \
3455       while (pushedSize > resultSize)                           \
3456       {                                                         \
3457           D (emitcode (";", "discarding unused result byte."););\
3458           emitcode ("pop", "acc");                              \
3459           pushedSize--;                                         \
3460       }                                                         \
3461       if (pushedSize < resultSize)                              \
3462       {                                                         \
3463           emitcode ("clr", "a");                                \
3464           /* Conversly, we haven't pushed enough here.          \
3465            * just zero-pad, and all is well.                    \
3466            */                                                   \
3467           while (pushedSize < resultSize)                       \
3468           {                                                     \
3469               emitcode("push", "acc");                          \
3470               pushedSize++;                                     \
3471           }                                                     \
3472       }                                                         \
3473       assert(pushedSize == resultSize);
3474
3475 /*-----------------------------------------------------------------*/
3476 /* genPlus - generates code for addition                           */
3477 /*-----------------------------------------------------------------*/
3478 static void
3479 genPlus (iCode * ic)
3480 {
3481   int size, offset = 0;
3482   bool pushResult = FALSE;
3483   int rSize;
3484
3485   D (emitcode (";", "genPlus "););
3486
3487   /* special cases :- */
3488
3489   AOP_OP_3_NOFATAL (ic, pushResult);
3490   if (pushResult)
3491     {
3492       D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3493     }
3494
3495   if (!pushResult)
3496     {
3497       /* if literal, literal on the right or
3498          if left requires ACC or right is already
3499          in ACC */
3500       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3501        || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3502           || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3503         {
3504           operand *t = IC_RIGHT (ic);
3505           IC_RIGHT (ic) = IC_LEFT (ic);
3506           IC_LEFT (ic) = t;
3507           emitcode (";", "Swapped plus args.");
3508         }
3509
3510       /* if both left & right are in bit
3511          space */
3512       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3513           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3514         {
3515           genPlusBits (ic);
3516           goto release;
3517         }
3518
3519       /* if left in bit space & right literal */
3520       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3521           AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3522         {
3523           emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3524           /* if result in bit space */
3525           if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3526             {
3527               if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3528                 emitcode ("cpl", "c");
3529               outBitC (IC_RESULT (ic));
3530             }
3531           else
3532             {
3533               size = getDataSize (IC_RESULT (ic));
3534               _startLazyDPSEvaluation ();
3535               while (size--)
3536                 {
3537                   MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3538                   emitcode ("addc", "a,#00");
3539                   aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3540                 }
3541               _endLazyDPSEvaluation ();
3542             }
3543           goto release;
3544         }
3545
3546       /* if I can do an increment instead
3547          of add then GOOD for ME */
3548       if (genPlusIncr (ic) == TRUE)
3549         {
3550           emitcode (";", "did genPlusIncr");
3551           goto release;
3552         }
3553
3554     }
3555   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3556
3557   _startLazyDPSEvaluation ();
3558   while (size--)
3559     {
3560       if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
3561         {
3562           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3563           if (offset == 0)
3564             emitcode ("add", "a,%s",
3565                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3566           else
3567             emitcode ("addc", "a,%s",
3568                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3569         }
3570       else
3571         {
3572           if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
3573           {
3574               /* right is going to use ACC or we would have taken the
3575                * above branch.
3576                */
3577               assert(AOP_NEEDSACC(IC_RIGHT(ic)));
3578        TR_AP("#3");
3579               D(emitcode(";", "+ AOP_ACC special case."););
3580               emitcode("xch", "a, %s", DP2_RESULT_REG);
3581           }
3582           MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3583           if (offset == 0)
3584           {
3585             if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
3586             {
3587          TR_AP("#4");
3588                 emitcode("add", "a, %s", DP2_RESULT_REG); 
3589             }
3590             else
3591             {
3592                 emitcode ("add", "a,%s",
3593                         aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE, FALSE));
3594             }
3595           }
3596           else
3597           {
3598             emitcode ("addc", "a,%s",
3599                   aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3600           }
3601         }
3602       if (!pushResult)
3603         {
3604           aopPut (AOP (IC_RESULT (ic)), "a", offset);
3605         }
3606       else
3607         {
3608           emitcode ("push", "acc");
3609         }
3610       offset++;
3611     }
3612   _endLazyDPSEvaluation ();
3613
3614   if (pushResult)
3615     {
3616       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3617
3618       size = getDataSize (IC_LEFT (ic));
3619       rSize = getDataSize (IC_RESULT (ic));
3620
3621       ADJUST_PUSHED_RESULT(size, rSize);
3622
3623       _startLazyDPSEvaluation ();
3624       while (size--)
3625         {
3626           emitcode ("pop", "acc");
3627           aopPut (AOP (IC_RESULT (ic)), "a", size);
3628         }
3629       _endLazyDPSEvaluation ();
3630     }
3631
3632   adjustArithmeticResult (ic);
3633
3634 release:
3635   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3636   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3637   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3638 }
3639
3640 /*-----------------------------------------------------------------*/
3641 /* genMinusDec :- does subtraction with deccrement if possible     */
3642 /*-----------------------------------------------------------------*/
3643 static bool
3644 genMinusDec (iCode * ic)
3645 {
3646   unsigned int icount;
3647   unsigned int size = getDataSize (IC_RESULT (ic));
3648
3649   /* will try to generate an increment */
3650   /* if the right side is not a literal
3651      we cannot */
3652   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3653     return FALSE;
3654
3655   /* if the literal value of the right hand side
3656      is greater than 4 then it is not worth it */
3657   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3658     return FALSE;
3659
3660   /* if decrement 16 bits in register */
3661   if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3662       AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3663       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3664       (size > 1) &&
3665       (icount == 1))
3666     {
3667       symbol *tlbl;
3668       int emitTlbl;
3669       int labelRange;
3670
3671       /* If the next instruction is a goto and the goto target
3672          * is <= 5 instructions previous to this, we can generate
3673          * jumps straight to that target.
3674        */
3675       if (ic->next && ic->next->op == GOTO
3676           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3677           && labelRange <= 5)
3678         {
3679           emitcode (";", "tail decrement optimized (range %d)", labelRange);
3680           tlbl = IC_LABEL (ic->next);
3681           emitTlbl = 0;
3682         }
3683       else
3684         {
3685           tlbl = newiTempLabel (NULL);
3686           emitTlbl = 1;
3687         }
3688
3689       emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3690       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3691           AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3692           IS_AOP_PREG (IC_RESULT (ic)))
3693         emitcode ("cjne", "%s,#0xff,%05d$"
3694                   ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3695                   ,tlbl->key + 100);
3696       else
3697         {
3698           emitcode ("mov", "a,#0xff");
3699           emitcode ("cjne", "a,%s,%05d$"
3700                     ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3701                     ,tlbl->key + 100);
3702         }
3703       emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3704       if (size > 2)
3705         {
3706           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3707               AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3708               IS_AOP_PREG (IC_RESULT (ic)))
3709             emitcode ("cjne", "%s,#0xff,%05d$"
3710                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3711                       ,tlbl->key + 100);
3712           else
3713             {
3714               emitcode ("cjne", "a,%s,%05d$"
3715                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3716                         ,tlbl->key + 100);
3717             }
3718           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3719         }
3720       if (size > 3)
3721         {
3722           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3723               AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3724               IS_AOP_PREG (IC_RESULT (ic)))
3725             emitcode ("cjne", "%s,#0xff,%05d$"
3726                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3727                       ,tlbl->key + 100);
3728           else
3729             {
3730               emitcode ("cjne", "a,%s,%05d$"
3731                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3732                         ,tlbl->key + 100);
3733             }
3734           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3735         }
3736       if (emitTlbl)
3737         {
3738           emitcode ("", "%05d$:", tlbl->key + 100);
3739         }
3740       return TRUE;
3741     }
3742
3743   /* if the sizes are greater than 1 then we cannot */
3744   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3745       AOP_SIZE (IC_LEFT (ic)) > 1)
3746     return FALSE;
3747
3748   /* we can if the aops of the left & result match or
3749      if they are in registers and the registers are the
3750      same */
3751   if (
3752        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3753        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3754        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3755     {
3756
3757       _startLazyDPSEvaluation ();
3758       while (icount--)
3759         {
3760           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
3761         }
3762       _endLazyDPSEvaluation ();
3763
3764       return TRUE;
3765     }
3766
3767   return FALSE;
3768 }
3769
3770 /*-----------------------------------------------------------------*/
3771 /* addSign - complete with sign                                    */
3772 /*-----------------------------------------------------------------*/
3773 static void
3774 addSign (operand * result, int offset, int sign)
3775 {
3776   int size = (getDataSize (result) - offset);
3777   if (size > 0)
3778     {
3779       _startLazyDPSEvaluation();
3780       if (sign)
3781         {
3782           emitcode ("rlc", "a");
3783           emitcode ("subb", "a,acc");
3784           while (size--)
3785           {
3786             aopPut (AOP (result), "a", offset++);
3787           }
3788         }
3789       else
3790       {
3791         while (size--)
3792         {
3793           aopPut (AOP (result), zero, offset++);
3794         }
3795       }
3796       _endLazyDPSEvaluation();
3797     }
3798 }
3799
3800 /*-----------------------------------------------------------------*/
3801 /* genMinusBits - generates code for subtraction  of two bits      */
3802 /*-----------------------------------------------------------------*/
3803 static void
3804 genMinusBits (iCode * ic)
3805 {
3806   symbol *lbl = newiTempLabel (NULL);
3807
3808   D (emitcode (";", "genMinusBits "););
3809
3810   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3811     {
3812       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3813       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3814       emitcode ("cpl", "c");
3815       emitcode ("", "%05d$:", (lbl->key + 100));
3816       outBitC (IC_RESULT (ic));
3817     }
3818   else
3819     {
3820       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3821       emitcode ("subb", "a,acc");
3822       emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3823       emitcode ("inc", "a");
3824       emitcode ("", "%05d$:", (lbl->key + 100));
3825       aopPut (AOP (IC_RESULT (ic)), "a", 0);
3826       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3827     }
3828 }
3829
3830 /*-----------------------------------------------------------------*/
3831 /* genMinus - generates code for subtraction                       */
3832 /*-----------------------------------------------------------------*/
3833 static void
3834 genMinus (iCode * ic)
3835 {
3836   int size, offset = 0;
3837   int rSize;
3838   unsigned long lit = 0L;
3839   bool pushResult = FALSE;
3840
3841   D (emitcode (";", "genMinus "););
3842
3843   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3844   aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
3845   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
3846       (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
3847     {
3848       pushResult = TRUE;
3849     }
3850   else
3851     {
3852       aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
3853
3854       /* special cases :- */
3855       /* if both left & right are in bit space */
3856       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3857           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3858         {
3859           genMinusBits (ic);
3860           goto release;
3861         }
3862
3863       /* if I can do an decrement instead
3864          of subtract then GOOD for ME */
3865       if (genMinusDec (ic) == TRUE)
3866         goto release;
3867
3868     }
3869
3870   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3871
3872   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3873     {
3874       CLRC;
3875     }
3876   else
3877     {
3878       lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3879       lit = -(long) lit;
3880     }
3881
3882
3883   /* if literal, add a,#-lit, else normal subb */
3884   _startLazyDPSEvaluation ();
3885   while (size--)
3886     {
3887       MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3888       if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3889         emitcode ("subb", "a,%s",
3890                   aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3891       else
3892         {
3893           /* first add without previous c */
3894           if (!offset) {
3895             if (!size && lit==-1) {
3896               emitcode ("dec", "a");
3897             } else {
3898               emitcode ("add", "a,#0x%02x",
3899                         (unsigned int) (lit & 0x0FFL));
3900             }
3901           } else {
3902             emitcode ("addc", "a,#0x%02x",
3903                       (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3904           }
3905         }
3906
3907       if (pushResult)
3908         {
3909           emitcode ("push", "acc");
3910         }
3911       else
3912         {
3913           aopPut (AOP (IC_RESULT (ic)), "a", offset);
3914         }
3915       offset++;
3916     }
3917   _endLazyDPSEvaluation ();
3918
3919   if (pushResult)
3920     {
3921       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3922
3923       size = getDataSize (IC_LEFT (ic));
3924       rSize = getDataSize (IC_RESULT (ic));
3925
3926       ADJUST_PUSHED_RESULT(size, rSize);
3927
3928       _startLazyDPSEvaluation ();
3929       while (size--)
3930         {
3931           emitcode ("pop", "acc");
3932           aopPut (AOP (IC_RESULT (ic)), "a", size);
3933         }
3934       _endLazyDPSEvaluation ();
3935     }
3936
3937   adjustArithmeticResult (ic);
3938
3939 release:
3940   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3941   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3942   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3943 }
3944
3945
3946 /*-----------------------------------------------------------------*/
3947 /* genMultbits :- multiplication of bits                           */
3948 /*-----------------------------------------------------------------*/
3949 static void
3950 genMultbits (operand * left,
3951              operand * right,
3952              operand * result,
3953              iCode   * ic)
3954 {
3955   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3956   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3957   aopOp(result, ic, TRUE, FALSE);
3958   outBitC (result);
3959 }
3960
3961
3962 /*-----------------------------------------------------------------*/
3963 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
3964 /*-----------------------------------------------------------------*/
3965 static void
3966 genMultOneByte (operand * left,
3967                 operand * right,
3968                 operand * result,
3969                 iCode   * ic)
3970 {
3971   sym_link *opetype = operandType (result);
3972   symbol *lbl;
3973
3974
3975   /* (if two literals: the value is computed before) */
3976   /* if one literal, literal on the right */
3977   if (AOP_TYPE (left) == AOP_LIT)
3978     {
3979       operand *t = right;
3980       right = left;
3981       left = t;
3982       emitcode (";", "swapped left and right");
3983     }
3984
3985   if (SPEC_USIGN(opetype)
3986       // ignore the sign of left and right, what else can we do?
3987       || (SPEC_USIGN(operandType(left)) && 
3988           SPEC_USIGN(operandType(right)))) {
3989     // just an unsigned 8*8=8/16 multiply
3990     //emitcode (";","unsigned");
3991     emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3992     MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3993     emitcode ("mul", "ab");
3994    
3995     _G.accInUse++;
3996     aopOp(result, ic, TRUE, FALSE);
3997       
3998       if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
3999       {
4000           // this should never happen
4001           fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4002                    AOP_SIZE(result), __FILE__, lineno);
4003           exit (1);
4004       }      
4005       
4006     aopPut (AOP (result), "a", 0);
4007     _G.accInUse--;
4008     if (AOP_SIZE(result)==2) 
4009     {
4010       aopPut (AOP (result), "b", 1);
4011     }
4012     return;
4013   }
4014
4015   // we have to do a signed multiply
4016
4017   emitcode (";", "signed");
4018   emitcode ("clr", "F0"); // reset sign flag
4019   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4020
4021   lbl=newiTempLabel(NULL);
4022   emitcode ("jnb", "acc.7,%05d$",  lbl->key+100);
4023   // left side is negative, 8-bit two's complement, this fails for -128
4024   emitcode ("setb", "F0"); // set sign flag
4025   emitcode ("cpl", "a");
4026   emitcode ("inc", "a");
4027
4028   emitcode ("", "%05d$:", lbl->key+100);
4029
4030   /* if literal */
4031   if (AOP_TYPE(right)==AOP_LIT) {
4032     signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
4033     /* AND literal negative */
4034     if ((int) val < 0) {
4035       emitcode ("cpl", "F0"); // complement sign flag
4036       emitcode ("mov", "b,#0x%02x", -val);
4037     } else {
4038       emitcode ("mov", "b,#0x%02x", val);
4039     }
4040   } else {
4041     lbl=newiTempLabel(NULL);
4042     emitcode ("mov", "b,a");
4043     emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4044     emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
4045     // right side is negative, 8-bit two's complement
4046     emitcode ("cpl", "F0"); // complement sign flag
4047     emitcode ("cpl", "a");
4048     emitcode ("inc", "a");
4049     emitcode ("", "%05d$:", lbl->key+100);
4050   }
4051   emitcode ("mul", "ab");
4052     
4053   _G.accInUse++;
4054   aopOp(result, ic, TRUE, FALSE);
4055     
4056   if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4057   {
4058     // this should never happen
4059       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4060                AOP_SIZE(result), __FILE__, lineno);
4061       exit (1);
4062   }    
4063     
4064   lbl=newiTempLabel(NULL);
4065   emitcode ("jnb", "F0,%05d$", lbl->key+100);
4066   // only ONE op was negative, we have to do a 8/16-bit two's complement
4067   emitcode ("cpl", "a"); // lsb
4068   if (AOP_SIZE(result)==1) {
4069     emitcode ("inc", "a");
4070   } else {
4071     emitcode ("add", "a,#1");
4072     emitcode ("xch", "a,b");
4073     emitcode ("cpl", "a"); // msb
4074     emitcode ("addc", "a,#0");
4075     emitcode ("xch", "a,b");
4076   }
4077
4078   emitcode ("", "%05d$:", lbl->key+100);
4079   aopPut (AOP (result), "a", 0);
4080   _G.accInUse--;
4081   if (AOP_SIZE(result)==2) {
4082     aopPut (AOP (result), "b", 1);
4083   }
4084 }
4085
4086 /*-----------------------------------------------------------------*/
4087 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply    */
4088 /*-----------------------------------------------------------------*/
4089 static void genMultTwoByte (operand *left, operand *right, 
4090                             operand *result, iCode *ic)
4091 {
4092         sym_link *retype = getSpec(operandType(right));
4093         sym_link *letype = getSpec(operandType(left));
4094         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4095         symbol *lbl;
4096
4097         if (AOP_TYPE (left) == AOP_LIT) {
4098                 operand *t = right;
4099                 right = left;
4100                 left = t;
4101         }
4102         /* save EA bit in F1 */
4103         lbl = newiTempLabel(NULL);
4104         emitcode ("setb","F1");
4105         emitcode ("jbc","EA,%05d$",lbl->key+100);
4106         emitcode ("clr","F1");
4107         emitcode("","%05d$:",lbl->key+100);
4108
4109         /* load up MB with right */
4110         if (!umult) {
4111                 emitcode("clr","F0");
4112                 if (AOP_TYPE(right) == AOP_LIT) {
4113                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
4114                         if (val < 0) {
4115                                 emitcode("setb","F0");
4116                                 val = -val;
4117                         }
4118                         emitcode ("mov","mb,#0x%02x",val & 0xff);
4119                         emitcode ("mov","mb,#0x%02x",(val >> 8) & 0xff);                    
4120                 } else {
4121                         lbl = newiTempLabel(NULL);
4122                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4123                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4124                         emitcode ("jnb","acc.7,%05d$",lbl->key+100);            
4125                         emitcode ("xch", "a,b");
4126                         emitcode ("cpl","a");
4127                         emitcode ("add", "a,#1");
4128                         emitcode ("xch", "a,b");
4129                         emitcode ("cpl", "a"); // msb
4130                         emitcode ("addc", "a,#0");
4131                         emitcode ("setb","F0");
4132                         emitcode ("","%05d$:",lbl->key+100);
4133                         emitcode ("mov","mb,b");
4134                         emitcode ("mov","mb,a");
4135                 }
4136         } else {
4137                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4138                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4139         }
4140         /* load up MA with left */
4141         if (!umult) {
4142                 lbl = newiTempLabel(NULL);
4143                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4144                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4145                 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4146                 emitcode ("xch", "a,b");
4147                 emitcode ("cpl","a");
4148                 emitcode ("add", "a,#1");
4149                 emitcode ("xch", "a,b");
4150                 emitcode ("cpl", "a"); // msb
4151                 emitcode ("addc","a,#0");
4152                 emitcode ("jbc","F0,%05d$",lbl->key+100);
4153                 emitcode ("setb","F0");
4154                 emitcode ("","%05d$:",lbl->key+100);
4155                 emitcode ("mov","ma,b");
4156                 emitcode ("mov","ma,a");
4157         } else {
4158                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4159                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4160         }
4161         /* wait for multiplication to finish */
4162         lbl = newiTempLabel(NULL);
4163         emitcode("","%05d$:", lbl->key+100);
4164         emitcode("mov","a,mcnt1");
4165         emitcode("anl","a,#0x80");
4166         emitcode("jnz","%05d$",lbl->key+100);
4167         
4168         freeAsmop (left, NULL, ic, TRUE);
4169         freeAsmop (right, NULL, ic,TRUE);
4170         aopOp(result, ic, TRUE, FALSE);
4171
4172         /* if unsigned then simple */   
4173         if (umult) {
4174                 emitcode ("mov","a,ma");
4175                 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4176                 emitcode ("mov","a,ma");
4177                 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4178                 aopPut(AOP(result),"ma",1);
4179                 aopPut(AOP(result),"ma",0);
4180         } else {
4181                 emitcode("push","ma");
4182                 emitcode("push","ma");
4183                 emitcode("push","ma");
4184                 MOVA("ma");
4185                 /* negate result if needed */
4186                 lbl = newiTempLabel(NULL);      
4187                 emitcode("jnb","F0,%05d$",lbl->key+100);
4188                 emitcode("cpl","a");
4189                 emitcode("add","a,#1");
4190                 emitcode("","%05d$:", lbl->key+100);
4191                 if (AOP_TYPE(result) == AOP_ACC)
4192                 {
4193                     D(emitcode(";", "ACC special case."););
4194                     /* We know result is the only live aop, and 
4195                      * it's obviously not a DPTR2, so AP is available.
4196                      */
4197                     emitcode("mov", "%s,acc", DP2_RESULT_REG);
4198                 }
4199                 else
4200                 {
4201                     aopPut(AOP(result),"a",0);
4202                 }
4203             
4204                 emitcode("pop","acc");
4205                 lbl = newiTempLabel(NULL);      
4206                 emitcode("jnb","F0,%05d$",lbl->key+100);
4207                 emitcode("cpl","a");
4208                 emitcode("addc","a,#0");
4209                 emitcode("","%05d$:", lbl->key+100);
4210                 aopPut(AOP(result),"a",1);
4211                 emitcode("pop","acc");
4212                 if (AOP_SIZE(result) >= 3) {
4213                         lbl = newiTempLabel(NULL);      
4214                         emitcode("jnb","F0,%05d$",lbl->key+100);
4215                         emitcode("cpl","a");
4216                         emitcode("addc","a,#0");                        
4217                         emitcode("","%05d$:", lbl->key+100);
4218                         aopPut(AOP(result),"a",2);
4219                 }
4220                 emitcode("pop","acc");
4221                 if (AOP_SIZE(result) >= 4) {
4222                         lbl = newiTempLabel(NULL);      
4223                         emitcode("jnb","F0,%05d$",lbl->key+100);
4224                         emitcode("cpl","a");
4225                         emitcode("addc","a,#0");                        
4226                         emitcode("","%05d$:", lbl->key+100);
4227                         aopPut(AOP(result),"a",3);
4228                 }
4229                 if (AOP_TYPE(result) == AOP_ACC)
4230                 {
4231                     /* We stashed the result away above. */
4232                     emitcode("mov", "acc,%s", DP2_RESULT_REG);
4233                 }           
4234                 
4235         }
4236         freeAsmop (result, NULL, ic, TRUE);
4237
4238         /* restore EA bit in F1 */
4239         lbl = newiTempLabel(NULL);
4240         emitcode ("jnb","F1,%05d$",lbl->key+100);
4241         emitcode ("setb","EA");
4242         emitcode("","%05d$:",lbl->key+100);
4243         return ;
4244 }
4245
4246 /*-----------------------------------------------------------------*/
4247 /* genMult - generates code for multiplication                     */
4248 /*-----------------------------------------------------------------*/
4249 static void
4250 genMult (iCode * ic)
4251 {
4252   operand *left = IC_LEFT (ic);
4253   operand *right = IC_RIGHT (ic);
4254   operand *result = IC_RESULT (ic);
4255
4256   D (emitcode (";", "genMult "););
4257
4258   /* assign the amsops */
4259   AOP_OP_2 (ic);
4260
4261   /* special cases first */
4262   /* both are bits */
4263   if (AOP_TYPE (left) == AOP_CRY &&
4264       AOP_TYPE (right) == AOP_CRY)
4265     {
4266       genMultbits (left, right, result, ic);
4267       goto release;
4268     }
4269
4270   /* if both are of size == 1 */
4271   if (AOP_SIZE (left) == 1 &&
4272       AOP_SIZE (right) == 1)
4273     {
4274       genMultOneByte (left, right, result, ic);
4275       goto release;
4276     }
4277
4278   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4279           /* use the ds390 ARITHMETIC accel UNIT */
4280           genMultTwoByte (left, right, result, ic);
4281           return ;
4282   }
4283   /* should have been converted to function call */
4284   assert (0);
4285
4286 release:
4287   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4288   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4289   freeAsmop (result, NULL, ic, TRUE);
4290 }
4291
4292 /*-----------------------------------------------------------------*/
4293 /* genDivbits :- division of bits                                  */
4294 /*-----------------------------------------------------------------*/
4295 static void
4296 genDivbits (operand * left,
4297             operand * right,
4298             operand * result,
4299             iCode   * ic)
4300 {
4301
4302   char *l;
4303
4304   /* the result must be bit */
4305   LOAD_AB_FOR_DIV (left, right, l);
4306   emitcode ("div", "ab");
4307   emitcode ("rrc", "a");
4308   aopOp(result, ic, TRUE, FALSE);
4309     
4310   aopPut (AOP (result), "c", 0);
4311 }
4312
4313 /*-----------------------------------------------------------------*/
4314 /* genDivOneByte : 8 bit division                                  */
4315 /*-----------------------------------------------------------------*/
4316 static void
4317 genDivOneByte (operand * left,
4318                operand * right,
4319                operand * result,
4320                iCode   * ic)
4321 {
4322   sym_link *opetype = operandType (result);
4323   char *l;
4324   symbol *lbl;
4325   int size, offset;
4326
4327   offset = 1;
4328   /* signed or unsigned */
4329   if (SPEC_USIGN (opetype))
4330     {
4331         /* unsigned is easy */
4332         LOAD_AB_FOR_DIV (left, right, l);
4333         emitcode ("div", "ab");
4334
4335         _G.accInUse++;
4336         aopOp(result, ic, TRUE, FALSE);
4337         aopPut (AOP (result), "a", 0);
4338         _G.accInUse--;
4339
4340         size = AOP_SIZE (result) - 1;
4341         
4342         while (size--)
4343         {
4344             aopPut (AOP (result), zero, offset++);
4345         }
4346       return;
4347     }
4348
4349   /* signed is a little bit more difficult */
4350
4351   /* save the signs of the operands */
4352   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4353   MOVA (l);
4354   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4355   emitcode ("push", "acc");     /* save it on the stack */
4356
4357   /* now sign adjust for both left & right */
4358   l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4359   MOVA (l);
4360   lbl = newiTempLabel (NULL);
4361   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4362   emitcode ("cpl", "a");
4363   emitcode ("inc", "a");
4364   emitcode ("", "%05d$:", (lbl->key + 100));
4365   emitcode ("mov", "b,a");
4366
4367   /* sign adjust left side */
4368   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4369   MOVA (l);
4370
4371   lbl = newiTempLabel (NULL);
4372   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4373   emitcode ("cpl", "a");
4374   emitcode ("inc", "a");
4375   emitcode ("", "%05d$:", (lbl->key + 100));
4376
4377   /* now the division */
4378   emitcode ("nop", "; workaround for DS80C390 div bug.");
4379   emitcode ("div", "ab");
4380   /* we are interested in the lower order
4381      only */
4382   emitcode ("mov", "b,a");
4383   lbl = newiTempLabel (NULL);
4384   emitcode ("pop", "acc");
4385   /* if there was an over flow we don't
4386      adjust the sign of the result */
4387   emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4388   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4389   CLRC;
4390   emitcode ("clr", "a");
4391   emitcode ("subb", "a,b");
4392   emitcode ("mov", "b,a");
4393   emitcode ("", "%05d$:", (lbl->key + 100));
4394
4395   /* now we are done */
4396     _G.accInUse++;
4397     aopOp(result, ic, TRUE, FALSE);
4398     
4399     aopPut (AOP (result), "b", 0);
4400     
4401     size = AOP_SIZE (result) - 1;
4402     
4403     if (size > 0)
4404     {
4405       emitcode ("mov", "c,b.7");
4406       emitcode ("subb", "a,acc");
4407     }
4408     while (size--)
4409     {
4410         aopPut (AOP (result), "a", offset++);
4411     }
4412     _G.accInUse--;
4413
4414 }
4415
4416 /*-----------------------------------------------------------------*/
4417 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide       */
4418 /*-----------------------------------------------------------------*/
4419 static void genDivTwoByte (operand *left, operand *right, 
4420                             operand *result, iCode *ic)
4421 {
4422         sym_link *retype = getSpec(operandType(right));
4423         sym_link *letype = getSpec(operandType(left));
4424         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4425         symbol *lbl;
4426
4427         /* save EA bit in F1 */
4428         lbl = newiTempLabel(NULL);
4429         emitcode ("setb","F1");
4430         emitcode ("jbc","EA,%05d$",lbl->key+100);
4431         emitcode ("clr","F1");
4432         emitcode("","%05d$:",lbl->key+100);
4433
4434         /* load up MA with left */
4435         if (!umult) {
4436                 emitcode("clr","F0");
4437                 lbl = newiTempLabel(NULL);
4438                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4439                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4440                 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4441                 emitcode ("xch", "a,b");
4442                 emitcode ("cpl","a");
4443                 emitcode ("add", "a,#1");
4444                 emitcode ("xch", "a,b");
4445                 emitcode ("cpl", "a"); // msb
4446                 emitcode ("addc","a,#0");
4447                 emitcode ("setb","F0");
4448                 emitcode ("","%05d$:",lbl->key+100);
4449                 emitcode ("mov","ma,b");
4450                 emitcode ("mov","ma,a");
4451         } else {
4452                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4453                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4454         }
4455
4456         /* load up MB with right */
4457         if (!umult) {
4458                 if (AOP_TYPE(right) == AOP_LIT) {
4459                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
4460                         if (val < 0) {
4461                                 lbl = newiTempLabel(NULL);
4462                                 emitcode ("jbc","F0,%05d$",lbl->key+100);
4463                                 emitcode("setb","F0");
4464                                 emitcode ("","%05d$:",lbl->key+100);
4465                                 val = -val;
4466                         } 
4467                         emitcode ("mov","mb,#0x%02x",val & 0xff);                   
4468                         emitcode ("mov","mb,#0x%02x",(val >> 8) & 0xff);
4469                 } else {
4470                         lbl = newiTempLabel(NULL);
4471                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4472                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4473                         emitcode ("jnb","acc.7,%05d$",lbl->key+100);            
4474                         emitcode ("xch", "a,b");
4475                         emitcode ("cpl","a");
4476                         emitcode ("add", "a,#1");
4477                         emitcode ("xch", "a,b");
4478                         emitcode ("cpl", "a"); // msb
4479                         emitcode ("addc", "a,#0");
4480                         emitcode ("jbc","F0,%05d$",lbl->key+100);
4481                         emitcode ("setb","F0");
4482                         emitcode ("","%05d$:",lbl->key+100);
4483                         emitcode ("mov","mb,b");
4484                         emitcode ("mov","mb,a");
4485                 }
4486         } else {
4487                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4488                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4489         }
4490
4491         /* wait for multiplication to finish */
4492         lbl = newiTempLabel(NULL);
4493         emitcode("","%05d$:", lbl->key+100);
4494         emitcode("mov","a,mcnt1");
4495         emitcode("anl","a,#0x80");
4496         emitcode("jnz","%05d$",lbl->key+100);
4497         
4498         freeAsmop (left, NULL, ic, TRUE);
4499         freeAsmop (right, NULL, ic,TRUE);
4500         aopOp(result, ic, TRUE, FALSE);
4501
4502         /* if unsigned then simple */   
4503         if (umult) {
4504                 aopPut(AOP(result),"ma",1);
4505                 aopPut(AOP(result),"ma",0);
4506         } else {
4507                 emitcode("push","ma");
4508                 MOVA("ma");
4509                 /* negate result if needed */
4510                 lbl = newiTempLabel(NULL);      
4511                 emitcode("jnb","F0,%05d$",lbl->key+100);
4512                 emitcode("cpl","a");
4513                 emitcode("add","a,#1");
4514                 emitcode("","%05d$:", lbl->key+100);
4515                 aopPut(AOP(result),"a",0);
4516                 emitcode("pop","acc");
4517                 lbl = newiTempLabel(NULL);      
4518                 emitcode("jnb","F0,%05d$",lbl->key+100);
4519                 emitcode("cpl","a");
4520                 emitcode("addc","a,#0");
4521                 emitcode("","%05d$:", lbl->key+100);
4522                 aopPut(AOP(result),"a",1);
4523         }
4524         freeAsmop (result, NULL, ic, TRUE);
4525         /* restore EA bit in F1 */
4526         lbl = newiTempLabel(NULL);
4527         emitcode ("jnb","F1,%05d$",lbl->key+100);
4528         emitcode ("setb","EA");
4529         emitcode("","%05d$:",lbl->key+100);
4530         return ;
4531 }
4532
4533 /*-----------------------------------------------------------------*/
4534 /* genDiv - generates code for division                            */
4535 /*-----------------------------------------------------------------*/
4536 static void
4537 genDiv (iCode * ic)
4538 {
4539   operand *left = IC_LEFT (ic);
4540   operand *right = IC_RIGHT (ic);
4541   operand *result = IC_RESULT (ic);
4542
4543   D (emitcode (";", "genDiv "););
4544
4545   /* assign the amsops */
4546   AOP_OP_2 (ic);
4547
4548   /* special cases first */
4549   /* both are bits */
4550   if (AOP_TYPE (left) == AOP_CRY &&
4551       AOP_TYPE (right) == AOP_CRY)
4552     {
4553       genDivbits (left, right, result, ic);
4554       goto release;
4555     }
4556
4557   /* if both are of size == 1 */
4558   if (AOP_SIZE (left) == 1 &&
4559       AOP_SIZE (right) == 1)
4560     {
4561       genDivOneByte (left, right, result, ic);
4562       goto release;
4563     }
4564
4565   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4566           /* use the ds390 ARITHMETIC accel UNIT */
4567           genDivTwoByte (left, right, result, ic);
4568           return ;
4569   }
4570   /* should have been converted to function call */
4571   assert (0);
4572 release:
4573   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4574   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4575   freeAsmop (result, NULL, ic, TRUE);
4576 }
4577
4578 /*-----------------------------------------------------------------*/
4579 /* genModbits :- modulus of bits                                   */
4580 /*-----------------------------------------------------------------*/
4581 static void
4582 genModbits (operand * left,
4583             operand * right,
4584             operand * result,
4585             iCode   * ic)
4586 {
4587
4588   char *l;
4589
4590   /* the result must be bit */
4591   LOAD_AB_FOR_DIV (left, right, l);
4592   emitcode ("div", "ab");
4593   emitcode ("mov", "a,b");
4594   emitcode ("rrc", "a");
4595   aopOp(result, ic, TRUE, FALSE);
4596   aopPut (AOP (result), "c", 0);
4597 }
4598
4599 /*-----------------------------------------------------------------*/
4600 /* genModOneByte : 8 bit modulus                                   */
4601 /*-----------------------------------------------------------------*/
4602 static void
4603 genModOneByte (operand * left,
4604                operand * right,
4605                operand * result,
4606                iCode   * ic)
4607 {
4608   sym_link *opetype = operandType (result);
4609   char *l;
4610   symbol *lbl;
4611
4612   /* signed or unsigned */
4613   if (SPEC_USIGN (opetype))
4614     {
4615       /* unsigned is easy */
4616       LOAD_AB_FOR_DIV (left, right, l);
4617       emitcode ("div", "ab");
4618       aopOp(result, ic, TRUE, FALSE);   
4619       aopPut (AOP (result), "b", 0);
4620       return;
4621     }
4622
4623   /* signed is a little bit more difficult */
4624
4625   /* save the signs of the operands */
4626   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4627   MOVA (l);
4628
4629   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4630   emitcode ("push", "acc");     /* save it on the stack */
4631
4632   /* now sign adjust for both left & right */
4633   l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4634   MOVA (l);
4635
4636   lbl = newiTempLabel (NULL);
4637   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4638   emitcode ("cpl", "a");
4639   emitcode ("inc", "a");
4640   emitcode ("", "%05d$:", (lbl->key + 100));
4641   emitcode ("mov", "b,a");
4642
4643   /* sign adjust left side */
4644   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4645   MOVA (l);
4646
4647   lbl = newiTempLabel (NULL);
4648   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4649   emitcode ("cpl", "a");
4650   emitcode ("inc", "a");
4651   emitcode ("", "%05d$:", (lbl->key + 100));
4652
4653   /* now the multiplication */
4654   emitcode ("nop", "; workaround for DS80C390 div bug.");
4655   emitcode ("div", "ab");
4656   /* we are interested in the lower order
4657      only */
4658   lbl = newiTempLabel (NULL);
4659   emitcode ("pop", "acc");
4660   /* if there was an over flow we don't
4661      adjust the sign of the result */
4662   emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4663   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4664   CLRC;
4665   emitcode ("clr", "a");
4666   emitcode ("subb", "a,b");
4667   emitcode ("mov", "b,a");
4668   emitcode ("", "%05d$:", (lbl->key + 100));
4669
4670   /* now we are done */
4671   aopOp(result, ic, TRUE, FALSE);    
4672   aopPut (AOP (result), "b", 0);
4673
4674 }
4675
4676 /*-----------------------------------------------------------------*/
4677 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus      */
4678 /*-----------------------------------------------------------------*/
4679 static void genModTwoByte (operand *left, operand *right, 
4680                             operand *result, iCode *ic)
4681 {
4682         sym_link *retype = getSpec(operandType(right));
4683         sym_link *letype = getSpec(operandType(left));
4684         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4685         symbol *lbl;
4686
4687         /* load up MA with left */
4688         /* save EA bit in F1 */
4689         lbl = newiTempLabel(NULL);
4690         emitcode ("setb","F1");
4691         emitcode ("jbc","EA,%05d$",lbl->key+100);
4692         emitcode ("clr","F1");
4693         emitcode("","%05d$:",lbl->key+100);
4694
4695         if (!umult) {
4696                 lbl = newiTempLabel(NULL);
4697                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4698                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4699                 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4700                 emitcode ("xch", "a,b");
4701                 emitcode ("cpl","a");
4702                 emitcode ("add", "a,#1");
4703                 emitcode ("xch", "a,b");
4704                 emitcode ("cpl", "a"); // msb
4705                 emitcode ("addc","a,#0");
4706                 emitcode ("","%05d$:",lbl->key+100);
4707                 emitcode ("mov","ma,b");
4708                 emitcode ("mov","ma,a");
4709         } else {
4710                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4711                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4712         }
4713
4714         /* load up MB with right */
4715         if (!umult) {
4716                 if (AOP_TYPE(right) == AOP_LIT) {
4717                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
4718                         if (val < 0) {
4719                                 val = -val;
4720                         } 
4721                         emitcode ("mov","mb,#0x%02x",val & 0xff);
4722                         emitcode ("mov","mb,#0x%02x",(val >> 8) & 0xff);                    
4723                 } else {
4724                         lbl = newiTempLabel(NULL);
4725                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4726                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4727                         emitcode ("jnb","acc.7,%05d$",lbl->key+100);            
4728                         emitcode ("xch", "a,b");
4729                         emitcode ("cpl","a");
4730                         emitcode ("add", "a,#1");
4731                         emitcode ("xch", "a,b");
4732                         emitcode ("cpl", "a"); // msb
4733                         emitcode ("addc", "a,#0");
4734                         emitcode ("","%05d$:",lbl->key+100);
4735                         emitcode ("mov","mb,b");
4736                         emitcode ("mov","mb,a");
4737                 }
4738         } else {
4739                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4740                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4741         }
4742
4743         /* wait for multiplication to finish */
4744         lbl = newiTempLabel(NULL);
4745         emitcode("","%05d$:", lbl->key+100);
4746         emitcode("mov","a,mcnt1");
4747         emitcode("anl","a,#0x80");
4748         emitcode("jnz","%05d$",lbl->key+100);
4749         
4750         freeAsmop (left, NULL, ic, TRUE);
4751         freeAsmop (right, NULL, ic,TRUE);
4752         aopOp(result, ic, TRUE, FALSE);
4753
4754         aopPut(AOP(result),"mb",1);
4755         aopPut(AOP(result),"mb",0);
4756         freeAsmop (result, NULL, ic, TRUE);
4757
4758         /* restore EA bit in F1 */
4759         lbl = newiTempLabel(NULL);
4760         emitcode ("jnb","F1,%05d$",lbl->key+100);
4761         emitcode ("setb","EA");
4762         emitcode("","%05d$:",lbl->key+100);
4763         return ;
4764 }
4765
4766 /*-----------------------------------------------------------------*/
4767 /* genMod - generates code for division                            */
4768 /*-----------------------------------------------------------------*/
4769 static void
4770 genMod (iCode * ic)
4771 {
4772   operand *left = IC_LEFT (ic);
4773   operand *right = IC_RIGHT (ic);
4774   operand *result = IC_RESULT (ic);
4775
4776   D (emitcode (";", "genMod "); );
4777
4778   /* assign the amsops */
4779   AOP_OP_2 (ic);
4780
4781   /* special cases first */
4782   /* both are bits */
4783   if (AOP_TYPE (left) == AOP_CRY &&
4784       AOP_TYPE (right) == AOP_CRY)
4785     {
4786       genModbits (left, right, result, ic);
4787       goto release;
4788     }
4789
4790   /* if both are of size == 1 */
4791   if (AOP_SIZE (left) == 1 &&
4792       AOP_SIZE (right) == 1)
4793     {
4794       genModOneByte (left, right, result, ic);
4795       goto release;
4796     }
4797
4798   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4799           /* use the ds390 ARITHMETIC accel UNIT */
4800           genModTwoByte (left, right, result, ic);
4801           return ;
4802   }
4803
4804   /* should have been converted to function call */
4805   assert (0);
4806
4807 release:
4808   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4809   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4810   freeAsmop (result, NULL, ic, TRUE);
4811 }
4812
4813 /*-----------------------------------------------------------------*/
4814 /* genIfxJump :- will create a jump depending on the ifx           */
4815 /*-----------------------------------------------------------------*/
4816 static void
4817 genIfxJump (iCode * ic, char *jval)
4818 {
4819   symbol *jlbl;
4820   symbol *tlbl = newiTempLabel (NULL);
4821   char *inst;
4822
4823   D (emitcode (";", "genIfxJump ");
4824     );
4825
4826   /* if true label then we jump if condition
4827      supplied is true */
4828   if (IC_TRUE (ic))
4829     {
4830       jlbl = IC_TRUE (ic);
4831       inst = ((strcmp (jval, "a") == 0 ? "jz" :
4832                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4833     }
4834   else
4835     {
4836       /* false label is present */
4837       jlbl = IC_FALSE (ic);
4838       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4839                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4840     }
4841   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4842     emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4843   else
4844     emitcode (inst, "%05d$", tlbl->key + 100);
4845   emitcode ("ljmp", "%05d$", jlbl->key + 100);
4846   emitcode ("", "%05d$:", tlbl->key + 100);
4847
4848   /* mark the icode as generated */
4849   ic->generated = 1;
4850 }
4851
4852 /*-----------------------------------------------------------------*/
4853 /* genCmp :- greater or less than comparison                       */
4854 /*-----------------------------------------------------------------*/
4855 static void
4856 genCmp (operand * left, operand * right,
4857         iCode * ic, iCode * ifx, int sign)
4858 {
4859   int size, offset = 0;
4860   unsigned long lit = 0L;
4861   operand *result;
4862
4863   D (emitcode (";", "genCmp");
4864     );
4865
4866   result = IC_RESULT (ic);
4867
4868   /* if left & right are bit variables */
4869   if (AOP_TYPE (left) == AOP_CRY &&
4870       AOP_TYPE (right) == AOP_CRY)
4871     {
4872       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4873       emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
4874     }
4875   else
4876     {
4877       /* subtract right from left if at the
4878          end the carry flag is set then we know that
4879          left is greater than right */
4880       size = max (AOP_SIZE (left), AOP_SIZE (right));
4881
4882       /* if unsigned char cmp with lit, do cjne left,#right,zz */
4883       if ((size == 1) && !sign &&
4884           (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4885         {
4886           symbol *lbl = newiTempLabel (NULL);
4887           emitcode ("cjne", "%s,%s,%05d$",
4888                     aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
4889                     aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4890                     lbl->key + 100);
4891           emitcode ("", "%05d$:", lbl->key + 100);
4892         }
4893       else
4894         {
4895           if (AOP_TYPE (right) == AOP_LIT)
4896             {
4897               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4898               /* optimize if(x < 0) or if(x >= 0) */
4899               if (lit == 0L)
4900                 {
4901                   if (!sign)
4902                     {
4903                       CLRC;
4904                     }
4905                   else
4906                     {
4907                       MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
4908
4909                       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4910                       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4911
4912                       aopOp (result, ic, FALSE, FALSE);
4913
4914                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4915                         {
4916                           freeAsmop (result, NULL, ic, TRUE);
4917                           genIfxJump (ifx, "acc.7");
4918                           return;
4919                         }
4920                       else
4921                         {
4922                           emitcode ("rlc", "a");
4923                         }
4924                       goto release_freedLR;
4925                     }
4926                   goto release;
4927                 }
4928             }
4929           CLRC;
4930           while (size--)
4931             {
4932               emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
4933               MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4934               emitcode (";", "genCmp #2");
4935               if (sign && (size == 0))
4936                 {
4937                   emitcode (";", "genCmp #3");
4938                   emitcode ("xrl", "a,#0x80");
4939                   if (AOP_TYPE (right) == AOP_LIT)
4940                     {
4941                       unsigned long lit = (unsigned long)
4942                       floatFromVal (AOP (right)->aopu.aop_lit);
4943                       emitcode (";", "genCmp #3.1");
4944                       emitcode ("subb", "a,#0x%02x",
4945                                 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4946                     }
4947                   else
4948                     {
4949                       emitcode (";", "genCmp #3.2");
4950                       if (AOP_NEEDSACC (right))
4951                         {
4952                           emitcode ("push", "acc");
4953                         }
4954                       emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
4955                                                        FALSE, FALSE, FALSE));
4956                       emitcode ("xrl", "b,#0x80");
4957                       if (AOP_NEEDSACC (right))
4958                         {
4959                           emitcode ("pop", "acc");
4960                         }
4961                       emitcode ("subb", "a,b");
4962                     }
4963                 }
4964               else
4965                 {
4966                   const char *s;
4967
4968                   emitcode (";", "genCmp #4");
4969                   if (AOP_NEEDSACC (right))
4970                     {
4971                       /* Yuck!! */
4972                       emitcode (";", "genCmp #4.1");
4973                       emitcode ("xch", "a, b");
4974                       MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
4975                       emitcode ("xch", "a, b");
4976                       s = "b";
4977                     }
4978                   else
4979                     {
4980                       emitcode (";", "genCmp #4.2");
4981                       s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
4982                     }
4983
4984                   emitcode ("subb", "a,%s", s);
4985                 }
4986             }
4987         }
4988     }
4989
4990 release:
4991 /* Don't need the left & right operands any more; do need the result. */
4992   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4993   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4994
4995   aopOp (result, ic, FALSE, FALSE);
4996
4997 release_freedLR:
4998
4999   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5000     {
5001       outBitC (result);
5002     }
5003   else
5004     {
5005       /* if the result is used in the next
5006          ifx conditional branch then generate
5007          code a little differently */
5008       if (ifx)
5009         {
5010           genIfxJump (ifx, "c");
5011         }
5012       else
5013         {
5014           outBitC (result);
5015         }
5016       /* leave the result in acc */
5017     }
5018   freeAsmop (result, NULL, ic, TRUE);
5019 }
5020
5021 /*-----------------------------------------------------------------*/
5022 /* genCmpGt :- greater than comparison                             */
5023 /*-----------------------------------------------------------------*/
5024 static void
5025 genCmpGt (iCode * ic, iCode * ifx)
5026 {
5027   operand *left, *right;
5028   sym_link *letype, *retype;
5029   int sign;
5030
5031   D (emitcode (";", "genCmpGt ");
5032     );
5033
5034   left = IC_LEFT (ic);
5035   right = IC_RIGHT (ic);
5036
5037   letype = getSpec (operandType (left));
5038   retype = getSpec (operandType (right));
5039   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5040
5041   /* assign the left & right amsops */
5042   AOP_OP_2 (ic);
5043
5044   genCmp (right, left, ic, ifx, sign);
5045 }
5046
5047 /*-----------------------------------------------------------------*/
5048 /* genCmpLt - less than comparisons                                */
5049 /*-----------------------------------------------------------------*/
5050 static void
5051 genCmpLt (iCode * ic, iCode * ifx)
5052 {
5053   operand *left, *right;
5054   sym_link *letype, *retype;
5055   int sign;
5056
5057   D (emitcode (";", "genCmpLt "););
5058
5059   left = IC_LEFT (ic);
5060   right = IC_RIGHT (ic);
5061
5062   letype = getSpec (operandType (left));
5063   retype = getSpec (operandType (right));
5064   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5065
5066   /* assign the left & right amsops */
5067   AOP_OP_2 (ic);
5068
5069   genCmp (left, right, ic, ifx, sign);
5070 }
5071
5072 /*-----------------------------------------------------------------*/
5073 /* gencjneshort - compare and jump if not equal                    */
5074 /*-----------------------------------------------------------------*/
5075 static void
5076 gencjneshort (operand * left, operand * right, symbol * lbl)
5077 {
5078   int size = max (AOP_SIZE (left), AOP_SIZE (right));
5079   int offset = 0;
5080   unsigned long lit = 0L;
5081
5082   D (emitcode (";", "gencjneshort");
5083     );
5084
5085   /* if the left side is a literal or
5086      if the right is in a pointer register and left
5087      is not */
5088   if ((AOP_TYPE (left) == AOP_LIT) ||
5089       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5090     {
5091       operand *t = right;
5092       right = left;
5093       left = t;
5094     }
5095
5096   if (AOP_TYPE (right) == AOP_LIT)
5097     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5098
5099   if (opIsGptr (left) || opIsGptr (right))
5100     {
5101       /* We are comparing a generic pointer to something.
5102        * Exclude the generic type byte from the comparison.
5103        */
5104       size--;
5105       D (emitcode (";", "cjneshort: generic ptr special case.");
5106         )
5107     }
5108
5109
5110   /* if the right side is a literal then anything goes */
5111   if (AOP_TYPE (right) == AOP_LIT &&
5112       AOP_TYPE (left) != AOP_DIR)
5113     {
5114       while (size--)
5115         {
5116           char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5117           MOVA (l);
5118           emitcode ("cjne", "a,%s,%05d$",
5119                     aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
5120                     lbl->key + 100);
5121           offset++;
5122         }
5123     }
5124
5125   /* if the right side is in a register or in direct space or
5126      if the left is a pointer register & right is not */
5127   else if (AOP_TYPE (right) == AOP_REG ||
5128            AOP_TYPE (right) == AOP_DIR ||
5129            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5130            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5131     {
5132       while (size--)
5133         {
5134           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5135           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5136               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5137             emitcode ("jnz", "%05d$", lbl->key + 100);
5138           else
5139             emitcode ("cjne", "a,%s,%05d$",
5140                       aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
5141                       lbl->key + 100);
5142           offset++;
5143         }
5144     }
5145   else
5146     {
5147       /* right is a pointer reg need both a & b */
5148       while (size--)
5149         {
5150           char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5151           if (strcmp (l, "b"))
5152             emitcode ("mov", "b,%s", l);
5153           MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5154           emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
5155           offset++;
5156         }
5157     }
5158 }
5159
5160 /*-----------------------------------------------------------------*/
5161 /* gencjne - compare and jump if not equal                         */
5162 /*-----------------------------------------------------------------*/
5163 static void
5164 gencjne (operand * left, operand * right, symbol * lbl)
5165 {
5166   symbol *tlbl = newiTempLabel (NULL);
5167
5168   D (emitcode (";", "gencjne");
5169     );
5170
5171   gencjneshort (left, right, lbl);
5172
5173   emitcode ("mov", "a,%s", one);
5174   emitcode ("sjmp", "%05d$", tlbl->key + 100);
5175   emitcode ("", "%05d$:", lbl->key + 100);
5176   emitcode ("clr", "a");
5177   emitcode ("", "%05d$:", tlbl->key + 100);
5178 }
5179
5180 /*-----------------------------------------------------------------*/
5181 /* genCmpEq - generates code for equal to                          */
5182 /*-----------------------------------------------------------------*/
5183 static void
5184 genCmpEq (iCode * ic, iCode * ifx)
5185 {
5186   operand *left, *right, *result;
5187
5188   D (emitcode (";", "genCmpEq ");
5189     );
5190
5191   AOP_OP_2 (ic);
5192   AOP_SET_LOCALS (ic);
5193
5194   /* if literal, literal on the right or
5195      if the right is in a pointer register and left
5196      is not */
5197   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5198       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5199     {
5200       operand *t = IC_RIGHT (ic);
5201       IC_RIGHT (ic) = IC_LEFT (ic);
5202       IC_LEFT (ic) = t;
5203     }
5204
5205   if (ifx &&                    /* !AOP_SIZE(result) */
5206       OP_SYMBOL (result) &&
5207       OP_SYMBOL (result)->regType == REG_CND)
5208     {
5209       symbol *tlbl;
5210       /* if they are both bit variables */
5211       if (AOP_TYPE (left) == AOP_CRY &&
5212           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5213         {
5214           if (AOP_TYPE (right) == AOP_LIT)
5215             {
5216               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5217               if (lit == 0L)
5218                 {
5219                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5220                   emitcode ("cpl", "c");
5221                 }
5222               else if (lit == 1L)
5223                 {
5224                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5225                 }
5226               else
5227                 {
5228                   emitcode ("clr", "c");
5229                 }
5230               /* AOP_TYPE(right) == AOP_CRY */
5231             }
5232           else
5233             {
5234               symbol *lbl = newiTempLabel (NULL);
5235               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5236               emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5237               emitcode ("cpl", "c");
5238               emitcode ("", "%05d$:", (lbl->key + 100));
5239             }
5240           /* if true label then we jump if condition
5241              supplied is true */
5242           tlbl = newiTempLabel (NULL);
5243           if (IC_TRUE (ifx))
5244             {
5245               emitcode ("jnc", "%05d$", tlbl->key + 100);
5246               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5247             }
5248           else
5249             {
5250               emitcode ("jc", "%05d$", tlbl->key + 100);
5251               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5252             }
5253           emitcode ("", "%05d$:", tlbl->key + 100);
5254         }
5255       else
5256         {
5257           tlbl = newiTempLabel (NULL);
5258           gencjneshort (left, right, tlbl);
5259           if (IC_TRUE (ifx))
5260             {
5261               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5262               emitcode ("", "%05d$:", tlbl->key + 100);
5263             }
5264           else
5265             {
5266               symbol *lbl = newiTempLabel (NULL);
5267               emitcode ("sjmp", "%05d$", lbl->key + 100);
5268               emitcode ("", "%05d$:", tlbl->key + 100);
5269               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5270               emitcode ("", "%05d$:", lbl->key + 100);
5271             }
5272         }
5273       /* mark the icode as generated */
5274       ifx->generated = 1;
5275
5276       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5277       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5278       return;
5279     }
5280
5281   /* if they are both bit variables */
5282   if (AOP_TYPE (left) == AOP_CRY &&
5283       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5284     {
5285       if (AOP_TYPE (right) == AOP_LIT)
5286         {
5287           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5288           if (lit == 0L)
5289             {
5290               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5291               emitcode ("cpl", "c");
5292             }
5293           else if (lit == 1L)
5294             {
5295               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5296             }
5297           else
5298             {
5299               emitcode ("clr", "c");
5300             }
5301           /* AOP_TYPE(right) == AOP_CRY */
5302         }
5303       else
5304         {
5305           symbol *lbl = newiTempLabel (NULL);
5306           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5307           emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5308           emitcode ("cpl", "c");
5309           emitcode ("", "%05d$:", (lbl->key + 100));
5310         }
5311
5312       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5313       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5314
5315       aopOp (result, ic, TRUE, FALSE);
5316
5317       /* c = 1 if egal */
5318       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5319         {
5320           outBitC (result);
5321           goto release;
5322         }
5323       if (ifx)
5324         {
5325           genIfxJump (ifx, "c");
5326           goto release;
5327         }
5328       /* if the result is used in an arithmetic operation
5329          then put the result in place */
5330       outBitC (result);
5331     }
5332   else
5333     {
5334       gencjne (left, right, newiTempLabel (NULL));
5335
5336       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5337       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5338
5339       aopOp (result, ic, TRUE, FALSE);
5340
5341       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5342         {
5343           aopPut (AOP (result), "a", 0);
5344           goto release;
5345         }
5346       if (ifx)
5347         {
5348           genIfxJump (ifx, "a");
5349           goto release;
5350         }
5351       /* if the result is used in an arithmetic operation
5352          then put the result in place */
5353       if (AOP_TYPE (result) != AOP_CRY)
5354         outAcc (result);
5355       /* leave the result in acc */
5356     }
5357
5358 release:
5359   freeAsmop (result, NULL, ic, TRUE);
5360 }
5361
5362 /*-----------------------------------------------------------------*/
5363 /* ifxForOp - returns the icode containing the ifx for operand     */
5364 /*-----------------------------------------------------------------*/
5365 static iCode *
5366 ifxForOp (operand * op, iCode * ic)
5367 {
5368   /* if true symbol then needs to be assigned */
5369   if (IS_TRUE_SYMOP (op))
5370     return NULL;
5371
5372   /* if this has register type condition and
5373      the next instruction is ifx with the same operand
5374      and live to of the operand is upto the ifx only then */
5375   if (ic->next &&
5376       ic->next->op == IFX &&
5377       IC_COND (ic->next)->key == op->key &&
5378       OP_SYMBOL (op)->liveTo <= ic->next->seq)
5379     return ic->next;
5380
5381   return NULL;
5382 }
5383 /*-----------------------------------------------------------------*/
5384 /* hasInc - operand is incremented before any other use            */
5385 /*-----------------------------------------------------------------*/
5386 static iCode *
5387 hasInc (operand *op, iCode *ic)
5388 {
5389   sym_link *type = operandType(op);
5390   sym_link *retype = getSpec (type);
5391   iCode *lic = ic->next;
5392   int isize ;
5393   
5394   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5395   if (!IS_SYMOP(op)) return NULL;
5396
5397   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5398   isize = getSize(type->next);
5399   while (lic) {
5400     /* if operand of the form op = op + <sizeof *op> */
5401     if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5402         isOperandEqual(IC_RESULT(lic),op) && 
5403         isOperandLiteral(IC_RIGHT(lic)) &&
5404         operandLitValue(IC_RIGHT(lic)) == isize) {
5405       return lic;
5406     }
5407     /* if the operand used or deffed */
5408     if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5409       return NULL;
5410     }
5411     lic = lic->next;
5412   }
5413   return NULL;
5414 }
5415
5416 /*-----------------------------------------------------------------*/
5417 /* genAndOp - for && operation                                     */
5418 /*-----------------------------------------------------------------*/
5419 static void
5420 genAndOp (iCode * ic)
5421 {
5422   operand *left, *right, *result;
5423   symbol *tlbl;
5424
5425   D (emitcode (";", "genAndOp "););
5426
5427   /* note here that && operations that are in an
5428      if statement are taken away by backPatchLabels
5429      only those used in arthmetic operations remain */
5430   AOP_OP_2 (ic);
5431   AOP_SET_LOCALS (ic);
5432
5433   /* if both are bit variables */
5434   if (AOP_TYPE (left) == AOP_CRY &&
5435       AOP_TYPE (right) == AOP_CRY)
5436     {
5437       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5438       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5439       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5440       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5441   
5442       aopOp (result,ic,FALSE, FALSE);
5443       outBitC (result);
5444     }
5445   else
5446     {
5447       tlbl = newiTempLabel (NULL);
5448       toBoolean (left);
5449       emitcode ("jz", "%05d$", tlbl->key + 100);
5450       toBoolean (right);
5451       emitcode ("", "%05d$:", tlbl->key + 100);
5452       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5453       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5454   
5455       aopOp (result,ic,FALSE, FALSE);
5456       outBitAcc (result);
5457     }
5458     freeAsmop (result, NULL, ic, TRUE);
5459 }
5460
5461
5462 /*-----------------------------------------------------------------*/
5463 /* genOrOp - for || operation                                      */
5464 /*-----------------------------------------------------------------*/
5465 static void
5466 genOrOp (iCode * ic)
5467 {
5468   operand *left, *right, *result;
5469   symbol *tlbl;
5470
5471   D (emitcode (";", "genOrOp "););
5472
5473   /* note here that || operations that are in an
5474      if statement are taken away by backPatchLabels
5475      only those used in arthmetic operations remain */
5476   AOP_OP_2 (ic);
5477   AOP_SET_LOCALS (ic);
5478
5479   /* if both are bit variables */
5480   if (AOP_TYPE (left) == AOP_CRY &&
5481       AOP_TYPE (right) == AOP_CRY)
5482     {
5483       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5484       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5485       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5486       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5487   
5488       aopOp (result,ic,FALSE, FALSE);
5489       
5490       outBitC (result);
5491     }
5492   else
5493     {
5494       tlbl = newiTempLabel (NULL);
5495       toBoolean (left);
5496       emitcode ("jnz", "%05d$", tlbl->key + 100);
5497       toBoolean (right);
5498       emitcode ("", "%05d$:", tlbl->key + 100);
5499       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5500       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5501   
5502       aopOp (result,ic,FALSE, FALSE);
5503       
5504       outBitAcc (result);
5505     }
5506
5507   freeAsmop (result, NULL, ic, TRUE);
5508 }
5509
5510 /*-----------------------------------------------------------------*/
5511 /* isLiteralBit - test if lit == 2^n                               */
5512 /*-----------------------------------------------------------------*/
5513 static int
5514 isLiteralBit (unsigned long lit)
5515 {
5516   unsigned long pw[32] =
5517   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5518    0x100L, 0x200L, 0x400L, 0x800L,
5519    0x1000L, 0x2000L, 0x4000L, 0x8000L,
5520    0x10000L, 0x20000L, 0x40000L, 0x80000L,
5521    0x100000L, 0x200000L, 0x400000L, 0x800000L,
5522    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5523    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5524   int idx;
5525
5526   for (idx = 0; idx < 32; idx++)
5527     if (lit == pw[idx])
5528       return idx + 1;
5529   return 0;
5530 }
5531
5532 /*-----------------------------------------------------------------*/
5533 /* continueIfTrue -                                                */
5534 /*-----------------------------------------------------------------*/
5535 static void
5536 continueIfTrue (iCode * ic)
5537 {
5538   if (IC_TRUE (ic))
5539     emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5540   ic->generated = 1;
5541 }
5542
5543 /*-----------------------------------------------------------------*/
5544 /* jmpIfTrue -                                                     */
5545 /*-----------------------------------------------------------------*/
5546 static void
5547 jumpIfTrue (iCode * ic)
5548 {
5549   if (!IC_TRUE (ic))
5550     emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5551   ic->generated = 1;
5552 }
5553
5554 /*-----------------------------------------------------------------*/
5555 /* jmpTrueOrFalse -                                                */
5556 /*-----------------------------------------------------------------*/
5557 static void
5558 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
5559 {
5560   // ugly but optimized by peephole
5561   if (IC_TRUE (ic))
5562     {
5563       symbol *nlbl = newiTempLabel (NULL);
5564       emitcode ("sjmp", "%05d$", nlbl->key + 100);
5565       emitcode ("", "%05d$:", tlbl->key + 100);
5566       emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5567       emitcode ("", "%05d$:", nlbl->key + 100);
5568     }
5569   else
5570     {
5571       emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5572       emitcode ("", "%05d$:", tlbl->key + 100);
5573     }
5574   ic->generated = 1;
5575 }
5576
5577 // Generate code to perform a bit-wise logic operation
5578 // on two operands in far space (assumed to already have been 
5579 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
5580 // in far space. This requires pushing the result on the stack
5581 // then popping it into the result.
5582 static void
5583 genFarFarLogicOp(iCode *ic, char *logicOp)
5584 {
5585       int size, resultSize, compSize;
5586       int offset = 0;
5587       
5588       TR_AP("#5");
5589       D(emitcode(";", "%s special case for 3 far operands.", logicOp););
5590       compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ? 
5591                   AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
5592       
5593       _startLazyDPSEvaluation();
5594       for (size = compSize; (size--); offset++)
5595       {
5596           MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
5597           emitcode ("mov", "%s, acc", DP2_RESULT_REG);
5598           MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
5599           
5600           emitcode (logicOp, "a,%s", DP2_RESULT_REG);
5601           emitcode ("push", "acc");
5602       }
5603       _endLazyDPSEvaluation();
5604      
5605       freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5606       freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5607       aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
5608      
5609       resultSize = AOP_SIZE(IC_RESULT(ic));
5610
5611       ADJUST_PUSHED_RESULT(compSize, resultSize);
5612
5613       _startLazyDPSEvaluation();
5614       while (compSize--)
5615       {
5616           emitcode ("pop", "acc");
5617           aopPut (AOP (IC_RESULT (ic)), "a", compSize);
5618       }
5619       _endLazyDPSEvaluation();
5620       freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
5621 }
5622
5623
5624 /*-----------------------------------------------------------------*/
5625 /* genAnd  - code for and                                          */
5626 /*-----------------------------------------------------------------*/
5627 static void
5628 genAnd (iCode * ic, iCode * ifx)
5629 {
5630   operand *left, *right, *result;
5631   int size, offset = 0;
5632   unsigned long lit = 0L;
5633   int bytelit = 0;
5634   char buffer[10];
5635   bool pushResult;
5636
5637   D (emitcode (";", "genAnd "););
5638
5639   AOP_OP_3_NOFATAL (ic, pushResult);
5640   AOP_SET_LOCALS (ic);
5641
5642   if (pushResult)
5643   {
5644       genFarFarLogicOp(ic, "anl");
5645       return;
5646   }  
5647
5648 #ifdef DEBUG_TYPE
5649   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5650             AOP_TYPE (result),
5651             AOP_TYPE (left), AOP_TYPE (right));
5652   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5653             AOP_SIZE (result),
5654             AOP_SIZE (left), AOP_SIZE (right));
5655 #endif
5656
5657   /* if left is a literal & right is not then exchange them */
5658   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5659 #ifdef LOGIC_OPS_BROKEN      
5660     ||  AOP_NEEDSACC (left)
5661 #endif
5662     )
5663     {
5664       operand *tmp = right;
5665       right = left;
5666       left = tmp;
5667     }
5668
5669   /* if result = right then exchange them */
5670   if (sameRegs (AOP (result), AOP (right)))
5671     {
5672       operand *tmp = right;
5673       right = left;
5674       left = tmp;
5675     }
5676
5677   /* if right is bit then exchange them */
5678   if (AOP_TYPE (right) == AOP_CRY &&
5679       AOP_TYPE (left) != AOP_CRY)
5680     {
5681       operand *tmp = right;
5682       right = left;
5683       left = tmp;
5684     }
5685   if (AOP_TYPE (right) == AOP_LIT)
5686     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5687
5688   size = AOP_SIZE (result);
5689
5690   // if(bit & yy)
5691   // result = bit & yy;
5692   if (AOP_TYPE (left) == AOP_CRY)
5693     {
5694       // c = bit & literal;
5695       if (AOP_TYPE (right) == AOP_LIT)
5696         {
5697           if (lit & 1)
5698             {
5699               if (size && sameRegs (AOP (result), AOP (left)))
5700                 // no change
5701                 goto release;
5702               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5703             }
5704           else
5705             {
5706               // bit(result) = 0;
5707               if (size && (AOP_TYPE (result) == AOP_CRY))
5708                 {
5709                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5710                   goto release;
5711                 }
5712               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5713                 {
5714                   jumpIfTrue (ifx);
5715                   goto release;
5716                 }
5717               emitcode ("clr", "c");
5718             }
5719         }
5720       else
5721         {
5722           if (AOP_TYPE (right) == AOP_CRY)
5723             {
5724               // c = bit & bit;
5725               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5726               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5727             }
5728           else
5729             {
5730               // c = bit & val;
5731               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
5732               // c = lsb
5733               emitcode ("rrc", "a");
5734               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5735             }
5736         }
5737       // bit = c
5738       // val = c
5739       if (size)
5740         outBitC (result);
5741       // if(bit & ...)
5742       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5743         genIfxJump (ifx, "c");
5744       goto release;
5745     }
5746
5747   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5748   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5749   if ((AOP_TYPE (right) == AOP_LIT) &&
5750       (AOP_TYPE (result) == AOP_CRY) &&
5751       (AOP_TYPE (left) != AOP_CRY))
5752     {
5753       int posbit = isLiteralBit (lit);
5754       /* left &  2^n */
5755       if (posbit)
5756         {
5757           posbit--;
5758           MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
5759           // bit = left & 2^n
5760           if (size)
5761             emitcode ("mov", "c,acc.%d", posbit & 0x07);
5762           // if(left &  2^n)
5763           else
5764             {
5765               if (ifx)
5766                 {
5767                   sprintf (buffer, "acc.%d", posbit & 0x07);
5768                   genIfxJump (ifx, buffer);
5769                 }
5770               goto release;
5771             }
5772         }
5773       else
5774         {
5775           symbol *tlbl = newiTempLabel (NULL);
5776           int sizel = AOP_SIZE (left);
5777           if (size)
5778             emitcode ("setb", "c");
5779           while (sizel--)
5780             {
5781               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5782                 {
5783                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5784                   // byte ==  2^n ?
5785                   if ((posbit = isLiteralBit (bytelit)) != 0)
5786                     emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5787                   else
5788                     {
5789                       if (bytelit != 0x0FFL)
5790                         emitcode ("anl", "a,%s",
5791                           aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
5792                       emitcode ("jnz", "%05d$", tlbl->key + 100);
5793                     }
5794                 }
5795               offset++;
5796             }
5797           // bit = left & literal
5798           if (size)
5799             {
5800               emitcode ("clr", "c");
5801               emitcode ("", "%05d$:", tlbl->key + 100);
5802             }
5803           // if(left & literal)
5804           else
5805             {
5806               if (ifx)
5807                 jmpTrueOrFalse (ifx, tlbl);
5808               goto release;
5809             }
5810         }
5811       outBitC (result);
5812       goto release;
5813     }
5814
5815   /* if left is same as result */
5816   if (sameRegs (AOP (result), AOP (left)))
5817     {
5818       for (; size--; offset++)
5819         {
5820           if (AOP_TYPE (right) == AOP_LIT)
5821             {
5822               if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5823                 continue;
5824               else if (bytelit == 0)
5825                 aopPut (AOP (result), zero, offset);
5826               else if (IS_AOP_PREG (result))
5827                 {
5828                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5829                   emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5830                   aopPut (AOP (result), "a", offset);
5831                 }
5832               else
5833                 emitcode ("anl", "%s,%s",
5834                           aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5835                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5836             }
5837           else
5838             {
5839               if (AOP_TYPE (left) == AOP_ACC)
5840                 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5841               else
5842                 {
5843                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5844                   if (IS_AOP_PREG (result))
5845                     {
5846                       emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5847                       aopPut (AOP (result), "a", offset);
5848
5849                     }
5850                   else
5851                     emitcode ("anl", "%s,a",
5852                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5853                 }
5854             }
5855         }
5856     }
5857   else
5858     {
5859       // left & result in different registers
5860       if (AOP_TYPE (result) == AOP_CRY)
5861         {
5862           // result = bit
5863           // if(size), result in bit
5864           // if(!size && ifx), conditional oper: if(left & right)
5865           symbol *tlbl = newiTempLabel (NULL);
5866           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5867           if (size)
5868             emitcode ("setb", "c");
5869           while (sizer--)
5870             {
5871               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5872                 emitcode ("anl", "a,%s",
5873                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5874               } else {
5875                 if (AOP_TYPE(left)==AOP_ACC) {
5876                   emitcode("mov", "b,a");
5877                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5878                   emitcode("anl", "a,b");
5879                 }else {
5880                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5881                   emitcode ("anl", "a,%s",
5882                             aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5883                 }
5884               }
5885               emitcode ("jnz", "%05d$", tlbl->key + 100);
5886               offset++;
5887             }
5888           if (size)
5889             {
5890               CLRC;
5891               emitcode ("", "%05d$:", tlbl->key + 100);
5892               outBitC (result);
5893             }
5894           else if (ifx)
5895             jmpTrueOrFalse (ifx, tlbl);
5896         }
5897       else
5898         {
5899           for (; (size--); offset++)
5900             {
5901               // normal case
5902               // result = left & right
5903               if (AOP_TYPE (right) == AOP_LIT)
5904                 {
5905                   if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5906                     {
5907                       aopPut (AOP (result),
5908                            aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5909                               offset);
5910                       continue;
5911                     }
5912                   else if (bytelit == 0)
5913                     {
5914                       aopPut (AOP (result), zero, offset);
5915                       continue;
5916                     }
5917                   D (emitcode (";", "better literal AND."););
5918                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5919                   emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
5920                                                     FALSE, FALSE, FALSE));
5921
5922                 }
5923               else
5924                 {
5925                   // faster than result <- left, anl result,right
5926                   // and better if result is SFR
5927                   if (AOP_TYPE (left) == AOP_ACC)
5928                     {
5929                       emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
5930                                                        FALSE, FALSE, FALSE));
5931                     }
5932                   else
5933                     {
5934                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
5935                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
5936                       {
5937                           emitcode("mov", "b,a");
5938                           rOp = "b";
5939                       }
5940                         
5941                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5942                       emitcode ("anl", "a,%s", rOp);
5943                     }                   
5944                 }
5945               aopPut (AOP (result), "a", offset);
5946             }
5947         }
5948     }
5949
5950 release:
5951   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5952   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5953   freeAsmop (result, NULL, ic, TRUE);
5954 }
5955
5956
5957 /*-----------------------------------------------------------------*/
5958 /* genOr  - code for or                                            */
5959 /*-----------------------------------------------------------------*/
5960 static void
5961 genOr (iCode * ic, iCode * ifx)
5962 {
5963   operand *left, *right, *result;
5964   int size, offset = 0;
5965   unsigned long lit = 0L;
5966   bool     pushResult;
5967
5968   D (emitcode (";", "genOr "););
5969
5970   AOP_OP_3_NOFATAL (ic, pushResult);
5971   AOP_SET_LOCALS (ic);
5972
5973   if (pushResult)
5974   {
5975       genFarFarLogicOp(ic, "orl");
5976       return;
5977   }
5978
5979
5980 #ifdef DEBUG_TYPE
5981   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5982             AOP_TYPE (result),
5983             AOP_TYPE (left), AOP_TYPE (right));
5984   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5985             AOP_SIZE (result),
5986             AOP_SIZE (left), AOP_SIZE (right));
5987 #endif
5988
5989   /* if left is a literal & right is not then exchange them */
5990   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5991 #ifdef LOGIC_OPS_BROKEN
5992    || AOP_NEEDSACC (left) // I think this is a net loss now.
5993 #endif      
5994       )
5995     {
5996       operand *tmp = right;
5997       right = left;
5998       left = tmp;
5999     }
6000
6001   /* if result = right then exchange them */
6002   if (sameRegs (AOP (result), AOP (right)))
6003     {
6004       operand *tmp = right;
6005       right = left;
6006       left = tmp;
6007     }
6008
6009   /* if right is bit then exchange them */
6010   if (AOP_TYPE (right) == AOP_CRY &&
6011       AOP_TYPE (left) != AOP_CRY)
6012     {
6013       operand *tmp = right;
6014       right = left;
6015       left = tmp;
6016     }
6017   if (AOP_TYPE (right) == AOP_LIT)
6018     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6019
6020   size = AOP_SIZE (result);
6021
6022   // if(bit | yy)
6023   // xx = bit | yy;
6024   if (AOP_TYPE (left) == AOP_CRY)
6025     {
6026       if (AOP_TYPE (right) == AOP_LIT)
6027         {
6028           // c = bit & literal;
6029           if (lit)
6030             {
6031               // lit != 0 => result = 1
6032               if (AOP_TYPE (result) == AOP_CRY)
6033                 {
6034                   if (size)
6035                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6036                   else if (ifx)
6037                     continueIfTrue (ifx);
6038                   goto release;
6039                 }
6040               emitcode ("setb", "c");
6041             }
6042           else
6043             {
6044               // lit == 0 => result = left
6045               if (size && sameRegs (AOP (result), AOP (left)))
6046                 goto release;
6047               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6048             }
6049         }
6050       else
6051         {
6052           if (AOP_TYPE (right) == AOP_CRY)
6053             {
6054               // c = bit | bit;
6055               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6056               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6057             }
6058           else
6059             {
6060               // c = bit | val;
6061               symbol *tlbl = newiTempLabel (NULL);
6062               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6063                 emitcode ("setb", "c");
6064               emitcode ("jb", "%s,%05d$",
6065                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
6066               toBoolean (right);
6067               emitcode ("jnz", "%05d$", tlbl->key + 100);
6068               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6069                 {
6070                   jmpTrueOrFalse (ifx, tlbl);
6071                   goto release;
6072                 }
6073               else
6074                 {
6075                   CLRC;
6076                   emitcode ("", "%05d$:", tlbl->key + 100);
6077                 }
6078             }
6079         }
6080       // bit = c
6081       // val = c
6082       if (size)
6083         outBitC (result);
6084       // if(bit | ...)
6085       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6086         genIfxJump (ifx, "c");
6087       goto release;
6088     }
6089
6090   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6091   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6092   if ((AOP_TYPE (right) == AOP_LIT) &&
6093       (AOP_TYPE (result) == AOP_CRY) &&
6094       (AOP_TYPE (left) != AOP_CRY))
6095     {
6096       if (lit)
6097         {
6098           // result = 1
6099           if (size)
6100             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6101           else
6102             continueIfTrue (ifx);
6103           goto release;
6104         }
6105       else
6106         {
6107           // lit = 0, result = boolean(left)
6108           if (size)
6109             emitcode ("setb", "c");
6110           toBoolean (right);
6111           if (size)
6112             {
6113               symbol *tlbl = newiTempLabel (NULL);
6114               emitcode ("jnz", "%05d$", tlbl->key + 100);
6115               CLRC;
6116               emitcode ("", "%05d$:", tlbl->key + 100);
6117             }
6118           else
6119             {
6120               genIfxJump (ifx, "a");
6121               goto release;
6122             }
6123         }
6124       outBitC (result);
6125       goto release;
6126     }
6127
6128   /* if left is same as result */
6129   if (sameRegs (AOP (result), AOP (left)))
6130     {
6131       for (; size--; offset++)
6132         {
6133           if (AOP_TYPE (right) == AOP_LIT)
6134             {
6135               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6136                 {
6137                   continue;
6138                 }
6139               else
6140                 {
6141                   if (IS_AOP_PREG (left))
6142                     {
6143                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6144                       emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6145                       aopPut (AOP (result), "a", offset);
6146                     }
6147                   else
6148                     {
6149                       emitcode ("orl", "%s,%s",
6150                             aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6151                          aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6152                     }
6153                 }
6154             }
6155           else
6156             {
6157               if (AOP_TYPE (left) == AOP_ACC)
6158                 {
6159                   emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6160                 }
6161               else
6162                 {
6163                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6164                   if (IS_AOP_PREG (left))
6165                     {
6166                       emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6167                       aopPut (AOP (result), "a", offset);
6168                     }
6169                   else
6170                     {
6171                       emitcode ("orl", "%s,a",
6172                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6173                     }
6174                 }
6175             }
6176         }
6177     }
6178   else
6179     {
6180       // left & result in different registers
6181       if (AOP_TYPE (result) == AOP_CRY)
6182         {
6183           // result = bit
6184           // if(size), result in bit
6185           // if(!size && ifx), conditional oper: if(left | right)
6186           symbol *tlbl = newiTempLabel (NULL);
6187           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6188           if (size)
6189             emitcode ("setb", "c");
6190           while (sizer--)
6191             {
6192               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6193                 emitcode ("orl", "a,%s",
6194                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6195               } else {
6196                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6197                 emitcode ("orl", "a,%s",
6198                           aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6199               }
6200               emitcode ("jnz", "%05d$", tlbl->key + 100);
6201               offset++;
6202             }
6203           if (size)
6204             {
6205               CLRC;
6206               emitcode ("", "%05d$:", tlbl->key + 100);
6207               outBitC (result);
6208             }
6209           else if (ifx)
6210             jmpTrueOrFalse (ifx, tlbl);
6211         }
6212       else
6213         {
6214             _startLazyDPSEvaluation();
6215           for (; (size--); offset++)
6216             {
6217               // normal case
6218               // result = left & right
6219               if (AOP_TYPE (right) == AOP_LIT)
6220                 {
6221                   if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6222                     {
6223                       aopPut (AOP (result),
6224                            aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6225                               offset);
6226                       continue;
6227                     }
6228                   D (emitcode (";", "better literal OR."););
6229                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6230                   emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
6231                                                     FALSE, FALSE, FALSE));
6232
6233                 }
6234               else
6235                 {
6236                   // faster than result <- left, anl result,right
6237                   // and better if result is SFR
6238                   if (AOP_TYPE (left) == AOP_ACC)
6239                     {
6240                       emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
6241                                                        FALSE, FALSE, FALSE));
6242                     }
6243                   else
6244                     {
6245                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6246                         
6247                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6248                       {
6249                           emitcode("mov", "b,a");
6250                           rOp = "b";
6251                       }
6252                         
6253                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6254                       emitcode ("orl", "a,%s", rOp);
6255                     }
6256                 }
6257               aopPut (AOP (result), "a", offset);
6258             }
6259             _endLazyDPSEvaluation();
6260         }
6261     }
6262
6263 release:
6264   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6265   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6266   freeAsmop (result, NULL, ic, TRUE);
6267 }
6268
6269 /*-----------------------------------------------------------------*/
6270 /* genXor - code for xclusive or                                   */
6271 /*-----------------------------------------------------------------*/
6272 static void
6273 genXor (iCode * ic, iCode * ifx)
6274 {
6275   operand *left, *right, *result;
6276   int size, offset = 0;
6277   unsigned long lit = 0L;
6278   bool pushResult;
6279
6280   D (emitcode (";", "genXor "););
6281
6282   AOP_OP_3_NOFATAL (ic, pushResult);
6283   AOP_SET_LOCALS (ic);
6284
6285   if (pushResult)
6286   {
6287       genFarFarLogicOp(ic, "xrl");
6288       return;
6289   }  
6290
6291 #ifdef DEBUG_TYPE
6292   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6293             AOP_TYPE (result),
6294             AOP_TYPE (left), AOP_TYPE (right));
6295   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6296             AOP_SIZE (result),
6297             AOP_SIZE (left), AOP_SIZE (right));
6298 #endif
6299
6300   /* if left is a literal & right is not ||
6301      if left needs acc & right does not */
6302   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) 
6303 #ifdef LOGIC_OPS_BROKEN      
6304       || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6305 #endif
6306      )
6307     {
6308       operand *tmp = right;
6309       right = left;
6310       left = tmp;
6311     }
6312
6313   /* if result = right then exchange them */
6314   if (sameRegs (AOP (result), AOP (right)))
6315     {
6316       operand *tmp = right;
6317       right = left;
6318       left = tmp;
6319     }
6320
6321   /* if right is bit then exchange them */
6322   if (AOP_TYPE (right) == AOP_CRY &&
6323       AOP_TYPE (left) != AOP_CRY)
6324     {
6325       operand *tmp = right;
6326       right = left;
6327       left = tmp;
6328     }
6329   if (AOP_TYPE (right) == AOP_LIT)
6330     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6331
6332   size = AOP_SIZE (result);
6333
6334   // if(bit ^ yy)
6335   // xx = bit ^ yy;
6336   if (AOP_TYPE (left) == AOP_CRY)
6337     {
6338       if (AOP_TYPE (right) == AOP_LIT)
6339         {
6340           // c = bit & literal;
6341           if (lit >> 1)
6342             {
6343               // lit>>1  != 0 => result = 1
6344               if (AOP_TYPE (result) == AOP_CRY)
6345                 {
6346                   if (size)
6347                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6348                   else if (ifx)
6349                     continueIfTrue (ifx);
6350                   goto release;
6351                 }
6352               emitcode ("setb", "c");
6353             }
6354           else
6355             {
6356               // lit == (0 or 1)
6357               if (lit == 0)
6358                 {
6359                   // lit == 0, result = left
6360                   if (size && sameRegs (AOP (result), AOP (left)))
6361                     goto release;
6362                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6363                 }
6364               else
6365                 {
6366                   // lit == 1, result = not(left)
6367                   if (size && sameRegs (AOP (result), AOP (left)))
6368                     {
6369                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6370                       goto release;
6371                     }
6372                   else
6373                     {
6374                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6375                       emitcode ("cpl", "c");
6376                     }
6377                 }
6378             }
6379
6380         }
6381       else
6382         {
6383           // right != literal
6384           symbol *tlbl = newiTempLabel (NULL);
6385           if (AOP_TYPE (right) == AOP_CRY)
6386             {
6387               // c = bit ^ bit;
6388               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6389             }
6390           else
6391             {
6392               int sizer = AOP_SIZE (right);
6393               // c = bit ^ val
6394               // if val>>1 != 0, result = 1
6395               emitcode ("setb", "c");
6396               while (sizer)
6397                 {
6398                   MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
6399                   if (sizer == 1)
6400                     // test the msb of the lsb
6401                     emitcode ("anl", "a,#0xfe");
6402                   emitcode ("jnz", "%05d$", tlbl->key + 100);
6403                   sizer--;
6404                 }
6405               // val = (0,1)
6406               emitcode ("rrc", "a");
6407             }
6408           emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6409           emitcode ("cpl", "c");
6410           emitcode ("", "%05d$:", (tlbl->key + 100));
6411         }
6412       // bit = c
6413       // val = c
6414       if (size)
6415         outBitC (result);
6416       // if(bit | ...)
6417       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6418         genIfxJump (ifx, "c");
6419       goto release;
6420     }
6421
6422   if (sameRegs (AOP (result), AOP (left)))
6423     {
6424       /* if left is same as result */
6425       for (; size--; offset++)
6426         {
6427           if (AOP_TYPE (right) == AOP_LIT)
6428             {
6429               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6430                 continue;
6431               else if (IS_AOP_PREG (left))
6432                 {
6433                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6434                   emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6435                   aopPut (AOP (result), "a", offset);
6436                 }
6437               else
6438                 emitcode ("xrl", "%s,%s",
6439                           aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6440                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6441             }
6442           else
6443             {
6444               if (AOP_TYPE (left) == AOP_ACC)
6445                 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6446               else
6447                 {
6448                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6449                   if (IS_AOP_PREG (left))
6450                     {
6451                       emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6452                       aopPut (AOP (result), "a", offset);
6453                     }
6454                   else
6455                     emitcode ("xrl", "%s,a",
6456                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6457                 }
6458             }
6459         }
6460     }
6461   else
6462     {
6463       // left & result in different registers
6464       if (AOP_TYPE (result) == AOP_CRY)
6465         {
6466           // result = bit
6467           // if(size), result in bit
6468           // if(!size && ifx), conditional oper: if(left ^ right)
6469           symbol *tlbl = newiTempLabel (NULL);
6470           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6471           if (size)
6472             emitcode ("setb", "c");
6473           while (sizer--)
6474             {
6475               if ((AOP_TYPE (right) == AOP_LIT) &&
6476                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6477                 {
6478                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6479                 }
6480               else
6481                 {
6482                   if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6483                     emitcode ("xrl", "a,%s",
6484                               aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6485                   } else {
6486                     MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6487                     emitcode ("xrl", "a,%s",
6488                               aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6489                   }
6490                 }
6491               emitcode ("jnz", "%05d$", tlbl->key + 100);
6492               offset++;
6493             }
6494           if (size)
6495             {
6496               CLRC;
6497               emitcode ("", "%05d$:", tlbl->key + 100);
6498               outBitC (result);
6499             }
6500           else if (ifx)
6501             jmpTrueOrFalse (ifx, tlbl);
6502         }
6503       else
6504         for (; (size--); offset++)
6505           {
6506             // normal case
6507             // result = left & right
6508             if (AOP_TYPE (right) == AOP_LIT)
6509               {
6510                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6511                   {
6512                     aopPut (AOP (result),
6513                             aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6514                             offset);
6515                     continue;
6516                   }
6517                 D (emitcode (";", "better literal XOR.");
6518                   );
6519                 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6520                 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
6521                                                   FALSE, FALSE, FALSE));
6522               }
6523             else
6524               {
6525                 // faster than result <- left, anl result,right
6526                 // and better if result is SFR
6527                 if (AOP_TYPE (left) == AOP_ACC)
6528                   {
6529                     emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
6530                                                      FALSE, FALSE, FALSE));
6531                   }
6532                 else
6533                   {
6534                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6535                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6536                       {
6537                           emitcode("mov", "b,a");
6538                           rOp = "b";
6539                       }
6540                         
6541                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6542                       emitcode ("xrl", "a,%s", rOp);
6543                   }
6544               }
6545             aopPut (AOP (result), "a", offset);
6546           }
6547     }
6548
6549 release:
6550   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6551   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6552   freeAsmop (result, NULL, ic, TRUE);
6553 }
6554
6555 /*-----------------------------------------------------------------*/
6556 /* genInline - write the inline code out                           */
6557 /*-----------------------------------------------------------------*/
6558 static void
6559 genInline (iCode * ic)
6560 {
6561   char *buffer, *bp, *bp1;
6562
6563   D (emitcode (";", "genInline ");
6564     );
6565
6566   _G.inLine += (!options.asmpeep);
6567
6568   buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6569   strcpy (buffer, IC_INLINE (ic));
6570
6571   /* emit each line as a code */
6572   while (*bp)
6573     {
6574       if (*bp == '\n')
6575         {
6576           *bp++ = '\0';
6577           emitcode (bp1, "");
6578           bp1 = bp;
6579         }
6580       else
6581         {
6582           if (*bp == ':')
6583             {
6584               bp++;
6585               *bp = '\0';
6586               bp++;
6587               emitcode (bp1, "");
6588               bp1 = bp;
6589             }
6590           else
6591             bp++;
6592         }
6593     }
6594   if (bp1 != bp)
6595     emitcode (bp1, "");
6596   /*     emitcode("",buffer); */
6597   _G.inLine -= (!options.asmpeep);
6598 }
6599
6600 /*-----------------------------------------------------------------*/
6601 /* genRRC - rotate right with carry                                */
6602 /*-----------------------------------------------------------------*/
6603 static void
6604 genRRC (iCode * ic)
6605 {
6606   operand *left, *result;
6607   int size, offset = 0;
6608   char *l;
6609
6610   D (emitcode (";", "genRRC ");
6611     );
6612
6613   /* rotate right with carry */
6614   left = IC_LEFT (ic);
6615   result = IC_RESULT (ic);
6616   aopOp (left, ic, FALSE, FALSE);
6617   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6618
6619   /* move it to the result */
6620   size = AOP_SIZE (result);
6621   offset = size - 1;
6622   CLRC;
6623
6624   _startLazyDPSEvaluation ();
6625   while (size--)
6626     {
6627       l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6628       MOVA (l);
6629       emitcode ("rrc", "a");
6630       if (AOP_SIZE (result) > 1)
6631         aopPut (AOP (result), "a", offset--);
6632     }
6633   _endLazyDPSEvaluation ();
6634
6635   /* now we need to put the carry into the
6636      highest order byte of the result */
6637   if (AOP_SIZE (result) > 1)
6638     {
6639       l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
6640       MOVA (l);
6641     }
6642   emitcode ("mov", "acc.7,c");
6643   aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
6644   freeAsmop (left, NULL, ic, TRUE);
6645   freeAsmop (result, NULL, ic, TRUE);
6646 }
6647
6648 /*-----------------------------------------------------------------*/
6649 /* genRLC - generate code for rotate left with carry               */
6650 /*-----------------------------------------------------------------*/
6651 static void
6652 genRLC (iCode * ic)
6653 {
6654   operand *left, *result;
6655   int size, offset = 0;
6656   char *l;
6657
6658   D (emitcode (";", "genRLC ");
6659     );
6660
6661   /* rotate right with carry */
6662   left = IC_LEFT (ic);
6663   result = IC_RESULT (ic);
6664   aopOp (left, ic, FALSE, FALSE);
6665   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6666
6667   /* move it to the result */
6668   size = AOP_SIZE (result);
6669   offset = 0;
6670   if (size--)
6671     {
6672       l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6673       MOVA (l);
6674       emitcode ("add", "a,acc");
6675       if (AOP_SIZE (result) > 1)
6676         {
6677           aopPut (AOP (result), "a", offset++);
6678         }
6679
6680       _startLazyDPSEvaluation ();
6681       while (size--)
6682         {
6683           l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6684           MOVA (l);
6685           emitcode ("rlc", "a");
6686           if (AOP_SIZE (result) > 1)
6687             aopPut (AOP (result), "a", offset++);
6688         }
6689       _endLazyDPSEvaluation ();
6690     }
6691   /* now we need to put the carry into the
6692      highest order byte of the result */
6693   if (AOP_SIZE (result) > 1)
6694     {
6695       l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
6696       MOVA (l);
6697     }
6698   emitcode ("mov", "acc.0,c");
6699   aopPut (AOP (result), "a", 0);
6700   freeAsmop (left, NULL, ic, TRUE);
6701   freeAsmop (result, NULL, ic, TRUE);
6702 }
6703
6704 /*-----------------------------------------------------------------*/
6705 /* genGetHbit - generates code get highest order bit               */
6706 /*-----------------------------------------------------------------*/
6707 static void
6708 genGetHbit (iCode * ic)
6709 {
6710   operand *left, *result;
6711   left = IC_LEFT (ic);
6712   result = IC_RESULT (ic);
6713   aopOp (left, ic, FALSE, FALSE);
6714   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6715
6716   D (emitcode (";", "genGetHbit ");
6717     );
6718
6719   /* get the highest order byte into a */
6720   MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
6721   if (AOP_TYPE (result) == AOP_CRY)
6722     {
6723       emitcode ("rlc", "a");
6724       outBitC (result);
6725     }
6726   else
6727     {
6728       emitcode ("rl", "a");
6729       emitcode ("anl", "a,#0x01");
6730       outAcc (result);
6731     }
6732
6733
6734   freeAsmop (left, NULL, ic, TRUE);
6735   freeAsmop (result, NULL, ic, TRUE);
6736 }
6737
6738 /*-----------------------------------------------------------------*/
6739 /* AccRol - rotate left accumulator by known count                 */
6740 /*-----------------------------------------------------------------*/
6741 static void
6742 AccRol (int shCount)
6743 {
6744   shCount &= 0x0007;            // shCount : 0..7
6745
6746   switch (shCount)
6747     {
6748     case 0:
6749       break;
6750     case 1:
6751       emitcode ("rl", "a");
6752       break;
6753     case 2:
6754       emitcode ("rl", "a");
6755       emitcode ("rl", "a");
6756       break;
6757     case 3:
6758       emitcode ("swap", "a");
6759       emitcode ("rr", "a");
6760       break;
6761     case 4:
6762       emitcode ("swap", "a");
6763       break;
6764     case 5:
6765       emitcode ("swap", "a");
6766       emitcode ("rl", "a");
6767       break;
6768     case 6:
6769       emitcode ("rr", "a");
6770       emitcode ("rr", "a");
6771       break;
6772     case 7:
6773       emitcode ("rr", "a");
6774       break;
6775     }
6776 }
6777
6778 /*-----------------------------------------------------------------*/
6779 /* AccLsh - left shift accumulator by known count                  */
6780 /*-----------------------------------------------------------------*/
6781 static void
6782 AccLsh (int shCount)
6783 {
6784   if (shCount != 0)
6785     {
6786       if (shCount == 1)
6787         emitcode ("add", "a,acc");
6788       else if (shCount == 2)
6789         {
6790           emitcode ("add", "a,acc");
6791           emitcode ("add", "a,acc");
6792         }
6793       else
6794         {
6795           /* rotate left accumulator */
6796           AccRol (shCount);
6797           /* and kill the lower order bits */
6798           emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6799         }
6800     }
6801 }
6802
6803 /*-----------------------------------------------------------------*/
6804 /* AccRsh - right shift accumulator by known count                 */
6805 /*-----------------------------------------------------------------*/
6806 static void
6807 AccRsh (int shCount)
6808 {
6809   if (shCount != 0)
6810     {
6811       if (shCount == 1)
6812         {
6813           CLRC;
6814           emitcode ("rrc", "a");
6815         }
6816       else
6817         {
6818           /* rotate right accumulator */
6819           AccRol (8 - shCount);
6820           /* and kill the higher order bits */
6821           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6822         }
6823     }
6824 }
6825
6826 #ifdef BETTER_LITERAL_SHIFT
6827 /*-----------------------------------------------------------------*/
6828 /* AccSRsh - signed right shift accumulator by known count                 */
6829 /*-----------------------------------------------------------------*/
6830 static void
6831 AccSRsh (int shCount)
6832 {
6833   symbol *tlbl;
6834   if (shCount != 0)
6835     {
6836       if (shCount == 1)
6837         {
6838           emitcode ("mov", "c,acc.7");
6839           emitcode ("rrc", "a");
6840         }
6841       else if (shCount == 2)
6842         {
6843           emitcode ("mov", "c,acc.7");
6844           emitcode ("rrc", "a");
6845           emitcode ("mov", "c,acc.7");
6846           emitcode ("rrc", "a");
6847         }
6848       else
6849         {
6850           tlbl = newiTempLabel (NULL);
6851           /* rotate right accumulator */
6852           AccRol (8 - shCount);
6853           /* and kill the higher order bits */
6854           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6855           emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6856           emitcode ("orl", "a,#0x%02x",
6857                     (unsigned char) ~SRMask[shCount]);
6858           emitcode ("", "%05d$:", tlbl->key + 100);
6859         }
6860     }
6861 }
6862 #endif
6863
6864 #ifdef BETTER_LITERAL_SHIFT
6865 /*-----------------------------------------------------------------*/
6866 /* shiftR1Left2Result - shift right one byte from left to result   */
6867 /*-----------------------------------------------------------------*/
6868 static void
6869 shiftR1Left2Result (operand * left, int offl,
6870                     operand * result, int offr,
6871                     int shCount, int sign)
6872 {
6873   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6874   /* shift right accumulator */
6875   if (sign)
6876     AccSRsh (shCount);
6877   else
6878     AccRsh (shCount);
6879   aopPut (AOP (result), "a", offr);
6880 }
6881 #endif
6882
6883 #ifdef BETTER_LITERAL_SHIFT
6884 /*-----------------------------------------------------------------*/
6885 /* shiftL1Left2Result - shift left one byte from left to result    */
6886 /*-----------------------------------------------------------------*/
6887 static void
6888 shiftL1Left2Result (operand * left, int offl,
6889                     operand * result, int offr, int shCount)
6890 {
6891   MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6892   /* shift left accumulator */
6893   AccLsh (shCount);
6894   aopPut (AOP (result), "a", offr);
6895 }
6896 #endif
6897
6898 #ifdef BETTER_LITERAL_SHIFT
6899 /*-----------------------------------------------------------------*/
6900 /* movLeft2Result - move byte from left to result                  */
6901 /*-----------------------------------------------------------------*/
6902 static void
6903 movLeft2Result (operand * left, int offl,
6904                 operand * result, int offr, int sign)
6905 {
6906   char *l;
6907   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6908   {
6909       l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
6910
6911       if (*l == '@' && (IS_AOP_PREG (result)))
6912       {
6913           emitcode ("mov", "a,%s", l);
6914           aopPut (AOP (result), "a", offr);
6915       }
6916       else
6917       {
6918           if (!sign)
6919           {
6920             aopPut (AOP (result), l, offr);
6921           }
6922           else
6923             {
6924               /* MSB sign in acc.7 ! */
6925               if (getDataSize (left) == offl + 1)
6926                 {
6927                   emitcode ("mov", "a,%s", l);
6928                   aopPut (AOP (result), "a", offr);
6929                 }
6930             }
6931       }
6932   }
6933 }
6934 #endif
6935
6936 #ifdef BETTER_LITERAL_SHIFT
6937 /*-----------------------------------------------------------------*/
6938 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
6939 /*-----------------------------------------------------------------*/
6940 static void
6941 AccAXRrl1 (char *x)
6942 {
6943   emitcode ("rrc", "a");
6944   emitcode ("xch", "a,%s", x);
6945   emitcode ("rrc", "a");
6946   emitcode ("xch", "a,%s", x);
6947 }
6948 #endif
6949
6950 #ifdef BETTER_LITERAL_SHIFT
6951 //REMOVE ME!!!
6952 /*-----------------------------------------------------------------*/
6953 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
6954 /*-----------------------------------------------------------------*/
6955 static void
6956 AccAXLrl1 (char *x)
6957 {
6958   emitcode ("xch", "a,%s", x);
6959   emitcode ("rlc", "a");
6960   emitcode ("xch", "a,%s", x);
6961   emitcode ("rlc", "a");
6962 }
6963 #endif
6964
6965 #ifdef BETTER_LITERAL_SHIFT
6966 /*-----------------------------------------------------------------*/
6967 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
6968 /*-----------------------------------------------------------------*/
6969 static void
6970 AccAXLsh1 (char *x)
6971 {
6972   emitcode ("xch", "a,%s", x);
6973   emitcode ("add", "a,acc");
6974   emitcode ("xch", "a,%s", x);
6975   emitcode ("rlc", "a");
6976 }
6977 #endif
6978
6979 #ifdef BETTER_LITERAL_SHIFT
6980 /*-----------------------------------------------------------------*/
6981 /* AccAXLsh - left shift a:x by known count (0..7)                 */
6982 /*-----------------------------------------------------------------*/
6983 static void
6984 AccAXLsh (char *x, int shCount)
6985 {
6986   switch (shCount)
6987     {
6988     case 0:
6989       break;
6990     case 1:
6991       AccAXLsh1 (x);
6992       break;
6993     case 2:
6994       AccAXLsh1 (x);
6995       AccAXLsh1 (x);
6996       break;
6997     case 3:
6998     case 4:
6999     case 5:                     // AAAAABBB:CCCCCDDD
7000
7001       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
7002
7003       emitcode ("anl", "a,#0x%02x",
7004                 SLMask[shCount]);       // BBB00000:CCCCCDDD
7005
7006       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
7007
7008       AccRol (shCount);         // DDDCCCCC:BBB00000
7009
7010       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
7011
7012       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
7013
7014       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
7015
7016       emitcode ("anl", "a,#0x%02x",
7017                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
7018
7019       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
7020
7021       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
7022
7023       break;
7024     case 6:                     // AAAAAABB:CCCCCCDD
7025       emitcode ("anl", "a,#0x%02x",
7026                 SRMask[shCount]);       // 000000BB:CCCCCCDD
7027       emitcode ("mov", "c,acc.0");      // c = B
7028       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
7029 #if 0
7030       AccAXRrl1 (x);            // BCCCCCCD:D000000B
7031       AccAXRrl1 (x);            // BBCCCCCC:DD000000
7032 #else
7033       emitcode("rrc","a"); 
7034       emitcode("xch","a,%s", x); 
7035       emitcode("rrc","a"); 
7036       emitcode("mov","c,acc.0"); //<< get correct bit 
7037       emitcode("xch","a,%s", x); 
7038
7039       emitcode("rrc","a"); 
7040       emitcode("xch","a,%s", x); 
7041       emitcode("rrc","a"); 
7042       emitcode("xch","a,%s", x); 
7043 #endif
7044       break;
7045     case 7:                     // a:x <<= 7
7046
7047       emitcode ("anl", "a,#0x%02x",
7048                 SRMask[shCount]);       // 0000000B:CCCCCCCD
7049
7050       emitcode ("mov", "c,acc.0");      // c = B
7051
7052       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
7053
7054       AccAXRrl1 (x);            // BCCCCCCC:D0000000
7055
7056       break;
7057     default:
7058       break;
7059     }
7060 }
7061 #endif
7062
7063 #ifdef BETTER_LITERAL_SHIFT
7064 //REMOVE ME!!!
7065 /*-----------------------------------------------------------------*/
7066 /* AccAXRsh - right shift a:x known count (0..7)                   */
7067 /*-----------------------------------------------------------------*/
7068 static void
7069 AccAXRsh (char *x, int shCount)
7070 {
7071   switch (shCount)
7072     {
7073     case 0:
7074       break;
7075     case 1:
7076       CLRC;
7077       AccAXRrl1 (x);            // 0->a:x
7078
7079       break;
7080     case 2:
7081       CLRC;
7082       AccAXRrl1 (x);            // 0->a:x
7083
7084       CLRC;
7085       AccAXRrl1 (x);            // 0->a:x
7086
7087       break;
7088     case 3:
7089     case 4:
7090     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7091
7092       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
7093
7094       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7095
7096       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7097
7098       emitcode ("anl", "a,#0x%02x",
7099                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7100
7101       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7102
7103       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7104
7105       emitcode ("anl", "a,#0x%02x",
7106                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7107
7108       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7109
7110       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7111
7112       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
7113
7114       break;
7115     case 6:                     // AABBBBBB:CCDDDDDD
7116
7117       emitcode ("mov", "c,acc.7");
7118       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7119
7120       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7121
7122       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7123
7124       emitcode ("anl", "a,#0x%02x",
7125                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7126
7127       break;
7128     case 7:                     // ABBBBBBB:CDDDDDDD
7129
7130       emitcode ("mov", "c,acc.7");      // c = A
7131
7132       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7133
7134       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7135
7136       emitcode ("anl", "a,#0x%02x",
7137                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7138
7139       break;
7140     default:
7141       break;
7142     }
7143 }
7144 #endif
7145
7146 #ifdef BETTER_LITERAL_SHIFT
7147 /*-----------------------------------------------------------------*/
7148 /* AccAXRshS - right shift signed a:x known count (0..7)           */
7149 /*-----------------------------------------------------------------*/
7150 static void
7151 AccAXRshS (char *x, int shCount)
7152 {
7153   symbol *tlbl;
7154   switch (shCount)
7155     {
7156     case 0:
7157       break;
7158     case 1:
7159       emitcode ("mov", "c,acc.7");
7160       AccAXRrl1 (x);            // s->a:x
7161
7162       break;
7163     case 2:
7164       emitcode ("mov", "c,acc.7");
7165       AccAXRrl1 (x);            // s->a:x
7166
7167       emitcode ("mov", "c,acc.7");
7168       AccAXRrl1 (x);            // s->a:x
7169
7170       break;
7171     case 3:
7172     case 4:
7173     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7174
7175       tlbl = newiTempLabel (NULL);
7176       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
7177
7178       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7179
7180       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7181
7182       emitcode ("anl", "a,#0x%02x",
7183                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7184
7185       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7186
7187       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7188
7189       emitcode ("anl", "a,#0x%02x",
7190                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7191
7192       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7193
7194       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7195
7196       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
7197
7198       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7199       emitcode ("orl", "a,#0x%02x",
7200                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
7201
7202       emitcode ("", "%05d$:", tlbl->key + 100);
7203       break;                    // SSSSAAAA:BBBCCCCC
7204
7205     case 6:                     // AABBBBBB:CCDDDDDD
7206
7207       tlbl = newiTempLabel (NULL);
7208       emitcode ("mov", "c,acc.7");
7209       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7210
7211       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7212
7213       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7214
7215       emitcode ("anl", "a,#0x%02x",
7216                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7217
7218       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7219       emitcode ("orl", "a,#0x%02x",
7220                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
7221
7222       emitcode ("", "%05d$:", tlbl->key + 100);
7223       break;
7224     case 7:                     // ABBBBBBB:CDDDDDDD
7225
7226       tlbl = newiTempLabel (NULL);
7227       emitcode ("mov", "c,acc.7");      // c = A
7228
7229       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7230
7231       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7232
7233       emitcode ("anl", "a,#0x%02x",
7234                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7235
7236       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7237       emitcode ("orl", "a,#0x%02x",
7238                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
7239
7240       emitcode ("", "%05d$:", tlbl->key + 100);
7241       break;
7242     default:
7243       break;
7244     }
7245 }
7246 #endif
7247
7248 #ifdef BETTER_LITERAL_SHIFT
7249 static void
7250 _loadLeftIntoAx(char    **lsb, 
7251                 operand *left, 
7252                 operand *result,
7253                 int     offl,
7254                 int     offr)
7255 {
7256   // Get the initial value from left into a pair of registers.
7257   // MSB must be in A, LSB can be any register.
7258   //
7259   // If the result is held in registers, it is an optimization
7260   // if the LSB can be held in the register which will hold the,
7261   // result LSB since this saves us from having to copy it into
7262   // the result following AccAXLsh.
7263   //
7264   // If the result is addressed indirectly, this is not a gain.
7265   if (AOP_NEEDSACC(result))
7266   {
7267        char *leftByte;
7268        
7269        _startLazyDPSEvaluation();
7270       if (AOP_TYPE(left) == AOP_DPTR2)
7271        {
7272            // Get MSB in A.
7273            MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
7274            // get LSB in DP2_RESULT_REG.
7275            leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
7276            assert(!strcmp(leftByte, DP2_RESULT_REG));
7277        }
7278        else
7279        {
7280            // get LSB into DP2_RESULT_REG
7281            leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
7282            if (strcmp(leftByte, DP2_RESULT_REG))
7283            {
7284                TR_AP("#7");
7285                emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7286            }
7287            // And MSB in A.
7288            leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
7289            assert(strcmp(leftByte, DP2_RESULT_REG));
7290            MOVA(leftByte);
7291        }
7292        _endLazyDPSEvaluation();
7293        *lsb = DP2_RESULT_REG;
7294   }
7295   else
7296   {
7297       if (sameRegs (AOP (result), AOP (left)) &&
7298         ((offl + MSB16) == offr))
7299       {
7300           /* don't crash result[offr] */
7301           MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
7302           emitcode ("xch", "a,%s", 
7303                     aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
7304       }
7305       else
7306       {
7307           movLeft2Result (left, offl, result, offr, 0);
7308           MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
7309       }
7310       *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
7311       assert(strcmp(*lsb,"a"));      
7312   }
7313 }
7314
7315 static void
7316 _storeAxResults(char    *lsb,
7317                 operand *result,
7318                 int     offr)
7319 {
7320   _startLazyDPSEvaluation();
7321   if (AOP_NEEDSACC(result))
7322   {
7323       /* We have to explicitly update the result LSB.
7324        */
7325       emitcode("xch","a,%s", lsb);
7326       aopPut(AOP(result), "a", offr);
7327       emitcode("mov","a,%s", lsb);
7328   }
7329   if (getDataSize (result) > 1)
7330   {
7331       aopPut (AOP (result), "a", offr + MSB16);
7332   }
7333   _endLazyDPSEvaluation();
7334 }
7335
7336 /*-----------------------------------------------------------------*/
7337 /* shiftL2Left2Result - shift left two bytes from left to result   */
7338 /*-----------------------------------------------------------------*/
7339 static void
7340 shiftL2Left2Result (operand * left, int offl,
7341                     operand * result, int offr, int shCount)
7342 {
7343   char *lsb;
7344
7345   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7346   
7347   AccAXLsh (lsb, shCount);
7348   
7349   _storeAxResults(lsb, result, offr);
7350 }
7351 #endif
7352
7353 #ifdef BETTER_LITERAL_SHIFT
7354 /*-----------------------------------------------------------------*/
7355 /* shiftR2Left2Result - shift right two bytes from left to result  */
7356 /*-----------------------------------------------------------------*/
7357 static void
7358 shiftR2Left2Result (operand * left, int offl,
7359                     operand * result, int offr,
7360                     int shCount, int sign)
7361 {
7362   char *lsb;
7363   
7364   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7365   
7366   /* a:x >> shCount (x = lsb(result)) */
7367   if (sign)
7368   {
7369      AccAXRshS(lsb, shCount);
7370   }
7371   else
7372   {
7373     AccAXRsh(lsb, shCount);
7374   }
7375   
7376   _storeAxResults(lsb, result, offr);
7377 }
7378 #endif
7379
7380 #if 0
7381 //REMOVE ME!!!
7382 /*-----------------------------------------------------------------*/
7383 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7384 /*-----------------------------------------------------------------*/
7385 static void
7386 shiftLLeftOrResult (operand * left, int offl,
7387                     operand * result, int offr, int shCount)
7388 {
7389   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7390   /* shift left accumulator */
7391   AccLsh (shCount);
7392   /* or with result */
7393   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7394   /* back to result */
7395   aopPut (AOP (result), "a", offr);
7396 }
7397 #endif
7398
7399 #if 0
7400 //REMOVE ME!!!
7401 /*-----------------------------------------------------------------*/
7402 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7403 /*-----------------------------------------------------------------*/
7404 static void
7405 shiftRLeftOrResult (operand * left, int offl,
7406                     operand * result, int offr, int shCount)
7407 {
7408   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7409   /* shift right accumulator */
7410   AccRsh (shCount);
7411   /* or with result */
7412   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7413   /* back to result */
7414   aopPut (AOP (result), "a", offr);
7415 }
7416 #endif
7417
7418 #ifdef BETTER_LITERAL_SHIFT
7419 /*-----------------------------------------------------------------*/
7420 /* genlshOne - left shift a one byte quantity by known count       */
7421 /*-----------------------------------------------------------------*/
7422 static void
7423 genlshOne (operand * result, operand * left, int shCount)
7424 {
7425   D (emitcode (";", "genlshOne "););
7426   shiftL1Left2Result (left, LSB, result, LSB, shCount);
7427 }
7428 #endif
7429
7430 #ifdef BETTER_LITERAL_SHIFT
7431 /*-----------------------------------------------------------------*/
7432 /* genlshTwo - left shift two bytes by known amount != 0           */
7433 /*-----------------------------------------------------------------*/
7434 static void
7435 genlshTwo (operand * result, operand * left, int shCount)
7436 {
7437   int size;
7438
7439   D (emitcode (";", "genlshTwo "););
7440
7441   size = getDataSize (result);
7442
7443   /* if shCount >= 8 */
7444   if (shCount >= 8)
7445   {
7446       shCount -= 8;
7447
7448       _startLazyDPSEvaluation();
7449
7450       if (size > 1)
7451         {
7452           if (shCount)
7453           {
7454             _endLazyDPSEvaluation();
7455             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7456             aopPut (AOP (result), zero, LSB);       
7457           }
7458           else
7459           {
7460             movLeft2Result (left, LSB, result, MSB16, 0);
7461             aopPut (AOP (result), zero, LSB);
7462             _endLazyDPSEvaluation();
7463           }
7464         }
7465         else
7466         {
7467           aopPut (AOP (result), zero, LSB);
7468           _endLazyDPSEvaluation();
7469         }
7470   }
7471
7472   /*  1 <= shCount <= 7 */
7473   else
7474     {
7475       if (size == 1)
7476       {
7477         shiftL1Left2Result (left, LSB, result, LSB, shCount);
7478       }
7479       else
7480       {
7481         shiftL2Left2Result (left, LSB, result, LSB, shCount);
7482       }
7483     }
7484 }
7485 #endif
7486
7487 #if 0
7488 //REMOVE ME!!!
7489 /*-----------------------------------------------------------------*/
7490 /* shiftLLong - shift left one long from left to result            */
7491 /* offl = LSB or MSB16                                             */
7492 /*-----------------------------------------------------------------*/
7493 static void
7494 shiftLLong (operand * left, operand * result, int offr)
7495 {
7496   char *l;
7497   int size = AOP_SIZE (result);
7498
7499   if (size >= LSB + offr)
7500     {
7501       l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
7502       MOVA (l);
7503       emitcode ("add", "a,acc");
7504       if (sameRegs (AOP (left), AOP (result)) &&
7505           size >= MSB16 + offr && offr != LSB)
7506         emitcode ("xch", "a,%s",
7507                   aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
7508       else
7509         aopPut (AOP (result), "a", LSB + offr);
7510     }
7511
7512   if (size >= MSB16 + offr)
7513     {
7514       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7515         {
7516           l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
7517           MOVA (l);
7518         }
7519       emitcode ("rlc", "a");
7520       if (sameRegs (AOP (left), AOP (result)) &&
7521           size >= MSB24 + offr && offr != LSB)
7522         emitcode ("xch", "a,%s",
7523                   aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
7524       else
7525         aopPut (AOP (result), "a", MSB16 + offr);
7526     }
7527
7528   if (size >= MSB24 + offr)
7529     {
7530       if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7531         {
7532           l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
7533           MOVA (l);
7534         }
7535       emitcode ("rlc", "a");
7536       if (sameRegs (AOP (left), AOP (result)) &&
7537           size >= MSB32 + offr && offr != LSB)
7538         emitcode ("xch", "a,%s",
7539                   aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
7540       else
7541         aopPut (AOP (result), "a", MSB24 + offr);
7542     }
7543
7544   if (size > MSB32 + offr)
7545     {
7546       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7547         {
7548           l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
7549           MOVA (l);
7550         }
7551       emitcode ("rlc", "a");
7552       aopPut (AOP (result), "a", MSB32 + offr);
7553     }
7554   if (offr != LSB)
7555     aopPut (AOP (result), zero, LSB);
7556 }
7557 #endif
7558
7559 #if 0
7560 //REMOVE ME!!!
7561 /*-----------------------------------------------------------------*/
7562 /* genlshFour - shift four byte by a known amount != 0             */
7563 /*-----------------------------------------------------------------*/
7564 static void
7565 genlshFour (operand * result, operand * left, int shCount)
7566 {
7567   int size;
7568
7569   D (emitcode (";", "genlshFour ");
7570     );
7571
7572   size = AOP_SIZE (result);
7573
7574   /* if shifting more that 3 bytes */
7575   if (shCount >= 24)
7576     {
7577       shCount -= 24;
7578       if (shCount)
7579         /* lowest order of left goes to the highest
7580            order of the destination */
7581         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7582       else
7583         movLeft2Result (left, LSB, result, MSB32, 0);
7584       aopPut (AOP (result), zero, LSB);
7585       aopPut (AOP (result), zero, MSB16);
7586       aopPut (AOP (result), zero, MSB24);
7587       return;
7588     }
7589
7590   /* more than two bytes */
7591   else if (shCount >= 16)
7592     {
7593       /* lower order two bytes goes to higher order two bytes */
7594       shCount -= 16;
7595       /* if some more remaining */
7596       if (shCount)
7597         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7598       else
7599         {
7600           movLeft2Result (left, MSB16, result, MSB32, 0);
7601           movLeft2Result (left, LSB, result, MSB24, 0);
7602         }
7603       aopPut (AOP (result), zero, MSB16);
7604       aopPut (AOP (result), zero, LSB);
7605       return;
7606     }
7607
7608   /* if more than 1 byte */
7609   else if (shCount >= 8)
7610     {
7611       /* lower order three bytes goes to higher order  three bytes */
7612       shCount -= 8;
7613       if (size == 2)
7614         {
7615           if (shCount)
7616             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7617           else
7618             movLeft2Result (left, LSB, result, MSB16, 0);
7619         }
7620       else
7621         {                       /* size = 4 */
7622           if (shCount == 0)
7623             {
7624               movLeft2Result (left, MSB24, result, MSB32, 0);
7625               movLeft2Result (left, MSB16, result, MSB24, 0);
7626               movLeft2Result (left, LSB, result, MSB16, 0);
7627               aopPut (AOP (result), zero, LSB);
7628             }
7629           else if (shCount == 1)
7630             shiftLLong (left, result, MSB16);
7631           else
7632             {
7633               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7634               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7635               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7636               aopPut (AOP (result), zero, LSB);
7637             }
7638         }
7639     }
7640
7641   /* 1 <= shCount <= 7 */
7642   else if (shCount <= 2)
7643     {
7644       shiftLLong (left, result, LSB);
7645       if (shCount == 2)
7646         shiftLLong (result, result, LSB);
7647     }
7648   /* 3 <= shCount <= 7, optimize */
7649   else
7650     {
7651       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7652       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7653       shiftL2Left2Result (left, LSB, result, LSB, shCount);
7654     }
7655 }
7656 #endif
7657
7658 #ifdef BETTER_LITERAL_SHIFT
7659 /*-----------------------------------------------------------------*/
7660 /* genLeftShiftLiteral - left shifting by known count              */
7661 /*-----------------------------------------------------------------*/
7662 static bool
7663 genLeftShiftLiteral (operand * left,
7664                      operand * right,
7665                      operand * result,
7666                      iCode * ic)
7667 {
7668   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7669   int size;
7670
7671   size = getSize (operandType (result));
7672
7673   D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
7674
7675   /* We only handle certain easy cases so far. */
7676   if ((shCount != 0)
7677    && (shCount < (size * 8))
7678    && (size != 1)
7679    && (size != 2))
7680   {
7681       D(emitcode (";", "genLeftShiftLiteral wimping out"););    
7682       return FALSE;
7683   }
7684
7685   freeAsmop (right, NULL, ic, TRUE);
7686
7687   aopOp(left, ic, FALSE, FALSE);
7688   aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
7689
7690 #if 1 // debug spew
7691   if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
7692   {
7693         emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
7694         if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
7695         {
7696            emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
7697         }
7698   }
7699   if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
7700   {
7701         emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
7702         if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
7703         {
7704            emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
7705         }       
7706   }  
7707 #endif
7708   
7709 #if VIEW_SIZE
7710   emitcode ("; shift left ", "result %d, left %d", size,
7711             AOP_SIZE (left));
7712 #endif
7713
7714   /* I suppose that the left size >= result size */
7715   if (shCount == 0)
7716   {
7717         _startLazyDPSEvaluation();
7718         while (size--)
7719         {
7720           movLeft2Result (left, size, result, size, 0);
7721         }
7722         _endLazyDPSEvaluation();
7723   }
7724   else if (shCount >= (size * 8))
7725   {
7726     _startLazyDPSEvaluation();
7727     while (size--)
7728     {
7729       aopPut (AOP (result), zero, size);
7730     }
7731     _endLazyDPSEvaluation();
7732   }
7733   else
7734   {
7735       switch (size)
7736         {
7737         case 1:
7738           genlshOne (result, left, shCount);
7739           break;
7740
7741         case 2:
7742           genlshTwo (result, left, shCount);
7743           break;
7744 #if 0
7745         case 4:
7746           genlshFour (result, left, shCount);
7747           break;
7748 #endif
7749         default:
7750           fprintf(stderr, "*** ack! mystery literal shift!\n");   
7751           break;
7752         }
7753     }
7754   freeAsmop (left, NULL, ic, TRUE);
7755   freeAsmop (result, NULL, ic, TRUE);
7756   return TRUE;
7757 }
7758 #endif
7759
7760 /*-----------------------------------------------------------------*/
7761 /* genLeftShift - generates code for left shifting                 */
7762 /*-----------------------------------------------------------------*/
7763 static void
7764 genLeftShift (iCode * ic)
7765 {
7766   operand *left, *right, *result;
7767   int size, offset;
7768   char *l;
7769   symbol *tlbl, *tlbl1;
7770
7771   D (emitcode (";", "genLeftShift "););
7772
7773   right = IC_RIGHT (ic);
7774   left = IC_LEFT (ic);
7775   result = IC_RESULT (ic);
7776
7777   aopOp (right, ic, FALSE, FALSE);
7778
7779
7780 #ifdef BETTER_LITERAL_SHIFT
7781   /* if the shift count is known then do it
7782      as efficiently as possible */
7783   if (AOP_TYPE (right) == AOP_LIT)
7784     {
7785       if (genLeftShiftLiteral (left, right, result, ic))
7786       {
7787         return;
7788       }
7789     }
7790 #endif
7791
7792   /* shift count is unknown then we have to form
7793      a loop get the loop count in B : Note: we take
7794      only the lower order byte since shifting
7795      more that 32 bits make no sense anyway, ( the
7796      largest size of an object can be only 32 bits ) */
7797
7798   if (AOP_TYPE (right) == AOP_LIT)
7799   {
7800       /* Really should be handled by genLeftShiftLiteral,
7801        * but since I'm too lazy to fix that today, at least we can make
7802        * some small improvement.
7803        */
7804        emitcode("mov", "b,#0x%02x",
7805                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7806   }
7807   else
7808   {
7809         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7810         emitcode ("inc", "b");
7811   }
7812   freeAsmop (right, NULL, ic, TRUE);
7813   aopOp (left, ic, FALSE, FALSE);
7814   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7815
7816   /* now move the left to the result if they are not the
7817      same */
7818   if (!sameRegs (AOP (left), AOP (result)) &&
7819       AOP_SIZE (result) > 1)
7820     {
7821
7822       size = AOP_SIZE (result);
7823       offset = 0;
7824       _startLazyDPSEvaluation ();
7825       while (size--)
7826         {
7827           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7828           if (*l == '@' && (IS_AOP_PREG (result)))
7829             {
7830
7831               emitcode ("mov", "a,%s", l);
7832               aopPut (AOP (result), "a", offset);
7833             }
7834           else
7835             aopPut (AOP (result), l, offset);
7836           offset++;
7837         }
7838       _endLazyDPSEvaluation ();
7839     }
7840
7841   tlbl = newiTempLabel (NULL);
7842   size = AOP_SIZE (result);
7843   offset = 0;
7844   tlbl1 = newiTempLabel (NULL);
7845
7846   /* if it is only one byte then */
7847   if (size == 1)
7848     {
7849       symbol *tlbl1 = newiTempLabel (NULL);
7850
7851       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7852       MOVA (l);
7853       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7854       emitcode ("", "%05d$:", tlbl->key + 100);
7855       emitcode ("add", "a,acc");
7856       emitcode ("", "%05d$:", tlbl1->key + 100);
7857       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7858       aopPut (AOP (result), "a", 0);
7859       goto release;
7860     }
7861
7862   reAdjustPreg (AOP (result));
7863
7864   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7865   emitcode ("", "%05d$:", tlbl->key + 100);
7866   l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7867   MOVA (l);
7868   emitcode ("add", "a,acc");
7869   aopPut (AOP (result), "a", offset++);
7870   _startLazyDPSEvaluation ();
7871   while (--size)
7872     {
7873       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7874       MOVA (l);
7875       emitcode ("rlc", "a");
7876       aopPut (AOP (result), "a", offset++);
7877     }
7878   _endLazyDPSEvaluation ();
7879   reAdjustPreg (AOP (result));
7880
7881   emitcode ("", "%05d$:", tlbl1->key + 100);
7882   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7883 release:
7884   freeAsmop (left, NULL, ic, TRUE);
7885   freeAsmop (result, NULL, ic, TRUE);
7886 }
7887
7888 #ifdef BETTER_LITERAL_SHIFT
7889 /*-----------------------------------------------------------------*/
7890 /* genrshOne - right shift a one byte quantity by known count      */
7891 /*-----------------------------------------------------------------*/
7892 static void
7893 genrshOne (operand * result, operand * left,
7894            int shCount, int sign)
7895 {
7896   D (emitcode (";", "genrshOne"););
7897   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7898 }
7899 #endif
7900
7901 #ifdef BETTER_LITERAL_SHIFT
7902 /*-----------------------------------------------------------------*/
7903 /* genrshTwo - right shift two bytes by known amount != 0          */
7904 /*-----------------------------------------------------------------*/
7905 static void
7906 genrshTwo (operand * result, operand * left,
7907            int shCount, int sign)
7908 {
7909   D (emitcode (";", "genrshTwo"););
7910
7911   /* if shCount >= 8 */
7912   if (shCount >= 8)
7913     {
7914       shCount -= 8;
7915       _startLazyDPSEvaluation();
7916       if (shCount)
7917       {
7918         shiftR1Left2Result (left, MSB16, result, LSB,
7919                             shCount, sign);
7920       }                     
7921       else
7922       {
7923         movLeft2Result (left, MSB16, result, LSB, sign);
7924       }
7925       addSign (result, MSB16, sign);
7926       _endLazyDPSEvaluation();
7927     }
7928
7929   /*  1 <= shCount <= 7 */
7930   else
7931   {
7932     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7933   }
7934 }
7935 #endif
7936
7937 #if 0
7938 //REMOVE ME!!!
7939 /*-----------------------------------------------------------------*/
7940 /* shiftRLong - shift right one long from left to result           */
7941 /* offl = LSB or MSB16                                             */
7942 /*-----------------------------------------------------------------*/
7943 static void
7944 shiftRLong (operand * left, int offl,
7945             operand * result, int sign)
7946 {
7947   int isSameRegs=sameRegs(AOP(left),AOP(result));
7948
7949   if (isSameRegs && offl>1) {
7950     // we are in big trouble, but this shouldn't happen
7951     werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
7952   }
7953
7954   MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7955   
7956   if (offl==MSB16) {
7957     // shift is > 8
7958     if (sign) {
7959       emitcode ("rlc", "a");
7960       emitcode ("subb", "a,acc");
7961       emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
7962     } else {
7963       aopPut (AOP(result), zero, MSB32);
7964     }
7965   }
7966
7967   if (!sign) {
7968     emitcode ("clr", "c");
7969   } else {
7970     emitcode ("mov", "c,acc.7");
7971   }
7972
7973   emitcode ("rrc", "a");
7974
7975   if (isSameRegs && offl==MSB16) {
7976     emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
7977   } else {
7978     aopPut (AOP (result), "a", MSB32);
7979     MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
7980   }
7981
7982   emitcode ("rrc", "a");
7983   if (isSameRegs && offl==1) {
7984     emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
7985   } else {
7986     aopPut (AOP (result), "a", MSB24);
7987     MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
7988   }
7989   emitcode ("rrc", "a");
7990   aopPut (AOP (result), "a", MSB16 - offl);
7991
7992   if (offl == LSB)
7993     {
7994       MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
7995       emitcode ("rrc", "a");
7996       aopPut (AOP (result), "a", LSB);
7997     }
7998 }
7999 #endif
8000
8001 #if 0
8002 //REMOVE ME!!!
8003 /*-----------------------------------------------------------------*/
8004 /* genrshFour - shift four byte by a known amount != 0             */
8005 /*-----------------------------------------------------------------*/
8006 static void
8007 genrshFour (operand * result, operand * left,
8008             int shCount, int sign)
8009 {
8010   D (emitcode (";", "genrshFour");
8011     );
8012
8013   /* if shifting more that 3 bytes */
8014   if (shCount >= 24)
8015     {
8016       shCount -= 24;
8017       if (shCount)
8018         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8019       else
8020         movLeft2Result (left, MSB32, result, LSB, sign);
8021       addSign (result, MSB16, sign);
8022     }
8023   else if (shCount >= 16)
8024     {
8025       shCount -= 16;
8026       if (shCount)
8027         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8028       else
8029         {
8030           movLeft2Result (left, MSB24, result, LSB, 0);
8031           movLeft2Result (left, MSB32, result, MSB16, sign);
8032         }
8033       addSign (result, MSB24, sign);
8034     }
8035   else if (shCount >= 8)
8036     {
8037       shCount -= 8;
8038       if (shCount == 1)
8039         shiftRLong (left, MSB16, result, sign);
8040       else if (shCount == 0)
8041         {
8042           movLeft2Result (left, MSB16, result, LSB, 0);
8043           movLeft2Result (left, MSB24, result, MSB16, 0);
8044           movLeft2Result (left, MSB32, result, MSB24, sign);
8045           addSign (result, MSB32, sign);
8046         }
8047       else
8048         {
8049           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8050           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8051           /* the last shift is signed */
8052           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8053           addSign (result, MSB32, sign);
8054         }
8055     }
8056   else
8057     {                           /* 1 <= shCount <= 7 */
8058       if (shCount <= 2)
8059         {
8060           shiftRLong (left, LSB, result, sign);
8061           if (shCount == 2)
8062             shiftRLong (result, LSB, result, sign);
8063         }
8064       else
8065         {
8066           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8067           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8068           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8069         }
8070     }
8071 }
8072 #endif
8073
8074 #ifdef BETTER_LITERAL_SHIFT
8075 /*-----------------------------------------------------------------*/
8076 /* genRightShiftLiteral - right shifting by known count            */
8077 /*-----------------------------------------------------------------*/
8078 static bool
8079 genRightShiftLiteral (operand * left,
8080                       operand * right,
8081                       operand * result,
8082                       iCode * ic,
8083                       int sign)
8084 {
8085   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8086   int size;
8087
8088   size = getSize (operandType (result));
8089
8090   D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8091
8092   /* We only handle certain easy cases so far. */
8093   if ((shCount != 0)
8094    && (shCount < (size * 8))
8095    && (size != 1)
8096    && (size != 2))
8097   {
8098       D(emitcode (";", "genRightShiftLiteral wimping out"););   
8099       return FALSE;
8100   }
8101
8102   freeAsmop (right, NULL, ic, TRUE);
8103
8104   aopOp (left, ic, FALSE, FALSE);
8105   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8106
8107 #if VIEW_SIZE
8108   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8109             AOP_SIZE (left));
8110 #endif
8111
8112   /* test the LEFT size !!! */
8113
8114   /* I suppose that the left size >= result size */
8115   if (shCount == 0)
8116   {
8117       size = getDataSize (result);
8118       _startLazyDPSEvaluation();
8119       while (size--)
8120       {
8121         movLeft2Result (left, size, result, size, 0);
8122       }
8123       _endLazyDPSEvaluation();
8124   }
8125   else if (shCount >= (size * 8))
8126     {
8127       if (sign)
8128       {
8129         /* get sign in acc.7 */
8130         MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
8131       }
8132       addSign (result, LSB, sign);
8133     }
8134   else
8135     {
8136       switch (size)
8137         {
8138         case 1:
8139           genrshOne (result, left, shCount, sign);
8140           break;
8141
8142         case 2:
8143           genrshTwo (result, left, shCount, sign);
8144           break;
8145 #if 0
8146         case 4:
8147           genrshFour (result, left, shCount, sign);
8148           break;
8149 #endif    
8150         default:
8151           break;
8152         }
8153
8154       freeAsmop (left, NULL, ic, TRUE);
8155       freeAsmop (result, NULL, ic, TRUE);
8156     }
8157     return TRUE;
8158 }
8159 #endif
8160
8161 /*-----------------------------------------------------------------*/
8162 /* genSignedRightShift - right shift of signed number              */
8163 /*-----------------------------------------------------------------*/
8164 static void
8165 genSignedRightShift (iCode * ic)
8166 {
8167   operand *right, *left, *result;
8168   int size, offset;
8169   char *l;
8170   symbol *tlbl, *tlbl1;
8171
8172   D (emitcode (";", "genSignedRightShift "););
8173
8174   /* we do it the hard way put the shift count in b
8175      and loop thru preserving the sign */
8176
8177   right = IC_RIGHT (ic);
8178   left = IC_LEFT (ic);
8179   result = IC_RESULT (ic);
8180
8181   aopOp (right, ic, FALSE, FALSE);
8182
8183 #ifdef BETTER_LITERAL_SHIFT
8184   if (AOP_TYPE (right) == AOP_LIT)
8185     {
8186       if (genRightShiftLiteral (left, right, result, ic, 1))
8187       {
8188         return;
8189       }
8190     }
8191 #endif
8192   /* shift count is unknown then we have to form
8193      a loop get the loop count in B : Note: we take
8194      only the lower order byte since shifting
8195      more that 32 bits make no sense anyway, ( the
8196      largest size of an object can be only 32 bits ) */
8197
8198   if (AOP_TYPE (right) == AOP_LIT)
8199   {
8200       /* Really should be handled by genRightShiftLiteral,
8201        * but since I'm too lazy to fix that today, at least we can make
8202        * some small improvement.
8203        */
8204        emitcode("mov", "b,#0x%02x",
8205                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8206   }
8207   else
8208   {
8209         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8210         emitcode ("inc", "b");
8211   }
8212   freeAsmop (right, NULL, ic, TRUE);
8213   aopOp (left, ic, FALSE, FALSE);
8214   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8215
8216   /* now move the left to the result if they are not the
8217      same */
8218   if (!sameRegs (AOP (left), AOP (result)) &&
8219       AOP_SIZE (result) > 1)
8220     {
8221
8222       size = AOP_SIZE (result);
8223       offset = 0;
8224       _startLazyDPSEvaluation ();
8225       while (size--)
8226         {
8227           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8228           if (*l == '@' && IS_AOP_PREG (result))
8229             {
8230
8231               emitcode ("mov", "a,%s", l);
8232               aopPut (AOP (result), "a", offset);
8233             }
8234           else
8235             aopPut (AOP (result), l, offset);
8236           offset++;
8237         }
8238       _endLazyDPSEvaluation ();
8239     }
8240
8241   /* mov the highest order bit to OVR */
8242   tlbl = newiTempLabel (NULL);
8243   tlbl1 = newiTempLabel (NULL);
8244
8245   size = AOP_SIZE (result);
8246   offset = size - 1;
8247   emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
8248   emitcode ("rlc", "a");
8249   emitcode ("mov", "ov,c");
8250   /* if it is only one byte then */
8251   if (size == 1)
8252     {
8253       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8254       MOVA (l);
8255       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8256       emitcode ("", "%05d$:", tlbl->key + 100);
8257       emitcode ("mov", "c,ov");
8258       emitcode ("rrc", "a");
8259       emitcode ("", "%05d$:", tlbl1->key + 100);
8260       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8261       aopPut (AOP (result), "a", 0);
8262       goto release;
8263     }
8264
8265   reAdjustPreg (AOP (result));
8266   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8267   emitcode ("", "%05d$:", tlbl->key + 100);
8268   emitcode ("mov", "c,ov");
8269   _startLazyDPSEvaluation ();
8270   while (size--)
8271     {
8272       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8273       MOVA (l);
8274       emitcode ("rrc", "a");
8275       aopPut (AOP (result), "a", offset--);
8276     }
8277   _endLazyDPSEvaluation ();
8278   reAdjustPreg (AOP (result));
8279   emitcode ("", "%05d$:", tlbl1->key + 100);
8280   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8281
8282 release:
8283   freeAsmop (left, NULL, ic, TRUE);
8284   freeAsmop (result, NULL, ic, TRUE);
8285 }
8286
8287 /*-----------------------------------------------------------------*/
8288 /* genRightShift - generate code for right shifting                */
8289 /*-----------------------------------------------------------------*/
8290 static void
8291 genRightShift (iCode * ic)
8292 {
8293   operand *right, *left, *result;
8294   sym_link *retype;
8295   int size, offset;
8296   char *l;
8297   symbol *tlbl, *tlbl1;
8298
8299   D (emitcode (";", "genRightShift "););
8300
8301   /* if signed then we do it the hard way preserve the
8302      sign bit moving it inwards */
8303   retype = getSpec (operandType (IC_RESULT (ic)));
8304
8305   if (!SPEC_USIGN (retype))
8306     {
8307       genSignedRightShift (ic);
8308       return;
8309     }
8310
8311   /* signed & unsigned types are treated the same : i.e. the
8312      signed is NOT propagated inwards : quoting from the
8313      ANSI - standard : "for E1 >> E2, is equivalent to division
8314      by 2**E2 if unsigned or if it has a non-negative value,
8315      otherwise the result is implementation defined ", MY definition
8316      is that the sign does not get propagated */
8317
8318   right = IC_RIGHT (ic);
8319   left = IC_LEFT (ic);
8320   result = IC_RESULT (ic);
8321
8322   aopOp (right, ic, FALSE, FALSE);
8323
8324 #ifdef BETTER_LITERAL_SHIFT
8325   /* if the shift count is known then do it
8326      as efficiently as possible */
8327   if (AOP_TYPE (right) == AOP_LIT)
8328     {
8329       if (genRightShiftLiteral (left, right, result, ic, 0))
8330       {
8331         return;
8332       }
8333     }
8334 #endif
8335
8336   /* shift count is unknown then we have to form
8337      a loop get the loop count in B : Note: we take
8338      only the lower order byte since shifting
8339      more that 32 bits make no sense anyway, ( the
8340      largest size of an object can be only 32 bits ) */
8341   
8342   if (AOP_TYPE (right) == AOP_LIT)
8343   {
8344       /* Really should be handled by genRightShiftLiteral,
8345        * but since I'm too lazy to fix that today, at least we can make
8346        * some small improvement.
8347        */
8348        emitcode("mov", "b,#0x%02x",
8349                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8350   }
8351   else
8352   {
8353         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8354         emitcode ("inc", "b");
8355   }
8356   freeAsmop (right, NULL, ic, TRUE);
8357   aopOp (left, ic, FALSE, FALSE);
8358   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8359
8360   /* now move the left to the result if they are not the
8361      same */
8362   if (!sameRegs (AOP (left), AOP (result)) &&
8363       AOP_SIZE (result) > 1)
8364     {
8365
8366       size = AOP_SIZE (result);
8367       offset = 0;
8368       _startLazyDPSEvaluation ();
8369       while (size--)
8370         {
8371           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8372           if (*l == '@' && IS_AOP_PREG (result))
8373             {
8374
8375               emitcode ("mov", "a,%s", l);
8376               aopPut (AOP (result), "a", offset);
8377             }
8378           else
8379             aopPut (AOP (result), l, offset);
8380           offset++;
8381         }
8382       _endLazyDPSEvaluation ();
8383     }
8384
8385   tlbl = newiTempLabel (NULL);
8386   tlbl1 = newiTempLabel (NULL);
8387   size = AOP_SIZE (result);
8388   offset = size - 1;
8389
8390   /* if it is only one byte then */
8391   if (size == 1)
8392     {
8393       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8394       MOVA (l);
8395       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8396       emitcode ("", "%05d$:", tlbl->key + 100);
8397       CLRC;
8398       emitcode ("rrc", "a");
8399       emitcode ("", "%05d$:", tlbl1->key + 100);
8400       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8401       aopPut (AOP (result), "a", 0);
8402       goto release;
8403     }
8404
8405   reAdjustPreg (AOP (result));
8406   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8407   emitcode ("", "%05d$:", tlbl->key + 100);
8408   CLRC;
8409   _startLazyDPSEvaluation ();
8410   while (size--)
8411     {
8412       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8413       MOVA (l);
8414       emitcode ("rrc", "a");
8415       aopPut (AOP (result), "a", offset--);
8416     }
8417   _endLazyDPSEvaluation ();
8418   reAdjustPreg (AOP (result));
8419
8420   emitcode ("", "%05d$:", tlbl1->key + 100);
8421   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8422
8423 release:
8424   freeAsmop (left, NULL, ic, TRUE);
8425   freeAsmop (result, NULL, ic, TRUE);
8426 }
8427
8428 /*-----------------------------------------------------------------*/
8429 /* genUnpackBits - generates code for unpacking bits               */
8430 /*-----------------------------------------------------------------*/
8431 static void
8432 genUnpackBits (operand * result, char *rname, int ptype)
8433 {
8434   int shCnt;
8435   int rlen = 0;
8436   sym_link *etype;
8437   int offset = 0;
8438
8439   D (emitcode (";", "genUnpackBits ");
8440     );
8441
8442   etype = getSpec (operandType (result));
8443
8444   /* read the first byte  */
8445   switch (ptype)
8446     {
8447
8448     case POINTER:
8449     case IPOINTER:
8450       emitcode ("mov", "a,@%s", rname);
8451       break;
8452
8453     case PPOINTER:
8454       emitcode ("movx", "a,@%s", rname);
8455       break;
8456
8457     case FPOINTER:
8458       emitcode ("movx", "a,@dptr");
8459       break;
8460
8461     case CPOINTER:
8462       emitcode ("clr", "a");
8463       emitcode ("movc", "a,@a+dptr");
8464       break;
8465
8466     case GPOINTER:
8467       emitcode ("lcall", "__gptrget");
8468       break;
8469     }
8470
8471   /* if we have bitdisplacement then it fits   */
8472   /* into this byte completely or if length is */
8473   /* less than a byte                          */
8474   if ((shCnt = SPEC_BSTR (etype)) ||
8475       (SPEC_BLEN (etype) <= 8))
8476     {
8477
8478       /* shift right acc */
8479       AccRsh (shCnt);
8480
8481       emitcode ("anl", "a,#0x%02x",
8482                 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
8483       aopPut (AOP (result), "a", offset);
8484       return;
8485     }
8486
8487   /* bit field did not fit in a byte  */
8488   rlen = SPEC_BLEN (etype) - 8;
8489   aopPut (AOP (result), "a", offset++);
8490
8491   while (1)
8492     {
8493
8494       switch (ptype)
8495         {
8496         case POINTER:
8497         case IPOINTER:
8498           emitcode ("inc", "%s", rname);
8499           emitcode ("mov", "a,@%s", rname);
8500           break;
8501
8502         case PPOINTER:
8503           emitcode ("inc", "%s", rname);
8504           emitcode ("movx", "a,@%s", rname);
8505           break;
8506
8507         case FPOINTER:
8508           emitcode ("inc", "dptr");
8509           emitcode ("movx", "a,@dptr");
8510           break;
8511
8512         case CPOINTER:
8513           emitcode ("clr", "a");
8514           emitcode ("inc", "dptr");
8515           emitcode ("movc", "a,@a+dptr");
8516           break;
8517
8518         case GPOINTER:
8519           emitcode ("inc", "dptr");
8520           emitcode ("lcall", "__gptrget");
8521           break;
8522         }
8523
8524       rlen -= 8;
8525       /* if we are done */
8526       if (rlen < 8)
8527         break;
8528
8529       aopPut (AOP (result), "a", offset++);
8530
8531     }
8532
8533   if (rlen)
8534     {
8535       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
8536       aopPut (AOP (result), "a", offset);
8537     }
8538
8539   return;
8540 }
8541
8542
8543 /*-----------------------------------------------------------------*/
8544 /* genDataPointerGet - generates code when ptr offset is known     */
8545 /*-----------------------------------------------------------------*/
8546 static void
8547 genDataPointerGet (operand * left,
8548                    operand * result,
8549                    iCode * ic)
8550 {
8551   char *l;
8552   char buffer[256];
8553   int size, offset = 0;
8554   aopOp (result, ic, TRUE, FALSE);
8555
8556   /* get the string representation of the name */
8557   l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
8558   size = AOP_SIZE (result);
8559   _startLazyDPSEvaluation ();
8560   while (size--)
8561     {
8562       if (offset)
8563         sprintf (buffer, "(%s + %d)", l + 1, offset);
8564       else
8565         sprintf (buffer, "%s", l + 1);
8566       aopPut (AOP (result), buffer, offset++);
8567     }
8568   _endLazyDPSEvaluation ();
8569
8570   freeAsmop (left, NULL, ic, TRUE);
8571   freeAsmop (result, NULL, ic, TRUE);
8572 }
8573
8574 /*-----------------------------------------------------------------*/
8575 /* genNearPointerGet - emitcode for near pointer fetch             */
8576 /*-----------------------------------------------------------------*/
8577 static void
8578 genNearPointerGet (operand * left,
8579                    operand * result,
8580                    iCode * ic,
8581                    iCode *pi)
8582 {
8583   asmop *aop = NULL;
8584   regs *preg = NULL;
8585   char *rname;
8586   sym_link *rtype, *retype, *letype;
8587   sym_link *ltype = operandType (left);
8588   char buffer[80];
8589
8590   rtype = operandType (result);
8591   retype = getSpec (rtype);
8592   letype = getSpec (ltype);
8593
8594   aopOp (left, ic, FALSE, FALSE);
8595
8596   /* if left is rematerialisable and
8597      result is not bit variable type and
8598      the left is pointer to data space i.e
8599      lower 128 bytes of space */
8600   if (AOP_TYPE (left) == AOP_IMMD &&
8601       !IS_BITVAR (retype) &&
8602       !IS_BITVAR (letype) &&
8603       DCL_TYPE (ltype) == POINTER)
8604     {
8605       genDataPointerGet (left, result, ic);
8606       return;
8607     }
8608
8609   /* if the value is already in a pointer register
8610      then don't need anything more */
8611   if (!AOP_INPREG (AOP (left)))
8612     {
8613       /* otherwise get a free pointer register */
8614       aop = newAsmop (0);
8615       preg = getFreePtr (ic, &aop, FALSE);
8616       emitcode ("mov", "%s,%s",
8617                 preg->name,
8618                 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8619       rname = preg->name;
8620     }
8621   else
8622     rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8623
8624   freeAsmop (left, NULL, ic, TRUE);
8625   aopOp (result, ic, FALSE, FALSE);
8626
8627   /* if bitfield then unpack the bits */
8628   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8629     genUnpackBits (result, rname, POINTER);
8630   else
8631     {
8632       /* we have can just get the values */
8633       int size = AOP_SIZE (result);
8634       int offset = 0;
8635
8636       while (size--)
8637         {
8638           if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8639             {
8640
8641               emitcode ("mov", "a,@%s", rname);
8642               aopPut (AOP (result), "a", offset);
8643             }
8644           else
8645             {
8646               sprintf (buffer, "@%s", rname);
8647               aopPut (AOP (result), buffer, offset);
8648             }
8649           offset++;
8650           if (size || pi)
8651             emitcode ("inc", "%s", rname);
8652         }
8653     }
8654
8655   /* now some housekeeping stuff */
8656   if (aop)
8657     {
8658       /* we had to allocate for this iCode */
8659       if (pi) { /* post increment present */
8660         aopPut(AOP ( left ),rname,0);
8661       }
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           !pi)
8676         {
8677           int size = AOP_SIZE (result) - 1;
8678           while (size--)
8679             emitcode ("dec", "%s", rname);
8680         }
8681     }
8682
8683   /* done */
8684   freeAsmop (result, NULL, ic, TRUE);
8685   if (pi) pi->generated = 1;
8686 }
8687
8688 /*-----------------------------------------------------------------*/
8689 /* genPagedPointerGet - emitcode for paged pointer fetch           */
8690 /*-----------------------------------------------------------------*/
8691 static void
8692 genPagedPointerGet (operand * left,
8693                     operand * result,
8694                     iCode * ic,
8695                     iCode * pi)
8696 {
8697   asmop *aop = NULL;
8698   regs *preg = NULL;
8699   char *rname;
8700   sym_link *rtype, *retype, *letype;
8701
8702   rtype = operandType (result);
8703   retype = getSpec (rtype);
8704   letype = getSpec (operandType (left));
8705   aopOp (left, ic, FALSE, FALSE);
8706
8707   /* if the value is already in a pointer register
8708      then don't need anything more */
8709   if (!AOP_INPREG (AOP (left)))
8710     {
8711       /* otherwise get a free pointer register */
8712       aop = newAsmop (0);
8713       preg = getFreePtr (ic, &aop, FALSE);
8714       emitcode ("mov", "%s,%s",
8715                 preg->name,
8716                 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8717       rname = preg->name;
8718     }
8719   else
8720     rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8721
8722   freeAsmop (left, NULL, ic, TRUE);
8723   aopOp (result, ic, FALSE, FALSE);
8724
8725   /* if bitfield then unpack the bits */
8726   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8727     genUnpackBits (result, rname, PPOINTER);
8728   else
8729     {
8730       /* we have can just get the values */
8731       int size = AOP_SIZE (result);
8732       int offset = 0;
8733
8734       while (size--)
8735         {
8736
8737           emitcode ("movx", "a,@%s", rname);
8738           aopPut (AOP (result), "a", offset);
8739
8740           offset++;
8741
8742           if (size || pi)
8743             emitcode ("inc", "%s", rname);
8744         }
8745     }
8746
8747   /* now some housekeeping stuff */
8748   if (aop)
8749     {
8750       /* we had to allocate for this iCode */
8751       if (pi) aopPut ( AOP (left), rname, 0);
8752       freeAsmop (NULL, aop, ic, TRUE);
8753     }
8754   else
8755     {
8756       /* we did not allocate which means left
8757          already in a pointer register, then
8758          if size > 0 && this could be used again
8759          we have to point it back to where it
8760          belongs */
8761       if (AOP_SIZE (result) > 1 &&
8762           !OP_SYMBOL (left)->remat &&
8763           (OP_SYMBOL (left)->liveTo > ic->seq ||
8764            ic->depth) &&
8765           !pi)
8766         {
8767           int size = AOP_SIZE (result) - 1;
8768           while (size--)
8769             emitcode ("dec", "%s", rname);
8770         }
8771     }
8772
8773   /* done */
8774   freeAsmop (result, NULL, ic, TRUE);
8775   if (pi) pi->generated = 1;
8776 }
8777
8778 /*-----------------------------------------------------------------*/
8779 /* genFarPointerGet - gget value from far space                    */
8780 /*-----------------------------------------------------------------*/
8781 static void
8782 genFarPointerGet (operand * left,
8783                   operand * result, iCode * ic, iCode *pi)
8784 {
8785   int size, offset;
8786   sym_link *retype = getSpec (operandType (result));
8787   sym_link *letype = getSpec (operandType (left));
8788   D (emitcode (";", "genFarPointerGet");
8789     );
8790
8791   aopOp (left, ic, FALSE, FALSE);
8792
8793   /* if the operand is already in dptr
8794      then we do nothing else we move the value to dptr */
8795   if (AOP_TYPE (left) != AOP_STR)
8796     {
8797       /* if this is remateriazable */
8798       if (AOP_TYPE (left) == AOP_IMMD)
8799         {
8800           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8801         }
8802       else
8803         {
8804           /* we need to get it byte by byte */
8805           _startLazyDPSEvaluation ();
8806           if (AOP_TYPE (left) != AOP_DPTR)
8807             {
8808               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8809               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8810               if (options.model == MODEL_FLAT24)
8811                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8812             }
8813           else
8814             {
8815               /* We need to generate a load to DPTR indirect through DPTR. */
8816               D (emitcode (";", "genFarPointerGet -- indirection special case.");
8817                 );
8818               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8819               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8820               if (options.model == MODEL_FLAT24)
8821                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8822               emitcode ("pop", "dph");
8823               emitcode ("pop", "dpl");
8824             }
8825           _endLazyDPSEvaluation ();
8826         }
8827     }
8828   /* so dptr know contains the address */
8829   freeAsmop (left, NULL, ic, TRUE);
8830   aopOp (result, ic, FALSE, TRUE);
8831
8832   /* if bit then unpack */
8833   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8834     genUnpackBits (result, "dptr", FPOINTER);
8835   else
8836     {
8837       size = AOP_SIZE (result);
8838       offset = 0;
8839
8840       _startLazyDPSEvaluation ();
8841       while (size--)
8842         {
8843
8844           genSetDPTR (0);
8845           _flushLazyDPS ();
8846
8847           emitcode ("movx", "a,@dptr");
8848           if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
8849             emitcode ("inc", "dptr");
8850
8851           aopPut (AOP (result), "a", offset++);
8852         }
8853       _endLazyDPSEvaluation ();
8854     }
8855   if (pi && AOP_TYPE (left) != AOP_IMMD) {
8856     aopPut ( AOP (left), "dpl", 0);
8857     aopPut ( AOP (left), "dph", 1);
8858     if (options.model == MODEL_FLAT24)
8859             aopPut ( AOP (left), "dpx", 2);
8860     pi->generated = 1;
8861   }
8862
8863   freeAsmop (result, NULL, ic, TRUE);
8864 }
8865
8866 /*-----------------------------------------------------------------*/
8867 /* emitcodePointerGet - gget value from code space                  */
8868 /*-----------------------------------------------------------------*/
8869 static void
8870 emitcodePointerGet (operand * left,
8871                     operand * result, iCode * ic, iCode *pi)
8872 {
8873   int size, offset;
8874   sym_link *retype = getSpec (operandType (result));
8875
8876   aopOp (left, ic, FALSE, FALSE);
8877
8878   /* if the operand is already in dptr
8879      then we do nothing else we move the value to dptr */
8880   if (AOP_TYPE (left) != AOP_STR)
8881     {
8882       /* if this is remateriazable */
8883       if (AOP_TYPE (left) == AOP_IMMD)
8884         {
8885           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8886         }
8887       else
8888         {                       /* we need to get it byte by byte */
8889           _startLazyDPSEvaluation ();
8890           if (AOP_TYPE (left) != AOP_DPTR)
8891             {
8892               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8893               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8894               if (options.model == MODEL_FLAT24)
8895                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8896             }
8897           else
8898             {
8899               /* We need to generate a load to DPTR indirect through DPTR. */
8900               D (emitcode (";", "gencodePointerGet -- indirection special case.");
8901                 );
8902               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8903               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8904               if (options.model == MODEL_FLAT24)
8905                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8906               emitcode ("pop", "dph");
8907               emitcode ("pop", "dpl");
8908             }
8909           _endLazyDPSEvaluation ();
8910         }
8911     }
8912   /* so dptr know contains the address */
8913   aopOp (result, ic, FALSE, TRUE);
8914
8915   /* if bit then unpack */
8916   if (IS_BITVAR (retype))
8917     genUnpackBits (result, "dptr", CPOINTER);
8918   else
8919     {
8920       size = AOP_SIZE (result);
8921       offset = 0;
8922
8923       _startLazyDPSEvaluation ();
8924       while (size--)
8925         {
8926           genSetDPTR (0);
8927           _flushLazyDPS ();
8928
8929           emitcode ("clr", "a");
8930           emitcode ("movc", "a,@a+dptr");
8931           if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
8932             emitcode ("inc", "dptr");
8933           aopPut (AOP (result), "a", offset++);
8934         }
8935       _endLazyDPSEvaluation ();
8936     }
8937   if (pi && AOP_TYPE (left) != AOP_IMMD) {
8938     aopPut ( AOP (left), "dpl", 0);
8939     aopPut ( AOP (left), "dph", 1);
8940     if (options.model == MODEL_FLAT24)
8941             aopPut ( AOP (left), "dpx", 2);
8942     pi->generated = 1;
8943   }
8944
8945   freeAsmop (left, NULL, ic, TRUE);
8946   freeAsmop (result, NULL, ic, TRUE);
8947 }
8948
8949 /*-----------------------------------------------------------------*/
8950 /* genGenPointerGet - gget value from generic pointer space        */
8951 /*-----------------------------------------------------------------*/
8952 static void
8953 genGenPointerGet (operand * left,
8954                   operand * result, iCode * ic, iCode * pi)
8955 {
8956   int size, offset;
8957   sym_link *retype = getSpec (operandType (result));
8958   sym_link *letype = getSpec (operandType (left));
8959
8960   D (emitcode (";", "genGenPointerGet "); );
8961
8962   aopOp (left, ic, FALSE, (OP_SYMBOL(left)->ruonly ? FALSE : TRUE));
8963
8964   /* if the operand is already in dptr
8965      then we do nothing else we move the value to dptr */
8966   if (AOP_TYPE (left) != AOP_STR)
8967     {
8968       /* if this is remateriazable */
8969       if (AOP_TYPE (left) == AOP_IMMD)
8970         {
8971           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8972           if (AOP(left)->aopu.aop_immd.from_cast_remat) 
8973                   emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, FALSE));
8974           else
8975                   emitcode ("mov", "b,#%d", pointerCode (retype));
8976         }
8977       else
8978         {                       /* we need to get it byte by byte */
8979           _startLazyDPSEvaluation ();
8980           if (AOP(left)->type==AOP_DPTR2) {
8981             char *l;
8982             l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
8983             genSetDPTR(0);
8984             _flushLazyDPS();
8985             emitcode ("mov", "dpl,%s", l);
8986             l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
8987             genSetDPTR(0);
8988             _flushLazyDPS();
8989             emitcode ("mov", "dph,%s", l);
8990             if (options.model == MODEL_FLAT24) {
8991               l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
8992               genSetDPTR(0);
8993               _flushLazyDPS();
8994               emitcode ("mov", "dpx,%s", l);
8995               emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8996             } else {
8997               emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8998             }
8999           } else {
9000             emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
9001             emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
9002             if (options.model == MODEL_FLAT24) {
9003               emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9004               emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
9005             } else {
9006               emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9007             }
9008           }
9009           _endLazyDPSEvaluation ();
9010         }
9011     }
9012   /* so dptr know contains the address */
9013   aopOp (result, ic, FALSE, TRUE);
9014
9015   /* if bit then unpack */
9016   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9017     genUnpackBits (result, "dptr", GPOINTER);
9018   else
9019     {
9020       size = AOP_SIZE (result);
9021       offset = 0;
9022
9023       while (size--)
9024         {
9025           emitcode ("lcall", "__gptrget");
9026           aopPut (AOP (result), "a", offset++);
9027           if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9028             emitcode ("inc", "dptr");
9029         }
9030     }
9031
9032   if (pi && AOP_TYPE (left) != AOP_IMMD) {
9033     aopPut ( AOP (left), "dpl", 0);
9034     aopPut ( AOP (left), "dph", 1);
9035     if (options.model == MODEL_FLAT24) {
9036             aopPut ( AOP (left), "dpx", 2);
9037             aopPut ( AOP (left), "b", 3);       
9038     } else  aopPut ( AOP (left), "b", 2);       
9039     pi->generated = 1;
9040   }
9041   freeAsmop (left, NULL, ic, TRUE);
9042   freeAsmop (result, NULL, ic, TRUE);
9043 }
9044
9045 /*-----------------------------------------------------------------*/
9046 /* genPointerGet - generate code for pointer get                   */
9047 /*-----------------------------------------------------------------*/
9048 static void
9049 genPointerGet (iCode * ic, iCode *pi)
9050 {
9051   operand *left, *result;
9052   sym_link *type, *etype;
9053   int p_type;
9054
9055   D (emitcode (";", "genPointerGet ");
9056     );
9057
9058   left = IC_LEFT (ic);
9059   result = IC_RESULT (ic);
9060
9061   /* depending on the type of pointer we need to
9062      move it to the correct pointer register */
9063   type = operandType (left);
9064   etype = getSpec (type);
9065   /* if left is of type of pointer then it is simple */
9066   if (IS_PTR (type) && !IS_FUNC (type->next))
9067     p_type = DCL_TYPE (type);
9068   else
9069     {
9070       /* we have to go by the storage class */
9071       p_type = PTR_TYPE (SPEC_OCLS (etype));
9072     }
9073   /* special case when cast remat */
9074   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9075       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9076           left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9077           type =   type = operandType (left);
9078           p_type = DCL_TYPE (type);
9079   }
9080   /* now that we have the pointer type we assign
9081      the pointer values */
9082   switch (p_type)
9083     {
9084
9085     case POINTER:
9086     case IPOINTER:
9087       genNearPointerGet (left, result, ic, pi);
9088       break;
9089
9090     case PPOINTER:
9091       genPagedPointerGet (left, result, ic, pi);
9092       break;
9093
9094     case FPOINTER:
9095       genFarPointerGet (left, result, ic, pi);
9096       break;
9097
9098     case CPOINTER:
9099       emitcodePointerGet (left, result, ic, pi);
9100       break;
9101
9102     case GPOINTER:
9103       genGenPointerGet (left, result, ic, pi);
9104       break;
9105     }
9106
9107 }
9108
9109 /*-----------------------------------------------------------------*/
9110 /* genPackBits - generates code for packed bit storage             */
9111 /*-----------------------------------------------------------------*/
9112 static void
9113 genPackBits (sym_link * etype,
9114              operand * right,
9115              char *rname, int p_type)
9116 {
9117   int shCount = 0;
9118   int offset = 0;
9119   int rLen = 0;
9120   int blen, bstr;
9121   char *l;
9122
9123   blen = SPEC_BLEN (etype);
9124   bstr = SPEC_BSTR (etype);
9125
9126   l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9127   MOVA (l);
9128
9129   /* if the bit lenth is less than or    */
9130   /* it exactly fits a byte then         */
9131   if (SPEC_BLEN (etype) <= 8)
9132     {
9133       shCount = SPEC_BSTR (etype);
9134
9135       /* shift left acc */
9136       AccLsh (shCount);
9137
9138       if (SPEC_BLEN (etype) < 8)
9139         {                       /* if smaller than a byte */
9140
9141
9142           switch (p_type)
9143             {
9144             case POINTER:
9145               emitcode ("mov", "b,a");
9146               emitcode ("mov", "a,@%s", rname);
9147               break;
9148
9149             case FPOINTER:
9150               emitcode ("mov", "b,a");
9151               emitcode ("movx", "a,@dptr");
9152               break;
9153
9154             case GPOINTER:
9155               emitcode ("push", "b");
9156               emitcode ("push", "acc");
9157               emitcode ("lcall", "__gptrget");
9158               emitcode ("pop", "b");
9159               break;
9160             }
9161
9162           emitcode ("anl", "a,#0x%02x", (unsigned char)
9163                     ((unsigned char) (0xFF << (blen + bstr)) |
9164                      (unsigned char) (0xFF >> (8 - bstr))));
9165           emitcode ("orl", "a,b");
9166           if (p_type == GPOINTER)
9167             emitcode ("pop", "b");
9168         }
9169     }
9170
9171   switch (p_type)
9172     {
9173     case POINTER:
9174       emitcode ("mov", "@%s,a", rname);
9175       break;
9176
9177     case FPOINTER:
9178       emitcode ("movx", "@dptr,a");
9179       break;
9180
9181     case GPOINTER:
9182       emitcode ("lcall", "__gptrput");
9183       break;
9184     }
9185
9186   /* if we r done */
9187   if (SPEC_BLEN (etype) <= 8)
9188     return;
9189
9190   emitcode ("inc", "%s", rname);
9191   rLen = SPEC_BLEN (etype);
9192
9193   /* now generate for lengths greater than one byte */
9194   while (1)
9195     {
9196
9197       l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
9198
9199       rLen -= 8;
9200       if (rLen < 8)
9201         break;
9202
9203       switch (p_type)
9204         {
9205         case POINTER:
9206           if (*l == '@')
9207             {
9208               MOVA (l);
9209               emitcode ("mov", "@%s,a", rname);
9210             }
9211           else
9212             emitcode ("mov", "@%s,%s", rname, l);
9213           break;
9214
9215         case FPOINTER:
9216           MOVA (l);
9217           emitcode ("movx", "@dptr,a");
9218           break;
9219
9220         case GPOINTER:
9221           MOVA (l);
9222           emitcode ("lcall", "__gptrput");
9223           break;
9224         }
9225       emitcode ("inc", "%s", rname);
9226     }
9227
9228   MOVA (l);
9229
9230   /* last last was not complete */
9231   if (rLen)
9232     {
9233       /* save the byte & read byte */
9234       switch (p_type)
9235         {
9236         case POINTER:
9237           emitcode ("mov", "b,a");
9238           emitcode ("mov", "a,@%s", rname);
9239           break;
9240
9241         case FPOINTER:
9242           emitcode ("mov", "b,a");
9243           emitcode ("movx", "a,@dptr");
9244           break;
9245
9246         case GPOINTER:
9247           emitcode ("push", "b");
9248           emitcode ("push", "acc");
9249           emitcode ("lcall", "__gptrget");
9250           emitcode ("pop", "b");
9251           break;
9252         }
9253
9254       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
9255       emitcode ("orl", "a,b");
9256     }
9257
9258   if (p_type == GPOINTER)
9259     emitcode ("pop", "b");
9260
9261   switch (p_type)
9262     {
9263
9264     case POINTER:
9265       emitcode ("mov", "@%s,a", rname);
9266       break;
9267
9268     case FPOINTER:
9269       emitcode ("movx", "@dptr,a");
9270       break;
9271
9272     case GPOINTER:
9273       emitcode ("lcall", "__gptrput");
9274       break;
9275     }
9276 }
9277 /*-----------------------------------------------------------------*/
9278 /* genDataPointerSet - remat pointer to data space                 */
9279 /*-----------------------------------------------------------------*/
9280 static void
9281 genDataPointerSet (operand * right,
9282                    operand * result,
9283                    iCode * ic)
9284 {
9285   int size, offset = 0;
9286   char *l, buffer[256];
9287
9288   aopOp (right, ic, FALSE, FALSE);
9289
9290   l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
9291   size = AOP_SIZE (right);
9292   while (size--)
9293     {
9294       if (offset)
9295         sprintf (buffer, "(%s + %d)", l + 1, offset);
9296       else
9297         sprintf (buffer, "%s", l + 1);
9298       emitcode ("mov", "%s,%s", buffer,
9299                 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
9300     }
9301
9302   freeAsmop (right, NULL, ic, TRUE);
9303   freeAsmop (result, NULL, ic, TRUE);
9304 }
9305
9306 /*-----------------------------------------------------------------*/
9307 /* genNearPointerSet - emitcode for near pointer put                */
9308 /*-----------------------------------------------------------------*/
9309 static void
9310 genNearPointerSet (operand * right,
9311                    operand * result,
9312                    iCode * ic,
9313                    iCode * pi)
9314 {
9315   asmop *aop = NULL;
9316   regs *preg = NULL;
9317   char *rname, *l;
9318   sym_link *retype, *letype;
9319   sym_link *ptype = operandType (result);
9320
9321   retype = getSpec (operandType (right));
9322   letype = getSpec (ptype);
9323
9324   aopOp (result, ic, FALSE, FALSE);
9325
9326   /* if the result is rematerializable &
9327      in data space & not a bit variable */
9328   if (AOP_TYPE (result) == AOP_IMMD &&
9329       DCL_TYPE (ptype) == POINTER &&
9330       !IS_BITVAR (retype) &&
9331       !IS_BITVAR (letype))
9332     {
9333       genDataPointerSet (right, result, ic);
9334       return;
9335     }
9336
9337   /* if the value is already in a pointer register
9338      then don't need anything more */
9339   if (!AOP_INPREG (AOP (result)))
9340     {
9341       /* otherwise get a free pointer register */
9342       aop = newAsmop (0);
9343       preg = getFreePtr (ic, &aop, FALSE);
9344       emitcode ("mov", "%s,%s",
9345                 preg->name,
9346                 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9347       rname = preg->name;
9348     }
9349   else
9350     rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9351
9352   aopOp (right, ic, FALSE, FALSE);
9353
9354   /* if bitfield then unpack the bits */
9355   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9356     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
9357   else
9358     {
9359       /* we have can just get the values */
9360       int size = AOP_SIZE (right);
9361       int offset = 0;
9362
9363       while (size--)
9364         {
9365           l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
9366           if (*l == '@')
9367             {
9368               MOVA (l);
9369               emitcode ("mov", "@%s,a", rname);
9370             }
9371           else
9372             emitcode ("mov", "@%s,%s", rname, l);
9373           if (size || pi)
9374             emitcode ("inc", "%s", rname);
9375           offset++;
9376         }
9377     }
9378
9379   /* now some housekeeping stuff */
9380   if (aop)
9381     {
9382       /* we had to allocate for this iCode */
9383       if (pi) aopPut (AOP (result),rname,0);
9384       freeAsmop (NULL, aop, ic, TRUE);
9385     }
9386   else
9387     {
9388       /* we did not allocate which means left
9389          already in a pointer register, then
9390          if size > 0 && this could be used again
9391          we have to point it back to where it
9392          belongs */
9393       if (AOP_SIZE (right) > 1 &&
9394           !OP_SYMBOL (result)->remat &&
9395           (OP_SYMBOL (result)->liveTo > ic->seq ||
9396            ic->depth) &&
9397           !pi)
9398         {
9399           int size = AOP_SIZE (right) - 1;
9400           while (size--)
9401             emitcode ("dec", "%s", rname);
9402         }
9403     }
9404
9405   /* done */
9406   if (pi) pi->generated = 1;
9407   freeAsmop (result, NULL, ic, TRUE);
9408   freeAsmop (right, NULL, ic, TRUE);
9409
9410
9411 }
9412
9413 /*-----------------------------------------------------------------*/
9414 /* genPagedPointerSet - emitcode for Paged pointer put             */
9415 /*-----------------------------------------------------------------*/
9416 static void
9417 genPagedPointerSet (operand * right,
9418                     operand * result,
9419                     iCode * ic,
9420                     iCode *pi)
9421 {
9422   asmop *aop = NULL;
9423   regs *preg = NULL;
9424   char *rname, *l;
9425   sym_link *retype, *letype;
9426
9427   retype = getSpec (operandType (right));
9428   letype = getSpec (operandType (result));
9429
9430   aopOp (result, ic, FALSE, FALSE);
9431
9432   /* if the value is already in a pointer register
9433      then don't need anything more */
9434   if (!AOP_INPREG (AOP (result)))
9435     {
9436       /* otherwise get a free pointer register */
9437       aop = newAsmop (0);
9438       preg = getFreePtr (ic, &aop, FALSE);
9439       emitcode ("mov", "%s,%s",
9440                 preg->name,
9441                 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9442       rname = preg->name;
9443     }
9444   else
9445     rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9446
9447   aopOp (right, ic, FALSE, FALSE);
9448
9449   /* if bitfield then unpack the bits */
9450   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9451     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
9452   else
9453     {
9454       /* we have can just get the values */
9455       int size = AOP_SIZE (right);
9456       int offset = 0;
9457
9458       while (size--)
9459         {
9460           l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
9461
9462           MOVA (l);
9463           emitcode ("movx", "@%s,a", rname);
9464
9465           if (size || pi)
9466             emitcode ("inc", "%s", rname);
9467
9468           offset++;
9469         }
9470     }
9471
9472   /* now some housekeeping stuff */
9473   if (aop)
9474     {
9475       if (pi) aopPut (AOP (result),rname,0);
9476       /* we had to allocate for this iCode */
9477       freeAsmop (NULL, aop, ic, TRUE);
9478     }
9479   else
9480     {
9481       /* we did not allocate which means left
9482          already in a pointer register, then
9483          if size > 0 && this could be used again
9484          we have to point it back to where it
9485          belongs */
9486       if (AOP_SIZE (right) > 1 &&
9487           !OP_SYMBOL (result)->remat &&
9488           (OP_SYMBOL (result)->liveTo > ic->seq ||
9489            ic->depth) &&
9490           !pi)
9491         {
9492           int size = AOP_SIZE (right) - 1;
9493           while (size--)
9494             emitcode ("dec", "%s", rname);
9495         }
9496     }
9497
9498   /* done */
9499   if (pi) pi->generated = 1;
9500   freeAsmop (result, NULL, ic, TRUE);
9501   freeAsmop (right, NULL, ic, TRUE);
9502
9503
9504 }
9505
9506 /*-----------------------------------------------------------------*/
9507 /* genFarPointerSet - set value from far space                     */
9508 /*-----------------------------------------------------------------*/
9509 static void
9510 genFarPointerSet (operand * right,
9511                   operand * result, iCode * ic, iCode *pi)
9512 {
9513   int size, offset;
9514   sym_link *retype = getSpec (operandType (right));
9515   sym_link *letype = getSpec (operandType (result));
9516
9517   aopOp (result, ic, FALSE, FALSE);
9518
9519   /* if the operand is already in dptr
9520      then we do nothing else we move the value to dptr */
9521   if (AOP_TYPE (result) != AOP_STR)
9522     {
9523       /* if this is remateriazable */
9524       if (AOP_TYPE (result) == AOP_IMMD)
9525         emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9526       else
9527         {
9528           /* we need to get it byte by byte */
9529           _startLazyDPSEvaluation ();
9530           if (AOP_TYPE (result) != AOP_DPTR)
9531             {
9532               emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9533               emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9534               if (options.model == MODEL_FLAT24)
9535                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9536             }
9537           else
9538             {
9539               /* We need to generate a load to DPTR indirect through DPTR. */
9540               D (emitcode (";", "genFarPointerSet -- indirection special case.");
9541                 );
9542               emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
9543               emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
9544               if (options.model == MODEL_FLAT24)
9545                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9546               emitcode ("pop", "dph");
9547               emitcode ("pop", "dpl");
9548             }
9549           _endLazyDPSEvaluation ();
9550         }
9551     }
9552   /* so dptr know contains the address */
9553   aopOp (right, ic, FALSE, TRUE);
9554
9555   /* if bit then unpack */
9556   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9557     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
9558   else
9559     {
9560       size = AOP_SIZE (right);
9561       offset = 0;
9562
9563       _startLazyDPSEvaluation ();
9564       while (size--)
9565         {
9566           char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9567           MOVA (l);
9568
9569           genSetDPTR (0);
9570           _flushLazyDPS ();
9571
9572           emitcode ("movx", "@dptr,a");
9573           if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
9574             emitcode ("inc", "dptr");
9575         }
9576       _endLazyDPSEvaluation ();
9577     }
9578
9579   if (pi && AOP_TYPE (result) != AOP_IMMD) {
9580     aopPut (AOP(result),"dpl",0);
9581     aopPut (AOP(result),"dph",1);
9582     if (options.model == MODEL_FLAT24)
9583         aopPut (AOP(result),"dpx",2);
9584     pi->generated=1;
9585   }
9586   freeAsmop (result, NULL, ic, TRUE);
9587   freeAsmop (right, NULL, ic, TRUE);
9588 }
9589
9590 /*-----------------------------------------------------------------*/
9591 /* genGenPointerSet - set value from generic pointer space         */
9592 /*-----------------------------------------------------------------*/
9593 static void
9594 genGenPointerSet (operand * right,
9595                   operand * result, iCode * ic, iCode *pi)
9596 {
9597   int size, offset;
9598   sym_link *retype = getSpec (operandType (right));
9599   sym_link *letype = getSpec (operandType (result));
9600
9601   aopOp (result, ic, FALSE, OP_SYMBOL(result)->ruonly ? FALSE : TRUE);
9602
9603   /* if the operand is already in dptr
9604      then we do nothing else we move the value to dptr */
9605   if (AOP_TYPE (result) != AOP_STR)
9606     {
9607       _startLazyDPSEvaluation ();
9608       /* if this is remateriazable */
9609       if (AOP_TYPE (result) == AOP_IMMD)
9610         {
9611           emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9612           if (AOP(result)->aopu.aop_immd.from_cast_remat) 
9613                   emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, FALSE));
9614           else
9615                   emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9616         }
9617       else
9618         {                       /* we need to get it byte by byte */
9619           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9620           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9621           if (options.model == MODEL_FLAT24) {
9622             emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9623             emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
9624           } else {
9625             emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9626           }
9627         }
9628       _endLazyDPSEvaluation ();
9629     }
9630   /* so dptr know contains the address */
9631   aopOp (right, ic, FALSE, TRUE);
9632
9633   /* if bit then unpack */
9634   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9635     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
9636   else
9637     {
9638       size = AOP_SIZE (right);
9639       offset = 0;
9640
9641       _startLazyDPSEvaluation ();
9642       while (size--)
9643         {
9644           char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9645           MOVA (l);
9646
9647           genSetDPTR (0);
9648           _flushLazyDPS ();
9649
9650           emitcode ("lcall", "__gptrput");
9651           if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
9652             emitcode ("inc", "dptr");
9653         }
9654       _endLazyDPSEvaluation ();
9655     }
9656
9657   if (pi && AOP_TYPE (result) != AOP_IMMD) {
9658     aopPut (AOP(result),"dpl",0);
9659     aopPut (AOP(result),"dph",1);
9660     if (options.model == MODEL_FLAT24) {
9661         aopPut (AOP(result),"dpx",2);
9662         aopPut (AOP(result),"b",3);
9663     } else {
9664         aopPut (AOP(result),"b",2);
9665     }
9666     pi->generated=1;
9667   }
9668   freeAsmop (result, NULL, ic, TRUE);
9669   freeAsmop (right, NULL, ic, TRUE);
9670 }
9671
9672 /*-----------------------------------------------------------------*/
9673 /* genPointerSet - stores the value into a pointer location        */
9674 /*-----------------------------------------------------------------*/
9675 static void
9676 genPointerSet (iCode * ic, iCode *pi)
9677 {
9678   operand *right, *result;
9679   sym_link *type, *etype;
9680   int p_type;
9681
9682   D (emitcode (";", "genPointerSet ");
9683     );
9684
9685   right = IC_RIGHT (ic);
9686   result = IC_RESULT (ic);
9687
9688   /* depending on the type of pointer we need to
9689      move it to the correct pointer register */
9690   type = operandType (result);
9691   etype = getSpec (type);
9692   /* if left is of type of pointer then it is simple */
9693   if (IS_PTR (type) && !IS_FUNC (type->next))
9694     {
9695       p_type = DCL_TYPE (type);
9696     }
9697   else
9698     {
9699       /* we have to go by the storage class */
9700       p_type = PTR_TYPE (SPEC_OCLS (etype));
9701     }
9702   /* special case when cast remat */
9703   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
9704       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
9705           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
9706           type =   type = operandType (result);
9707           p_type = DCL_TYPE (type);
9708   }
9709
9710   /* now that we have the pointer type we assign
9711      the pointer values */
9712   switch (p_type)
9713     {
9714
9715     case POINTER:
9716     case IPOINTER:
9717       genNearPointerSet (right, result, ic, pi);
9718       break;
9719
9720     case PPOINTER:
9721       genPagedPointerSet (right, result, ic, pi);
9722       break;
9723
9724     case FPOINTER:
9725       genFarPointerSet (right, result, ic, pi);
9726       break;
9727
9728     case GPOINTER:
9729       genGenPointerSet (right, result, ic, pi);
9730       break;
9731     }
9732
9733 }
9734
9735 /*-----------------------------------------------------------------*/
9736 /* genIfx - generate code for Ifx statement                        */
9737 /*-----------------------------------------------------------------*/
9738 static void
9739 genIfx (iCode * ic, iCode * popIc)
9740 {
9741   operand *cond = IC_COND (ic);
9742   int isbit = 0;
9743
9744   D (emitcode (";", "genIfx "););
9745
9746   aopOp (cond, ic, FALSE, FALSE);
9747
9748   /* get the value into acc */
9749   if (AOP_TYPE (cond) != AOP_CRY)
9750     toBoolean (cond);
9751   else
9752     isbit = 1;
9753   /* the result is now in the accumulator */
9754   freeAsmop (cond, NULL, ic, TRUE);
9755
9756   /* if there was something to be popped then do it */
9757   if (popIc)
9758     genIpop (popIc);
9759
9760   /* if the condition is  a bit variable */
9761   if (isbit && IS_ITEMP (cond) &&
9762       SPIL_LOC (cond))
9763     genIfxJump (ic, SPIL_LOC (cond)->rname);
9764   else if (isbit && !IS_ITEMP (cond))
9765     genIfxJump (ic, OP_SYMBOL (cond)->rname);
9766   else
9767     genIfxJump (ic, "a");
9768
9769   ic->generated = 1;
9770 }
9771
9772 /*-----------------------------------------------------------------*/
9773 /* genAddrOf - generates code for address of                       */
9774 /*-----------------------------------------------------------------*/
9775 static void
9776 genAddrOf (iCode * ic)
9777 {
9778   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
9779   int size, offset;
9780
9781   D (emitcode (";", "genAddrOf ");
9782     );
9783
9784   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9785
9786   /* if the operand is on the stack then we
9787      need to get the stack offset of this
9788      variable */
9789   if (sym->onStack)
9790     {
9791       /* if it has an offset then we need to compute
9792          it */
9793       if (sym->stack)
9794         {
9795           emitcode ("mov", "a,_bp");
9796           emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
9797           aopPut (AOP (IC_RESULT (ic)), "a", 0);
9798         }
9799       else
9800         {
9801           /* we can just move _bp */
9802           aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
9803         }
9804       /* fill the result with zero */
9805       size = AOP_SIZE (IC_RESULT (ic)) - 1;
9806
9807
9808       if (options.stack10bit && size < (FPTRSIZE - 1))
9809         {
9810           fprintf (stderr,
9811                    "*** warning: pointer to stack var truncated.\n");
9812         }
9813
9814       offset = 1;
9815       while (size--)
9816         {
9817           /* Yuck! */
9818           if (options.stack10bit && offset == 2)
9819             {
9820               aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
9821             }
9822           else
9823             {
9824               aopPut (AOP (IC_RESULT (ic)), zero, offset++);
9825             }
9826         }
9827
9828       goto release;
9829     }
9830
9831   /* object not on stack then we need the name */
9832   size = AOP_SIZE (IC_RESULT (ic));
9833   offset = 0;
9834
9835   while (size--)
9836     {
9837       char s[SDCC_NAME_MAX];
9838       if (offset)
9839         sprintf (s, "#(%s >> %d)",
9840                  sym->rname,
9841                  offset * 8);
9842       else
9843         sprintf (s, "#%s", sym->rname);
9844       aopPut (AOP (IC_RESULT (ic)), s, offset++);
9845     }
9846
9847 release:
9848   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9849
9850 }
9851
9852 /*-----------------------------------------------------------------*/
9853 /* genArrayInit - generates code for address of                       */
9854 /*-----------------------------------------------------------------*/
9855 static void
9856 genArrayInit (iCode * ic)
9857 {
9858     literalList *iLoop;
9859     int         ix, count;
9860     int         elementSize = 0, eIndex;
9861     unsigned    val, lastVal;
9862     sym_link    *type;
9863     operand     *left=IC_LEFT(ic);
9864     
9865     D (emitcode (";", "genArrayInit "););
9866
9867     aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
9868     
9869     if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
9870     {
9871         // Load immediate value into DPTR.
9872         emitcode("mov", "dptr, %s",
9873              aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, TRUE));
9874     }
9875     else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
9876     {
9877 #if 0
9878       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9879               "Unexpected operand to genArrayInit.\n");
9880       exit(1);
9881 #else
9882       // a regression because of SDCCcse.c:1.52
9883       emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9884       emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9885       if (options.model == MODEL_FLAT24)
9886         emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9887 #endif
9888     }
9889     
9890     type = operandType(IC_LEFT(ic));
9891     
9892     if (type && type->next)
9893     {
9894         elementSize = getSize(type->next);
9895     }
9896     else
9897     {
9898         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9899                                 "can't determine element size in genArrayInit.\n");
9900         exit(1);
9901     }
9902     
9903     iLoop = IC_ARRAYILIST(ic);
9904     lastVal = 0xffff;
9905     
9906     while (iLoop)
9907     {
9908         bool firstpass = TRUE;
9909         
9910         emitcode(";", "store %d x 0x%x to DPTR (element size %d)", 
9911                  iLoop->count, (int)iLoop->literalValue, elementSize);
9912         
9913         ix = iLoop->count;
9914         
9915         while (ix)
9916         {
9917             symbol *tlbl = NULL;
9918             
9919             count = ix > 256 ? 256 : ix;
9920             
9921             if (count > 1)
9922             {
9923                 tlbl = newiTempLabel (NULL);
9924                 if (firstpass || (count & 0xff))
9925                 {
9926                     emitcode("mov", "b, #0x%x", count & 0xff);
9927                 }
9928                 
9929                 emitcode ("", "%05d$:", tlbl->key + 100);
9930             }
9931             
9932             firstpass = FALSE;
9933                 
9934             for (eIndex = 0; eIndex < elementSize; eIndex++)
9935             {
9936                 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
9937                 if (val != lastVal)
9938                 {
9939                     emitcode("mov", "a, #0x%x", val);
9940                     lastVal = val;
9941                 }
9942                 
9943                 emitcode("movx", "@dptr, a");
9944                 emitcode("inc", "dptr");
9945             }
9946             
9947             if (count > 1)
9948             {
9949                 emitcode("djnz", "b, %05d$", tlbl->key + 100);
9950             }
9951             
9952             ix -= count;
9953         }
9954         
9955         iLoop = iLoop->next;
9956     }
9957     
9958     freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
9959 }
9960
9961 /*-----------------------------------------------------------------*/
9962 /* genFarFarAssign - assignment when both are in far space         */
9963 /*-----------------------------------------------------------------*/
9964 static void
9965 genFarFarAssign (operand * result, operand * right, iCode * ic)
9966 {
9967   int size = AOP_SIZE (right);
9968   int offset = 0;
9969   symbol *rSym = NULL;
9970
9971   if (size == 1)
9972   {
9973       /* quick & easy case. */
9974       D(emitcode(";","genFarFarAssign (1 byte case)"););      
9975       MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
9976       freeAsmop (right, NULL, ic, FALSE);
9977       /* now assign DPTR to result */
9978       _G.accInUse++;
9979       aopOp(result, ic, FALSE, FALSE);
9980       _G.accInUse--;
9981       aopPut(AOP(result), "a", 0);
9982       freeAsmop(result, NULL, ic, FALSE);
9983       return;
9984   }
9985   
9986   /* See if we've got an underlying symbol to abuse. */
9987   if (IS_SYMOP(result) && OP_SYMBOL(result))
9988   {
9989       if (IS_TRUE_SYMOP(result))
9990       {
9991           rSym = OP_SYMBOL(result);
9992       }
9993       else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
9994       {
9995           rSym = OP_SYMBOL(result)->usl.spillLoc;
9996       }
9997   }
9998              
9999   if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10000   {
10001       /* We can use the '390 auto-toggle feature to good effect here. */
10002       
10003       D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10004       emitcode("mov", "dps, #0x21");    /* Select DPTR2 & auto-toggle. */
10005       emitcode ("mov", "dptr,#%s", rSym->rname); 
10006       /* DP2 = result, DP1 = right, DP1 is current. */
10007       while (size)
10008       {
10009           emitcode("movx", "a,@dptr");
10010           emitcode("movx", "@dptr,a");
10011           if (--size)
10012           {
10013                emitcode("inc", "dptr");
10014                emitcode("inc", "dptr");
10015           }
10016       }
10017       emitcode("mov", "dps, #0");
10018       freeAsmop (right, NULL, ic, FALSE);
10019 #if 0
10020 some alternative code for processors without auto-toggle
10021 no time to test now, so later well put in...kpb
10022         D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10023         emitcode("mov", "dps, #0x01");  /* Select DPTR2. */
10024         emitcode ("mov", "dptr,#%s", rSym->rname); 
10025         /* DP2 = result, DP1 = right, DP1 is current. */
10026         while (size)
10027         {
10028           --size;
10029           emitcode("movx", "a,@dptr");
10030           if (size)
10031             emitcode("inc", "dptr");
10032           emitcode("inc", "dps");
10033           emitcode("movx", "@dptr,a");
10034           if (size)
10035             emitcode("inc", "dptr");
10036           emitcode("inc", "dps");
10037         }
10038         emitcode("mov", "dps, #0");
10039         freeAsmop (right, NULL, ic, FALSE);
10040 #endif
10041   }
10042   else
10043   {
10044       D (emitcode (";", "genFarFarAssign"););
10045       aopOp (result, ic, TRUE, TRUE);
10046
10047       _startLazyDPSEvaluation ();
10048       
10049       while (size--)
10050         {
10051           aopPut (AOP (result),
10052                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
10053           offset++;
10054         }
10055       _endLazyDPSEvaluation ();
10056       freeAsmop (result, NULL, ic, FALSE);
10057       freeAsmop (right, NULL, ic, FALSE);
10058   }
10059 }
10060
10061 /*-----------------------------------------------------------------*/
10062 /* genAssign - generate code for assignment                        */
10063 /*-----------------------------------------------------------------*/
10064 static void
10065 genAssign (iCode * ic)
10066 {
10067   operand *result, *right;
10068   int size, offset;
10069   unsigned long lit = 0L;
10070
10071   D (emitcode (";", "genAssign ");
10072     );
10073
10074   result = IC_RESULT (ic);
10075   right = IC_RIGHT (ic);
10076
10077   /* if they are the same */
10078   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10079     return;
10080
10081   aopOp (right, ic, FALSE, FALSE);
10082
10083   emitcode (";", "genAssign: resultIsFar = %s",
10084             isOperandInFarSpace (result) ?
10085             "TRUE" : "FALSE");
10086
10087   /* special case both in far space */
10088   if ((AOP_TYPE (right) == AOP_DPTR ||
10089        AOP_TYPE (right) == AOP_DPTR2) &&
10090   /* IS_TRUE_SYMOP(result)       && */
10091       isOperandInFarSpace (result))
10092     {
10093       genFarFarAssign (result, right, ic);
10094       return;
10095     }
10096
10097   aopOp (result, ic, TRUE, FALSE);
10098
10099   /* if they are the same registers */
10100   if (sameRegs (AOP (right), AOP (result)))
10101     goto release;
10102
10103   /* if the result is a bit */
10104   if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10105     {
10106       /* if the right size is a literal then
10107          we know what the value is */
10108       if (AOP_TYPE (right) == AOP_LIT)
10109         {
10110           if (((int) operandLitValue (right)))
10111             aopPut (AOP (result), one, 0);
10112           else
10113             aopPut (AOP (result), zero, 0);
10114           goto release;
10115         }
10116
10117       /* the right is also a bit variable */
10118       if (AOP_TYPE (right) == AOP_CRY)
10119         {
10120           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10121           aopPut (AOP (result), "c", 0);
10122           goto release;
10123         }
10124
10125       /* we need to or */
10126       toBoolean (right);
10127       aopPut (AOP (result), "a", 0);
10128       goto release;
10129     }
10130
10131   /* bit variables done */
10132   /* general case */
10133   size = AOP_SIZE (result);
10134   offset = 0;
10135   if (AOP_TYPE (right) == AOP_LIT)
10136     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10137
10138   if ((size > 1) &&
10139       (AOP_TYPE (result) != AOP_REG) &&
10140       (AOP_TYPE (right) == AOP_LIT) &&
10141       !IS_FLOAT (operandType (right)))
10142     {
10143       _startLazyDPSEvaluation ();
10144       while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10145         {
10146           aopPut (AOP (result),
10147                   aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
10148                   offset);
10149           offset++;
10150           size--;
10151         }
10152       /* And now fill the rest with zeros. */
10153       if (size)
10154         {
10155           emitcode ("clr", "a");
10156         }
10157       while (size--)
10158         {
10159           aopPut (AOP (result), "a", offset++);
10160         }
10161       _endLazyDPSEvaluation ();
10162     }
10163   else
10164     {
10165       _startLazyDPSEvaluation ();
10166       while (size--)
10167         {
10168           aopPut (AOP (result),
10169                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10170                   offset);
10171           offset++;
10172         }
10173       _endLazyDPSEvaluation ();
10174     }
10175
10176 release:
10177   freeAsmop (right, NULL, ic, FALSE);
10178   freeAsmop (result, NULL, ic, TRUE);
10179 }
10180
10181 /*-----------------------------------------------------------------*/
10182 /* genJumpTab - generates code for jump table                      */
10183 /*-----------------------------------------------------------------*/
10184 static void
10185 genJumpTab (iCode * ic)
10186 {
10187   symbol *jtab;
10188   char *l;
10189
10190   D (emitcode (";", "genJumpTab ");
10191     );
10192
10193   aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10194   /* get the condition into accumulator */
10195   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
10196   MOVA (l);
10197   /* multiply by four! */
10198   emitcode ("add", "a,acc");
10199   emitcode ("add", "a,acc");
10200   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10201
10202   jtab = newiTempLabel (NULL);
10203   emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
10204   emitcode ("jmp", "@a+dptr");
10205   emitcode ("", "%05d$:", jtab->key + 100);
10206   /* now generate the jump labels */
10207   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10208        jtab = setNextItem (IC_JTLABELS (ic)))
10209     emitcode ("ljmp", "%05d$", jtab->key + 100);
10210
10211 }
10212
10213 /*-----------------------------------------------------------------*/
10214 /* genCast - gen code for casting                                  */
10215 /*-----------------------------------------------------------------*/
10216 static void
10217 genCast (iCode * ic)
10218 {
10219   operand *result = IC_RESULT (ic);
10220   sym_link *ctype = operandType (IC_LEFT (ic));
10221   sym_link *rtype = operandType (IC_RIGHT (ic));
10222   operand *right = IC_RIGHT (ic);
10223   int size, offset;
10224
10225   D (emitcode (";", "genCast ");
10226     );
10227
10228   /* if they are equivalent then do nothing */
10229   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10230     return;
10231
10232   aopOp (right, ic, FALSE, FALSE);
10233   aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
10234
10235   /* if the result is a bit */
10236   // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10237   if (IS_BITVAR(OP_SYMBOL(result)->type))
10238     {
10239       /* if the right size is a literal then
10240          we know what the value is */
10241       if (AOP_TYPE (right) == AOP_LIT)
10242         {
10243           if (((int) operandLitValue (right)))
10244             aopPut (AOP (result), one, 0);
10245           else
10246             aopPut (AOP (result), zero, 0);
10247
10248           goto release;
10249         }
10250
10251       /* the right is also a bit variable */
10252       if (AOP_TYPE (right) == AOP_CRY)
10253         {
10254           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10255           aopPut (AOP (result), "c", 0);
10256           goto release;
10257         }
10258
10259       /* we need to or */
10260       toBoolean (right);
10261       aopPut (AOP (result), "a", 0);
10262       goto release;
10263     }
10264
10265   /* if they are the same size : or less */
10266   if (AOP_SIZE (result) <= AOP_SIZE (right))
10267     {
10268
10269       /* if they are in the same place */
10270       if (sameRegs (AOP (right), AOP (result)))
10271         goto release;
10272
10273       /* if they in different places then copy */
10274       size = AOP_SIZE (result);
10275       offset = 0;
10276       _startLazyDPSEvaluation ();
10277       while (size--)
10278         {
10279           aopPut (AOP (result),
10280                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10281                   offset);
10282           offset++;
10283         }
10284       _endLazyDPSEvaluation ();
10285       goto release;
10286     }
10287
10288
10289   /* if the result is of type pointer */
10290   if (IS_PTR (ctype))
10291     {
10292
10293       int p_type;
10294       sym_link *type = operandType (right);
10295
10296       /* pointer to generic pointer */
10297       if (IS_GENPTR (ctype))
10298         {
10299           char *l = zero;
10300
10301           if (IS_PTR (type))
10302             {
10303               p_type = DCL_TYPE (type);
10304             }
10305           else
10306             {
10307 #if OLD_CAST_BEHAVIOR
10308               /* KV: we are converting a non-pointer type to
10309                * a generic pointer. This (ifdef'd out) code
10310                * says that the resulting generic pointer
10311                * should have the same class as the storage
10312                * location of the non-pointer variable.
10313                *
10314                * For example, converting an int (which happens
10315                * to be stored in DATA space) to a pointer results
10316                * in a DATA generic pointer; if the original int
10317                * in XDATA space, so will be the resulting pointer.
10318                *
10319                * I don't like that behavior, and thus this change:
10320                * all such conversions will be forced to XDATA and
10321                * throw a warning. If you want some non-XDATA
10322                * type, or you want to suppress the warning, you
10323                * must go through an intermediate cast, like so:
10324                *
10325                * char _generic *gp = (char _xdata *)(intVar);
10326                */
10327               sym_link *etype = getSpec (type);
10328
10329               /* we have to go by the storage class */
10330               if (SPEC_OCLS (etype) != generic)
10331                 {
10332                   p_type = PTR_TYPE (SPEC_OCLS (etype));
10333                 }
10334               else
10335 #endif
10336                 {
10337                   /* Converting unknown class (i.e. register variable)
10338                    * to generic pointer. This is not good, but
10339                    * we'll make a guess (and throw a warning).
10340                    */
10341                   p_type = FPOINTER;
10342                   werror (W_INT_TO_GEN_PTR_CAST);
10343                 }
10344             }
10345
10346           /* the first two bytes are known */
10347           size = GPTRSIZE - 1;
10348           offset = 0;
10349           _startLazyDPSEvaluation ();
10350           while (size--)
10351             {
10352               aopPut (AOP (result),
10353                       aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10354                       offset);
10355               offset++;
10356             }
10357           _endLazyDPSEvaluation ();
10358
10359           /* the last byte depending on type */
10360           switch (p_type)
10361             {
10362             case IPOINTER:
10363             case POINTER:
10364               l = zero;
10365               break;
10366             case FPOINTER:
10367               l = one;
10368               break;
10369             case CPOINTER:
10370               l = "#0x02";
10371               break;
10372             case PPOINTER:
10373               l = "#0x03";
10374               break;
10375
10376             default:
10377               /* this should never happen */
10378               werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10379                       "got unknown pointer type");
10380               exit (1);
10381             }
10382           aopPut (AOP (result), l, GPTRSIZE - 1);
10383           goto release;
10384         }
10385
10386       /* just copy the pointers */
10387       size = AOP_SIZE (result);
10388       offset = 0;
10389       _startLazyDPSEvaluation ();
10390       while (size--)
10391         {
10392           aopPut (AOP (result),
10393                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10394                   offset);
10395           offset++;
10396         }
10397       _endLazyDPSEvaluation ();
10398       goto release;
10399     }
10400
10401   /* so we now know that the size of destination is greater
10402      than the size of the source */
10403   /* we move to result for the size of source */
10404   size = AOP_SIZE (right);
10405   offset = 0;
10406   _startLazyDPSEvaluation ();
10407   while (size--)
10408     {
10409       aopPut (AOP (result),
10410               aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10411               offset);
10412       offset++;
10413     }
10414   _endLazyDPSEvaluation ();
10415
10416   /* now depending on the sign of the source && destination */
10417   size = AOP_SIZE (result) - AOP_SIZE (right);
10418   /* if unsigned or not an integral type */
10419   /* also, if the source is a bit, we don't need to sign extend, because
10420    * it can't possibly have set the sign bit.
10421    */
10422   if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
10423     {
10424       while (size--)
10425         {
10426           aopPut (AOP (result), zero, offset++);
10427         }
10428     }
10429   else
10430     {
10431       /* we need to extend the sign :{ */
10432       char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
10433                         FALSE, FALSE, TRUE);
10434       MOVA (l);
10435       emitcode ("rlc", "a");
10436       emitcode ("subb", "a,acc");
10437       while (size--)
10438         aopPut (AOP (result), "a", offset++);
10439     }
10440
10441   /* we are done hurray !!!! */
10442
10443 release:
10444   freeAsmop (right, NULL, ic, TRUE);
10445   freeAsmop (result, NULL, ic, TRUE);
10446
10447 }
10448
10449 /*-----------------------------------------------------------------*/
10450 /* genDjnz - generate decrement & jump if not zero instrucion      */
10451 /*-----------------------------------------------------------------*/
10452 static int
10453 genDjnz (iCode * ic, iCode * ifx)
10454 {
10455   symbol *lbl, *lbl1;
10456   if (!ifx)
10457     return 0;
10458
10459   /* if the if condition has a false label
10460      then we cannot save */
10461   if (IC_FALSE (ifx))
10462     return 0;
10463
10464   /* if the minus is not of the form
10465      a = a - 1 */
10466   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
10467       !IS_OP_LITERAL (IC_RIGHT (ic)))
10468     return 0;
10469
10470   if (operandLitValue (IC_RIGHT (ic)) != 1)
10471     return 0;
10472
10473   /* if the size of this greater than one then no
10474      saving */
10475   if (getSize (operandType (IC_RESULT (ic))) > 1)
10476     return 0;
10477
10478   /* otherwise we can save BIG */
10479   D(emitcode(";", "genDjnz"););
10480
10481   lbl = newiTempLabel (NULL);
10482   lbl1 = newiTempLabel (NULL);
10483
10484   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10485
10486   if (AOP_NEEDSACC(IC_RESULT(ic)))
10487   {
10488       /* If the result is accessed indirectly via
10489        * the accumulator, we must explicitly write
10490        * it back after the decrement.
10491        */
10492       char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
10493       
10494       if (strcmp(rByte, "a"))
10495       {
10496            /* Something is hopelessly wrong */
10497            fprintf(stderr, "*** warning: internal error at %s:%d\n",
10498                    __FILE__, __LINE__);
10499            /* We can just give up; the generated code will be inefficient,
10500             * but what the hey.
10501             */
10502            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10503            return 0;
10504       }
10505       emitcode ("dec", "%s", rByte);
10506       aopPut(AOP(IC_RESULT(ic)), rByte, 0);
10507       emitcode ("jnz", "%05d$", lbl->key + 100);
10508   }
10509   else if (IS_AOP_PREG (IC_RESULT (ic)))
10510     {
10511       emitcode ("dec", "%s",
10512                 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10513       emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10514       emitcode ("jnz", "%05d$", lbl->key + 100);
10515     }
10516   else
10517     {
10518       emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
10519                 lbl->key + 100);
10520     }
10521   emitcode ("sjmp", "%05d$", lbl1->key + 100);
10522   emitcode ("", "%05d$:", lbl->key + 100);
10523   emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
10524   emitcode ("", "%05d$:", lbl1->key + 100);
10525
10526   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10527   ifx->generated = 1;
10528   return 1;
10529 }
10530
10531 /*-----------------------------------------------------------------*/
10532 /* genReceive - generate code for a receive iCode                  */
10533 /*-----------------------------------------------------------------*/
10534 static void
10535 genReceive (iCode * ic)
10536 {
10537
10538   D (emitcode (";", "genReceive ");
10539     );
10540
10541   if (isOperandInFarSpace (IC_RESULT (ic)) &&
10542       (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
10543        IS_TRUE_SYMOP (IC_RESULT (ic))))
10544     {
10545       int size = getSize (operandType (IC_RESULT (ic)));
10546       int offset = fReturnSizeDS390 - size;
10547       while (size--)
10548         {
10549           emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
10550                             fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
10551           offset++;
10552         }
10553       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10554       size = AOP_SIZE (IC_RESULT (ic));
10555       offset = 0;
10556       while (size--)
10557         {
10558           emitcode ("pop", "acc");
10559           aopPut (AOP (IC_RESULT (ic)), "a", offset++);
10560         }
10561
10562     }
10563   else
10564     {
10565       _G.accInUse++;
10566       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10567       _G.accInUse--;
10568       assignResultValue (IC_RESULT (ic));
10569     }
10570
10571   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10572 }
10573
10574 /*-----------------------------------------------------------------*/
10575 /* gen390Code - generate code for Dallas 390 based controllers     */
10576 /*-----------------------------------------------------------------*/
10577 void
10578 gen390Code (iCode * lic)
10579 {
10580   iCode *ic;
10581   int cln = 0;
10582
10583   lineHead = lineCurr = NULL;
10584
10585   if (options.model == MODEL_FLAT24) {
10586     fReturnSizeDS390 = 5;
10587     fReturn = fReturn24;
10588   } else {
10589     fReturnSizeDS390 = 4;
10590     fReturn = fReturn16;
10591     options.stack10bit=0;
10592   }
10593 #if 0
10594   //REMOVE ME!!!
10595   /* print the allocation information */
10596   if (allocInfo)
10597     printAllocInfo (currFunc, codeOutFile);
10598 #endif
10599   /* if debug information required */
10600   if (options.debug && currFunc)
10601     {
10602       cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
10603       _G.debugLine = 1;
10604       if (IS_STATIC (currFunc->etype))
10605         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
10606       else
10607         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
10608       _G.debugLine = 0;
10609     }
10610   /* stack pointer name */
10611   if (options.useXstack)
10612     spname = "_spx";
10613   else
10614     spname = "sp";
10615
10616
10617   for (ic = lic; ic; ic = ic->next)
10618     {
10619
10620       if (cln != ic->lineno)
10621         {
10622           if (options.debug)
10623             {
10624               _G.debugLine = 1;
10625               emitcode ("", "C$%s$%d$%d$%d ==.",
10626                         FileBaseName (ic->filename), ic->lineno,
10627                         ic->level, ic->block);
10628               _G.debugLine = 0;
10629             }
10630           emitcode (";", "%s %d", ic->filename, ic->lineno);
10631           cln = ic->lineno;
10632         }
10633       /* if the result is marked as
10634          spilt and rematerializable or code for
10635          this has already been generated then
10636          do nothing */
10637       if (resultRemat (ic) || ic->generated)
10638         continue;
10639
10640       /* depending on the operation */
10641       switch (ic->op)
10642         {
10643         case '!':
10644           genNot (ic);
10645           break;
10646
10647         case '~':
10648           genCpl (ic);
10649           break;
10650
10651         case UNARYMINUS:
10652           genUminus (ic);
10653           break;
10654
10655         case IPUSH:
10656           genIpush (ic);
10657           break;
10658
10659         case IPOP:
10660           /* IPOP happens only when trying to restore a
10661              spilt live range, if there is an ifx statement
10662              following this pop then the if statement might
10663              be using some of the registers being popped which
10664              would destory the contents of the register so
10665              we need to check for this condition and handle it */
10666           if (ic->next &&
10667               ic->next->op == IFX &&
10668               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
10669             genIfx (ic->next, ic);
10670           else
10671             genIpop (ic);
10672           break;
10673
10674         case CALL:
10675           genCall (ic);
10676           break;
10677
10678         case PCALL:
10679           genPcall (ic);
10680           break;
10681
10682         case FUNCTION:
10683           genFunction (ic);
10684           break;
10685
10686         case ENDFUNCTION:
10687           genEndFunction (ic);
10688           break;
10689
10690         case RETURN:
10691           genRet (ic);
10692           break;
10693
10694         case LABEL:
10695           genLabel (ic);
10696           break;
10697
10698         case GOTO:
10699           genGoto (ic);
10700           break;
10701
10702         case '+':
10703           genPlus (ic);
10704           break;
10705
10706         case '-':
10707           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
10708             genMinus (ic);
10709           break;
10710
10711         case '*':
10712           genMult (ic);
10713           break;
10714
10715         case '/':
10716           genDiv (ic);
10717           break;
10718
10719         case '%':
10720           genMod (ic);
10721           break;
10722
10723         case '>':
10724           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
10725           break;
10726
10727         case '<':
10728           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
10729           break;
10730
10731         case LE_OP:
10732         case GE_OP:
10733         case NE_OP:
10734
10735           /* note these two are xlated by algebraic equivalence
10736              during parsing SDCC.y */
10737           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10738                   "got '>=' or '<=' shouldn't have come here");
10739           break;
10740
10741         case EQ_OP:
10742           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
10743           break;
10744
10745         case AND_OP:
10746           genAndOp (ic);
10747           break;
10748
10749         case OR_OP:
10750           genOrOp (ic);
10751           break;
10752
10753         case '^':
10754           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
10755           break;
10756
10757         case '|':
10758           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
10759           break;
10760
10761         case BITWISEAND:
10762           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
10763           break;
10764
10765         case INLINEASM:
10766           genInline (ic);
10767           break;
10768
10769         case RRC:
10770           genRRC (ic);
10771           break;
10772
10773         case RLC:
10774           genRLC (ic);
10775           break;
10776
10777         case GETHBIT:
10778           genGetHbit (ic);
10779           break;
10780
10781         case LEFT_OP:
10782           genLeftShift (ic);
10783           break;
10784
10785         case RIGHT_OP:
10786           genRightShift (ic);
10787           break;
10788
10789         case GET_VALUE_AT_ADDRESS:
10790           genPointerGet (ic,hasInc(IC_LEFT(ic),ic));
10791           break;
10792
10793         case '=':
10794           if (POINTER_SET (ic))
10795             genPointerSet (ic,hasInc(IC_RESULT(ic),ic));
10796           else
10797             genAssign (ic);
10798           break;
10799
10800         case IFX:
10801           genIfx (ic, NULL);
10802           break;
10803
10804         case ADDRESS_OF:
10805           genAddrOf (ic);
10806           break;
10807
10808         case JUMPTABLE:
10809           genJumpTab (ic);
10810           break;
10811
10812         case CAST:
10813           genCast (ic);
10814           break;
10815
10816         case RECEIVE:
10817           genReceive (ic);
10818           break;
10819
10820         case SEND:
10821           addSet (&_G.sendSet, ic);
10822           break;
10823
10824         case ARRAYINIT:
10825             genArrayInit(ic);
10826             break;
10827             
10828         default:
10829           ic = ic;
10830         }
10831     }
10832
10833
10834   /* now we are ready to call the
10835      peep hole optimizer */
10836   if (!options.nopeep)
10837     peepHole (&lineHead);
10838
10839   /* now do the actual printing */
10840   printLine (lineHead, codeOutFile);
10841   return;
10842 }