Added __builtin function __builtin_memset_x
[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,_bpx");
464       emitcode ("clr","c");
465       emitcode ("subb", "a,#0x%02x",
466                 -((sym->stack < 0) ?
467                   ((short) (sym->stack - _G.nRegsSaved)) :
468                   ((short) sym->stack)) & 0xff);
469       emitcode ("mov","b,a");
470       emitcode ("mov","a,_bpx+1");
471       emitcode ("subb","a,#0x%02x",(-((sym->stack < 0) ?
472                                      ((short) (sym->stack - _G.nRegsSaved)) :
473                                      ((short) sym->stack)) >> 8) & 0xff);
474       if (useDP2) {
475           if (options.model == MODEL_FLAT24)
476               emitcode ("mov", "dpx1,#0x%02x", (options.stack_loc >> 16) & 0xff);
477           TR_DPTR("#2");
478           emitcode ("mov", "dph1,a");
479           emitcode ("mov", "dpl1,b");
480       } else {
481           if (options.model == MODEL_FLAT24)
482               emitcode ("mov", "dpx,#0x%02x", (options.stack_loc >> 16) & 0xff);
483           emitcode ("mov", "dph,a");
484           emitcode ("mov", "dpl,b");
485       }
486
487       if (_G.accInUse)
488         emitcode ("pop", "acc");
489
490       sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
491       aop->size = getSize (sym->type);
492       return aop;
493     }
494
495   /* if in bit space */
496   if (IN_BITSPACE (space))
497     {
498       sym->aop = aop = newAsmop (AOP_CRY);
499       aop->aopu.aop_dir = sym->rname;
500       aop->size = getSize (sym->type);
501       return aop;
502     }
503   /* if it is in direct space */
504   if (IN_DIRSPACE (space))
505     {
506       sym->aop = aop = newAsmop (AOP_DIR);
507       aop->aopu.aop_dir = sym->rname;
508       aop->size = getSize (sym->type);
509       return aop;
510     }
511
512   /* special case for a function */
513   if (IS_FUNC (sym->type))
514     {
515       sym->aop = aop = newAsmop (AOP_IMMD);
516       aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
517       strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
518       aop->size = FPTRSIZE;
519       return aop;
520     }
521
522   /* only remaining is far space */
523   /* in which case DPTR gets the address */
524   sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
525   if (useDP2)
526     {
527       genSetDPTR (1);
528       _flushLazyDPS ();
529       emitcode ("mov", "dptr,#%s", sym->rname);
530       genSetDPTR (0);
531     }
532   else
533     {
534       emitcode ("mov", "dptr,#%s", sym->rname);
535     }
536   aop->size = getSize (sym->type);
537
538   /* if it is in code space */
539   if (IN_CODESPACE (space))
540     aop->code = 1;
541
542   return aop;
543 }
544
545 /*-----------------------------------------------------------------*/
546 /* aopForRemat - rematerialzes an object                           */
547 /*-----------------------------------------------------------------*/
548 static asmop *
549 aopForRemat (symbol * sym)
550 {
551   iCode *ic = sym->rematiCode;
552   asmop *aop = newAsmop (AOP_IMMD);
553   int ptr_type =0;
554   int val = 0;
555
556   for (;;)
557     {
558       if (ic->op == '+')
559         val += (int) operandLitValue (IC_RIGHT (ic));
560       else if (ic->op == '-')
561         val -= (int) operandLitValue (IC_RIGHT (ic));
562       else if (IS_CAST_ICODE(ic)) {
563               sym_link *from_type = operandType(IC_RIGHT(ic));
564               aop->aopu.aop_immd.from_cast_remat = 1;
565               ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
566               ptr_type = DCL_TYPE(from_type);
567               if (ptr_type == IPOINTER) {
568                 // bug #481053
569                 ptr_type = POINTER;
570               }
571               continue ;
572       } else break;
573       
574       ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
575     }
576
577   if (val)
578     sprintf (buffer, "(%s %c 0x%04x)",
579              OP_SYMBOL (IC_LEFT (ic))->rname,
580              val >= 0 ? '+' : '-',
581              abs (val) & 0xffff);
582   else
583     strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
584
585   aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
586   strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
587   /* set immd2 field if required */
588   if (aop->aopu.aop_immd.from_cast_remat) {
589           sprintf(buffer,"#0x%02x",ptr_type);
590           aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
591           strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
592   }
593
594   return aop;
595 }
596
597 /*-----------------------------------------------------------------*/
598 /* regsInCommon - two operands have some registers in common       */
599 /*-----------------------------------------------------------------*/
600 static bool
601 regsInCommon (operand * op1, operand * op2)
602 {
603   symbol *sym1, *sym2;
604   int i;
605
606   /* if they have registers in common */
607   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
608     return FALSE;
609
610   sym1 = OP_SYMBOL (op1);
611   sym2 = OP_SYMBOL (op2);
612
613   if (sym1->nRegs == 0 || sym2->nRegs == 0)
614     return FALSE;
615
616   for (i = 0; i < sym1->nRegs; i++)
617     {
618       int j;
619       if (!sym1->regs[i])
620         continue;
621
622       for (j = 0; j < sym2->nRegs; j++)
623         {
624           if (!sym2->regs[j])
625             continue;
626
627           if (sym2->regs[j] == sym1->regs[i])
628             return TRUE;
629         }
630     }
631
632   return FALSE;
633 }
634
635 /*-----------------------------------------------------------------*/
636 /* operandsEqu - equivalent                                        */
637 /*-----------------------------------------------------------------*/
638 static bool
639 operandsEqu (operand * op1, operand * op2)
640 {
641   symbol *sym1, *sym2;
642
643   /* if they not symbols */
644   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
645     return FALSE;
646
647   sym1 = OP_SYMBOL (op1);
648   sym2 = OP_SYMBOL (op2);
649
650   /* if both are itemps & one is spilt
651      and the other is not then false */
652   if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
653       sym1->isspilt != sym2->isspilt)
654     return FALSE;
655
656   /* if they are the same */
657   if (sym1 == sym2)
658     return TRUE;
659
660   if (strcmp (sym1->rname, sym2->rname) == 0)
661     return TRUE;
662
663
664   /* if left is a tmp & right is not */
665   if (IS_ITEMP (op1) &&
666       !IS_ITEMP (op2) &&
667       sym1->isspilt &&
668       (sym1->usl.spillLoc == sym2))
669     return TRUE;
670
671   if (IS_ITEMP (op2) &&
672       !IS_ITEMP (op1) &&
673       sym2->isspilt &&
674       sym1->level > 0 &&
675       (sym2->usl.spillLoc == sym1))
676     return TRUE;
677
678   return FALSE;
679 }
680
681 /*-----------------------------------------------------------------*/
682 /* sameRegs - two asmops have the same registers                   */
683 /*-----------------------------------------------------------------*/
684 static bool
685 sameRegs (asmop * aop1, asmop * aop2)
686 {
687   int i;
688
689   if (aop1 == aop2)
690     {
691       if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
692         {
693           return FALSE;
694         }
695       return TRUE;
696     }
697
698   if (aop1->type != AOP_REG ||
699       aop2->type != AOP_REG)
700     return FALSE;
701
702   if (aop1->size != aop2->size)
703     return FALSE;
704
705   for (i = 0; i < aop1->size; i++)
706     if (aop1->aopu.aop_reg[i] !=
707         aop2->aopu.aop_reg[i])
708       return FALSE;
709
710   return TRUE;
711 }
712
713 /*-----------------------------------------------------------------*/
714 /* aopOp - allocates an asmop for an operand  :                    */
715 /*-----------------------------------------------------------------*/
716 static void
717 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
718 {
719   asmop *aop;
720   symbol *sym;
721   int i;
722
723   if (!op)
724     return;
725
726   /* if this a literal */
727   if (IS_OP_LITERAL (op))
728     {
729       op->aop = aop = newAsmop (AOP_LIT);
730       aop->aopu.aop_lit = op->operand.valOperand;
731       aop->size = getSize (operandType (op));
732       return;
733     }
734
735   /* if already has a asmop then continue */
736   if (op->aop)
737     return;
738
739   /* if the underlying symbol has a aop */
740   if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
741     {
742       op->aop = OP_SYMBOL (op)->aop;
743       return;
744     }
745
746   /* if this is a true symbol */
747   if (IS_TRUE_SYMOP (op))
748     {
749       op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
750       return;
751     }
752
753   /* this is a temporary : this has
754      only four choices :
755      a) register
756      b) spillocation
757      c) rematerialize
758      d) conditional
759      e) can be a return use only */
760
761   sym = OP_SYMBOL (op);
762
763
764   /* if the type is a conditional */
765   if (sym->regType == REG_CND)
766     {
767       aop = op->aop = sym->aop = newAsmop (AOP_CRY);
768       aop->size = 0;
769       return;
770     }
771
772   /* if it is spilt then two situations
773      a) is rematerialize
774      b) has a spill location */
775   if (sym->isspilt || sym->nRegs == 0)
776     {
777
778       /* rematerialize it NOW */
779       if (sym->remat)
780         {
781           sym->aop = op->aop = aop =
782             aopForRemat (sym);
783           aop->size = getSize (sym->type);
784           return;
785         }
786
787       if (sym->accuse)
788         {
789           int i;
790           aop = op->aop = sym->aop = newAsmop (AOP_ACC);
791           aop->size = getSize (sym->type);
792           for (i = 0; i < 2; i++)
793             aop->aopu.aop_str[i] = accUse[i];
794           return;
795         }
796
797       if (sym->ruonly)
798         {
799           int i;
800
801           if (useDP2)
802             {
803               /* a AOP_STR uses DPTR, but DPTR is already in use;
804                * we're just hosed.
805                */
806               fprintf (stderr, "*** Internal error: AOP_STR with DPTR in use! for operand %s\n",sym->name);
807             }
808
809           aop = op->aop = sym->aop = newAsmop (AOP_STR);
810           aop->size = getSize (sym->type);
811           for (i = 0; i < (int) fReturnSizeDS390; i++)
812             aop->aopu.aop_str[i] = fReturn[i];
813           return;
814         }
815
816       /* else spill location  */
817       sym->aop = op->aop = aop =
818         aopForSym (ic, sym->usl.spillLoc, result, useDP2);
819       aop->size = getSize (sym->type);
820       return;
821     }
822
823   /* must be in a register */
824   sym->aop = op->aop = aop = newAsmop (AOP_REG);
825   aop->size = sym->nRegs;
826   for (i = 0; i < sym->nRegs; i++)
827     aop->aopu.aop_reg[i] = sym->regs[i];
828 }
829
830 /*-----------------------------------------------------------------*/
831 /* freeAsmop - free up the asmop given to an operand               */
832 /*----------------------------------------------------------------*/
833 static void
834 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
835 {
836   asmop *aop;
837
838   if (!op)
839     aop = aaop;
840   else
841     aop = op->aop;
842
843   if (!aop)
844     return;
845
846   if (aop->freed)
847     goto dealloc;
848
849   aop->freed = 1;
850
851   /* depending on the asmop type only three cases need work AOP_RO
852      , AOP_R1 && AOP_STK */
853   switch (aop->type)
854     {
855     case AOP_R0:
856       if (_G.r0Pushed)
857         {
858           if (pop)
859             {
860               emitcode ("pop", "ar0");
861               _G.r0Pushed--;
862             }
863         }
864       bitVectUnSetBit (ic->rUsed, R0_IDX);
865       break;
866
867     case AOP_R1:
868       if (_G.r1Pushed)
869         {
870           if (pop)
871             {
872               emitcode ("pop", "ar1");
873               _G.r1Pushed--;
874             }
875         }
876       bitVectUnSetBit (ic->rUsed, R1_IDX);
877       break;
878
879     case AOP_STK:
880       {
881         int sz = aop->size;
882         int stk = aop->aopu.aop_stk + aop->size;
883         bitVectUnSetBit (ic->rUsed, R0_IDX);
884         bitVectUnSetBit (ic->rUsed, R1_IDX);
885
886         getFreePtr (ic, &aop, FALSE);
887
888         if (options.stack10bit)
889           {
890             /* I'm not sure what to do here yet... */
891             /* #STUB */
892             fprintf (stderr,
893                      "*** Warning: probably generating bad code for "
894                      "10 bit stack mode.\n");
895           }
896
897         if (stk)
898           {
899             emitcode ("mov", "a,_bp");
900             emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
901             emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
902           }
903         else
904           {
905             emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
906           }
907
908         while (sz--)
909           {
910             emitcode ("pop", "acc");
911             emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
912             if (!sz)
913               break;
914             emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
915           }
916         op->aop = aop;
917         freeAsmop (op, NULL, ic, TRUE);
918         if (_G.r0Pushed)
919           {
920             emitcode ("pop", "ar0");
921             _G.r0Pushed--;
922           }
923
924         if (_G.r1Pushed)
925           {
926             emitcode ("pop", "ar1");
927             _G.r1Pushed--;
928           }
929       }
930     }
931
932 dealloc:
933   /* all other cases just dealloc */
934   if (op)
935     {
936       op->aop = NULL;
937       if (IS_SYMOP (op))
938         {
939           OP_SYMBOL (op)->aop = NULL;
940           /* if the symbol has a spill */
941           if (SPIL_LOC (op))
942             SPIL_LOC (op)->aop = NULL;
943         }
944     }
945 }
946
947 /*------------------------------------------------------------------*/
948 /* aopGet - for fetching value of the aop                           */
949 /*                    */
950 /* Set canClobberACC if you are sure it is OK to clobber the value  */
951 /* in the accumulator. Set it FALSE otherwise; FALSE is always safe, */
952 /* just less efficient.               */
953 /*------------------------------------------------------------------*/
954
955 static char *
956 aopGet (asmop * aop,
957         int offset,
958         bool bit16,
959         bool dname,
960         bool canClobberACC)
961 {
962   char *s = buffer;
963   char *rs;
964
965   /* offset is greater than
966      size then zero */
967   if (offset > (aop->size - 1) &&
968       aop->type != AOP_LIT)
969     return zero;
970
971   /* depending on type */
972   switch (aop->type)
973     {
974
975     case AOP_R0:
976     case AOP_R1:
977       /* if we need to increment it */
978       while (offset > aop->coff)
979         {
980           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
981           aop->coff++;
982         }
983
984       while (offset < aop->coff)
985         {
986           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
987           aop->coff--;
988         }
989
990       aop->coff = offset;
991       if (aop->paged)
992         {
993           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
994           return (dname ? "acc" : "a");
995         }
996       sprintf (s, "@%s", aop->aopu.aop_ptr->name);
997       rs = Safe_calloc (1, strlen (s) + 1);
998       strcpy (rs, s);
999       return rs;
1000
1001     case AOP_DPTR:
1002     case AOP_DPTR2:
1003
1004       if (aop->type == AOP_DPTR2)
1005         {
1006           genSetDPTR (1);
1007           if (!canClobberACC)
1008             {
1009                     TR_AP("#1");
1010                     emitcode ("xch", "a, %s", DP2_RESULT_REG);
1011             }
1012         }
1013
1014       _flushLazyDPS ();
1015
1016       while (offset > aop->coff)
1017         {
1018           emitcode ("inc", "dptr");
1019           aop->coff++;
1020         }
1021
1022       while (offset < aop->coff)
1023         {
1024           emitcode ("lcall", "__decdptr");
1025           aop->coff--;
1026         }
1027
1028       aop->coff = offset;
1029       if (aop->code)
1030         {
1031           emitcode ("clr", "a");
1032           emitcode ("movc", "a,@a+dptr");
1033         }
1034       else
1035         {
1036           emitcode ("movx", "a,@dptr");
1037         }
1038
1039       if (aop->type == AOP_DPTR2)
1040         {
1041           genSetDPTR (0);
1042           if (!canClobberACC)
1043             {
1044        TR_AP("#2");
1045               emitcode ("xch", "a, %s", DP2_RESULT_REG);
1046               return DP2_RESULT_REG;
1047             }
1048         }
1049       return (dname ? "acc" : "a");
1050
1051     case AOP_IMMD:
1052       if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
1053               sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
1054       } else if (bit16)
1055         sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
1056       else if (offset)
1057         sprintf (s, "#(%s >> %d)",
1058                  aop->aopu.aop_immd.aop_immd1,
1059                  offset * 8);
1060       else
1061         sprintf (s, "#%s",
1062                  aop->aopu.aop_immd.aop_immd1);
1063       rs = Safe_calloc (1, strlen (s) + 1);
1064       strcpy (rs, s);
1065       return rs;
1066
1067     case AOP_DIR:
1068       if (offset)
1069         sprintf (s, "(%s + %d)",
1070                  aop->aopu.aop_dir,
1071                  offset);
1072       else
1073         sprintf (s, "%s", aop->aopu.aop_dir);
1074       rs = Safe_calloc (1, strlen (s) + 1);
1075       strcpy (rs, s);
1076       return rs;
1077
1078     case AOP_REG:
1079       if (dname)
1080         return aop->aopu.aop_reg[offset]->dname;
1081       else
1082         return aop->aopu.aop_reg[offset]->name;
1083
1084     case AOP_CRY:
1085       emitcode ("clr", "a");
1086       emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1087       emitcode ("rlc", "a");
1088       return (dname ? "acc" : "a");
1089
1090     case AOP_ACC:
1091       if (!offset && dname)
1092         return "acc";
1093       return aop->aopu.aop_str[offset];
1094
1095     case AOP_LIT:
1096       return aopLiteral (aop->aopu.aop_lit, offset);
1097
1098     case AOP_STR:
1099       aop->coff = offset;
1100       if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1101           dname)
1102         return "acc";
1103
1104       return aop->aopu.aop_str[offset];
1105
1106     }
1107
1108   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1109           "aopget got unsupported aop->type");
1110   exit (1);
1111 }
1112 /*-----------------------------------------------------------------*/
1113 /* aopPut - puts a string for a aop                                */
1114 /*-----------------------------------------------------------------*/
1115 static void
1116 aopPut (asmop * aop, char *s, int offset)
1117 {
1118   char *d = buffer;
1119
1120   if (aop->size && offset > (aop->size - 1))
1121     {
1122       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1123               "aopPut got offset > aop->size");
1124       exit (1);
1125     }
1126
1127   /* will assign value to value */
1128   /* depending on where it is ofcourse */
1129   switch (aop->type)
1130     {
1131     case AOP_DIR:
1132       if (offset)
1133         sprintf (d, "(%s + %d)",
1134                  aop->aopu.aop_dir, offset);
1135       else
1136         sprintf (d, "%s", aop->aopu.aop_dir);
1137
1138       if (strcmp (d, s))
1139         emitcode ("mov", "%s,%s", d, s);
1140
1141       break;
1142
1143     case AOP_REG:
1144       if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1145           strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1146         {
1147           if (*s == '@' ||
1148               strcmp (s, "r0") == 0 ||
1149               strcmp (s, "r1") == 0 ||
1150               strcmp (s, "r2") == 0 ||
1151               strcmp (s, "r3") == 0 ||
1152               strcmp (s, "r4") == 0 ||
1153               strcmp (s, "r5") == 0 ||
1154               strcmp (s, "r6") == 0 ||
1155               strcmp (s, "r7") == 0)
1156             emitcode ("mov", "%s,%s",
1157                       aop->aopu.aop_reg[offset]->dname, s);
1158           else
1159             emitcode ("mov", "%s,%s",
1160                       aop->aopu.aop_reg[offset]->name, s);
1161         }
1162       break;
1163
1164     case AOP_DPTR:
1165     case AOP_DPTR2:
1166
1167       if (aop->type == AOP_DPTR2)
1168         {
1169           genSetDPTR (1);
1170         }
1171       _flushLazyDPS ();
1172
1173       if (aop->code)
1174         {
1175           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1176                   "aopPut writting to code space");
1177           exit (1);
1178         }
1179
1180       while (offset > aop->coff)
1181         {
1182           aop->coff++;
1183           emitcode ("inc", "dptr");
1184         }
1185
1186       while (offset < aop->coff)
1187         {
1188           aop->coff--;
1189           emitcode ("lcall", "__decdptr");
1190         }
1191
1192       aop->coff = offset;
1193
1194       /* if not in accumulater */
1195       MOVA (s);
1196
1197       emitcode ("movx", "@dptr,a");
1198
1199       if (aop->type == AOP_DPTR2)
1200         {
1201           genSetDPTR (0);
1202         }
1203       break;
1204
1205     case AOP_R0:
1206     case AOP_R1:
1207       while (offset > aop->coff)
1208         {
1209           aop->coff++;
1210           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1211         }
1212       while (offset < aop->coff)
1213         {
1214           aop->coff--;
1215           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1216         }
1217       aop->coff = offset;
1218
1219       if (aop->paged)
1220         {
1221           MOVA (s);
1222           emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1223
1224         }
1225       else if (*s == '@')
1226         {
1227           MOVA (s);
1228           emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1229         }
1230       else if (strcmp (s, "r0") == 0 ||
1231                strcmp (s, "r1") == 0 ||
1232                strcmp (s, "r2") == 0 ||
1233                strcmp (s, "r3") == 0 ||
1234                strcmp (s, "r4") == 0 ||
1235                strcmp (s, "r5") == 0 ||
1236                strcmp (s, "r6") == 0 ||
1237                strcmp (s, "r7") == 0)
1238         {
1239           char buffer[10];
1240           sprintf (buffer, "a%s", s);
1241           emitcode ("mov", "@%s,%s",
1242                     aop->aopu.aop_ptr->name, buffer);
1243         }
1244       else
1245         emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1246
1247       break;
1248
1249     case AOP_STK:
1250       if (strcmp (s, "a") == 0)
1251         emitcode ("push", "acc");
1252       else
1253         if (*s=='@') {
1254           MOVA(s);
1255           emitcode ("push", "acc");
1256         } else {
1257           emitcode ("push", s);
1258         }
1259
1260       break;
1261
1262     case AOP_CRY:
1263       /* if bit variable */
1264       if (!aop->aopu.aop_dir)
1265         {
1266           emitcode ("clr", "a");
1267           emitcode ("rlc", "a");
1268         }
1269       else
1270         {
1271           if (s == zero)
1272             emitcode ("clr", "%s", aop->aopu.aop_dir);
1273           else if (s == one)
1274             emitcode ("setb", "%s", aop->aopu.aop_dir);
1275           else if (!strcmp (s, "c"))
1276             emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1277           else
1278             {
1279               if (strcmp (s, "a"))
1280                 {
1281                   MOVA (s);
1282                 }
1283               {
1284                 symbol *lbl = newiTempLabel (NULL);
1285                 emitcode ("clr", "c");
1286                 emitcode ("jz", "%05d$", lbl->key + 100);
1287                 emitcode ("cpl", "c");
1288                 emitcode ("", "%05d$:", lbl->key + 100);
1289                 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1290               }
1291             }
1292         }
1293       break;
1294
1295     case AOP_STR:
1296       aop->coff = offset;
1297       if (strcmp (aop->aopu.aop_str[offset], s))
1298         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1299       break;
1300
1301     case AOP_ACC:
1302       aop->coff = offset;
1303       if (!offset && (strcmp (s, "acc") == 0))
1304         break;
1305
1306       if (strcmp (aop->aopu.aop_str[offset], s))
1307         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1308       break;
1309
1310     default:
1311       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1312               "aopPut got unsupported aop->type");
1313       exit (1);
1314     }
1315
1316 }
1317
1318
1319 /*--------------------------------------------------------------------*/
1320 /* reAdjustPreg - points a register back to where it should (coff==0) */
1321 /*--------------------------------------------------------------------*/
1322 static void
1323 reAdjustPreg (asmop * aop)
1324 {
1325   if ((aop->coff==0) || (aop->size <= 1)) {
1326     return;
1327   }
1328
1329   switch (aop->type)
1330     {
1331     case AOP_R0:
1332     case AOP_R1:
1333       while (aop->coff--)
1334         emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1335       break;
1336     case AOP_DPTR:
1337     case AOP_DPTR2:
1338       if (aop->type == AOP_DPTR2)
1339         {
1340           genSetDPTR (1);
1341           _flushLazyDPS ();
1342         }
1343       while (aop->coff--)
1344         {
1345           emitcode ("lcall", "__decdptr");
1346         }
1347
1348       if (aop->type == AOP_DPTR2)
1349         {
1350           genSetDPTR (0);
1351         }
1352       break;
1353
1354     }
1355   aop->coff=0;
1356 }
1357
1358 #define AOP(op) op->aop
1359 #define AOP_TYPE(op) AOP(op)->type
1360 #define AOP_SIZE(op) AOP(op)->size
1361 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1362                        AOP_TYPE(x) == AOP_R0))
1363
1364 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
1365                         AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1366                          AOP(x)->paged))
1367
1368 #define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
1369                       (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1370                       x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1371
1372 /* Workaround for DS80C390 bug: div ab may return bogus results
1373  * if A is accessed in instruction immediately before the div.
1374  *
1375  * Will be fixed in B4 rev of processor, Dallas claims.
1376  */
1377
1378 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L)       \
1379     if (!AOP_NEEDSACC(RIGHT))         \
1380     {               \
1381       /* We can load A first, then B, since     \
1382        * B (the RIGHT operand) won't clobber A,   \
1383        * thus avoiding touching A right before the div. \
1384        */             \
1385       D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1386       L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE);     \
1387       MOVA(L);            \
1388       emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1389     }               \
1390     else              \
1391     {               \
1392       /* Just stuff in a nop after loading A. */    \
1393       emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1394       L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE);   \
1395       MOVA(L);            \
1396       emitcode("nop", "; workaround for DS80C390 div bug.");  \
1397     }
1398
1399 /*-----------------------------------------------------------------*/
1400 /* genNotFloat - generates not for float operations              */
1401 /*-----------------------------------------------------------------*/
1402 static void
1403 genNotFloat (operand * op, operand * res)
1404 {
1405   int size, offset;
1406   char *l;
1407   symbol *tlbl;
1408
1409   D (emitcode (";", "genNotFloat ");
1410     );
1411
1412   /* we will put 127 in the first byte of
1413      the result */
1414   aopPut (AOP (res), "#127", 0);
1415   size = AOP_SIZE (op) - 1;
1416   offset = 1;
1417
1418   _startLazyDPSEvaluation ();
1419   l = aopGet (op->aop, offset++, FALSE, FALSE, TRUE);
1420   MOVA (l);
1421
1422   while (size--)
1423     {
1424       emitcode ("orl", "a,%s",
1425                 aopGet (op->aop,
1426                         offset++, FALSE, FALSE, FALSE));
1427     }
1428   _endLazyDPSEvaluation ();
1429
1430   tlbl = newiTempLabel (NULL);
1431   aopPut (res->aop, one, 1);
1432   emitcode ("jz", "%05d$", (tlbl->key + 100));
1433   aopPut (res->aop, zero, 1);
1434   emitcode ("", "%05d$:", (tlbl->key + 100));
1435
1436   size = res->aop->size - 2;
1437   offset = 2;
1438   /* put zeros in the rest */
1439   while (size--)
1440     aopPut (res->aop, zero, offset++);
1441 }
1442
1443 /*-----------------------------------------------------------------*/
1444 /* opIsGptr: returns non-zero if the passed operand is       */
1445 /* a generic pointer type.             */
1446 /*-----------------------------------------------------------------*/
1447 static int
1448 opIsGptr (operand * op)
1449 {
1450   sym_link *type = operandType (op);
1451
1452   if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1453     {
1454       return 1;
1455     }
1456   return 0;
1457 }
1458
1459 /*-----------------------------------------------------------------*/
1460 /* getDataSize - get the operand data size                         */
1461 /*-----------------------------------------------------------------*/
1462 static int
1463 getDataSize (operand * op)
1464 {
1465   int size;
1466   size = AOP_SIZE (op);
1467   if (size == GPTRSIZE)
1468     {
1469       sym_link *type = operandType (op);
1470       if (IS_GENPTR (type))
1471         {
1472           /* generic pointer; arithmetic operations
1473            * should ignore the high byte (pointer type).
1474            */
1475           size--;
1476         }
1477     }
1478   return size;
1479 }
1480
1481 /*-----------------------------------------------------------------*/
1482 /* outAcc - output Acc                                             */
1483 /*-----------------------------------------------------------------*/
1484 static void
1485 outAcc (operand * result)
1486 {
1487   int size, offset;
1488   size = getDataSize (result);
1489   if (size)
1490     {
1491       aopPut (AOP (result), "a", 0);
1492       size--;
1493       offset = 1;
1494       /* unsigned or positive */
1495       while (size--)
1496         {
1497           aopPut (AOP (result), zero, offset++);
1498         }
1499     }
1500 }
1501
1502 /*-----------------------------------------------------------------*/
1503 /* outBitC - output a bit C                                        */
1504 /*-----------------------------------------------------------------*/
1505 static void
1506 outBitC (operand * result)
1507 {
1508   /* if the result is bit */
1509   if (AOP_TYPE (result) == AOP_CRY)
1510     {
1511       aopPut (AOP (result), "c", 0);
1512     }
1513   else
1514     {
1515       emitcode ("clr", "a");
1516       emitcode ("rlc", "a");
1517       outAcc (result);
1518     }
1519 }
1520
1521 /*-----------------------------------------------------------------*/
1522 /* toBoolean - emit code for orl a,operator(sizeop)                */
1523 /*-----------------------------------------------------------------*/
1524 static void
1525 toBoolean (operand * oper)
1526 {
1527   int   size = AOP_SIZE (oper) - 1;
1528   int   offset = 1;
1529   bool usedB = FALSE;
1530
1531   /* The generic part of a generic pointer should
1532    * not participate in it's truth value.
1533    *
1534    * i.e. 0x10000000 is zero.
1535    */
1536   if (opIsGptr (oper))
1537     {
1538       D (emitcode (";", "toBoolean: generic ptr special case.");
1539         );
1540       size--;
1541     }
1542
1543   _startLazyDPSEvaluation ();
1544   if (AOP_NEEDSACC (oper) && size)
1545     {
1546       usedB = TRUE;
1547       emitcode ("push", "b");
1548       emitcode ("mov", "b, %s", aopGet (AOP (oper), 0, FALSE, FALSE, FALSE));
1549     }
1550   else
1551     {
1552       MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, TRUE));
1553     }
1554   while (size--)
1555     {
1556       if (usedB)
1557         {
1558           emitcode ("orl", "b,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1559         }
1560       else
1561         {
1562           emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1563         }
1564     }
1565   _endLazyDPSEvaluation ();
1566
1567   if (usedB)
1568     {
1569       emitcode ("mov", "a,b");
1570       emitcode ("pop", "b");
1571     }
1572 }
1573
1574
1575 /*-----------------------------------------------------------------*/
1576 /* genNot - generate code for ! operation                          */
1577 /*-----------------------------------------------------------------*/
1578 static void
1579 genNot (iCode * ic)
1580 {
1581   symbol *tlbl;
1582   sym_link *optype = operandType (IC_LEFT (ic));
1583
1584   D (emitcode (";", "genNot ");
1585     );
1586
1587   /* assign asmOps to operand & result */
1588   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1589   aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1590
1591   /* if in bit space then a special case */
1592   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1593     {
1594       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1595       emitcode ("cpl", "c");
1596       outBitC (IC_RESULT (ic));
1597       goto release;
1598     }
1599
1600   /* if type float then do float */
1601   if (IS_FLOAT (optype))
1602     {
1603       genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1604       goto release;
1605     }
1606
1607   toBoolean (IC_LEFT (ic));
1608
1609   tlbl = newiTempLabel (NULL);
1610   emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1611   emitcode ("", "%05d$:", tlbl->key + 100);
1612   outBitC (IC_RESULT (ic));
1613
1614 release:
1615   /* release the aops */
1616   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1617   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1618 }
1619
1620
1621 /*-----------------------------------------------------------------*/
1622 /* genCpl - generate code for complement                           */
1623 /*-----------------------------------------------------------------*/
1624 static void
1625 genCpl (iCode * ic)
1626 {
1627   int offset = 0;
1628   int size;
1629
1630   D (emitcode (";", "genCpl ");
1631     );
1632
1633
1634   /* assign asmOps to operand & result */
1635   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1636   aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1637
1638   /* if both are in bit space then
1639      a special case */
1640   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1641       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1642     {
1643
1644       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1645       emitcode ("cpl", "c");
1646       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1647       goto release;
1648     }
1649
1650   size = AOP_SIZE (IC_RESULT (ic));
1651   _startLazyDPSEvaluation ();
1652   while (size--)
1653     {
1654       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1655       MOVA (l);
1656       emitcode ("cpl", "a");
1657       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1658     }
1659   _endLazyDPSEvaluation ();
1660
1661
1662 release:
1663   /* release the aops */
1664   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1665   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1666 }
1667
1668 /*-----------------------------------------------------------------*/
1669 /* genUminusFloat - unary minus for floating points                */
1670 /*-----------------------------------------------------------------*/
1671 static void
1672 genUminusFloat (operand * op, operand * result)
1673 {
1674   int size, offset = 0;
1675   char *l;
1676   /* for this we just need to flip the
1677      first it then copy the rest in place */
1678   D (emitcode (";", "genUminusFloat");
1679     );
1680
1681   _startLazyDPSEvaluation ();
1682   size = AOP_SIZE (op) - 1;
1683   l = aopGet (AOP (op), 3, FALSE, FALSE, TRUE);
1684   MOVA (l);
1685
1686   emitcode ("cpl", "acc.7");
1687   aopPut (AOP (result), "a", 3);
1688
1689   while (size--)
1690     {
1691       aopPut (AOP (result),
1692               aopGet (AOP (op), offset, FALSE, FALSE, FALSE),
1693               offset);
1694       offset++;
1695     }
1696   _endLazyDPSEvaluation ();
1697 }
1698
1699 /*-----------------------------------------------------------------*/
1700 /* genUminus - unary minus code generation                         */
1701 /*-----------------------------------------------------------------*/
1702 static void
1703 genUminus (iCode * ic)
1704 {
1705   int offset, size;
1706   sym_link *optype, *rtype;
1707
1708   D (emitcode (";", "genUminus ");
1709     );
1710
1711
1712   /* assign asmops */
1713   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1714   aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1715
1716   /* if both in bit space then special
1717      case */
1718   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1719       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1720     {
1721
1722       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1723       emitcode ("cpl", "c");
1724       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1725       goto release;
1726     }
1727
1728   optype = operandType (IC_LEFT (ic));
1729   rtype = operandType (IC_RESULT (ic));
1730
1731   /* if float then do float stuff */
1732   if (IS_FLOAT (optype))
1733     {
1734       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1735       goto release;
1736     }
1737
1738   /* otherwise subtract from zero */
1739   size = AOP_SIZE (IC_LEFT (ic));
1740   offset = 0;
1741   _startLazyDPSEvaluation ();
1742   while (size--)
1743     {
1744       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1745       if (!strcmp (l, "a"))
1746         {
1747           if (offset == 0)
1748             SETC;
1749           emitcode ("cpl", "a");
1750           emitcode ("addc", "a,#0");
1751         }
1752       else
1753         {
1754           if (offset == 0)
1755             CLRC;
1756           emitcode ("clr", "a");
1757           emitcode ("subb", "a,%s", l);
1758         }
1759       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1760     }
1761   _endLazyDPSEvaluation ();
1762
1763   /* if any remaining bytes in the result */
1764   /* we just need to propagate the sign   */
1765   if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1766     {
1767       emitcode ("rlc", "a");
1768       emitcode ("subb", "a,acc");
1769       while (size--)
1770         aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1771     }
1772
1773 release:
1774   /* release the aops */
1775   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1776   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1777 }
1778
1779 /*-----------------------------------------------------------------*/
1780 /* saveRegisters - will look for a call and save the registers     */
1781 /*-----------------------------------------------------------------*/
1782 static void
1783 saveRegisters (iCode * lic)
1784 {
1785   int i;
1786   iCode *ic;
1787   bitVect *rsave;
1788   sym_link *detype;
1789
1790   /* look for call */
1791   for (ic = lic; ic; ic = ic->next)
1792     if (ic->op == CALL || ic->op == PCALL)
1793       break;
1794
1795   if (!ic)
1796     {
1797       fprintf (stderr, "found parameter push with no function call\n");
1798       return;
1799     }
1800
1801   /* if the registers have been saved already then
1802      do nothing */
1803   if (ic->regsSaved || IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic)))) return ;
1804
1805   /* special case if DPTR alive across a function call then must save it 
1806      even though callee saves */
1807   if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
1808       int i =0;
1809       rsave = newBitVect(ic->rMask->size);
1810       for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
1811           if (bitVectBitValue(ic->rMask,i))
1812               rsave = bitVectSetBit(rsave,i);
1813       }
1814   } else {
1815       /* find the registers in use at this time
1816          and push them away to safety */
1817       rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1818                              ic->rUsed);
1819   }
1820   ic->regsSaved = 1;
1821   if (options.useXstack)
1822     {
1823       if (bitVectBitValue (rsave, R0_IDX))
1824         emitcode ("mov", "b,r0");
1825       emitcode ("mov", "r0,%s", spname);
1826       for (i = 0; i < ds390_nRegs; i++)
1827         {
1828           if (bitVectBitValue (rsave, i))
1829             {
1830               if (i == R0_IDX)
1831                 emitcode ("mov", "a,b");
1832               else
1833                 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
1834               emitcode ("movx", "@r0,a");
1835               emitcode ("inc", "r0");
1836             }
1837         }
1838       emitcode ("mov", "%s,r0", spname);
1839       if (bitVectBitValue (rsave, R0_IDX))
1840         emitcode ("mov", "r0,b");
1841     }
1842   else
1843     for (i = 0; i < ds390_nRegs; i++)
1844       {
1845         if (bitVectBitValue (rsave, i))
1846           emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
1847       }
1848
1849   detype = getSpec (operandType (IC_LEFT (ic)));
1850 }
1851
1852 /*-----------------------------------------------------------------*/
1853 /* unsaveRegisters - pop the pushed registers                      */
1854 /*-----------------------------------------------------------------*/
1855 static void
1856 unsaveRegisters (iCode * ic)
1857 {
1858   int i;
1859   bitVect *rsave;
1860
1861   if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
1862       int i =0;
1863       rsave = newBitVect(ic->rMask->size);
1864       for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
1865           if (bitVectBitValue(ic->rMask,i))
1866               rsave = bitVectSetBit(rsave,i);
1867       }
1868   } else {
1869       /* find the registers in use at this time
1870          and push them away to safety */
1871       rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1872                              ic->rUsed);
1873   }
1874   if (options.useXstack)
1875     {
1876       emitcode ("mov", "r0,%s", spname);
1877       for (i = ds390_nRegs; i >= 0; i--)
1878         {
1879           if (bitVectBitValue (rsave, i))
1880             {
1881               emitcode ("dec", "r0");
1882               emitcode ("movx", "a,@r0");
1883               if (i == R0_IDX)
1884                 emitcode ("mov", "b,a");
1885               else
1886                 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
1887             }
1888
1889         }
1890       emitcode ("mov", "%s,r0", spname);
1891       if (bitVectBitValue (rsave, R0_IDX))
1892         emitcode ("mov", "r0,b");
1893     }
1894   else
1895     for (i = ds390_nRegs; i >= 0; i--)
1896       {
1897         if (bitVectBitValue (rsave, i))
1898           emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
1899       }
1900
1901 }
1902
1903
1904 /*-----------------------------------------------------------------*/
1905 /* pushSide -                */
1906 /*-----------------------------------------------------------------*/
1907 static void
1908 pushSide (operand * oper, int size)
1909 {
1910   int offset = 0;
1911   _startLazyDPSEvaluation ();
1912   while (size--)
1913     {
1914       char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, FALSE);
1915       if (AOP_TYPE (oper) != AOP_REG &&
1916           AOP_TYPE (oper) != AOP_DIR &&
1917           strcmp (l, "a"))
1918         {
1919           emitcode ("mov", "a,%s", l);
1920           emitcode ("push", "acc");
1921         }
1922       else
1923         emitcode ("push", "%s", l);
1924     }
1925   _endLazyDPSEvaluation ();
1926 }
1927
1928 /*-----------------------------------------------------------------*/
1929 /* assignResultValue -               */
1930 /*-----------------------------------------------------------------*/
1931 static void
1932 assignResultValue (operand * oper)
1933 {
1934   int offset = 0;
1935   int size = AOP_SIZE (oper);
1936
1937   _startLazyDPSEvaluation ();
1938   while (size--)
1939     {
1940       aopPut (AOP (oper), fReturn[offset], offset);
1941       offset++;
1942     }
1943   _endLazyDPSEvaluation ();
1944 }
1945
1946
1947 /*-----------------------------------------------------------------*/
1948 /* genXpush - pushes onto the external stack                       */
1949 /*-----------------------------------------------------------------*/
1950 static void
1951 genXpush (iCode * ic)
1952 {
1953   asmop *aop = newAsmop (0);
1954   regs *r;
1955   int size, offset = 0;
1956
1957   D (emitcode (";", "genXpush ");
1958     );
1959
1960   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1961   r = getFreePtr (ic, &aop, FALSE);
1962
1963
1964   emitcode ("mov", "%s,_spx", r->name);
1965
1966   size = AOP_SIZE (IC_LEFT (ic));
1967   _startLazyDPSEvaluation ();
1968   while (size--)
1969     {
1970
1971       char *l = aopGet (AOP (IC_LEFT (ic)),
1972                         offset++, FALSE, FALSE, TRUE);
1973       MOVA (l);
1974       emitcode ("movx", "@%s,a", r->name);
1975       emitcode ("inc", "%s", r->name);
1976
1977     }
1978   _endLazyDPSEvaluation ();
1979
1980
1981   emitcode ("mov", "_spx,%s", r->name);
1982
1983   freeAsmop (NULL, aop, ic, TRUE);
1984   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1985 }
1986
1987 /*-----------------------------------------------------------------*/
1988 /* genIpush - genrate code for pushing this gets a little complex  */
1989 /*-----------------------------------------------------------------*/
1990 static void
1991 genIpush (iCode * ic)
1992 {
1993   int size, offset = 0;
1994   char *l;
1995
1996   D (emitcode (";", "genIpush ");
1997     );
1998
1999   /* if this is not a parm push : ie. it is spill push
2000      and spill push is always done on the local stack */
2001   if (!ic->parmPush)
2002     {
2003
2004       /* and the item is spilt then do nothing */
2005       if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2006         return;
2007
2008       aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2009       size = AOP_SIZE (IC_LEFT (ic));
2010       /* push it on the stack */
2011       _startLazyDPSEvaluation ();
2012       while (size--)
2013         {
2014           l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, TRUE);
2015           if (*l == '#')
2016             {
2017               MOVA (l);
2018               l = "acc";
2019             }
2020           emitcode ("push", "%s", l);
2021         }
2022       _endLazyDPSEvaluation ();
2023       return;
2024     }
2025
2026   /* this is a paramter push: in this case we call
2027      the routine to find the call and save those
2028      registers that need to be saved */
2029   saveRegisters (ic);
2030
2031   /* if use external stack then call the external
2032      stack pushing routine */
2033   if (options.useXstack)
2034     {
2035       genXpush (ic);
2036       return;
2037     }
2038
2039   /* then do the push */
2040   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2041
2042   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2043   size = AOP_SIZE (IC_LEFT (ic));
2044
2045   _startLazyDPSEvaluation ();
2046   while (size--)
2047     {
2048       l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, FALSE);
2049       if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2050           AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2051           strcmp (l, "a"))
2052         {
2053           emitcode ("mov", "a,%s", l);
2054           emitcode ("push", "acc");
2055         }
2056       else
2057         emitcode ("push", "%s", l);
2058     }
2059   _endLazyDPSEvaluation ();
2060
2061   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2062 }
2063
2064 /*-----------------------------------------------------------------*/
2065 /* genIpop - recover the registers: can happen only for spilling   */
2066 /*-----------------------------------------------------------------*/
2067 static void
2068 genIpop (iCode * ic)
2069 {
2070   int size, offset;
2071
2072   D (emitcode (";", "genIpop ");
2073     );
2074
2075
2076   /* if the temp was not pushed then */
2077   if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2078     return;
2079
2080   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2081   size = AOP_SIZE (IC_LEFT (ic));
2082   offset = (size - 1);
2083   _startLazyDPSEvaluation ();
2084   while (size--)
2085     {
2086       emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2087                                      FALSE, TRUE, TRUE));
2088     }
2089   _endLazyDPSEvaluation ();
2090
2091   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2092 }
2093
2094 /*-----------------------------------------------------------------*/
2095 /* unsaveRBank - restores the resgister bank from stack            */
2096 /*-----------------------------------------------------------------*/
2097 static void
2098 unsaveRBank (int bank, iCode * ic, bool popPsw)
2099 {
2100   int i;
2101   asmop *aop = NULL;
2102   regs *r = NULL;
2103
2104   if (options.useXstack)
2105   {
2106       if (!ic)
2107       {
2108           /* Assume r0 is available for use. */
2109           r = ds390_regWithIdx (R0_IDX);;          
2110       } 
2111       else
2112       {
2113           aop = newAsmop (0);
2114           r = getFreePtr (ic, &aop, FALSE);
2115       }
2116       emitcode ("mov", "%s,_spx", r->name);      
2117   }
2118   
2119   if (popPsw)
2120     {
2121       if (options.useXstack)
2122       {
2123           emitcode ("movx", "a,@%s", r->name);
2124           emitcode ("mov", "psw,a");
2125           emitcode ("dec", "%s", r->name);
2126         }
2127       else
2128       {
2129         emitcode ("pop", "psw");
2130       }
2131     }
2132
2133   for (i = (ds390_nRegs - 1); i >= 0; i--)
2134     {
2135       if (options.useXstack)
2136         {
2137           emitcode ("movx", "a,@%s", r->name);
2138           emitcode ("mov", "(%s+%d),a",
2139                     regs390[i].base, 8 * bank + regs390[i].offset);
2140           emitcode ("dec", "%s", r->name);
2141
2142         }
2143       else
2144         emitcode ("pop", "(%s+%d)",
2145                   regs390[i].base, 8 * bank + regs390[i].offset);
2146     }
2147
2148   if (options.useXstack)
2149     {
2150       emitcode ("mov", "_spx,%s", r->name);
2151     }
2152     
2153   if (aop)
2154   {
2155       freeAsmop (NULL, aop, ic, TRUE);  
2156   }    
2157 }
2158
2159 /*-----------------------------------------------------------------*/
2160 /* saveRBank - saves an entire register bank on the stack          */
2161 /*-----------------------------------------------------------------*/
2162 static void
2163 saveRBank (int bank, iCode * ic, bool pushPsw)
2164 {
2165   int i;
2166   asmop *aop = NULL;
2167   regs *r = NULL;
2168
2169   if (options.useXstack)
2170     {
2171         if (!ic)
2172         {
2173           /* Assume r0 is available for use. */
2174                   r = ds390_regWithIdx (R0_IDX);;
2175         }
2176         else
2177         {
2178           aop = newAsmop (0);
2179           r = getFreePtr (ic, &aop, FALSE);
2180         }
2181         emitcode ("mov", "%s,_spx", r->name);    
2182     }
2183
2184   for (i = 0; i < ds390_nRegs; i++)
2185     {
2186       if (options.useXstack)
2187         {
2188           emitcode ("inc", "%s", r->name);
2189           emitcode ("mov", "a,(%s+%d)",
2190                     regs390[i].base, 8 * bank + regs390[i].offset);
2191           emitcode ("movx", "@%s,a", r->name);
2192         }
2193       else
2194         emitcode ("push", "(%s+%d)",
2195                   regs390[i].base, 8 * bank + regs390[i].offset);
2196     }
2197
2198   if (pushPsw)
2199     {
2200       if (options.useXstack)
2201         {
2202           emitcode ("mov", "a,psw");
2203           emitcode ("movx", "@%s,a", r->name);
2204           emitcode ("inc", "%s", r->name);
2205           emitcode ("mov", "_spx,%s", r->name);
2206         }
2207       else
2208       {
2209         emitcode ("push", "psw");
2210       }
2211
2212       emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2213     }
2214   
2215   if (aop)
2216   {
2217        freeAsmop (NULL, aop, ic, TRUE);
2218   }    
2219     
2220   if (ic)
2221   {  
2222       ic->bankSaved = 1;
2223   }
2224 }
2225
2226 /*-----------------------------------------------------------------*/
2227 /* genCall - generates a call statement                            */
2228 /*-----------------------------------------------------------------*/
2229 static void
2230 genCall (iCode * ic)
2231 {
2232   sym_link *dtype;
2233   bool restoreBank = FALSE;
2234   bool swapBanks = FALSE;
2235
2236   D (emitcode (";", "genCall "););
2237
2238   /* if we are calling a not _naked function that is not using
2239      the same register bank then we need to save the
2240      destination registers on the stack */
2241   dtype = operandType (IC_LEFT (ic));
2242   if (dtype && !IFFUNC_ISNAKED(dtype) &&
2243       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2244       IFFUNC_ISISR (currFunc->type))
2245   {
2246       if (!ic->bankSaved) 
2247       {
2248            /* This is unexpected; the bank should have been saved in
2249             * genFunction.
2250             */
2251            saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2252            restoreBank = TRUE;
2253       }
2254       swapBanks = TRUE;
2255   }
2256   
2257     /* if caller saves & we have not saved then */
2258     if (!ic->regsSaved)
2259       saveRegisters (ic);
2260   
2261   /* if send set is not empty the assign */
2262   /* We've saved all the registers we care about;
2263   * therefore, we may clobber any register not used
2264   * in the calling convention (i.e. anything not in
2265   * fReturn.
2266   */
2267   if (_G.sendSet)
2268     {
2269       iCode *sic;
2270
2271       for (sic = setFirstItem (_G.sendSet); sic;
2272            sic = setNextItem (_G.sendSet))
2273         {
2274           int size, offset = 0;
2275
2276 #if 0
2277           aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2278           size = AOP_SIZE (IC_LEFT (sic));
2279
2280           _startLazyDPSEvaluation ();
2281           while (size--)
2282             {
2283               char *l = aopGet (AOP(IC_LEFT(sic)), offset,
2284                                 FALSE, FALSE, TRUE);
2285                 if ((AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR) && size)
2286                 {
2287                     emitcode("mov", "%s,%s", regs390[offset].name, l);
2288                 }
2289                 else if (strcmp (l, fReturn[offset]))
2290                 {
2291                     emitcode ("mov", "%s,%s",
2292                               fReturn[offset],
2293                               l);
2294                 }
2295               offset++;
2296             }
2297           _endLazyDPSEvaluation ();
2298           if (AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR)
2299           {
2300               size = AOP_SIZE (IC_LEFT (sic));
2301               if (size)
2302               {
2303                  size--;
2304               }
2305               while (size)
2306               {
2307                    size--;
2308                    emitcode("mov", "%s,%s",
2309                                     fReturn[size], regs390[size].name);
2310               }
2311           }
2312 #else
2313           // we know that dpl(hxb) is the result, so
2314           _startLazyDPSEvaluation ();
2315           size=getSize(operandType(IC_LEFT(sic)));
2316           if (size>1) {
2317             aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2318           } else {
2319             aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2320           }
2321           while (size--)
2322             {
2323               char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2324                                 FALSE, FALSE, TRUE);
2325               if (strcmp (l, fReturn[offset]))
2326                 {
2327                   emitcode ("mov", "%s,%s",
2328                             fReturn[offset],
2329                             l);
2330                 }
2331               offset++;
2332             }
2333           _endLazyDPSEvaluation ();
2334 #endif
2335           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2336         }
2337       _G.sendSet = NULL;
2338     }  
2339     
2340   if (swapBanks)
2341   {
2342         emitcode ("mov", "psw,#0x%02x", 
2343            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2344   }
2345
2346   /* make the call */
2347   emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2348                             OP_SYMBOL (IC_LEFT (ic))->rname :
2349                             OP_SYMBOL (IC_LEFT (ic))->name));
2350
2351   if (swapBanks)
2352   {
2353        emitcode ("mov", "psw,#0x%02x", 
2354           ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2355   }
2356
2357   /* if we need assign a result value */
2358   if ((IS_ITEMP (IC_RESULT (ic)) &&
2359        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2360         OP_SYMBOL (IC_RESULT (ic))->accuse ||
2361         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2362       IS_TRUE_SYMOP (IC_RESULT (ic)))
2363     {
2364       if (isOperandInFarSpace (IC_RESULT (ic))
2365           && getSize (operandType (IC_RESULT (ic))) <= 2)
2366         {
2367           int size = getSize (operandType (IC_RESULT (ic)));
2368
2369           /* Special case for 1 or 2 byte return in far space. */
2370           MOVA (fReturn[0]);
2371           if (size > 1)
2372             {
2373               emitcode ("mov", "b,%s", fReturn[1]);
2374             }
2375
2376           aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2377           aopPut (AOP (IC_RESULT (ic)), "a", 0);
2378
2379           if (size > 1)
2380             {
2381               aopPut (AOP (IC_RESULT (ic)), "b", 1);
2382             }
2383           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2384         }
2385       else
2386         {
2387           _G.accInUse++;
2388           aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2389           _G.accInUse--;
2390
2391           assignResultValue (IC_RESULT (ic));
2392
2393           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2394         }
2395     }
2396
2397   /* adjust the stack for parameters if
2398      required */
2399   if (ic->parmBytes) {
2400       if (options.stack10bit) {
2401           emitcode ("clr","c");
2402           emitcode ("mov","a,sp");
2403           emitcode ("subb","a,#0x%02x",ic->parmBytes & 0xff);
2404           emitcode ("mov","sp,a");
2405           emitcode ("mov","a,esp");
2406           emitcode ("subb","a,#0x%02x",(ic->parmBytes >> 8) & 0xff);
2407           emitcode ("mov","esp,a");       
2408       } else {
2409           int i;
2410           if (ic->parmBytes > 3) {
2411               emitcode ("mov", "a,%s", spname);
2412               emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2413               emitcode ("mov", "%s,a", spname);
2414           } else
2415               for (i = 0; i < ic->parmBytes; i++)
2416                   emitcode ("dec", "%s", spname);
2417       }
2418   }
2419
2420   /* if we hade saved some registers then unsave them */
2421   if (ic->regsSaved)
2422     unsaveRegisters (ic);
2423
2424   /* if register bank was saved then pop them */
2425   if (restoreBank)
2426     unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2427 }
2428
2429 /*-----------------------------------------------------------------*/
2430 /* genPcall - generates a call by pointer statement                */
2431 /*-----------------------------------------------------------------*/
2432 static void
2433 genPcall (iCode * ic)
2434 {
2435   sym_link *dtype;
2436   symbol *rlbl = newiTempLabel (NULL);
2437   bool restoreBank=FALSE;
2438
2439   D (emitcode (";", "genPcall ");
2440     );
2441
2442
2443   /* if caller saves & we have not saved then */
2444   if (!ic->regsSaved)
2445     saveRegisters (ic);
2446
2447   /* if we are calling a function that is not using
2448      the same register bank then we need to save the
2449      destination registers on the stack */
2450   dtype = operandType (IC_LEFT (ic));
2451   if (dtype && !IFFUNC_ISNAKED(dtype) &&
2452       IFFUNC_ISISR (currFunc->type) &&
2453       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2454     saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2455     restoreBank=TRUE;
2456   }
2457
2458   /* push the return address on to the stack */
2459   emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2460   emitcode ("push", "acc");
2461   emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2462   emitcode ("push", "acc");
2463
2464   if (options.model == MODEL_FLAT24)
2465     {
2466       emitcode ("mov", "a,#(%05d$ >> 16)", (rlbl->key + 100));
2467       emitcode ("push", "acc");
2468     }
2469
2470   /* now push the calling address */
2471   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2472
2473   pushSide (IC_LEFT (ic), FPTRSIZE);
2474
2475   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2476
2477   /* if send set is not empty the assign */
2478   if (_G.sendSet)
2479     {
2480       iCode *sic;
2481
2482       for (sic = setFirstItem (_G.sendSet); sic;
2483            sic = setNextItem (_G.sendSet))
2484         {
2485           int size, offset = 0;
2486
2487           // we know that dpl(hxb) is the result, so
2488           _startLazyDPSEvaluation ();
2489           size=getSize(operandType(IC_LEFT(sic)));
2490           if (size>1) {
2491             aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2492           } else {
2493             aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2494           }
2495           while (size--)
2496             {
2497               char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2498                                 FALSE, FALSE, TRUE);
2499               if (strcmp (l, fReturn[offset]))
2500                 {
2501                   emitcode ("mov", "%s,%s",
2502                             fReturn[offset],
2503                             l);
2504                 }
2505               offset++;
2506             }
2507           _endLazyDPSEvaluation ();
2508           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2509         }
2510       _G.sendSet = NULL;
2511     }
2512
2513   emitcode ("ret", "");
2514   emitcode ("", "%05d$:", (rlbl->key + 100));
2515
2516
2517   /* if we need assign a result value */
2518   if ((IS_ITEMP (IC_RESULT (ic)) &&
2519        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2520         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2521       IS_TRUE_SYMOP (IC_RESULT (ic)))
2522     {
2523
2524       _G.accInUse++;
2525       aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2526       _G.accInUse--;
2527
2528       assignResultValue (IC_RESULT (ic));
2529
2530       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2531     }
2532
2533   /* adjust the stack for parameters if
2534      required */
2535   if (ic->parmBytes)
2536     {
2537       int i;
2538       if (ic->parmBytes > 3)
2539         {
2540           emitcode ("mov", "a,%s", spname);
2541           emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2542           emitcode ("mov", "%s,a", spname);
2543         }
2544       else
2545         for (i = 0; i < ic->parmBytes; i++)
2546           emitcode ("dec", "%s", spname);
2547
2548     }
2549
2550   /* if register bank was saved then unsave them */
2551   if (restoreBank)
2552     unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2553   
2554   /* if we hade saved some registers then
2555      unsave them */
2556   if (ic->regsSaved)
2557     unsaveRegisters (ic);
2558
2559 }
2560
2561 /*-----------------------------------------------------------------*/
2562 /* resultRemat - result  is rematerializable                       */
2563 /*-----------------------------------------------------------------*/
2564 static int
2565 resultRemat (iCode * ic)
2566 {
2567   if (SKIP_IC (ic) || ic->op == IFX)
2568     return 0;
2569
2570   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2571     {
2572       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2573       if (sym->remat && !POINTER_SET (ic))
2574         return 1;
2575     }
2576
2577   return 0;
2578 }
2579
2580 #if defined(__BORLANDC__) || defined(_MSC_VER)
2581 #define STRCASECMP stricmp
2582 #else
2583 #define STRCASECMP strcasecmp
2584 #endif
2585
2586 /*-----------------------------------------------------------------*/
2587 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2588 /*-----------------------------------------------------------------*/
2589 static bool
2590 inExcludeList (char *s)
2591 {
2592   int i = 0;
2593
2594   if (options.excludeRegs[i] &&
2595       STRCASECMP (options.excludeRegs[i], "none") == 0)
2596     return FALSE;
2597
2598   for (i = 0; options.excludeRegs[i]; i++)
2599     {
2600       if (options.excludeRegs[i] &&
2601           STRCASECMP (s, options.excludeRegs[i]) == 0)
2602         return TRUE;
2603     }
2604   return FALSE;
2605 }
2606
2607 /*-----------------------------------------------------------------*/
2608 /* genFunction - generated code for function entry                 */
2609 /*-----------------------------------------------------------------*/
2610 static void
2611 genFunction (iCode * ic)
2612 {
2613   symbol *sym;
2614   sym_link *ftype;
2615   bool   switchedPSW = FALSE;
2616
2617   D (emitcode (";", "genFunction "););
2618
2619   _G.nRegsSaved = 0;
2620   /* create the function header */
2621   emitcode (";", "-----------------------------------------");
2622   emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2623   emitcode (";", "-----------------------------------------");
2624
2625   emitcode ("", "%s:", sym->rname);
2626   ftype = operandType (IC_LEFT (ic));
2627
2628   if (IFFUNC_ISNAKED(ftype))
2629   {
2630       emitcode(";", "naked function: no prologue.");
2631       return;
2632   }
2633   
2634   if (options.stack_probe) 
2635       emitcode ("lcall","__stack_probe");
2636   /* if critical function then turn interrupts off */
2637   if (IFFUNC_ISCRITICAL (ftype))
2638     emitcode ("clr", "ea");
2639
2640   /* here we need to generate the equates for the
2641      register bank if required */
2642   if (FUNC_REGBANK (ftype) != rbank)
2643     {
2644       int i;
2645
2646       rbank = FUNC_REGBANK (ftype);
2647       for (i = 0; i < ds390_nRegs; i++)
2648         {
2649           if (regs390[i].print) {
2650               if (strcmp (regs390[i].base, "0") == 0)
2651                   emitcode ("", "%s = 0x%02x",
2652                             regs390[i].dname,
2653                             8 * rbank + regs390[i].offset);
2654               else
2655                   emitcode ("", "%s = %s + 0x%02x",
2656                             regs390[i].dname,
2657                             regs390[i].base,
2658                             8 * rbank + regs390[i].offset);
2659           }
2660         }
2661     }
2662
2663   /* if this is an interrupt service routine then
2664      save acc, b, dpl, dph  */
2665   if (IFFUNC_ISISR (sym->type))
2666     {
2667
2668       if (!inExcludeList ("acc"))
2669         emitcode ("push", "acc");
2670       if (!inExcludeList ("b"))
2671         emitcode ("push", "b");
2672       if (!inExcludeList ("dpl"))
2673         emitcode ("push", "dpl");
2674       if (!inExcludeList ("dph"))
2675         emitcode ("push", "dph");
2676       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2677         {
2678           emitcode ("push", "dpx");
2679           /* Make sure we're using standard DPTR */
2680           emitcode ("push", "dps");
2681           emitcode ("mov", "dps, #0x00");
2682           if (options.stack10bit)
2683             {
2684               /* This ISR could conceivably use DPTR2. Better save it. */
2685               emitcode ("push", "dpl1");
2686               emitcode ("push", "dph1");
2687               emitcode ("push", "dpx1");
2688               emitcode ("push",  DP2_RESULT_REG);
2689             }
2690         }
2691       /* if this isr has no bank i.e. is going to
2692          run with bank 0 , then we need to save more
2693          registers :-) */
2694       if (!FUNC_REGBANK (sym->type))
2695         {
2696
2697           /* if this function does not call any other
2698              function then we can be economical and
2699              save only those registers that are used */
2700           if (!IFFUNC_HASFCALL(sym->type))
2701             {
2702               int i;
2703
2704               /* if any registers used */
2705               if (sym->regsUsed)
2706                 {
2707                   /* save the registers used */
2708                   for (i = 0; i < sym->regsUsed->size; i++)
2709                     {
2710                       if (bitVectBitValue (sym->regsUsed, i) ||
2711                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2712                         emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2713                     }
2714                 }
2715
2716             }
2717           else
2718             {
2719               /* this function has  a function call cannot
2720                  determines register usage so we will have to push the
2721                  entire bank */
2722               saveRBank (0, ic, FALSE);
2723             }
2724         }
2725         else
2726         {
2727             /* This ISR uses a non-zero bank.
2728              *
2729              * We assume that the bank is available for our
2730              * exclusive use.
2731              *
2732              * However, if this ISR calls a function which uses some
2733              * other bank, we must save that bank entirely.
2734              */
2735             unsigned long banksToSave = 0;
2736             
2737             if (IFFUNC_HASFCALL(sym->type))
2738             {
2739
2740 #define MAX_REGISTER_BANKS 4
2741
2742                 iCode *i;
2743                 int ix;
2744
2745                 for (i = ic; i; i = i->next)
2746                 {
2747                     if (i->op == ENDFUNCTION)
2748                     {
2749                         /* we got to the end OK. */
2750                         break;
2751                     }
2752                     
2753                     if (i->op == CALL)
2754                     {
2755                         sym_link *dtype;
2756                         
2757                         dtype = operandType (IC_LEFT(i));
2758                         if (dtype 
2759                          && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2760                         {
2761                              /* Mark this bank for saving. */
2762                              if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2763                              {
2764                                  werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2765                              }
2766                              else
2767                              {
2768                                  banksToSave |= (1 << FUNC_REGBANK(dtype));
2769                              }
2770                              
2771                              /* And note that we don't need to do it in 
2772                               * genCall.
2773                               */
2774                              i->bankSaved = 1;
2775                         }
2776                     }
2777                     if (i->op == PCALL)
2778                     {
2779                         /* This is a mess; we have no idea what
2780                          * register bank the called function might
2781                          * use.
2782                          *
2783                          * The only thing I can think of to do is
2784                          * throw a warning and hope.
2785                          */
2786                         werror(W_FUNCPTR_IN_USING_ISR);   
2787                     }
2788                 }
2789
2790                 if (banksToSave && options.useXstack)
2791                 {
2792                     /* Since we aren't passing it an ic, 
2793                      * saveRBank will assume r0 is available to abuse.
2794                      *
2795                      * So switch to our (trashable) bank now, so
2796                      * the caller's R0 isn't trashed.
2797                      */
2798                     emitcode ("push", "psw");
2799                     emitcode ("mov", "psw,#0x%02x", 
2800                               (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2801                     switchedPSW = TRUE;
2802                 }
2803                 
2804                 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2805                 {
2806                      if (banksToSave & (1 << ix))
2807                      {
2808                          saveRBank(ix, NULL, FALSE);
2809                      }
2810                 }
2811             }
2812             // jwk: this needs a closer look
2813             SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2814         }
2815     }
2816   else
2817     {
2818       /* if callee-save to be used for this function
2819          then save the registers being used in this function */
2820       if (IFFUNC_CALLEESAVES(sym->type))
2821         {
2822           int i;
2823
2824           /* if any registers used */
2825           if (sym->regsUsed)
2826             {
2827               /* save the registers used */
2828               for (i = 0; i < sym->regsUsed->size; i++)
2829                 {
2830                   if (bitVectBitValue (sym->regsUsed, i) ||
2831                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2832                     {
2833                       emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2834                       _G.nRegsSaved++;
2835                     }
2836                 }
2837             }
2838         }
2839     }
2840
2841   /* set the register bank to the desired value */
2842   if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
2843    && !switchedPSW)
2844     {
2845       emitcode ("push", "psw");
2846       emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2847     }
2848
2849   if (IFFUNC_ISREENT (sym->type) || options.stackAuto) {
2850       if (options.stack10bit) {
2851           emitcode ("push","_bpx");
2852           emitcode ("push","_bpx+1");
2853           emitcode ("mov","_bpx,%s",spname);
2854           emitcode ("mov","_bpx+1,esp");
2855           emitcode ("anl","_bpx+1,#3");
2856       } else {
2857           if (options.useXstack) {
2858               emitcode ("mov", "r0,%s", spname);
2859               emitcode ("mov", "a,_bp");
2860               emitcode ("movx", "@r0,a");
2861               emitcode ("inc", "%s", spname);
2862           } else {
2863               /* set up the stack */
2864               emitcode ("push", "_bp"); /* save the callers stack  */
2865           }
2866           emitcode ("mov", "_bp,%s", spname);
2867       }
2868   }
2869
2870   /* adjust the stack for the function */
2871   if (sym->stack) {
2872       int i = sym->stack;
2873       if (options.stack10bit) {
2874           if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);
2875           assert (sym->recvSize <= 4);
2876           emitcode ("mov","a,sp");
2877           emitcode ("add","a,#0x%02x", ((short) sym->stack & 0xff));
2878           emitcode ("mov","sp,a");
2879           emitcode ("mov","a,esp");
2880           emitcode ("addc","a,#0x%02x", (((short) sym->stack) >> 8) & 0xff);
2881           emitcode ("mov","esp,a");
2882       } else {
2883           if (i > 256)
2884               werror (W_STACK_OVERFLOW, sym->name);
2885           
2886           if (i > 3 && sym->recvSize < 4) {
2887               
2888               emitcode ("mov", "a,sp");
2889               emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2890               emitcode ("mov", "sp,a");
2891               
2892           } else
2893               while (i--)
2894                   emitcode ("inc", "sp");
2895       }
2896   }
2897
2898   if (sym->xstack)
2899     {
2900
2901       emitcode ("mov", "a,_spx");
2902       emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2903       emitcode ("mov", "_spx,a");
2904     }
2905
2906 }
2907
2908 /*-----------------------------------------------------------------*/
2909 /* genEndFunction - generates epilogue for functions               */
2910 /*-----------------------------------------------------------------*/
2911 static void
2912 genEndFunction (iCode * ic)
2913 {
2914   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2915
2916   D (emitcode (";", "genEndFunction "););
2917
2918   if (IFFUNC_ISNAKED(sym->type))
2919   {
2920       emitcode(";", "naked function: no epilogue.");
2921       return;
2922   }
2923
2924   if (IFFUNC_ISREENT (sym->type) || options.stackAuto) {
2925       if (options.stack10bit) {
2926           emitcode ("mov", "sp,_bpx", spname);
2927           emitcode ("mov", "esp,_bpx+1", spname);
2928       } else {
2929           emitcode ("mov", "%s,_bp", spname);
2930       }
2931   }
2932
2933   /* if use external stack but some variables were
2934      added to the local stack then decrement the
2935      local stack */
2936   if (options.useXstack && sym->stack) {
2937       emitcode ("mov", "a,sp");
2938       emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2939       emitcode ("mov", "sp,a");
2940   }
2941
2942
2943   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto)) {
2944       if (options.useXstack) {
2945           emitcode ("mov", "r0,%s", spname);
2946           emitcode ("movx", "a,@r0");
2947           emitcode ("mov", "_bp,a");
2948           emitcode ("dec", "%s", spname);
2949       } else {
2950           if (options.stack10bit) {
2951               emitcode ("pop", "_bpx+1");
2952               emitcode ("pop", "_bpx");
2953           } else {
2954               emitcode ("pop", "_bp");
2955           }
2956       }
2957   }
2958
2959   /* restore the register bank  */
2960   if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
2961   {
2962     if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
2963      || !options.useXstack)
2964     {
2965         /* Special case of ISR using non-zero bank with useXstack
2966          * is handled below.
2967          */
2968         emitcode ("pop", "psw");
2969     }
2970   }
2971
2972   if (IFFUNC_ISISR (sym->type))
2973     {
2974
2975       /* now we need to restore the registers */
2976       /* if this isr has no bank i.e. is going to
2977          run with bank 0 , then we need to save more
2978          registers :-) */
2979       if (!FUNC_REGBANK (sym->type))
2980         {
2981           /* if this function does not call any other
2982              function then we can be economical and
2983              save only those registers that are used */
2984           if (!IFFUNC_HASFCALL(sym->type))
2985             {
2986               int i;
2987
2988               /* if any registers used */
2989               if (sym->regsUsed)
2990                 {
2991                   /* save the registers used */
2992                   for (i = sym->regsUsed->size; i >= 0; i--)
2993                     {
2994                       if (bitVectBitValue (sym->regsUsed, i) ||
2995                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2996                         emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2997                     }
2998                 }
2999
3000             }
3001           else
3002             {
3003               /* this function has  a function call cannot
3004                  determines register usage so we will have to pop the
3005                  entire bank */
3006               unsaveRBank (0, ic, FALSE);
3007             }
3008         }
3009         else
3010         {
3011             /* This ISR uses a non-zero bank.
3012              *
3013              * Restore any register banks saved by genFunction
3014              * in reverse order.
3015              */
3016           // jwk: this needs a closer look
3017             unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3018             int ix;
3019           
3020             for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3021             {
3022                 if (savedBanks & (1 << ix))
3023                 {
3024                     unsaveRBank(ix, NULL, FALSE);
3025                 }
3026             }
3027             
3028             if (options.useXstack)
3029             {
3030                 /* Restore bank AFTER calling unsaveRBank,
3031                  * since it can trash r0.
3032                  */
3033                 emitcode ("pop", "psw");
3034             }
3035         }
3036
3037       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3038         {
3039           if (options.stack10bit)
3040             {
3041               emitcode ("pop", DP2_RESULT_REG);
3042               emitcode ("pop", "dpx1");
3043               emitcode ("pop", "dph1");
3044               emitcode ("pop", "dpl1");
3045             }
3046           emitcode ("pop", "dps");
3047           emitcode ("pop", "dpx");
3048         }
3049       if (!inExcludeList ("dph"))
3050         emitcode ("pop", "dph");
3051       if (!inExcludeList ("dpl"))
3052         emitcode ("pop", "dpl");
3053       if (!inExcludeList ("b"))
3054         emitcode ("pop", "b");
3055       if (!inExcludeList ("acc"))
3056         emitcode ("pop", "acc");
3057
3058       if (IFFUNC_ISCRITICAL (sym->type))
3059         emitcode ("setb", "ea");
3060
3061       /* if debug then send end of function */
3062       if (options.debug && currFunc) {
3063           _G.debugLine = 1;
3064           emitcode ("", "C$%s$%d$%d$%d ==.",
3065                     FileBaseName (ic->filename), currFunc->lastLine,
3066                     ic->level, ic->block);
3067           if (IS_STATIC (currFunc->etype))
3068             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3069           else
3070             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3071           _G.debugLine = 0;
3072         }
3073
3074       emitcode ("reti", "");
3075     }
3076   else
3077     {
3078       if (IFFUNC_ISCRITICAL (sym->type))
3079         emitcode ("setb", "ea");
3080
3081       if (IFFUNC_CALLEESAVES(sym->type))
3082         {
3083           int i;
3084
3085           /* if any registers used */
3086           if (sym->regsUsed)
3087             {
3088               /* save the registers used */
3089               for (i = sym->regsUsed->size; i >= 0; i--)
3090                 {
3091                   if (bitVectBitValue (sym->regsUsed, i) ||
3092                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3093                     emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3094                 }
3095             }
3096
3097         }
3098
3099       /* if debug then send end of function */
3100       if (options.debug && currFunc)
3101         {
3102           _G.debugLine = 1;
3103           emitcode ("", "C$%s$%d$%d$%d ==.",
3104                     FileBaseName (ic->filename), currFunc->lastLine,
3105                     ic->level, ic->block);
3106           if (IS_STATIC (currFunc->etype))
3107             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3108           else
3109             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3110           _G.debugLine = 0;
3111         }
3112
3113       emitcode ("ret", "");
3114     }
3115
3116 }
3117
3118 /*-----------------------------------------------------------------*/
3119 /* genRet - generate code for return statement                     */
3120 /*-----------------------------------------------------------------*/
3121 static void
3122 genRet (iCode * ic)
3123 {
3124   int size, offset = 0, pushed = 0;
3125
3126   D (emitcode (";", "genRet ");
3127     );
3128
3129   /* if we have no return value then
3130      just generate the "ret" */
3131   if (!IC_LEFT (ic))
3132     goto jumpret;
3133
3134   /* we have something to return then
3135      move the return value into place */
3136   aopOp (IC_LEFT (ic), ic, FALSE, 
3137          (IS_SYMOP(IC_LEFT(ic)) && OP_SYMBOL(IC_LEFT(ic))->ruonly ? FALSE :TRUE));
3138   size = AOP_SIZE (IC_LEFT (ic));
3139
3140   _startLazyDPSEvaluation ();
3141   while (size--)
3142     {
3143       char *l;
3144       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3145         {
3146           l = aopGet (AOP (IC_LEFT (ic)), offset++,
3147                       FALSE, TRUE, FALSE);
3148           emitcode ("push", "%s", l);
3149           pushed++;
3150         }
3151       else
3152         {
3153           /* Since A is the last element of fReturn,
3154            * is is OK to clobber it in the aopGet.
3155            */
3156           l = aopGet (AOP (IC_LEFT (ic)), offset,
3157                       FALSE, FALSE, TRUE);
3158           if (strcmp (fReturn[offset], l))
3159             emitcode ("mov", "%s,%s", fReturn[offset++], l);
3160         }
3161     }
3162   _endLazyDPSEvaluation ();
3163
3164   if (pushed)
3165     {
3166       while (pushed)
3167         {
3168           pushed--;
3169           if (strcmp (fReturn[pushed], "a"))
3170             emitcode ("pop", fReturn[pushed]);
3171           else
3172             emitcode ("pop", "acc");
3173         }
3174     }
3175   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3176
3177 jumpret:
3178   /* generate a jump to the return label
3179      if the next is not the return statement */
3180   if (!(ic->next && ic->next->op == LABEL &&
3181         IC_LABEL (ic->next) == returnLabel))
3182
3183     emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3184
3185 }
3186
3187 /*-----------------------------------------------------------------*/
3188 /* genLabel - generates a label                                    */
3189 /*-----------------------------------------------------------------*/
3190 static void
3191 genLabel (iCode * ic)
3192 {
3193   /* special case never generate */
3194   if (IC_LABEL (ic) == entryLabel)
3195     return;
3196
3197   D (emitcode (";", "genLabel ");
3198     );
3199
3200   emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3201 }
3202
3203 /*-----------------------------------------------------------------*/
3204 /* genGoto - generates a ljmp                                      */
3205 /*-----------------------------------------------------------------*/
3206 static void
3207 genGoto (iCode * ic)
3208 {
3209   D (emitcode (";", "genGoto ");
3210     );
3211   emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
3212 }
3213
3214 /*-----------------------------------------------------------------*/
3215 /* findLabelBackwards: walks back through the iCode chain looking  */
3216 /* for the given label. Returns number of iCode instructions     */
3217 /* between that label and given ic.          */
3218 /* Returns zero if label not found.          */
3219 /*-----------------------------------------------------------------*/
3220 static int
3221 findLabelBackwards (iCode * ic, int key)
3222 {
3223   int count = 0;
3224
3225   while (ic->prev)
3226     {
3227       ic = ic->prev;
3228       count++;
3229
3230       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3231         {
3232           /* printf("findLabelBackwards = %d\n", count); */
3233           return count;
3234         }
3235     }
3236
3237   return 0;
3238 }
3239
3240 /*-----------------------------------------------------------------*/
3241 /* genPlusIncr :- does addition with increment if possible         */
3242 /*-----------------------------------------------------------------*/
3243 static bool
3244 genPlusIncr (iCode * ic)
3245 {
3246   unsigned int icount;
3247   unsigned int size = getDataSize (IC_RESULT (ic));
3248
3249   /* will try to generate an increment */
3250   /* if the right side is not a literal
3251      we cannot */
3252   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3253     return FALSE;
3254
3255   /* if the literal value of the right hand side
3256      is greater than 4 then it is not worth it */
3257   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3258     return FALSE;
3259
3260   /* if increment 16 bits in register */
3261   if (
3262        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3263        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3264        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3265        (size > 1) &&
3266        (icount == 1))
3267     {
3268       symbol *tlbl;
3269       int emitTlbl;
3270       int labelRange;
3271
3272       /* If the next instruction is a goto and the goto target
3273        * is <= 5 instructions previous to this, we can generate
3274        * jumps straight to that target.
3275        */
3276       if (ic->next && ic->next->op == GOTO
3277           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3278           && labelRange <= 5)
3279         {
3280           emitcode (";", "tail increment optimized (range %d)", labelRange);
3281           tlbl = IC_LABEL (ic->next);
3282           emitTlbl = 0;
3283         }
3284       else
3285         {
3286           tlbl = newiTempLabel (NULL);
3287           emitTlbl = 1;
3288         }
3289       emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3290       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3291           IS_AOP_PREG (IC_RESULT (ic)))
3292         emitcode ("cjne", "%s,#0x00,%05d$"
3293                   ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3294                   ,tlbl->key + 100);
3295       else
3296         {
3297           emitcode ("clr", "a");
3298           emitcode ("cjne", "a,%s,%05d$"
3299                     ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3300                     ,tlbl->key + 100);
3301         }
3302
3303       emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3304       if (size > 2)
3305         {
3306           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3307               IS_AOP_PREG (IC_RESULT (ic)))
3308             emitcode ("cjne", "%s,#0x00,%05d$"
3309                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3310                       ,tlbl->key + 100);
3311           else
3312             emitcode ("cjne", "a,%s,%05d$"
3313                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3314                       ,tlbl->key + 100);
3315
3316           emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3317         }
3318       if (size > 3)
3319         {
3320           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3321               IS_AOP_PREG (IC_RESULT (ic)))
3322             emitcode ("cjne", "%s,#0x00,%05d$"
3323                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3324                       ,tlbl->key + 100);
3325           else
3326             {
3327               emitcode ("cjne", "a,%s,%05d$"
3328                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3329                         ,tlbl->key + 100);
3330             }
3331           emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3332         }
3333
3334       if (emitTlbl)
3335         {
3336           emitcode ("", "%05d$:", tlbl->key + 100);
3337         }
3338       return TRUE;
3339     }
3340
3341   /* if the sizes are greater than 1 then we cannot */
3342   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3343       AOP_SIZE (IC_LEFT (ic)) > 1)
3344     return FALSE;
3345
3346   /* we can if the aops of the left & result match or
3347      if they are in registers and the registers are the
3348      same */
3349   if (
3350        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3351        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3352        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3353     {
3354
3355       if (icount > 3)
3356         {
3357           MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3358           emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3359           aopPut (AOP (IC_RESULT (ic)), "a", 0);
3360         }
3361       else
3362         {
3363
3364           _startLazyDPSEvaluation ();
3365           while (icount--)
3366             {
3367               emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3368             }
3369           _endLazyDPSEvaluation ();
3370         }
3371
3372       return TRUE;
3373     }
3374
3375   return FALSE;
3376 }
3377
3378 /*-----------------------------------------------------------------*/
3379 /* outBitAcc - output a bit in acc                                 */
3380 /*-----------------------------------------------------------------*/
3381 static void
3382 outBitAcc (operand * result)
3383 {
3384   symbol *tlbl = newiTempLabel (NULL);
3385   /* if the result is a bit */
3386   if (AOP_TYPE (result) == AOP_CRY)
3387     {
3388       aopPut (AOP (result), "a", 0);
3389     }
3390   else
3391     {
3392       emitcode ("jz", "%05d$", tlbl->key + 100);
3393       emitcode ("mov", "a,%s", one);
3394       emitcode ("", "%05d$:", tlbl->key + 100);
3395       outAcc (result);
3396     }
3397 }
3398
3399 /*-----------------------------------------------------------------*/
3400 /* genPlusBits - generates code for addition of two bits           */
3401 /*-----------------------------------------------------------------*/
3402 static void
3403 genPlusBits (iCode * ic)
3404 {
3405   D (emitcode (";", "genPlusBits ");
3406     );
3407   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3408     {
3409       symbol *lbl = newiTempLabel (NULL);
3410       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3411       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3412       emitcode ("cpl", "c");
3413       emitcode ("", "%05d$:", (lbl->key + 100));
3414       outBitC (IC_RESULT (ic));
3415     }
3416   else
3417     {
3418       emitcode ("clr", "a");
3419       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3420       emitcode ("rlc", "a");
3421       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3422       emitcode ("addc", "a,#0x00");
3423       outAcc (IC_RESULT (ic));
3424     }
3425 }
3426
3427 static void
3428 adjustArithmeticResult (iCode * ic)
3429 {
3430   if (opIsGptr (IC_RESULT (ic)) &&
3431       opIsGptr (IC_LEFT (ic)) &&
3432       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3433     {
3434       aopPut (AOP (IC_RESULT (ic)),
3435               aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3436               GPTRSIZE - 1);
3437     }
3438
3439   if (opIsGptr (IC_RESULT (ic)) &&
3440       opIsGptr (IC_RIGHT (ic)) &&
3441       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3442     {
3443       aopPut (AOP (IC_RESULT (ic)),
3444             aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3445               GPTRSIZE - 1);
3446     }
3447
3448   if (opIsGptr (IC_RESULT (ic)) &&
3449       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3450       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3451       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3452       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3453     {
3454       char buffer[5];
3455       sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3456       aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3457     }
3458 }
3459
3460 #if 0 // AOP_OP_3 is deprecated; nobody likes Ack errors.
3461       // Please don't bring it back without a really good reason.
3462 // Macro to aopOp all three operands of an ic. Will fatal if this cannot be done
3463 // (because all three operands are in far space).
3464 #define AOP_OP_3(ic) \
3465     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3466     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3467     aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3468               (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3469     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3470         AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3471     { \
3472         /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3473         fprintf(stderr,                                  \
3474                "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno);   \
3475     }
3476 #endif
3477
3478 // Macro to aopOp all three operands of an ic. If this cannot be done, 
3479 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3480 // will be set TRUE. The caller must then handle the case specially, noting
3481 // that the IC_RESULT operand is not aopOp'd.
3482 #define AOP_OP_3_NOFATAL(ic, rc) \
3483     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3484     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR) || \
3485                                   (OP_SYMBOL(IC_RESULT(ic))->ruonly)); \
3486     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3487         (isOperandInFarSpace(IC_RESULT(ic)) || OP_SYMBOL(IC_RESULT(ic))->ruonly )) \
3488     { \
3489        /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3490        rc = TRUE; \
3491     }  \
3492     else \
3493     { \
3494        aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3495                                      (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3496        rc = FALSE; \
3497        if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3498            AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3499        { \
3500             /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3501             fprintf(stderr,                                  \
3502                     "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno);   \
3503        } \
3504     }
3505
3506 // aopOp the left & right operands of an ic.
3507 #define AOP_OP_2(ic) \
3508     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3509     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3510
3511 // convienience macro.
3512 #define AOP_SET_LOCALS(ic) \
3513     left = IC_LEFT(ic); \
3514     right = IC_RIGHT(ic); \
3515     result = IC_RESULT(ic);
3516
3517
3518 // Given an integer value of pushedSize bytes on the stack,
3519 // adjust it to be resultSize bytes, either by discarding
3520 // the most significant bytes or by zero-padding.
3521 //
3522 // On exit from this macro, pushedSize will have been adjusted to
3523 // equal resultSize, and ACC may be trashed.
3524 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize)            \
3525       /* If the pushed data is bigger than the result,          \
3526        * simply discard unused bytes. Icky, but works.          \
3527        */                                                       \
3528       while (pushedSize > resultSize)                           \
3529       {                                                         \
3530           D (emitcode (";", "discarding unused result byte."););\
3531           emitcode ("pop", "acc");                              \
3532           pushedSize--;                                         \
3533       }                                                         \
3534       if (pushedSize < resultSize)                              \
3535       {                                                         \
3536           emitcode ("clr", "a");                                \
3537           /* Conversly, we haven't pushed enough here.          \
3538            * just zero-pad, and all is well.                    \
3539            */                                                   \
3540           while (pushedSize < resultSize)                       \
3541           {                                                     \
3542               emitcode("push", "acc");                          \
3543               pushedSize++;                                     \
3544           }                                                     \
3545       }                                                         \
3546       assert(pushedSize == resultSize);
3547
3548 /*-----------------------------------------------------------------*/
3549 /* genPlus - generates code for addition                           */
3550 /*-----------------------------------------------------------------*/
3551 static void
3552 genPlus (iCode * ic)
3553 {
3554   int size, offset = 0;
3555   bool pushResult = FALSE;
3556   int rSize;
3557
3558   D (emitcode (";", "genPlus "););
3559
3560   /* special cases :- */
3561   if ( IS_SYMOP(IC_LEFT(ic)) && OP_SYMBOL(IC_LEFT(ic))->ruonly &&
3562       isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
3563       aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
3564       size = floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
3565       if (size <= 9) {
3566           while (size--) emitcode ("inc","dptr");
3567       } else {
3568           emitcode ("mov","a,dpl");
3569           emitcode ("add","a,#0x%02x",size & 0xff);
3570           emitcode ("mov","dpl,a");
3571           emitcode ("mov","a,dph");
3572           emitcode ("addc","a,#0x%02x",(size >> 8) & 0xff);
3573           emitcode ("mov","dph,a");
3574           emitcode ("mov","a,dpx");
3575           emitcode ("addc","a,#0x%02x",(size >> 16) & 0xff);
3576           emitcode ("mov","dpx,a");
3577       }
3578       freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
3579       return ;
3580   }
3581   if ( IS_SYMOP(IC_LEFT(ic)) && 
3582        OP_SYMBOL(IC_LEFT(ic))->remat &&
3583        isOperandInFarSpace(IC_RIGHT(ic))) {
3584       operand *op = IC_RIGHT(ic);
3585       IC_RIGHT(ic) = IC_LEFT(ic);
3586       IC_LEFT(ic) = op;
3587   }
3588                 
3589   AOP_OP_3_NOFATAL (ic, pushResult);
3590   if (pushResult)
3591     {
3592       D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3593     }
3594
3595   if (!pushResult)
3596     {
3597       /* if literal, literal on the right or
3598          if left requires ACC or right is already
3599          in ACC */
3600       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3601        || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3602           || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3603         {
3604           operand *t = IC_RIGHT (ic);
3605           IC_RIGHT (ic) = IC_LEFT (ic);
3606           IC_LEFT (ic) = t;
3607           emitcode (";", "Swapped plus args.");
3608         }
3609
3610       /* if both left & right are in bit
3611          space */
3612       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3613           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3614         {
3615           genPlusBits (ic);
3616           goto release;
3617         }
3618
3619       /* if left in bit space & right literal */
3620       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3621           AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3622         {
3623           emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3624           /* if result in bit space */
3625           if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3626             {
3627               if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3628                 emitcode ("cpl", "c");
3629               outBitC (IC_RESULT (ic));
3630             }
3631           else
3632             {
3633               size = getDataSize (IC_RESULT (ic));
3634               _startLazyDPSEvaluation ();
3635               while (size--)
3636                 {
3637                   MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3638                   emitcode ("addc", "a,#00");
3639                   aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3640                 }
3641               _endLazyDPSEvaluation ();
3642             }
3643           goto release;
3644         }
3645
3646       /* if I can do an increment instead
3647          of add then GOOD for ME */
3648       if (genPlusIncr (ic) == TRUE)
3649         {
3650           emitcode (";", "did genPlusIncr");
3651           goto release;
3652         }
3653
3654     }
3655   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3656
3657   _startLazyDPSEvaluation ();
3658   while (size--)
3659     {
3660       if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
3661         {
3662           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3663           if (offset == 0)
3664             emitcode ("add", "a,%s",
3665                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3666           else
3667             emitcode ("addc", "a,%s",
3668                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3669         }
3670       else
3671         {
3672           if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
3673           {
3674               /* right is going to use ACC or we would have taken the
3675                * above branch.
3676                */
3677               assert(AOP_NEEDSACC(IC_RIGHT(ic)));
3678        TR_AP("#3");
3679               D(emitcode(";", "+ AOP_ACC special case."););
3680               emitcode("xch", "a, %s", DP2_RESULT_REG);
3681           }
3682           MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3683           if (offset == 0)
3684           {
3685             if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
3686             {
3687          TR_AP("#4");
3688                 emitcode("add", "a, %s", DP2_RESULT_REG); 
3689             }
3690             else
3691             {
3692                 emitcode ("add", "a,%s",
3693                         aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE, FALSE));
3694             }
3695           }
3696           else
3697           {
3698             emitcode ("addc", "a,%s",
3699                   aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3700           }
3701         }
3702       if (!pushResult)
3703         {
3704           aopPut (AOP (IC_RESULT (ic)), "a", offset);
3705         }
3706       else
3707         {
3708           emitcode ("push", "acc");
3709         }
3710       offset++;
3711     }
3712   _endLazyDPSEvaluation ();
3713
3714   if (pushResult)
3715     {
3716       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3717
3718       size = getDataSize (IC_LEFT (ic));
3719       rSize = getDataSize (IC_RESULT (ic));
3720
3721       ADJUST_PUSHED_RESULT(size, rSize);
3722
3723       _startLazyDPSEvaluation ();
3724       while (size--)
3725         {
3726           emitcode ("pop", "acc");
3727           aopPut (AOP (IC_RESULT (ic)), "a", size);
3728         }
3729       _endLazyDPSEvaluation ();
3730     }
3731
3732   adjustArithmeticResult (ic);
3733
3734 release:
3735   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3736   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3737   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3738 }
3739
3740 /*-----------------------------------------------------------------*/
3741 /* genMinusDec :- does subtraction with deccrement if possible     */
3742 /*-----------------------------------------------------------------*/
3743 static bool
3744 genMinusDec (iCode * ic)
3745 {
3746   unsigned int icount;
3747   unsigned int size = getDataSize (IC_RESULT (ic));
3748
3749   /* will try to generate an increment */
3750   /* if the right side is not a literal
3751      we cannot */
3752   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3753     return FALSE;
3754
3755   /* if the literal value of the right hand side
3756      is greater than 4 then it is not worth it */
3757   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3758     return FALSE;
3759
3760   /* if decrement 16 bits in register */
3761   if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3762       AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3763       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3764       (size > 1) &&
3765       (icount == 1))
3766     {
3767       symbol *tlbl;
3768       int emitTlbl;
3769       int labelRange;
3770
3771       /* If the next instruction is a goto and the goto target
3772          * is <= 5 instructions previous to this, we can generate
3773          * jumps straight to that target.
3774        */
3775       if (ic->next && ic->next->op == GOTO
3776           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3777           && labelRange <= 5)
3778         {
3779           emitcode (";", "tail decrement optimized (range %d)", labelRange);
3780           tlbl = IC_LABEL (ic->next);
3781           emitTlbl = 0;
3782         }
3783       else
3784         {
3785           tlbl = newiTempLabel (NULL);
3786           emitTlbl = 1;
3787         }
3788
3789       emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3790       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3791           AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3792           IS_AOP_PREG (IC_RESULT (ic)))
3793         emitcode ("cjne", "%s,#0xff,%05d$"
3794                   ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3795                   ,tlbl->key + 100);
3796       else
3797         {
3798           emitcode ("mov", "a,#0xff");
3799           emitcode ("cjne", "a,%s,%05d$"
3800                     ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3801                     ,tlbl->key + 100);
3802         }
3803       emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3804       if (size > 2)
3805         {
3806           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3807               AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3808               IS_AOP_PREG (IC_RESULT (ic)))
3809             emitcode ("cjne", "%s,#0xff,%05d$"
3810                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3811                       ,tlbl->key + 100);
3812           else
3813             {
3814               emitcode ("cjne", "a,%s,%05d$"
3815                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3816                         ,tlbl->key + 100);
3817             }
3818           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3819         }
3820       if (size > 3)
3821         {
3822           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3823               AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3824               IS_AOP_PREG (IC_RESULT (ic)))
3825             emitcode ("cjne", "%s,#0xff,%05d$"
3826                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3827                       ,tlbl->key + 100);
3828           else
3829             {
3830               emitcode ("cjne", "a,%s,%05d$"
3831                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3832                         ,tlbl->key + 100);
3833             }
3834           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3835         }
3836       if (emitTlbl)
3837         {
3838           emitcode ("", "%05d$:", tlbl->key + 100);
3839         }
3840       return TRUE;
3841     }
3842
3843   /* if the sizes are greater than 1 then we cannot */
3844   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3845       AOP_SIZE (IC_LEFT (ic)) > 1)
3846     return FALSE;
3847
3848   /* we can if the aops of the left & result match or
3849      if they are in registers and the registers are the
3850      same */
3851   if (
3852        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3853        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3854        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3855     {
3856
3857       _startLazyDPSEvaluation ();
3858       while (icount--)
3859         {
3860           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
3861         }
3862       _endLazyDPSEvaluation ();
3863
3864       return TRUE;
3865     }
3866
3867   return FALSE;
3868 }
3869
3870 /*-----------------------------------------------------------------*/
3871 /* addSign - complete with sign                                    */
3872 /*-----------------------------------------------------------------*/
3873 static void
3874 addSign (operand * result, int offset, int sign)
3875 {
3876   int size = (getDataSize (result) - offset);
3877   if (size > 0)
3878     {
3879       _startLazyDPSEvaluation();
3880       if (sign)
3881         {
3882           emitcode ("rlc", "a");
3883           emitcode ("subb", "a,acc");
3884           while (size--)
3885           {
3886             aopPut (AOP (result), "a", offset++);
3887           }
3888         }
3889       else
3890       {
3891         while (size--)
3892         {
3893           aopPut (AOP (result), zero, offset++);
3894         }
3895       }
3896       _endLazyDPSEvaluation();
3897     }
3898 }
3899
3900 /*-----------------------------------------------------------------*/
3901 /* genMinusBits - generates code for subtraction  of two bits      */
3902 /*-----------------------------------------------------------------*/
3903 static void
3904 genMinusBits (iCode * ic)
3905 {
3906   symbol *lbl = newiTempLabel (NULL);
3907
3908   D (emitcode (";", "genMinusBits "););
3909
3910   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3911     {
3912       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3913       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3914       emitcode ("cpl", "c");
3915       emitcode ("", "%05d$:", (lbl->key + 100));
3916       outBitC (IC_RESULT (ic));
3917     }
3918   else
3919     {
3920       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3921       emitcode ("subb", "a,acc");
3922       emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3923       emitcode ("inc", "a");
3924       emitcode ("", "%05d$:", (lbl->key + 100));
3925       aopPut (AOP (IC_RESULT (ic)), "a", 0);
3926       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3927     }
3928 }
3929
3930 /*-----------------------------------------------------------------*/
3931 /* genMinus - generates code for subtraction                       */
3932 /*-----------------------------------------------------------------*/
3933 static void
3934 genMinus (iCode * ic)
3935 {
3936   int size, offset = 0;
3937   int rSize;
3938   unsigned long lit = 0L;
3939   bool pushResult = FALSE;
3940
3941   D (emitcode (";", "genMinus "););
3942
3943   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3944   aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
3945   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
3946       (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
3947     {
3948       pushResult = TRUE;
3949     }
3950   else
3951     {
3952       aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
3953
3954       /* special cases :- */
3955       /* if both left & right are in bit space */
3956       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3957           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3958         {
3959           genMinusBits (ic);
3960           goto release;
3961         }
3962
3963       /* if I can do an decrement instead
3964          of subtract then GOOD for ME */
3965       if (genMinusDec (ic) == TRUE)
3966         goto release;
3967
3968     }
3969
3970   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3971
3972   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3973     {
3974       CLRC;
3975     }
3976   else
3977     {
3978       lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3979       lit = -(long) lit;
3980     }
3981
3982
3983   /* if literal, add a,#-lit, else normal subb */
3984   _startLazyDPSEvaluation ();
3985   while (size--)
3986     {
3987       MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3988       if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3989         emitcode ("subb", "a,%s",
3990                   aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3991       else
3992         {
3993           /* first add without previous c */
3994           if (!offset) {
3995             if (!size && lit==-1) {
3996               emitcode ("dec", "a");
3997             } else {
3998               emitcode ("add", "a,#0x%02x",
3999                         (unsigned int) (lit & 0x0FFL));
4000             }
4001           } else {
4002             emitcode ("addc", "a,#0x%02x",
4003                       (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4004           }
4005         }
4006
4007       if (pushResult)
4008         {
4009           emitcode ("push", "acc");
4010         }
4011       else
4012         {
4013           aopPut (AOP (IC_RESULT (ic)), "a", offset);
4014         }
4015       offset++;
4016     }
4017   _endLazyDPSEvaluation ();
4018
4019   if (pushResult)
4020     {
4021       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4022
4023       size = getDataSize (IC_LEFT (ic));
4024       rSize = getDataSize (IC_RESULT (ic));
4025
4026       ADJUST_PUSHED_RESULT(size, rSize);
4027
4028       _startLazyDPSEvaluation ();
4029       while (size--)
4030         {
4031           emitcode ("pop", "acc");
4032           aopPut (AOP (IC_RESULT (ic)), "a", size);
4033         }
4034       _endLazyDPSEvaluation ();
4035     }
4036
4037   adjustArithmeticResult (ic);
4038
4039 release:
4040   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4041   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4042   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4043 }
4044
4045
4046 /*-----------------------------------------------------------------*/
4047 /* genMultbits :- multiplication of bits                           */
4048 /*-----------------------------------------------------------------*/
4049 static void
4050 genMultbits (operand * left,
4051              operand * right,
4052              operand * result,
4053              iCode   * ic)
4054 {
4055   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4056   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4057   aopOp(result, ic, TRUE, FALSE);
4058   outBitC (result);
4059 }
4060
4061
4062 /*-----------------------------------------------------------------*/
4063 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
4064 /*-----------------------------------------------------------------*/
4065 static void
4066 genMultOneByte (operand * left,
4067                 operand * right,
4068                 operand * result,
4069                 iCode   * ic)
4070 {
4071   sym_link *opetype = operandType (result);
4072   symbol *lbl;
4073
4074
4075   /* (if two literals: the value is computed before) */
4076   /* if one literal, literal on the right */
4077   if (AOP_TYPE (left) == AOP_LIT)
4078     {
4079       operand *t = right;
4080       right = left;
4081       left = t;
4082       emitcode (";", "swapped left and right");
4083     }
4084
4085   if (SPEC_USIGN(opetype)
4086       // ignore the sign of left and right, what else can we do?
4087       || (SPEC_USIGN(operandType(left)) && 
4088           SPEC_USIGN(operandType(right)))) {
4089     // just an unsigned 8*8=8/16 multiply
4090     //emitcode (";","unsigned");
4091     emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4092     MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4093     emitcode ("mul", "ab");
4094    
4095     _G.accInUse++;
4096     aopOp(result, ic, TRUE, FALSE);
4097       
4098       if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4099       {
4100           // this should never happen
4101           fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4102                    AOP_SIZE(result), __FILE__, lineno);
4103           exit (1);
4104       }      
4105       
4106     aopPut (AOP (result), "a", 0);
4107     _G.accInUse--;
4108     if (AOP_SIZE(result)==2) 
4109     {
4110       aopPut (AOP (result), "b", 1);
4111     }
4112     return;
4113   }
4114
4115   // we have to do a signed multiply
4116
4117   emitcode (";", "signed");
4118   emitcode ("clr", "F0"); // reset sign flag
4119   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4120
4121   lbl=newiTempLabel(NULL);
4122   emitcode ("jnb", "acc.7,%05d$",  lbl->key+100);
4123   // left side is negative, 8-bit two's complement, this fails for -128
4124   emitcode ("setb", "F0"); // set sign flag
4125   emitcode ("cpl", "a");
4126   emitcode ("inc", "a");
4127
4128   emitcode ("", "%05d$:", lbl->key+100);
4129
4130   /* if literal */
4131   if (AOP_TYPE(right)==AOP_LIT) {
4132     signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
4133     /* AND literal negative */
4134     if ((int) val < 0) {
4135       emitcode ("cpl", "F0"); // complement sign flag
4136       emitcode ("mov", "b,#0x%02x", -val);
4137     } else {
4138       emitcode ("mov", "b,#0x%02x", val);
4139     }
4140   } else {
4141     lbl=newiTempLabel(NULL);
4142     emitcode ("mov", "b,a");
4143     emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4144     emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
4145     // right side is negative, 8-bit two's complement
4146     emitcode ("cpl", "F0"); // complement sign flag
4147     emitcode ("cpl", "a");
4148     emitcode ("inc", "a");
4149     emitcode ("", "%05d$:", lbl->key+100);
4150   }
4151   emitcode ("mul", "ab");
4152     
4153   _G.accInUse++;
4154   aopOp(result, ic, TRUE, FALSE);
4155     
4156   if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4157   {
4158     // this should never happen
4159       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4160                AOP_SIZE(result), __FILE__, lineno);
4161       exit (1);
4162   }    
4163     
4164   lbl=newiTempLabel(NULL);
4165   emitcode ("jnb", "F0,%05d$", lbl->key+100);
4166   // only ONE op was negative, we have to do a 8/16-bit two's complement
4167   emitcode ("cpl", "a"); // lsb
4168   if (AOP_SIZE(result)==1) {
4169     emitcode ("inc", "a");
4170   } else {
4171     emitcode ("add", "a,#1");
4172     emitcode ("xch", "a,b");
4173     emitcode ("cpl", "a"); // msb
4174     emitcode ("addc", "a,#0");
4175     emitcode ("xch", "a,b");
4176   }
4177
4178   emitcode ("", "%05d$:", lbl->key+100);
4179   aopPut (AOP (result), "a", 0);
4180   _G.accInUse--;
4181   if (AOP_SIZE(result)==2) {
4182     aopPut (AOP (result), "b", 1);
4183   }
4184 }
4185
4186 /*-----------------------------------------------------------------*/
4187 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply    */
4188 /*-----------------------------------------------------------------*/
4189 static void genMultTwoByte (operand *left, operand *right, 
4190                             operand *result, iCode *ic)
4191 {
4192         sym_link *retype = getSpec(operandType(right));
4193         sym_link *letype = getSpec(operandType(left));
4194         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4195         symbol *lbl;
4196
4197         if (AOP_TYPE (left) == AOP_LIT) {
4198                 operand *t = right;
4199                 right = left;
4200                 left = t;
4201         }
4202         /* save EA bit in F1 */
4203         lbl = newiTempLabel(NULL);
4204         emitcode ("setb","F1");
4205         emitcode ("jbc","EA,%05d$",lbl->key+100);
4206         emitcode ("clr","F1");
4207         emitcode("","%05d$:",lbl->key+100);
4208
4209         /* load up MB with right */
4210         if (!umult) {
4211                 emitcode("clr","F0");
4212                 if (AOP_TYPE(right) == AOP_LIT) {
4213                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
4214                         if (val < 0) {
4215                                 emitcode("setb","F0");
4216                                 val = -val;
4217                         }
4218                         emitcode ("mov","mb,#0x%02x",val & 0xff);
4219                         emitcode ("mov","mb,#0x%02x",(val >> 8) & 0xff);                    
4220                 } else {
4221                         lbl = newiTempLabel(NULL);
4222                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4223                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4224                         emitcode ("jnb","acc.7,%05d$",lbl->key+100);            
4225                         emitcode ("xch", "a,b");
4226                         emitcode ("cpl","a");
4227                         emitcode ("add", "a,#1");
4228                         emitcode ("xch", "a,b");
4229                         emitcode ("cpl", "a"); // msb
4230                         emitcode ("addc", "a,#0");
4231                         emitcode ("setb","F0");
4232                         emitcode ("","%05d$:",lbl->key+100);
4233                         emitcode ("mov","mb,b");
4234                         emitcode ("mov","mb,a");
4235                 }
4236         } else {
4237                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4238                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4239         }
4240         /* load up MA with left */
4241         if (!umult) {
4242                 lbl = newiTempLabel(NULL);
4243                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4244                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4245                 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4246                 emitcode ("xch", "a,b");
4247                 emitcode ("cpl","a");
4248                 emitcode ("add", "a,#1");
4249                 emitcode ("xch", "a,b");
4250                 emitcode ("cpl", "a"); // msb
4251                 emitcode ("addc","a,#0");
4252                 emitcode ("jbc","F0,%05d$",lbl->key+100);
4253                 emitcode ("setb","F0");
4254                 emitcode ("","%05d$:",lbl->key+100);
4255                 emitcode ("mov","ma,b");
4256                 emitcode ("mov","ma,a");
4257         } else {
4258                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4259                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4260         }
4261         /* wait for multiplication to finish */
4262         lbl = newiTempLabel(NULL);
4263         emitcode("","%05d$:", lbl->key+100);
4264         emitcode("mov","a,mcnt1");
4265         emitcode("anl","a,#0x80");
4266         emitcode("jnz","%05d$",lbl->key+100);
4267         
4268         freeAsmop (left, NULL, ic, TRUE);
4269         freeAsmop (right, NULL, ic,TRUE);
4270         aopOp(result, ic, TRUE, FALSE);
4271
4272         /* if unsigned then simple */   
4273         if (umult) {
4274                 emitcode ("mov","a,ma");
4275                 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4276                 emitcode ("mov","a,ma");
4277                 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4278                 aopPut(AOP(result),"ma",1);
4279                 aopPut(AOP(result),"ma",0);
4280         } else {
4281                 emitcode("push","ma");
4282                 emitcode("push","ma");
4283                 emitcode("push","ma");
4284                 MOVA("ma");
4285                 /* negate result if needed */
4286                 lbl = newiTempLabel(NULL);      
4287                 emitcode("jnb","F0,%05d$",lbl->key+100);
4288                 emitcode("cpl","a");
4289                 emitcode("add","a,#1");
4290                 emitcode("","%05d$:", lbl->key+100);
4291                 if (AOP_TYPE(result) == AOP_ACC)
4292                 {
4293                     D(emitcode(";", "ACC special case."););
4294                     /* We know result is the only live aop, and 
4295                      * it's obviously not a DPTR2, so AP is available.
4296                      */
4297                     emitcode("mov", "%s,acc", DP2_RESULT_REG);
4298                 }
4299                 else
4300                 {
4301                     aopPut(AOP(result),"a",0);
4302                 }
4303             
4304                 emitcode("pop","acc");
4305                 lbl = newiTempLabel(NULL);      
4306                 emitcode("jnb","F0,%05d$",lbl->key+100);
4307                 emitcode("cpl","a");
4308                 emitcode("addc","a,#0");
4309                 emitcode("","%05d$:", lbl->key+100);
4310                 aopPut(AOP(result),"a",1);
4311                 emitcode("pop","acc");
4312                 if (AOP_SIZE(result) >= 3) {
4313                         lbl = newiTempLabel(NULL);      
4314                         emitcode("jnb","F0,%05d$",lbl->key+100);
4315                         emitcode("cpl","a");
4316                         emitcode("addc","a,#0");                        
4317                         emitcode("","%05d$:", lbl->key+100);
4318                         aopPut(AOP(result),"a",2);
4319                 }
4320                 emitcode("pop","acc");
4321                 if (AOP_SIZE(result) >= 4) {
4322                         lbl = newiTempLabel(NULL);      
4323                         emitcode("jnb","F0,%05d$",lbl->key+100);
4324                         emitcode("cpl","a");
4325                         emitcode("addc","a,#0");                        
4326                         emitcode("","%05d$:", lbl->key+100);
4327                         aopPut(AOP(result),"a",3);
4328                 }
4329                 if (AOP_TYPE(result) == AOP_ACC)
4330                 {
4331                     /* We stashed the result away above. */
4332                     emitcode("mov", "acc,%s", DP2_RESULT_REG);
4333                 }           
4334                 
4335         }
4336         freeAsmop (result, NULL, ic, TRUE);
4337
4338         /* restore EA bit in F1 */
4339         lbl = newiTempLabel(NULL);
4340         emitcode ("jnb","F1,%05d$",lbl->key+100);
4341         emitcode ("setb","EA");
4342         emitcode("","%05d$:",lbl->key+100);
4343         return ;
4344 }
4345
4346 /*-----------------------------------------------------------------*/
4347 /* genMult - generates code for multiplication                     */
4348 /*-----------------------------------------------------------------*/
4349 static void
4350 genMult (iCode * ic)
4351 {
4352   operand *left = IC_LEFT (ic);
4353   operand *right = IC_RIGHT (ic);
4354   operand *result = IC_RESULT (ic);
4355
4356   D (emitcode (";", "genMult "););
4357
4358   /* assign the amsops */
4359   AOP_OP_2 (ic);
4360
4361   /* special cases first */
4362   /* both are bits */
4363   if (AOP_TYPE (left) == AOP_CRY &&
4364       AOP_TYPE (right) == AOP_CRY)
4365     {
4366       genMultbits (left, right, result, ic);
4367       goto release;
4368     }
4369
4370   /* if both are of size == 1 */
4371   if (AOP_SIZE (left) == 1 &&
4372       AOP_SIZE (right) == 1)
4373     {
4374       genMultOneByte (left, right, result, ic);
4375       goto release;
4376     }
4377
4378   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4379           /* use the ds390 ARITHMETIC accel UNIT */
4380           genMultTwoByte (left, right, result, ic);
4381           return ;
4382   }
4383   /* should have been converted to function call */
4384   assert (0);
4385
4386 release:
4387   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4388   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4389   freeAsmop (result, NULL, ic, TRUE);
4390 }
4391
4392 /*-----------------------------------------------------------------*/
4393 /* genDivbits :- division of bits                                  */
4394 /*-----------------------------------------------------------------*/
4395 static void
4396 genDivbits (operand * left,
4397             operand * right,
4398             operand * result,
4399             iCode   * ic)
4400 {
4401
4402   char *l;
4403
4404   /* the result must be bit */
4405   LOAD_AB_FOR_DIV (left, right, l);
4406   emitcode ("div", "ab");
4407   emitcode ("rrc", "a");
4408   aopOp(result, ic, TRUE, FALSE);
4409     
4410   aopPut (AOP (result), "c", 0);
4411 }
4412
4413 /*-----------------------------------------------------------------*/
4414 /* genDivOneByte : 8 bit division                                  */
4415 /*-----------------------------------------------------------------*/
4416 static void
4417 genDivOneByte (operand * left,
4418                operand * right,
4419                operand * result,
4420                iCode   * ic)
4421 {
4422   sym_link *opetype = operandType (result);
4423   char *l;
4424   symbol *lbl;
4425   int size, offset;
4426
4427   offset = 1;
4428   /* signed or unsigned */
4429   if (SPEC_USIGN (opetype))
4430     {
4431         /* unsigned is easy */
4432         LOAD_AB_FOR_DIV (left, right, l);
4433         emitcode ("div", "ab");
4434
4435         _G.accInUse++;
4436         aopOp(result, ic, TRUE, FALSE);
4437         aopPut (AOP (result), "a", 0);
4438         _G.accInUse--;
4439
4440         size = AOP_SIZE (result) - 1;
4441         
4442         while (size--)
4443         {
4444             aopPut (AOP (result), zero, offset++);
4445         }
4446       return;
4447     }
4448
4449   /* signed is a little bit more difficult */
4450
4451   /* save the signs of the operands */
4452   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4453   MOVA (l);
4454   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4455   emitcode ("push", "acc");     /* save it on the stack */
4456
4457   /* now sign adjust for both left & right */
4458   l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4459   MOVA (l);
4460   lbl = newiTempLabel (NULL);
4461   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4462   emitcode ("cpl", "a");
4463   emitcode ("inc", "a");
4464   emitcode ("", "%05d$:", (lbl->key + 100));
4465   emitcode ("mov", "b,a");
4466
4467   /* sign adjust left side */
4468   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4469   MOVA (l);
4470
4471   lbl = newiTempLabel (NULL);
4472   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4473   emitcode ("cpl", "a");
4474   emitcode ("inc", "a");
4475   emitcode ("", "%05d$:", (lbl->key + 100));
4476
4477   /* now the division */
4478   emitcode ("nop", "; workaround for DS80C390 div bug.");
4479   emitcode ("div", "ab");
4480   /* we are interested in the lower order
4481      only */
4482   emitcode ("mov", "b,a");
4483   lbl = newiTempLabel (NULL);
4484   emitcode ("pop", "acc");
4485   /* if there was an over flow we don't
4486      adjust the sign of the result */
4487   emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4488   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4489   CLRC;
4490   emitcode ("clr", "a");
4491   emitcode ("subb", "a,b");
4492   emitcode ("mov", "b,a");
4493   emitcode ("", "%05d$:", (lbl->key + 100));
4494
4495   /* now we are done */
4496     _G.accInUse++;
4497     aopOp(result, ic, TRUE, FALSE);
4498     
4499     aopPut (AOP (result), "b", 0);
4500     
4501     size = AOP_SIZE (result) - 1;
4502     
4503     if (size > 0)
4504     {
4505       emitcode ("mov", "c,b.7");
4506       emitcode ("subb", "a,acc");
4507     }
4508     while (size--)
4509     {
4510         aopPut (AOP (result), "a", offset++);
4511     }
4512     _G.accInUse--;
4513
4514 }
4515
4516 /*-----------------------------------------------------------------*/
4517 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide       */
4518 /*-----------------------------------------------------------------*/
4519 static void genDivTwoByte (operand *left, operand *right, 
4520                             operand *result, iCode *ic)
4521 {
4522         sym_link *retype = getSpec(operandType(right));
4523         sym_link *letype = getSpec(operandType(left));
4524         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4525         symbol *lbl;
4526
4527         /* save EA bit in F1 */
4528         lbl = newiTempLabel(NULL);
4529         emitcode ("setb","F1");
4530         emitcode ("jbc","EA,%05d$",lbl->key+100);
4531         emitcode ("clr","F1");
4532         emitcode("","%05d$:",lbl->key+100);
4533
4534         /* load up MA with left */
4535         if (!umult) {
4536                 emitcode("clr","F0");
4537                 lbl = newiTempLabel(NULL);
4538                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4539                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4540                 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4541                 emitcode ("xch", "a,b");
4542                 emitcode ("cpl","a");
4543                 emitcode ("add", "a,#1");
4544                 emitcode ("xch", "a,b");
4545                 emitcode ("cpl", "a"); // msb
4546                 emitcode ("addc","a,#0");
4547                 emitcode ("setb","F0");
4548                 emitcode ("","%05d$:",lbl->key+100);
4549                 emitcode ("mov","ma,b");
4550                 emitcode ("mov","ma,a");
4551         } else {
4552                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4553                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4554         }
4555
4556         /* load up MB with right */
4557         if (!umult) {
4558                 if (AOP_TYPE(right) == AOP_LIT) {
4559                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
4560                         if (val < 0) {
4561                                 lbl = newiTempLabel(NULL);
4562                                 emitcode ("jbc","F0,%05d$",lbl->key+100);
4563                                 emitcode("setb","F0");
4564                                 emitcode ("","%05d$:",lbl->key+100);
4565                                 val = -val;
4566                         } 
4567                         emitcode ("mov","mb,#0x%02x",val & 0xff);                   
4568                         emitcode ("mov","mb,#0x%02x",(val >> 8) & 0xff);
4569                 } else {
4570                         lbl = newiTempLabel(NULL);
4571                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4572                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4573                         emitcode ("jnb","acc.7,%05d$",lbl->key+100);            
4574                         emitcode ("xch", "a,b");
4575                         emitcode ("cpl","a");
4576                         emitcode ("add", "a,#1");
4577                         emitcode ("xch", "a,b");
4578                         emitcode ("cpl", "a"); // msb
4579                         emitcode ("addc", "a,#0");
4580                         emitcode ("jbc","F0,%05d$",lbl->key+100);
4581                         emitcode ("setb","F0");
4582                         emitcode ("","%05d$:",lbl->key+100);
4583                         emitcode ("mov","mb,b");
4584                         emitcode ("mov","mb,a");
4585                 }
4586         } else {
4587                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4588                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4589         }
4590
4591         /* wait for multiplication to finish */
4592         lbl = newiTempLabel(NULL);
4593         emitcode("","%05d$:", lbl->key+100);
4594         emitcode("mov","a,mcnt1");
4595         emitcode("anl","a,#0x80");
4596         emitcode("jnz","%05d$",lbl->key+100);
4597         
4598         freeAsmop (left, NULL, ic, TRUE);
4599         freeAsmop (right, NULL, ic,TRUE);
4600         aopOp(result, ic, TRUE, FALSE);
4601
4602         /* if unsigned then simple */   
4603         if (umult) {
4604                 aopPut(AOP(result),"ma",1);
4605                 aopPut(AOP(result),"ma",0);
4606         } else {
4607                 emitcode("push","ma");
4608                 MOVA("ma");
4609                 /* negate result if needed */
4610                 lbl = newiTempLabel(NULL);      
4611                 emitcode("jnb","F0,%05d$",lbl->key+100);
4612                 emitcode("cpl","a");
4613                 emitcode("add","a,#1");
4614                 emitcode("","%05d$:", lbl->key+100);
4615                 aopPut(AOP(result),"a",0);
4616                 emitcode("pop","acc");
4617                 lbl = newiTempLabel(NULL);      
4618                 emitcode("jnb","F0,%05d$",lbl->key+100);
4619                 emitcode("cpl","a");
4620                 emitcode("addc","a,#0");
4621                 emitcode("","%05d$:", lbl->key+100);
4622                 aopPut(AOP(result),"a",1);
4623         }
4624         freeAsmop (result, NULL, ic, TRUE);
4625         /* restore EA bit in F1 */
4626         lbl = newiTempLabel(NULL);
4627         emitcode ("jnb","F1,%05d$",lbl->key+100);
4628         emitcode ("setb","EA");
4629         emitcode("","%05d$:",lbl->key+100);
4630         return ;
4631 }
4632
4633 /*-----------------------------------------------------------------*/
4634 /* genDiv - generates code for division                            */
4635 /*-----------------------------------------------------------------*/
4636 static void
4637 genDiv (iCode * ic)
4638 {
4639   operand *left = IC_LEFT (ic);
4640   operand *right = IC_RIGHT (ic);
4641   operand *result = IC_RESULT (ic);
4642
4643   D (emitcode (";", "genDiv "););
4644
4645   /* assign the amsops */
4646   AOP_OP_2 (ic);
4647
4648   /* special cases first */
4649   /* both are bits */
4650   if (AOP_TYPE (left) == AOP_CRY &&
4651       AOP_TYPE (right) == AOP_CRY)
4652     {
4653       genDivbits (left, right, result, ic);
4654       goto release;
4655     }
4656
4657   /* if both are of size == 1 */
4658   if (AOP_SIZE (left) == 1 &&
4659       AOP_SIZE (right) == 1)
4660     {
4661       genDivOneByte (left, right, result, ic);
4662       goto release;
4663     }
4664
4665   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4666           /* use the ds390 ARITHMETIC accel UNIT */
4667           genDivTwoByte (left, right, result, ic);
4668           return ;
4669   }
4670   /* should have been converted to function call */
4671   assert (0);
4672 release:
4673   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4674   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4675   freeAsmop (result, NULL, ic, TRUE);
4676 }
4677
4678 /*-----------------------------------------------------------------*/
4679 /* genModbits :- modulus of bits                                   */
4680 /*-----------------------------------------------------------------*/
4681 static void
4682 genModbits (operand * left,
4683             operand * right,
4684             operand * result,
4685             iCode   * ic)
4686 {
4687
4688   char *l;
4689
4690   /* the result must be bit */
4691   LOAD_AB_FOR_DIV (left, right, l);
4692   emitcode ("div", "ab");
4693   emitcode ("mov", "a,b");
4694   emitcode ("rrc", "a");
4695   aopOp(result, ic, TRUE, FALSE);
4696   aopPut (AOP (result), "c", 0);
4697 }
4698
4699 /*-----------------------------------------------------------------*/
4700 /* genModOneByte : 8 bit modulus                                   */
4701 /*-----------------------------------------------------------------*/
4702 static void
4703 genModOneByte (operand * left,
4704                operand * right,
4705                operand * result,
4706                iCode   * ic)
4707 {
4708   sym_link *opetype = operandType (result);
4709   char *l;
4710   symbol *lbl;
4711
4712   /* signed or unsigned */
4713   if (SPEC_USIGN (opetype))
4714     {
4715       /* unsigned is easy */
4716       LOAD_AB_FOR_DIV (left, right, l);
4717       emitcode ("div", "ab");
4718       aopOp(result, ic, TRUE, FALSE);   
4719       aopPut (AOP (result), "b", 0);
4720       return;
4721     }
4722
4723   /* signed is a little bit more difficult */
4724
4725   /* save the signs of the operands */
4726   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4727   MOVA (l);
4728
4729   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4730   emitcode ("push", "acc");     /* save it on the stack */
4731
4732   /* now sign adjust for both left & right */
4733   l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4734   MOVA (l);
4735
4736   lbl = newiTempLabel (NULL);
4737   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4738   emitcode ("cpl", "a");
4739   emitcode ("inc", "a");
4740   emitcode ("", "%05d$:", (lbl->key + 100));
4741   emitcode ("mov", "b,a");
4742
4743   /* sign adjust left side */
4744   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4745   MOVA (l);
4746
4747   lbl = newiTempLabel (NULL);
4748   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4749   emitcode ("cpl", "a");
4750   emitcode ("inc", "a");
4751   emitcode ("", "%05d$:", (lbl->key + 100));
4752
4753   /* now the multiplication */
4754   emitcode ("nop", "; workaround for DS80C390 div bug.");
4755   emitcode ("div", "ab");
4756   /* we are interested in the lower order
4757      only */
4758   lbl = newiTempLabel (NULL);
4759   emitcode ("pop", "acc");
4760   /* if there was an over flow we don't
4761      adjust the sign of the result */
4762   emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4763   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4764   CLRC;
4765   emitcode ("clr", "a");
4766   emitcode ("subb", "a,b");
4767   emitcode ("mov", "b,a");
4768   emitcode ("", "%05d$:", (lbl->key + 100));
4769
4770   /* now we are done */
4771   aopOp(result, ic, TRUE, FALSE);    
4772   aopPut (AOP (result), "b", 0);
4773
4774 }
4775
4776 /*-----------------------------------------------------------------*/
4777 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus      */
4778 /*-----------------------------------------------------------------*/
4779 static void genModTwoByte (operand *left, operand *right, 
4780                             operand *result, iCode *ic)
4781 {
4782         sym_link *retype = getSpec(operandType(right));
4783         sym_link *letype = getSpec(operandType(left));
4784         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4785         symbol *lbl;
4786
4787         /* load up MA with left */
4788         /* save EA bit in F1 */
4789         lbl = newiTempLabel(NULL);
4790         emitcode ("setb","F1");
4791         emitcode ("jbc","EA,%05d$",lbl->key+100);
4792         emitcode ("clr","F1");
4793         emitcode("","%05d$:",lbl->key+100);
4794
4795         if (!umult) {
4796                 lbl = newiTempLabel(NULL);
4797                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4798                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4799                 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4800                 emitcode ("xch", "a,b");
4801                 emitcode ("cpl","a");
4802                 emitcode ("add", "a,#1");
4803                 emitcode ("xch", "a,b");
4804                 emitcode ("cpl", "a"); // msb
4805                 emitcode ("addc","a,#0");
4806                 emitcode ("","%05d$:",lbl->key+100);
4807                 emitcode ("mov","ma,b");
4808                 emitcode ("mov","ma,a");
4809         } else {
4810                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4811                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4812         }
4813
4814         /* load up MB with right */
4815         if (!umult) {
4816                 if (AOP_TYPE(right) == AOP_LIT) {
4817                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
4818                         if (val < 0) {
4819                                 val = -val;
4820                         } 
4821                         emitcode ("mov","mb,#0x%02x",val & 0xff);
4822                         emitcode ("mov","mb,#0x%02x",(val >> 8) & 0xff);                    
4823                 } else {
4824                         lbl = newiTempLabel(NULL);
4825                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4826                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4827                         emitcode ("jnb","acc.7,%05d$",lbl->key+100);            
4828                         emitcode ("xch", "a,b");
4829                         emitcode ("cpl","a");
4830                         emitcode ("add", "a,#1");
4831                         emitcode ("xch", "a,b");
4832                         emitcode ("cpl", "a"); // msb
4833                         emitcode ("addc", "a,#0");
4834                         emitcode ("","%05d$:",lbl->key+100);
4835                         emitcode ("mov","mb,b");
4836                         emitcode ("mov","mb,a");
4837                 }
4838         } else {
4839                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4840                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4841         }
4842
4843         /* wait for multiplication to finish */
4844         lbl = newiTempLabel(NULL);
4845         emitcode("","%05d$:", lbl->key+100);
4846         emitcode("mov","a,mcnt1");
4847         emitcode("anl","a,#0x80");
4848         emitcode("jnz","%05d$",lbl->key+100);
4849         
4850         freeAsmop (left, NULL, ic, TRUE);
4851         freeAsmop (right, NULL, ic,TRUE);
4852         aopOp(result, ic, TRUE, FALSE);
4853
4854         aopPut(AOP(result),"mb",1);
4855         aopPut(AOP(result),"mb",0);
4856         freeAsmop (result, NULL, ic, TRUE);
4857
4858         /* restore EA bit in F1 */
4859         lbl = newiTempLabel(NULL);
4860         emitcode ("jnb","F1,%05d$",lbl->key+100);
4861         emitcode ("setb","EA");
4862         emitcode("","%05d$:",lbl->key+100);
4863         return ;
4864 }
4865
4866 /*-----------------------------------------------------------------*/
4867 /* genMod - generates code for division                            */
4868 /*-----------------------------------------------------------------*/
4869 static void
4870 genMod (iCode * ic)
4871 {
4872   operand *left = IC_LEFT (ic);
4873   operand *right = IC_RIGHT (ic);
4874   operand *result = IC_RESULT (ic);
4875
4876   D (emitcode (";", "genMod "); );
4877
4878   /* assign the amsops */
4879   AOP_OP_2 (ic);
4880
4881   /* special cases first */
4882   /* both are bits */
4883   if (AOP_TYPE (left) == AOP_CRY &&
4884       AOP_TYPE (right) == AOP_CRY)
4885     {
4886       genModbits (left, right, result, ic);
4887       goto release;
4888     }
4889
4890   /* if both are of size == 1 */
4891   if (AOP_SIZE (left) == 1 &&
4892       AOP_SIZE (right) == 1)
4893     {
4894       genModOneByte (left, right, result, ic);
4895       goto release;
4896     }
4897
4898   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4899           /* use the ds390 ARITHMETIC accel UNIT */
4900           genModTwoByte (left, right, result, ic);
4901           return ;
4902   }
4903
4904   /* should have been converted to function call */
4905   assert (0);
4906
4907 release:
4908   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4909   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4910   freeAsmop (result, NULL, ic, TRUE);
4911 }
4912
4913 /*-----------------------------------------------------------------*/
4914 /* genIfxJump :- will create a jump depending on the ifx           */
4915 /*-----------------------------------------------------------------*/
4916 static void
4917 genIfxJump (iCode * ic, char *jval)
4918 {
4919   symbol *jlbl;
4920   symbol *tlbl = newiTempLabel (NULL);
4921   char *inst;
4922
4923   D (emitcode (";", "genIfxJump ");
4924     );
4925
4926   /* if true label then we jump if condition
4927      supplied is true */
4928   if (IC_TRUE (ic))
4929     {
4930       jlbl = IC_TRUE (ic);
4931       inst = ((strcmp (jval, "a") == 0 ? "jz" :
4932                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4933     }
4934   else
4935     {
4936       /* false label is present */
4937       jlbl = IC_FALSE (ic);
4938       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4939                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4940     }
4941   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4942     emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4943   else
4944     emitcode (inst, "%05d$", tlbl->key + 100);
4945   emitcode ("ljmp", "%05d$", jlbl->key + 100);
4946   emitcode ("", "%05d$:", tlbl->key + 100);
4947
4948   /* mark the icode as generated */
4949   ic->generated = 1;
4950 }
4951
4952 /*-----------------------------------------------------------------*/
4953 /* genCmp :- greater or less than comparison                       */
4954 /*-----------------------------------------------------------------*/
4955 static void
4956 genCmp (operand * left, operand * right,
4957         iCode * ic, iCode * ifx, int sign)
4958 {
4959   int size, offset = 0;
4960   unsigned long lit = 0L;
4961   operand *result;
4962
4963   D (emitcode (";", "genCmp");
4964     );
4965
4966   result = IC_RESULT (ic);
4967
4968   /* if left & right are bit variables */
4969   if (AOP_TYPE (left) == AOP_CRY &&
4970       AOP_TYPE (right) == AOP_CRY)
4971     {
4972       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4973       emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
4974     }
4975   else
4976     {
4977       /* subtract right from left if at the
4978          end the carry flag is set then we know that
4979          left is greater than right */
4980       size = max (AOP_SIZE (left), AOP_SIZE (right));
4981
4982       /* if unsigned char cmp with lit, do cjne left,#right,zz */
4983       if ((size == 1) && !sign &&
4984           (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4985         {
4986           symbol *lbl = newiTempLabel (NULL);
4987           emitcode ("cjne", "%s,%s,%05d$",
4988                     aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
4989                     aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4990                     lbl->key + 100);
4991           emitcode ("", "%05d$:", lbl->key + 100);
4992         }
4993       else
4994         {
4995           if (AOP_TYPE (right) == AOP_LIT)
4996             {
4997               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4998               /* optimize if(x < 0) or if(x >= 0) */
4999               if (lit == 0L)
5000                 {
5001                   if (!sign)
5002                     {
5003                       CLRC;
5004                     }
5005                   else
5006                     {
5007                       MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
5008
5009                       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5010                       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5011
5012                       aopOp (result, ic, FALSE, FALSE);
5013
5014                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5015                         {
5016                           freeAsmop (result, NULL, ic, TRUE);
5017                           genIfxJump (ifx, "acc.7");
5018                           return;
5019                         }
5020                       else
5021                         {
5022                           emitcode ("rlc", "a");
5023                         }
5024                       goto release_freedLR;
5025                     }
5026                   goto release;
5027                 }
5028             }
5029           CLRC;
5030           while (size--)
5031             {
5032               emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5033               MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5034               emitcode (";", "genCmp #2");
5035               if (sign && (size == 0))
5036                 {
5037                   emitcode (";", "genCmp #3");
5038                   emitcode ("xrl", "a,#0x80");
5039                   if (AOP_TYPE (right) == AOP_LIT)
5040                     {
5041                       unsigned long lit = (unsigned long)
5042                       floatFromVal (AOP (right)->aopu.aop_lit);
5043                       emitcode (";", "genCmp #3.1");
5044                       emitcode ("subb", "a,#0x%02x",
5045                                 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5046                     }
5047                   else
5048                     {
5049                       emitcode (";", "genCmp #3.2");
5050                       if (AOP_NEEDSACC (right))
5051                         {
5052                           emitcode ("push", "acc");
5053                         }
5054                       emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
5055                                                        FALSE, FALSE, FALSE));
5056                       emitcode ("xrl", "b,#0x80");
5057                       if (AOP_NEEDSACC (right))
5058                         {
5059                           emitcode ("pop", "acc");
5060                         }
5061                       emitcode ("subb", "a,b");
5062                     }
5063                 }
5064               else
5065                 {
5066                   const char *s;
5067
5068                   emitcode (";", "genCmp #4");
5069                   if (AOP_NEEDSACC (right))
5070                     {
5071                       /* Yuck!! */
5072                       emitcode (";", "genCmp #4.1");
5073                       emitcode ("xch", "a, b");
5074                       MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
5075                       emitcode ("xch", "a, b");
5076                       s = "b";
5077                     }
5078                   else
5079                     {
5080                       emitcode (";", "genCmp #4.2");
5081                       s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
5082                     }
5083
5084                   emitcode ("subb", "a,%s", s);
5085                 }
5086             }
5087         }
5088     }
5089
5090 release:
5091 /* Don't need the left & right operands any more; do need the result. */
5092   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5093   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5094
5095   aopOp (result, ic, FALSE, FALSE);
5096
5097 release_freedLR:
5098
5099   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5100     {
5101       outBitC (result);
5102     }
5103   else
5104     {
5105       /* if the result is used in the next
5106          ifx conditional branch then generate
5107          code a little differently */
5108       if (ifx)
5109         {
5110           genIfxJump (ifx, "c");
5111         }
5112       else
5113         {
5114           outBitC (result);
5115         }
5116       /* leave the result in acc */
5117     }
5118   freeAsmop (result, NULL, ic, TRUE);
5119 }
5120
5121 /*-----------------------------------------------------------------*/
5122 /* genCmpGt :- greater than comparison                             */
5123 /*-----------------------------------------------------------------*/
5124 static void
5125 genCmpGt (iCode * ic, iCode * ifx)
5126 {
5127   operand *left, *right;
5128   sym_link *letype, *retype;
5129   int sign;
5130
5131   D (emitcode (";", "genCmpGt ");
5132     );
5133
5134   left = IC_LEFT (ic);
5135   right = IC_RIGHT (ic);
5136
5137   letype = getSpec (operandType (left));
5138   retype = getSpec (operandType (right));
5139   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5140
5141   /* assign the left & right amsops */
5142   AOP_OP_2 (ic);
5143
5144   genCmp (right, left, ic, ifx, sign);
5145 }
5146
5147 /*-----------------------------------------------------------------*/
5148 /* genCmpLt - less than comparisons                                */
5149 /*-----------------------------------------------------------------*/
5150 static void
5151 genCmpLt (iCode * ic, iCode * ifx)
5152 {
5153   operand *left, *right;
5154   sym_link *letype, *retype;
5155   int sign;
5156
5157   D (emitcode (";", "genCmpLt "););
5158
5159   left = IC_LEFT (ic);
5160   right = IC_RIGHT (ic);
5161
5162   letype = getSpec (operandType (left));
5163   retype = getSpec (operandType (right));
5164   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5165
5166   /* assign the left & right amsops */
5167   AOP_OP_2 (ic);
5168
5169   genCmp (left, right, ic, ifx, sign);
5170 }
5171
5172 /*-----------------------------------------------------------------*/
5173 /* gencjneshort - compare and jump if not equal                    */
5174 /*-----------------------------------------------------------------*/
5175 static void
5176 gencjneshort (operand * left, operand * right, symbol * lbl)
5177 {
5178   int size = max (AOP_SIZE (left), AOP_SIZE (right));
5179   int offset = 0;
5180   unsigned long lit = 0L;
5181
5182   D (emitcode (";", "gencjneshort");
5183     );
5184
5185   /* if the left side is a literal or
5186      if the right is in a pointer register and left
5187      is not */
5188   if ((AOP_TYPE (left) == AOP_LIT) ||
5189       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5190     {
5191       operand *t = right;
5192       right = left;
5193       left = t;
5194     }
5195
5196   if (AOP_TYPE (right) == AOP_LIT)
5197     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5198
5199   if (opIsGptr (left) || opIsGptr (right))
5200     {
5201       /* We are comparing a generic pointer to something.
5202        * Exclude the generic type byte from the comparison.
5203        */
5204       size--;
5205       D (emitcode (";", "cjneshort: generic ptr special case.");
5206         )
5207     }
5208
5209
5210   /* if the right side is a literal then anything goes */
5211   if (AOP_TYPE (right) == AOP_LIT &&
5212       AOP_TYPE (left) != AOP_DIR)
5213     {
5214       while (size--)
5215         {
5216           char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5217           MOVA (l);
5218           emitcode ("cjne", "a,%s,%05d$",
5219                     aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
5220                     lbl->key + 100);
5221           offset++;
5222         }
5223     }
5224
5225   /* if the right side is in a register or in direct space or
5226      if the left is a pointer register & right is not */
5227   else if (AOP_TYPE (right) == AOP_REG ||
5228            AOP_TYPE (right) == AOP_DIR ||
5229            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5230            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5231     {
5232       while (size--)
5233         {
5234           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5235           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5236               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5237             emitcode ("jnz", "%05d$", lbl->key + 100);
5238           else
5239             emitcode ("cjne", "a,%s,%05d$",
5240                       aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
5241                       lbl->key + 100);
5242           offset++;
5243         }
5244     }
5245   else
5246     {
5247       /* right is a pointer reg need both a & b */
5248       while (size--)
5249         {
5250           char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5251           if (strcmp (l, "b"))
5252             emitcode ("mov", "b,%s", l);
5253           MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5254           emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
5255           offset++;
5256         }
5257     }
5258 }
5259
5260 /*-----------------------------------------------------------------*/
5261 /* gencjne - compare and jump if not equal                         */
5262 /*-----------------------------------------------------------------*/
5263 static void
5264 gencjne (operand * left, operand * right, symbol * lbl)
5265 {
5266   symbol *tlbl = newiTempLabel (NULL);
5267
5268   D (emitcode (";", "gencjne");
5269     );
5270
5271   gencjneshort (left, right, lbl);
5272
5273   emitcode ("mov", "a,%s", one);
5274   emitcode ("sjmp", "%05d$", tlbl->key + 100);
5275   emitcode ("", "%05d$:", lbl->key + 100);
5276   emitcode ("clr", "a");
5277   emitcode ("", "%05d$:", tlbl->key + 100);
5278 }
5279
5280 /*-----------------------------------------------------------------*/
5281 /* genCmpEq - generates code for equal to                          */
5282 /*-----------------------------------------------------------------*/
5283 static void
5284 genCmpEq (iCode * ic, iCode * ifx)
5285 {
5286   operand *left, *right, *result;
5287
5288   D (emitcode (";", "genCmpEq ");
5289     );
5290
5291   AOP_OP_2 (ic);
5292   AOP_SET_LOCALS (ic);
5293
5294   /* if literal, literal on the right or
5295      if the right is in a pointer register and left
5296      is not */
5297   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5298       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5299     {
5300       operand *t = IC_RIGHT (ic);
5301       IC_RIGHT (ic) = IC_LEFT (ic);
5302       IC_LEFT (ic) = t;
5303     }
5304
5305   if (ifx &&                    /* !AOP_SIZE(result) */
5306       OP_SYMBOL (result) &&
5307       OP_SYMBOL (result)->regType == REG_CND)
5308     {
5309       symbol *tlbl;
5310       /* if they are both bit variables */
5311       if (AOP_TYPE (left) == AOP_CRY &&
5312           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5313         {
5314           if (AOP_TYPE (right) == AOP_LIT)
5315             {
5316               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5317               if (lit == 0L)
5318                 {
5319                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5320                   emitcode ("cpl", "c");
5321                 }
5322               else if (lit == 1L)
5323                 {
5324                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5325                 }
5326               else
5327                 {
5328                   emitcode ("clr", "c");
5329                 }
5330               /* AOP_TYPE(right) == AOP_CRY */
5331             }
5332           else
5333             {
5334               symbol *lbl = newiTempLabel (NULL);
5335               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5336               emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5337               emitcode ("cpl", "c");
5338               emitcode ("", "%05d$:", (lbl->key + 100));
5339             }
5340           /* if true label then we jump if condition
5341              supplied is true */
5342           tlbl = newiTempLabel (NULL);
5343           if (IC_TRUE (ifx))
5344             {
5345               emitcode ("jnc", "%05d$", tlbl->key + 100);
5346               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5347             }
5348           else
5349             {
5350               emitcode ("jc", "%05d$", tlbl->key + 100);
5351               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5352             }
5353           emitcode ("", "%05d$:", tlbl->key + 100);
5354         }
5355       else
5356         {
5357           tlbl = newiTempLabel (NULL);
5358           gencjneshort (left, right, tlbl);
5359           if (IC_TRUE (ifx))
5360             {
5361               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5362               emitcode ("", "%05d$:", tlbl->key + 100);
5363             }
5364           else
5365             {
5366               symbol *lbl = newiTempLabel (NULL);
5367               emitcode ("sjmp", "%05d$", lbl->key + 100);
5368               emitcode ("", "%05d$:", tlbl->key + 100);
5369               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5370               emitcode ("", "%05d$:", lbl->key + 100);
5371             }
5372         }
5373       /* mark the icode as generated */
5374       ifx->generated = 1;
5375
5376       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5377       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5378       return;
5379     }
5380
5381   /* if they are both bit variables */
5382   if (AOP_TYPE (left) == AOP_CRY &&
5383       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5384     {
5385       if (AOP_TYPE (right) == AOP_LIT)
5386         {
5387           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5388           if (lit == 0L)
5389             {
5390               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5391               emitcode ("cpl", "c");
5392             }
5393           else if (lit == 1L)
5394             {
5395               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5396             }
5397           else
5398             {
5399               emitcode ("clr", "c");
5400             }
5401           /* AOP_TYPE(right) == AOP_CRY */
5402         }
5403       else
5404         {
5405           symbol *lbl = newiTempLabel (NULL);
5406           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5407           emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5408           emitcode ("cpl", "c");
5409           emitcode ("", "%05d$:", (lbl->key + 100));
5410         }
5411
5412       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5413       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5414
5415       aopOp (result, ic, TRUE, FALSE);
5416
5417       /* c = 1 if egal */
5418       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5419         {
5420           outBitC (result);
5421           goto release;
5422         }
5423       if (ifx)
5424         {
5425           genIfxJump (ifx, "c");
5426           goto release;
5427         }
5428       /* if the result is used in an arithmetic operation
5429          then put the result in place */
5430       outBitC (result);
5431     }
5432   else
5433     {
5434       gencjne (left, right, newiTempLabel (NULL));
5435
5436       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5437       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5438
5439       aopOp (result, ic, TRUE, FALSE);
5440
5441       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5442         {
5443           aopPut (AOP (result), "a", 0);
5444           goto release;
5445         }
5446       if (ifx)
5447         {
5448           genIfxJump (ifx, "a");
5449           goto release;
5450         }
5451       /* if the result is used in an arithmetic operation
5452          then put the result in place */
5453       if (AOP_TYPE (result) != AOP_CRY)
5454         outAcc (result);
5455       /* leave the result in acc */
5456     }
5457
5458 release:
5459   freeAsmop (result, NULL, ic, TRUE);
5460 }
5461
5462 /*-----------------------------------------------------------------*/
5463 /* ifxForOp - returns the icode containing the ifx for operand     */
5464 /*-----------------------------------------------------------------*/
5465 static iCode *
5466 ifxForOp (operand * op, iCode * ic)
5467 {
5468   /* if true symbol then needs to be assigned */
5469   if (IS_TRUE_SYMOP (op))
5470     return NULL;
5471
5472   /* if this has register type condition and
5473      the next instruction is ifx with the same operand
5474      and live to of the operand is upto the ifx only then */
5475   if (ic->next &&
5476       ic->next->op == IFX &&
5477       IC_COND (ic->next)->key == op->key &&
5478       OP_SYMBOL (op)->liveTo <= ic->next->seq)
5479     return ic->next;
5480
5481   return NULL;
5482 }
5483 /*-----------------------------------------------------------------*/
5484 /* hasInc - operand is incremented before any other use            */
5485 /*-----------------------------------------------------------------*/
5486 static iCode *
5487 hasInc (operand *op, iCode *ic)
5488 {
5489   sym_link *type = operandType(op);
5490   sym_link *retype = getSpec (type);
5491   iCode *lic = ic->next;
5492   int isize ;
5493   
5494   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5495   if (!IS_SYMOP(op)) return NULL;
5496
5497   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5498   isize = getSize(type->next);
5499   while (lic) {
5500       /* if operand of the form op = op + <sizeof *op> */
5501       if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5502           isOperandEqual(IC_RESULT(lic),op) && 
5503           isOperandLiteral(IC_RIGHT(lic)) &&
5504           operandLitValue(IC_RIGHT(lic)) == isize) {
5505           return lic;
5506       }
5507       /* if the operand used or deffed */
5508       if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5509           return NULL;
5510       }
5511       /* if GOTO or IFX */
5512       if (lic->op == IFX || lic->op == GOTO) break;
5513       lic = lic->next;
5514   }
5515   return NULL;
5516 }
5517
5518 /*-----------------------------------------------------------------*/
5519 /* genAndOp - for && operation                                     */
5520 /*-----------------------------------------------------------------*/
5521 static void
5522 genAndOp (iCode * ic)
5523 {
5524   operand *left, *right, *result;
5525   symbol *tlbl;
5526
5527   D (emitcode (";", "genAndOp "););
5528
5529   /* note here that && operations that are in an
5530      if statement are taken away by backPatchLabels
5531      only those used in arthmetic operations remain */
5532   AOP_OP_2 (ic);
5533   AOP_SET_LOCALS (ic);
5534
5535   /* if both are bit variables */
5536   if (AOP_TYPE (left) == AOP_CRY &&
5537       AOP_TYPE (right) == AOP_CRY)
5538     {
5539       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5540       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5541       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5542       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5543   
5544       aopOp (result,ic,FALSE, FALSE);
5545       outBitC (result);
5546     }
5547   else
5548     {
5549       tlbl = newiTempLabel (NULL);
5550       toBoolean (left);
5551       emitcode ("jz", "%05d$", tlbl->key + 100);
5552       toBoolean (right);
5553       emitcode ("", "%05d$:", tlbl->key + 100);
5554       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5555       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5556   
5557       aopOp (result,ic,FALSE, FALSE);
5558       outBitAcc (result);
5559     }
5560     freeAsmop (result, NULL, ic, TRUE);
5561 }
5562
5563
5564 /*-----------------------------------------------------------------*/
5565 /* genOrOp - for || operation                                      */
5566 /*-----------------------------------------------------------------*/
5567 static void
5568 genOrOp (iCode * ic)
5569 {
5570   operand *left, *right, *result;
5571   symbol *tlbl;
5572
5573   D (emitcode (";", "genOrOp "););
5574
5575   /* note here that || operations that are in an
5576      if statement are taken away by backPatchLabels
5577      only those used in arthmetic operations remain */
5578   AOP_OP_2 (ic);
5579   AOP_SET_LOCALS (ic);
5580
5581   /* if both are bit variables */
5582   if (AOP_TYPE (left) == AOP_CRY &&
5583       AOP_TYPE (right) == AOP_CRY)
5584     {
5585       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5586       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5587       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5588       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5589   
5590       aopOp (result,ic,FALSE, FALSE);
5591       
5592       outBitC (result);
5593     }
5594   else
5595     {
5596       tlbl = newiTempLabel (NULL);
5597       toBoolean (left);
5598       emitcode ("jnz", "%05d$", tlbl->key + 100);
5599       toBoolean (right);
5600       emitcode ("", "%05d$:", tlbl->key + 100);
5601       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5602       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5603   
5604       aopOp (result,ic,FALSE, FALSE);
5605       
5606       outBitAcc (result);
5607     }
5608
5609   freeAsmop (result, NULL, ic, TRUE);
5610 }
5611
5612 /*-----------------------------------------------------------------*/
5613 /* isLiteralBit - test if lit == 2^n                               */
5614 /*-----------------------------------------------------------------*/
5615 static int
5616 isLiteralBit (unsigned long lit)
5617 {
5618   unsigned long pw[32] =
5619   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5620    0x100L, 0x200L, 0x400L, 0x800L,
5621    0x1000L, 0x2000L, 0x4000L, 0x8000L,
5622    0x10000L, 0x20000L, 0x40000L, 0x80000L,
5623    0x100000L, 0x200000L, 0x400000L, 0x800000L,
5624    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5625    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5626   int idx;
5627
5628   for (idx = 0; idx < 32; idx++)
5629     if (lit == pw[idx])
5630       return idx + 1;
5631   return 0;
5632 }
5633
5634 /*-----------------------------------------------------------------*/
5635 /* continueIfTrue -                                                */
5636 /*-----------------------------------------------------------------*/
5637 static void
5638 continueIfTrue (iCode * ic)
5639 {
5640   if (IC_TRUE (ic))
5641     emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5642   ic->generated = 1;
5643 }
5644
5645 /*-----------------------------------------------------------------*/
5646 /* jmpIfTrue -                                                     */
5647 /*-----------------------------------------------------------------*/
5648 static void
5649 jumpIfTrue (iCode * ic)
5650 {
5651   if (!IC_TRUE (ic))
5652     emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5653   ic->generated = 1;
5654 }
5655
5656 /*-----------------------------------------------------------------*/
5657 /* jmpTrueOrFalse -                                                */
5658 /*-----------------------------------------------------------------*/
5659 static void
5660 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
5661 {
5662   // ugly but optimized by peephole
5663   if (IC_TRUE (ic))
5664     {
5665       symbol *nlbl = newiTempLabel (NULL);
5666       emitcode ("sjmp", "%05d$", nlbl->key + 100);
5667       emitcode ("", "%05d$:", tlbl->key + 100);
5668       emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5669       emitcode ("", "%05d$:", nlbl->key + 100);
5670     }
5671   else
5672     {
5673       emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5674       emitcode ("", "%05d$:", tlbl->key + 100);
5675     }
5676   ic->generated = 1;
5677 }
5678
5679 // Generate code to perform a bit-wise logic operation
5680 // on two operands in far space (assumed to already have been 
5681 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
5682 // in far space. This requires pushing the result on the stack
5683 // then popping it into the result.
5684 static void
5685 genFarFarLogicOp(iCode *ic, char *logicOp)
5686 {
5687       int size, resultSize, compSize;
5688       int offset = 0;
5689       
5690       TR_AP("#5");
5691       D(emitcode(";", "%s special case for 3 far operands.", logicOp););
5692       compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ? 
5693                   AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
5694       
5695       _startLazyDPSEvaluation();
5696       for (size = compSize; (size--); offset++)
5697       {
5698           MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
5699           emitcode ("mov", "%s, acc", DP2_RESULT_REG);
5700           MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
5701           
5702           emitcode (logicOp, "a,%s", DP2_RESULT_REG);
5703           emitcode ("push", "acc");
5704       }
5705       _endLazyDPSEvaluation();
5706      
5707       freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5708       freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5709       aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
5710      
5711       resultSize = AOP_SIZE(IC_RESULT(ic));
5712
5713       ADJUST_PUSHED_RESULT(compSize, resultSize);
5714
5715       _startLazyDPSEvaluation();
5716       while (compSize--)
5717       {
5718           emitcode ("pop", "acc");
5719           aopPut (AOP (IC_RESULT (ic)), "a", compSize);
5720       }
5721       _endLazyDPSEvaluation();
5722       freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
5723 }
5724
5725
5726 /*-----------------------------------------------------------------*/
5727 /* genAnd  - code for and                                          */
5728 /*-----------------------------------------------------------------*/
5729 static void
5730 genAnd (iCode * ic, iCode * ifx)
5731 {
5732   operand *left, *right, *result;
5733   int size, offset = 0;
5734   unsigned long lit = 0L;
5735   int bytelit = 0;
5736   char buffer[10];
5737   bool pushResult;
5738
5739   D (emitcode (";", "genAnd "););
5740
5741   AOP_OP_3_NOFATAL (ic, pushResult);
5742   AOP_SET_LOCALS (ic);
5743
5744   if (pushResult)
5745   {
5746       genFarFarLogicOp(ic, "anl");
5747       return;
5748   }  
5749
5750 #ifdef DEBUG_TYPE
5751   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5752             AOP_TYPE (result),
5753             AOP_TYPE (left), AOP_TYPE (right));
5754   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5755             AOP_SIZE (result),
5756             AOP_SIZE (left), AOP_SIZE (right));
5757 #endif
5758
5759   /* if left is a literal & right is not then exchange them */
5760   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5761 #ifdef LOGIC_OPS_BROKEN      
5762     ||  AOP_NEEDSACC (left)
5763 #endif
5764     )
5765     {
5766       operand *tmp = right;
5767       right = left;
5768       left = tmp;
5769     }
5770
5771   /* if result = right then exchange them */
5772   if (sameRegs (AOP (result), AOP (right)))
5773     {
5774       operand *tmp = right;
5775       right = left;
5776       left = tmp;
5777     }
5778
5779   /* if right is bit then exchange them */
5780   if (AOP_TYPE (right) == AOP_CRY &&
5781       AOP_TYPE (left) != AOP_CRY)
5782     {
5783       operand *tmp = right;
5784       right = left;
5785       left = tmp;
5786     }
5787   if (AOP_TYPE (right) == AOP_LIT)
5788     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5789
5790   size = AOP_SIZE (result);
5791
5792   // if(bit & yy)
5793   // result = bit & yy;
5794   if (AOP_TYPE (left) == AOP_CRY)
5795     {
5796       // c = bit & literal;
5797       if (AOP_TYPE (right) == AOP_LIT)
5798         {
5799           if (lit & 1)
5800             {
5801               if (size && sameRegs (AOP (result), AOP (left)))
5802                 // no change
5803                 goto release;
5804               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5805             }
5806           else
5807             {
5808               // bit(result) = 0;
5809               if (size && (AOP_TYPE (result) == AOP_CRY))
5810                 {
5811                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5812                   goto release;
5813                 }
5814               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5815                 {
5816                   jumpIfTrue (ifx);
5817                   goto release;
5818                 }
5819               emitcode ("clr", "c");
5820             }
5821         }
5822       else
5823         {
5824           if (AOP_TYPE (right) == AOP_CRY)
5825             {
5826               // c = bit & bit;
5827               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5828               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5829             }
5830           else
5831             {
5832               // c = bit & val;
5833               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
5834               // c = lsb
5835               emitcode ("rrc", "a");
5836               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5837             }
5838         }
5839       // bit = c
5840       // val = c
5841       if (size)
5842         outBitC (result);
5843       // if(bit & ...)
5844       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5845         genIfxJump (ifx, "c");
5846       goto release;
5847     }
5848
5849   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5850   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5851   if ((AOP_TYPE (right) == AOP_LIT) &&
5852       (AOP_TYPE (result) == AOP_CRY) &&
5853       (AOP_TYPE (left) != AOP_CRY))
5854     {
5855       int posbit = isLiteralBit (lit);
5856       /* left &  2^n */
5857       if (posbit)
5858         {
5859           posbit--;
5860           MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
5861           // bit = left & 2^n
5862           if (size)
5863             emitcode ("mov", "c,acc.%d", posbit & 0x07);
5864           // if(left &  2^n)
5865           else
5866             {
5867               if (ifx)
5868                 {
5869                   sprintf (buffer, "acc.%d", posbit & 0x07);
5870                   genIfxJump (ifx, buffer);
5871                 }
5872               goto release;
5873             }
5874         }
5875       else
5876         {
5877           symbol *tlbl = newiTempLabel (NULL);
5878           int sizel = AOP_SIZE (left);
5879           if (size)
5880             emitcode ("setb", "c");
5881           while (sizel--)
5882             {
5883               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5884                 {
5885                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5886                   // byte ==  2^n ?
5887                   if ((posbit = isLiteralBit (bytelit)) != 0)
5888                     emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5889                   else
5890                     {
5891                       if (bytelit != 0x0FFL)
5892                         emitcode ("anl", "a,%s",
5893                           aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
5894                       emitcode ("jnz", "%05d$", tlbl->key + 100);
5895                     }
5896                 }
5897               offset++;
5898             }
5899           // bit = left & literal
5900           if (size)
5901             {
5902               emitcode ("clr", "c");
5903               emitcode ("", "%05d$:", tlbl->key + 100);
5904             }
5905           // if(left & literal)
5906           else
5907             {
5908               if (ifx)
5909                 jmpTrueOrFalse (ifx, tlbl);
5910               goto release;
5911             }
5912         }
5913       outBitC (result);
5914       goto release;
5915     }
5916
5917   /* if left is same as result */
5918   if (sameRegs (AOP (result), AOP (left)))
5919     {
5920       for (; size--; offset++)
5921         {
5922           if (AOP_TYPE (right) == AOP_LIT)
5923             {
5924               if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5925                 continue;
5926               else if (bytelit == 0)
5927                 aopPut (AOP (result), zero, offset);
5928               else if (IS_AOP_PREG (result))
5929                 {
5930                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5931                   emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5932                   aopPut (AOP (result), "a", offset);
5933                 }
5934               else
5935                 emitcode ("anl", "%s,%s",
5936                           aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5937                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5938             }
5939           else
5940             {
5941               if (AOP_TYPE (left) == AOP_ACC)
5942                 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5943               else
5944                 {
5945                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5946                   if (IS_AOP_PREG (result))
5947                     {
5948                       emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5949                       aopPut (AOP (result), "a", offset);
5950
5951                     }
5952                   else
5953                     emitcode ("anl", "%s,a",
5954                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5955                 }
5956             }
5957         }
5958     }
5959   else
5960     {
5961       // left & result in different registers
5962       if (AOP_TYPE (result) == AOP_CRY)
5963         {
5964           // result = bit
5965           // if(size), result in bit
5966           // if(!size && ifx), conditional oper: if(left & right)
5967           symbol *tlbl = newiTempLabel (NULL);
5968           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5969           if (size)
5970             emitcode ("setb", "c");
5971           while (sizer--)
5972             {
5973               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5974                 emitcode ("anl", "a,%s",
5975                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5976               } else {
5977                 if (AOP_TYPE(left)==AOP_ACC) {
5978                   emitcode("mov", "b,a");
5979                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5980                   emitcode("anl", "a,b");
5981                 }else {
5982                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5983                   emitcode ("anl", "a,%s",
5984                             aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5985                 }
5986               }
5987               emitcode ("jnz", "%05d$", tlbl->key + 100);
5988               offset++;
5989             }
5990           if (size)
5991             {
5992               CLRC;
5993               emitcode ("", "%05d$:", tlbl->key + 100);
5994               outBitC (result);
5995             }
5996           else if (ifx)
5997             jmpTrueOrFalse (ifx, tlbl);
5998         }
5999       else
6000         {
6001           for (; (size--); offset++)
6002             {
6003               // normal case
6004               // result = left & right
6005               if (AOP_TYPE (right) == AOP_LIT)
6006                 {
6007                   if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6008                     {
6009                       aopPut (AOP (result),
6010                            aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6011                               offset);
6012                       continue;
6013                     }
6014                   else if (bytelit == 0)
6015                     {
6016                       aopPut (AOP (result), zero, offset);
6017                       continue;
6018                     }
6019                   D (emitcode (";", "better literal AND."););
6020                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6021                   emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6022                                                     FALSE, FALSE, FALSE));
6023
6024                 }
6025               else
6026                 {
6027                   // faster than result <- left, anl result,right
6028                   // and better if result is SFR
6029                   if (AOP_TYPE (left) == AOP_ACC)
6030                     {
6031                       emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
6032                                                        FALSE, FALSE, FALSE));
6033                     }
6034                   else
6035                     {
6036                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6037                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6038                       {
6039                           emitcode("mov", "b,a");
6040                           rOp = "b";
6041                       }
6042                         
6043                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6044                       emitcode ("anl", "a,%s", rOp);
6045                     }                   
6046                 }
6047               aopPut (AOP (result), "a", offset);
6048             }
6049         }
6050     }
6051
6052 release:
6053   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6054   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6055   freeAsmop (result, NULL, ic, TRUE);
6056 }
6057
6058
6059 /*-----------------------------------------------------------------*/
6060 /* genOr  - code for or                                            */
6061 /*-----------------------------------------------------------------*/
6062 static void
6063 genOr (iCode * ic, iCode * ifx)
6064 {
6065   operand *left, *right, *result;
6066   int size, offset = 0;
6067   unsigned long lit = 0L;
6068   bool     pushResult;
6069
6070   D (emitcode (";", "genOr "););
6071
6072   AOP_OP_3_NOFATAL (ic, pushResult);
6073   AOP_SET_LOCALS (ic);
6074
6075   if (pushResult)
6076   {
6077       genFarFarLogicOp(ic, "orl");
6078       return;
6079   }
6080
6081
6082 #ifdef DEBUG_TYPE
6083   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6084             AOP_TYPE (result),
6085             AOP_TYPE (left), AOP_TYPE (right));
6086   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6087             AOP_SIZE (result),
6088             AOP_SIZE (left), AOP_SIZE (right));
6089 #endif
6090
6091   /* if left is a literal & right is not then exchange them */
6092   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6093 #ifdef LOGIC_OPS_BROKEN
6094    || AOP_NEEDSACC (left) // I think this is a net loss now.
6095 #endif      
6096       )
6097     {
6098       operand *tmp = right;
6099       right = left;
6100       left = tmp;
6101     }
6102
6103   /* if result = right then exchange them */
6104   if (sameRegs (AOP (result), AOP (right)))
6105     {
6106       operand *tmp = right;
6107       right = left;
6108       left = tmp;
6109     }
6110
6111   /* if right is bit then exchange them */
6112   if (AOP_TYPE (right) == AOP_CRY &&
6113       AOP_TYPE (left) != AOP_CRY)
6114     {
6115       operand *tmp = right;
6116       right = left;
6117       left = tmp;
6118     }
6119   if (AOP_TYPE (right) == AOP_LIT)
6120     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6121
6122   size = AOP_SIZE (result);
6123
6124   // if(bit | yy)
6125   // xx = bit | yy;
6126   if (AOP_TYPE (left) == AOP_CRY)
6127     {
6128       if (AOP_TYPE (right) == AOP_LIT)
6129         {
6130           // c = bit & literal;
6131           if (lit)
6132             {
6133               // lit != 0 => result = 1
6134               if (AOP_TYPE (result) == AOP_CRY)
6135                 {
6136                   if (size)
6137                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6138                   else if (ifx)
6139                     continueIfTrue (ifx);
6140                   goto release;
6141                 }
6142               emitcode ("setb", "c");
6143             }
6144           else
6145             {
6146               // lit == 0 => result = left
6147               if (size && sameRegs (AOP (result), AOP (left)))
6148                 goto release;
6149               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6150             }
6151         }
6152       else
6153         {
6154           if (AOP_TYPE (right) == AOP_CRY)
6155             {
6156               // c = bit | bit;
6157               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6158               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6159             }
6160           else
6161             {
6162               // c = bit | val;
6163               symbol *tlbl = newiTempLabel (NULL);
6164               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6165                 emitcode ("setb", "c");
6166               emitcode ("jb", "%s,%05d$",
6167                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
6168               toBoolean (right);
6169               emitcode ("jnz", "%05d$", tlbl->key + 100);
6170               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6171                 {
6172                   jmpTrueOrFalse (ifx, tlbl);
6173                   goto release;
6174                 }
6175               else
6176                 {
6177                   CLRC;
6178                   emitcode ("", "%05d$:", tlbl->key + 100);
6179                 }
6180             }
6181         }
6182       // bit = c
6183       // val = c
6184       if (size)
6185         outBitC (result);
6186       // if(bit | ...)
6187       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6188         genIfxJump (ifx, "c");
6189       goto release;
6190     }
6191
6192   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6193   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6194   if ((AOP_TYPE (right) == AOP_LIT) &&
6195       (AOP_TYPE (result) == AOP_CRY) &&
6196       (AOP_TYPE (left) != AOP_CRY))
6197     {
6198       if (lit)
6199         {
6200           // result = 1
6201           if (size)
6202             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6203           else
6204             continueIfTrue (ifx);
6205           goto release;
6206         }
6207       else
6208         {
6209           // lit = 0, result = boolean(left)
6210           if (size)
6211             emitcode ("setb", "c");
6212           toBoolean (right);
6213           if (size)
6214             {
6215               symbol *tlbl = newiTempLabel (NULL);
6216               emitcode ("jnz", "%05d$", tlbl->key + 100);
6217               CLRC;
6218               emitcode ("", "%05d$:", tlbl->key + 100);
6219             }
6220           else
6221             {
6222               genIfxJump (ifx, "a");
6223               goto release;
6224             }
6225         }
6226       outBitC (result);
6227       goto release;
6228     }
6229
6230   /* if left is same as result */
6231   if (sameRegs (AOP (result), AOP (left)))
6232     {
6233       for (; size--; offset++)
6234         {
6235           if (AOP_TYPE (right) == AOP_LIT)
6236             {
6237               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6238                 {
6239                   continue;
6240                 }
6241               else
6242                 {
6243                   if (IS_AOP_PREG (left))
6244                     {
6245                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6246                       emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6247                       aopPut (AOP (result), "a", offset);
6248                     }
6249                   else
6250                     {
6251                       emitcode ("orl", "%s,%s",
6252                             aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6253                          aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6254                     }
6255                 }
6256             }
6257           else
6258             {
6259               if (AOP_TYPE (left) == AOP_ACC)
6260                 {
6261                   emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6262                 }
6263               else
6264                 {
6265                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6266                   if (IS_AOP_PREG (left))
6267                     {
6268                       emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6269                       aopPut (AOP (result), "a", offset);
6270                     }
6271                   else
6272                     {
6273                       emitcode ("orl", "%s,a",
6274                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6275                     }
6276                 }
6277             }
6278         }
6279     }
6280   else
6281     {
6282       // left & result in different registers
6283       if (AOP_TYPE (result) == AOP_CRY)
6284         {
6285           // result = bit
6286           // if(size), result in bit
6287           // if(!size && ifx), conditional oper: if(left | right)
6288           symbol *tlbl = newiTempLabel (NULL);
6289           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6290           if (size)
6291             emitcode ("setb", "c");
6292           while (sizer--)
6293             {
6294               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6295                 emitcode ("orl", "a,%s",
6296                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6297               } else {
6298                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6299                 emitcode ("orl", "a,%s",
6300                           aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6301               }
6302               emitcode ("jnz", "%05d$", tlbl->key + 100);
6303               offset++;
6304             }
6305           if (size)
6306             {
6307               CLRC;
6308               emitcode ("", "%05d$:", tlbl->key + 100);
6309               outBitC (result);
6310             }
6311           else if (ifx)
6312             jmpTrueOrFalse (ifx, tlbl);
6313         }
6314       else
6315         {
6316             _startLazyDPSEvaluation();
6317           for (; (size--); offset++)
6318             {
6319               // normal case
6320               // result = left & right
6321               if (AOP_TYPE (right) == AOP_LIT)
6322                 {
6323                   if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6324                     {
6325                       aopPut (AOP (result),
6326                            aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6327                               offset);
6328                       continue;
6329                     }
6330                   D (emitcode (";", "better literal OR."););
6331                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6332                   emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
6333                                                     FALSE, FALSE, FALSE));
6334
6335                 }
6336               else
6337                 {
6338                   // faster than result <- left, anl result,right
6339                   // and better if result is SFR
6340                   if (AOP_TYPE (left) == AOP_ACC)
6341                     {
6342                       emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
6343                                                        FALSE, FALSE, FALSE));
6344                     }
6345                   else
6346                     {
6347                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6348                         
6349                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6350                       {
6351                           emitcode("mov", "b,a");
6352                           rOp = "b";
6353                       }
6354                         
6355                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6356                       emitcode ("orl", "a,%s", rOp);
6357                     }
6358                 }
6359               aopPut (AOP (result), "a", offset);
6360             }
6361             _endLazyDPSEvaluation();
6362         }
6363     }
6364
6365 release:
6366   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6367   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6368   freeAsmop (result, NULL, ic, TRUE);
6369 }
6370
6371 /*-----------------------------------------------------------------*/
6372 /* genXor - code for xclusive or                                   */
6373 /*-----------------------------------------------------------------*/
6374 static void
6375 genXor (iCode * ic, iCode * ifx)
6376 {
6377   operand *left, *right, *result;
6378   int size, offset = 0;
6379   unsigned long lit = 0L;
6380   bool pushResult;
6381
6382   D (emitcode (";", "genXor "););
6383
6384   AOP_OP_3_NOFATAL (ic, pushResult);
6385   AOP_SET_LOCALS (ic);
6386
6387   if (pushResult)
6388   {
6389       genFarFarLogicOp(ic, "xrl");
6390       return;
6391   }  
6392
6393 #ifdef DEBUG_TYPE
6394   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6395             AOP_TYPE (result),
6396             AOP_TYPE (left), AOP_TYPE (right));
6397   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6398             AOP_SIZE (result),
6399             AOP_SIZE (left), AOP_SIZE (right));
6400 #endif
6401
6402   /* if left is a literal & right is not ||
6403      if left needs acc & right does not */
6404   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) 
6405 #ifdef LOGIC_OPS_BROKEN      
6406       || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6407 #endif
6408      )
6409     {
6410       operand *tmp = right;
6411       right = left;
6412       left = tmp;
6413     }
6414
6415   /* if result = right then exchange them */
6416   if (sameRegs (AOP (result), AOP (right)))
6417     {
6418       operand *tmp = right;
6419       right = left;
6420       left = tmp;
6421     }
6422
6423   /* if right is bit then exchange them */
6424   if (AOP_TYPE (right) == AOP_CRY &&
6425       AOP_TYPE (left) != AOP_CRY)
6426     {
6427       operand *tmp = right;
6428       right = left;
6429       left = tmp;
6430     }
6431   if (AOP_TYPE (right) == AOP_LIT)
6432     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6433
6434   size = AOP_SIZE (result);
6435
6436   // if(bit ^ yy)
6437   // xx = bit ^ yy;
6438   if (AOP_TYPE (left) == AOP_CRY)
6439     {
6440       if (AOP_TYPE (right) == AOP_LIT)
6441         {
6442           // c = bit & literal;
6443           if (lit >> 1)
6444             {
6445               // lit>>1  != 0 => result = 1
6446               if (AOP_TYPE (result) == AOP_CRY)
6447                 {
6448                   if (size)
6449                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6450                   else if (ifx)
6451                     continueIfTrue (ifx);
6452                   goto release;
6453                 }
6454               emitcode ("setb", "c");
6455             }
6456           else
6457             {
6458               // lit == (0 or 1)
6459               if (lit == 0)
6460                 {
6461                   // lit == 0, result = left
6462                   if (size && sameRegs (AOP (result), AOP (left)))
6463                     goto release;
6464                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6465                 }
6466               else
6467                 {
6468                   // lit == 1, result = not(left)
6469                   if (size && sameRegs (AOP (result), AOP (left)))
6470                     {
6471                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6472                       goto release;
6473                     }
6474                   else
6475                     {
6476                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6477                       emitcode ("cpl", "c");
6478                     }
6479                 }
6480             }
6481
6482         }
6483       else
6484         {
6485           // right != literal
6486           symbol *tlbl = newiTempLabel (NULL);
6487           if (AOP_TYPE (right) == AOP_CRY)
6488             {
6489               // c = bit ^ bit;
6490               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6491             }
6492           else
6493             {
6494               int sizer = AOP_SIZE (right);
6495               // c = bit ^ val
6496               // if val>>1 != 0, result = 1
6497               emitcode ("setb", "c");
6498               while (sizer)
6499                 {
6500                   MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
6501                   if (sizer == 1)
6502                     // test the msb of the lsb
6503                     emitcode ("anl", "a,#0xfe");
6504                   emitcode ("jnz", "%05d$", tlbl->key + 100);
6505                   sizer--;
6506                 }
6507               // val = (0,1)
6508               emitcode ("rrc", "a");
6509             }
6510           emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6511           emitcode ("cpl", "c");
6512           emitcode ("", "%05d$:", (tlbl->key + 100));
6513         }
6514       // bit = c
6515       // val = c
6516       if (size)
6517         outBitC (result);
6518       // if(bit | ...)
6519       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6520         genIfxJump (ifx, "c");
6521       goto release;
6522     }
6523
6524   if (sameRegs (AOP (result), AOP (left)))
6525     {
6526       /* if left is same as result */
6527       for (; size--; offset++)
6528         {
6529           if (AOP_TYPE (right) == AOP_LIT)
6530             {
6531               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6532                 continue;
6533               else if (IS_AOP_PREG (left))
6534                 {
6535                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6536                   emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6537                   aopPut (AOP (result), "a", offset);
6538                 }
6539               else
6540                 emitcode ("xrl", "%s,%s",
6541                           aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6542                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6543             }
6544           else
6545             {
6546               if (AOP_TYPE (left) == AOP_ACC)
6547                 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6548               else
6549                 {
6550                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6551                   if (IS_AOP_PREG (left))
6552                     {
6553                       emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6554                       aopPut (AOP (result), "a", offset);
6555                     }
6556                   else
6557                     emitcode ("xrl", "%s,a",
6558                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6559                 }
6560             }
6561         }
6562     }
6563   else
6564     {
6565       // left & result in different registers
6566       if (AOP_TYPE (result) == AOP_CRY)
6567         {
6568           // result = bit
6569           // if(size), result in bit
6570           // if(!size && ifx), conditional oper: if(left ^ right)
6571           symbol *tlbl = newiTempLabel (NULL);
6572           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6573                   
6574           if (size)
6575             emitcode ("setb", "c");
6576           while (sizer--)
6577             {
6578               if ((AOP_TYPE (right) == AOP_LIT) &&
6579                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6580                 {
6581                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6582                 }
6583               else
6584                 {
6585                   if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6586                     emitcode ("xrl", "a,%s",
6587                               aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6588                   } else {
6589                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6590                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6591                       {
6592                           emitcode("mov", "b,a");
6593                           rOp = "b";
6594                       }
6595                         
6596                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6597                       emitcode ("xrl", "a,%s", rOp);                  
6598                   }
6599                 }
6600               emitcode ("jnz", "%05d$", tlbl->key + 100);
6601               offset++;
6602             }
6603           if (size)
6604             {
6605               CLRC;
6606               emitcode ("", "%05d$:", tlbl->key + 100);
6607               outBitC (result);
6608             }
6609           else if (ifx)
6610             jmpTrueOrFalse (ifx, tlbl);
6611         }
6612       else
6613         {
6614         for (; (size--); offset++)
6615           {
6616             // normal case
6617             // result = left & right
6618             if (AOP_TYPE (right) == AOP_LIT)
6619               {
6620                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6621                   {
6622                     aopPut (AOP (result),
6623                             aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6624                             offset);
6625                     continue;
6626                   }
6627                 D (emitcode (";", "better literal XOR."););
6628                 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6629                 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
6630                                                   FALSE, FALSE, FALSE));
6631               }
6632             else
6633               {
6634                 // faster than result <- left, anl result,right
6635                 // and better if result is SFR
6636                 if (AOP_TYPE (left) == AOP_ACC)
6637                   {
6638                     emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
6639                                                      FALSE, FALSE, FALSE));
6640                   }
6641                 else
6642                   {
6643                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6644                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6645                       {
6646                           emitcode("mov", "b,a");
6647                           rOp = "b";
6648                       }
6649                         
6650                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6651                       emitcode ("xrl", "a,%s", rOp);
6652                   }
6653               }
6654             aopPut (AOP (result), "a", offset);
6655           }
6656         }
6657         
6658     }
6659
6660 release:
6661   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6662   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6663   freeAsmop (result, NULL, ic, TRUE);
6664 }
6665
6666 /*-----------------------------------------------------------------*/
6667 /* genInline - write the inline code out                           */
6668 /*-----------------------------------------------------------------*/
6669 static void
6670 genInline (iCode * ic)
6671 {
6672   char *buffer, *bp, *bp1;
6673
6674   D (emitcode (";", "genInline ");
6675     );
6676
6677   _G.inLine += (!options.asmpeep);
6678
6679   buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6680   strcpy (buffer, IC_INLINE (ic));
6681
6682   /* emit each line as a code */
6683   while (*bp)
6684     {
6685       if (*bp == '\n')
6686         {
6687           *bp++ = '\0';
6688           emitcode (bp1, "");
6689           bp1 = bp;
6690         }
6691       else
6692         {
6693           if (*bp == ':')
6694             {
6695               bp++;
6696               *bp = '\0';
6697               bp++;
6698               emitcode (bp1, "");
6699               bp1 = bp;
6700             }
6701           else
6702             bp++;
6703         }
6704     }
6705   if (bp1 != bp)
6706     emitcode (bp1, "");
6707   /*     emitcode("",buffer); */
6708   _G.inLine -= (!options.asmpeep);
6709 }
6710
6711 /*-----------------------------------------------------------------*/
6712 /* genRRC - rotate right with carry                                */
6713 /*-----------------------------------------------------------------*/
6714 static void
6715 genRRC (iCode * ic)
6716 {
6717   operand *left, *result;
6718   int size, offset = 0;
6719   char *l;
6720
6721   D (emitcode (";", "genRRC ");
6722     );
6723
6724   /* rotate right with carry */
6725   left = IC_LEFT (ic);
6726   result = IC_RESULT (ic);
6727   aopOp (left, ic, FALSE, FALSE);
6728   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6729
6730   /* move it to the result */
6731   size = AOP_SIZE (result);
6732   offset = size - 1;
6733   CLRC;
6734
6735   _startLazyDPSEvaluation ();
6736   while (size--)
6737     {
6738       l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6739       MOVA (l);
6740       emitcode ("rrc", "a");
6741       if (AOP_SIZE (result) > 1)
6742         aopPut (AOP (result), "a", offset--);
6743     }
6744   _endLazyDPSEvaluation ();
6745
6746   /* now we need to put the carry into the
6747      highest order byte of the result */
6748   if (AOP_SIZE (result) > 1)
6749     {
6750       l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
6751       MOVA (l);
6752     }
6753   emitcode ("mov", "acc.7,c");
6754   aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
6755   freeAsmop (left, NULL, ic, TRUE);
6756   freeAsmop (result, NULL, ic, TRUE);
6757 }
6758
6759 /*-----------------------------------------------------------------*/
6760 /* genRLC - generate code for rotate left with carry               */
6761 /*-----------------------------------------------------------------*/
6762 static void
6763 genRLC (iCode * ic)
6764 {
6765   operand *left, *result;
6766   int size, offset = 0;
6767   char *l;
6768
6769   D (emitcode (";", "genRLC ");
6770     );
6771
6772   /* rotate right with carry */
6773   left = IC_LEFT (ic);
6774   result = IC_RESULT (ic);
6775   aopOp (left, ic, FALSE, FALSE);
6776   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6777
6778   /* move it to the result */
6779   size = AOP_SIZE (result);
6780   offset = 0;
6781   if (size--)
6782     {
6783       l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6784       MOVA (l);
6785       emitcode ("add", "a,acc");
6786       if (AOP_SIZE (result) > 1)
6787         {
6788           aopPut (AOP (result), "a", offset++);
6789         }
6790
6791       _startLazyDPSEvaluation ();
6792       while (size--)
6793         {
6794           l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6795           MOVA (l);
6796           emitcode ("rlc", "a");
6797           if (AOP_SIZE (result) > 1)
6798             aopPut (AOP (result), "a", offset++);
6799         }
6800       _endLazyDPSEvaluation ();
6801     }
6802   /* now we need to put the carry into the
6803      highest order byte of the result */
6804   if (AOP_SIZE (result) > 1)
6805     {
6806       l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
6807       MOVA (l);
6808     }
6809   emitcode ("mov", "acc.0,c");
6810   aopPut (AOP (result), "a", 0);
6811   freeAsmop (left, NULL, ic, TRUE);
6812   freeAsmop (result, NULL, ic, TRUE);
6813 }
6814
6815 /*-----------------------------------------------------------------*/
6816 /* genGetHbit - generates code get highest order bit               */
6817 /*-----------------------------------------------------------------*/
6818 static void
6819 genGetHbit (iCode * ic)
6820 {
6821   operand *left, *result;
6822   left = IC_LEFT (ic);
6823   result = IC_RESULT (ic);
6824   aopOp (left, ic, FALSE, FALSE);
6825   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6826
6827   D (emitcode (";", "genGetHbit ");
6828     );
6829
6830   /* get the highest order byte into a */
6831   MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
6832   if (AOP_TYPE (result) == AOP_CRY)
6833     {
6834       emitcode ("rlc", "a");
6835       outBitC (result);
6836     }
6837   else
6838     {
6839       emitcode ("rl", "a");
6840       emitcode ("anl", "a,#0x01");
6841       outAcc (result);
6842     }
6843
6844
6845   freeAsmop (left, NULL, ic, TRUE);
6846   freeAsmop (result, NULL, ic, TRUE);
6847 }
6848
6849 /*-----------------------------------------------------------------*/
6850 /* AccRol - rotate left accumulator by known count                 */
6851 /*-----------------------------------------------------------------*/
6852 static void
6853 AccRol (int shCount)
6854 {
6855   shCount &= 0x0007;            // shCount : 0..7
6856
6857   switch (shCount)
6858     {
6859     case 0:
6860       break;
6861     case 1:
6862       emitcode ("rl", "a");
6863       break;
6864     case 2:
6865       emitcode ("rl", "a");
6866       emitcode ("rl", "a");
6867       break;
6868     case 3:
6869       emitcode ("swap", "a");
6870       emitcode ("rr", "a");
6871       break;
6872     case 4:
6873       emitcode ("swap", "a");
6874       break;
6875     case 5:
6876       emitcode ("swap", "a");
6877       emitcode ("rl", "a");
6878       break;
6879     case 6:
6880       emitcode ("rr", "a");
6881       emitcode ("rr", "a");
6882       break;
6883     case 7:
6884       emitcode ("rr", "a");
6885       break;
6886     }
6887 }
6888
6889 /*-----------------------------------------------------------------*/
6890 /* AccLsh - left shift accumulator by known count                  */
6891 /*-----------------------------------------------------------------*/
6892 static void
6893 AccLsh (int shCount)
6894 {
6895   if (shCount != 0)
6896     {
6897       if (shCount == 1)
6898         emitcode ("add", "a,acc");
6899       else if (shCount == 2)
6900         {
6901           emitcode ("add", "a,acc");
6902           emitcode ("add", "a,acc");
6903         }
6904       else
6905         {
6906           /* rotate left accumulator */
6907           AccRol (shCount);
6908           /* and kill the lower order bits */
6909           emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6910         }
6911     }
6912 }
6913
6914 /*-----------------------------------------------------------------*/
6915 /* AccRsh - right shift accumulator by known count                 */
6916 /*-----------------------------------------------------------------*/
6917 static void
6918 AccRsh (int shCount)
6919 {
6920   if (shCount != 0)
6921     {
6922       if (shCount == 1)
6923         {
6924           CLRC;
6925           emitcode ("rrc", "a");
6926         }
6927       else
6928         {
6929           /* rotate right accumulator */
6930           AccRol (8 - shCount);
6931           /* and kill the higher order bits */
6932           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6933         }
6934     }
6935 }
6936
6937 #ifdef BETTER_LITERAL_SHIFT
6938 /*-----------------------------------------------------------------*/
6939 /* AccSRsh - signed right shift accumulator by known count                 */
6940 /*-----------------------------------------------------------------*/
6941 static void
6942 AccSRsh (int shCount)
6943 {
6944   symbol *tlbl;
6945   if (shCount != 0)
6946     {
6947       if (shCount == 1)
6948         {
6949           emitcode ("mov", "c,acc.7");
6950           emitcode ("rrc", "a");
6951         }
6952       else if (shCount == 2)
6953         {
6954           emitcode ("mov", "c,acc.7");
6955           emitcode ("rrc", "a");
6956           emitcode ("mov", "c,acc.7");
6957           emitcode ("rrc", "a");
6958         }
6959       else
6960         {
6961           tlbl = newiTempLabel (NULL);
6962           /* rotate right accumulator */
6963           AccRol (8 - shCount);
6964           /* and kill the higher order bits */
6965           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6966           emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6967           emitcode ("orl", "a,#0x%02x",
6968                     (unsigned char) ~SRMask[shCount]);
6969           emitcode ("", "%05d$:", tlbl->key + 100);
6970         }
6971     }
6972 }
6973 #endif
6974
6975 #ifdef BETTER_LITERAL_SHIFT
6976 /*-----------------------------------------------------------------*/
6977 /* shiftR1Left2Result - shift right one byte from left to result   */
6978 /*-----------------------------------------------------------------*/
6979 static void
6980 shiftR1Left2Result (operand * left, int offl,
6981                     operand * result, int offr,
6982                     int shCount, int sign)
6983 {
6984   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6985   /* shift right accumulator */
6986   if (sign)
6987     AccSRsh (shCount);
6988   else
6989     AccRsh (shCount);
6990   aopPut (AOP (result), "a", offr);
6991 }
6992 #endif
6993
6994 #ifdef BETTER_LITERAL_SHIFT
6995 /*-----------------------------------------------------------------*/
6996 /* shiftL1Left2Result - shift left one byte from left to result    */
6997 /*-----------------------------------------------------------------*/
6998 static void
6999 shiftL1Left2Result (operand * left, int offl,
7000                     operand * result, int offr, int shCount)
7001 {
7002   MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7003   /* shift left accumulator */
7004   AccLsh (shCount);
7005   aopPut (AOP (result), "a", offr);
7006 }
7007 #endif
7008
7009 #ifdef BETTER_LITERAL_SHIFT
7010 /*-----------------------------------------------------------------*/
7011 /* movLeft2Result - move byte from left to result                  */
7012 /*-----------------------------------------------------------------*/
7013 static void
7014 movLeft2Result (operand * left, int offl,
7015                 operand * result, int offr, int sign)
7016 {
7017   char *l;
7018   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7019   {
7020       l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
7021
7022       if (*l == '@' && (IS_AOP_PREG (result)))
7023       {
7024           emitcode ("mov", "a,%s", l);
7025           aopPut (AOP (result), "a", offr);
7026       }
7027       else
7028       {
7029           if (!sign)
7030           {
7031             aopPut (AOP (result), l, offr);
7032           }
7033           else
7034             {
7035               /* MSB sign in acc.7 ! */
7036               if (getDataSize (left) == offl + 1)
7037                 {
7038                   emitcode ("mov", "a,%s", l);
7039                   aopPut (AOP (result), "a", offr);
7040                 }
7041             }
7042       }
7043   }
7044 }
7045 #endif
7046
7047 #ifdef BETTER_LITERAL_SHIFT
7048 /*-----------------------------------------------------------------*/
7049 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
7050 /*-----------------------------------------------------------------*/
7051 static void
7052 AccAXRrl1 (char *x)
7053 {
7054   emitcode ("rrc", "a");
7055   emitcode ("xch", "a,%s", x);
7056   emitcode ("rrc", "a");
7057   emitcode ("xch", "a,%s", x);
7058 }
7059 #endif
7060
7061 #ifdef BETTER_LITERAL_SHIFT
7062 //REMOVE ME!!!
7063 /*-----------------------------------------------------------------*/
7064 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
7065 /*-----------------------------------------------------------------*/
7066 static void
7067 AccAXLrl1 (char *x)
7068 {
7069   emitcode ("xch", "a,%s", x);
7070   emitcode ("rlc", "a");
7071   emitcode ("xch", "a,%s", x);
7072   emitcode ("rlc", "a");
7073 }
7074 #endif
7075
7076 #ifdef BETTER_LITERAL_SHIFT
7077 /*-----------------------------------------------------------------*/
7078 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
7079 /*-----------------------------------------------------------------*/
7080 static void
7081 AccAXLsh1 (char *x)
7082 {
7083   emitcode ("xch", "a,%s", x);
7084   emitcode ("add", "a,acc");
7085   emitcode ("xch", "a,%s", x);
7086   emitcode ("rlc", "a");
7087 }
7088 #endif
7089
7090 #ifdef BETTER_LITERAL_SHIFT
7091 /*-----------------------------------------------------------------*/
7092 /* AccAXLsh - left shift a:x by known count (0..7)                 */
7093 /*-----------------------------------------------------------------*/
7094 static void
7095 AccAXLsh (char *x, int shCount)
7096 {
7097   switch (shCount)
7098     {
7099     case 0:
7100       break;
7101     case 1:
7102       AccAXLsh1 (x);
7103       break;
7104     case 2:
7105       AccAXLsh1 (x);
7106       AccAXLsh1 (x);
7107       break;
7108     case 3:
7109     case 4:
7110     case 5:                     // AAAAABBB:CCCCCDDD
7111
7112       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
7113
7114       emitcode ("anl", "a,#0x%02x",
7115                 SLMask[shCount]);       // BBB00000:CCCCCDDD
7116
7117       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
7118
7119       AccRol (shCount);         // DDDCCCCC:BBB00000
7120
7121       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
7122
7123       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
7124
7125       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
7126
7127       emitcode ("anl", "a,#0x%02x",
7128                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
7129
7130       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
7131
7132       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
7133
7134       break;
7135     case 6:                     // AAAAAABB:CCCCCCDD
7136       emitcode ("anl", "a,#0x%02x",
7137                 SRMask[shCount]);       // 000000BB:CCCCCCDD
7138       emitcode ("mov", "c,acc.0");      // c = B
7139       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
7140 #if 0
7141       AccAXRrl1 (x);            // BCCCCCCD:D000000B
7142       AccAXRrl1 (x);            // BBCCCCCC:DD000000
7143 #else
7144       emitcode("rrc","a"); 
7145       emitcode("xch","a,%s", x); 
7146       emitcode("rrc","a"); 
7147       emitcode("mov","c,acc.0"); //<< get correct bit 
7148       emitcode("xch","a,%s", x); 
7149
7150       emitcode("rrc","a"); 
7151       emitcode("xch","a,%s", x); 
7152       emitcode("rrc","a"); 
7153       emitcode("xch","a,%s", x); 
7154 #endif
7155       break;
7156     case 7:                     // a:x <<= 7
7157
7158       emitcode ("anl", "a,#0x%02x",
7159                 SRMask[shCount]);       // 0000000B:CCCCCCCD
7160
7161       emitcode ("mov", "c,acc.0");      // c = B
7162
7163       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
7164
7165       AccAXRrl1 (x);            // BCCCCCCC:D0000000
7166
7167       break;
7168     default:
7169       break;
7170     }
7171 }
7172 #endif
7173
7174 #ifdef BETTER_LITERAL_SHIFT
7175 //REMOVE ME!!!
7176 /*-----------------------------------------------------------------*/
7177 /* AccAXRsh - right shift a:x known count (0..7)                   */
7178 /*-----------------------------------------------------------------*/
7179 static void
7180 AccAXRsh (char *x, int shCount)
7181 {
7182   switch (shCount)
7183     {
7184     case 0:
7185       break;
7186     case 1:
7187       CLRC;
7188       AccAXRrl1 (x);            // 0->a:x
7189
7190       break;
7191     case 2:
7192       CLRC;
7193       AccAXRrl1 (x);            // 0->a:x
7194
7195       CLRC;
7196       AccAXRrl1 (x);            // 0->a:x
7197
7198       break;
7199     case 3:
7200     case 4:
7201     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7202
7203       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
7204
7205       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7206
7207       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7208
7209       emitcode ("anl", "a,#0x%02x",
7210                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7211
7212       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7213
7214       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7215
7216       emitcode ("anl", "a,#0x%02x",
7217                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7218
7219       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7220
7221       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7222
7223       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
7224
7225       break;
7226     case 6:                     // AABBBBBB:CCDDDDDD
7227
7228       emitcode ("mov", "c,acc.7");
7229       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7230
7231       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7232
7233       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7234
7235       emitcode ("anl", "a,#0x%02x",
7236                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7237
7238       break;
7239     case 7:                     // ABBBBBBB:CDDDDDDD
7240
7241       emitcode ("mov", "c,acc.7");      // c = A
7242
7243       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7244
7245       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7246
7247       emitcode ("anl", "a,#0x%02x",
7248                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7249
7250       break;
7251     default:
7252       break;
7253     }
7254 }
7255 #endif
7256
7257 #ifdef BETTER_LITERAL_SHIFT
7258 /*-----------------------------------------------------------------*/
7259 /* AccAXRshS - right shift signed a:x known count (0..7)           */
7260 /*-----------------------------------------------------------------*/
7261 static void
7262 AccAXRshS (char *x, int shCount)
7263 {
7264   symbol *tlbl;
7265   switch (shCount)
7266     {
7267     case 0:
7268       break;
7269     case 1:
7270       emitcode ("mov", "c,acc.7");
7271       AccAXRrl1 (x);            // s->a:x
7272
7273       break;
7274     case 2:
7275       emitcode ("mov", "c,acc.7");
7276       AccAXRrl1 (x);            // s->a:x
7277
7278       emitcode ("mov", "c,acc.7");
7279       AccAXRrl1 (x);            // s->a:x
7280
7281       break;
7282     case 3:
7283     case 4:
7284     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7285
7286       tlbl = newiTempLabel (NULL);
7287       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
7288
7289       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7290
7291       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7292
7293       emitcode ("anl", "a,#0x%02x",
7294                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7295
7296       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7297
7298       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7299
7300       emitcode ("anl", "a,#0x%02x",
7301                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7302
7303       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7304
7305       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7306
7307       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
7308
7309       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7310       emitcode ("orl", "a,#0x%02x",
7311                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
7312
7313       emitcode ("", "%05d$:", tlbl->key + 100);
7314       break;                    // SSSSAAAA:BBBCCCCC
7315
7316     case 6:                     // AABBBBBB:CCDDDDDD
7317
7318       tlbl = newiTempLabel (NULL);
7319       emitcode ("mov", "c,acc.7");
7320       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7321
7322       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7323
7324       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7325
7326       emitcode ("anl", "a,#0x%02x",
7327                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7328
7329       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7330       emitcode ("orl", "a,#0x%02x",
7331                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
7332
7333       emitcode ("", "%05d$:", tlbl->key + 100);
7334       break;
7335     case 7:                     // ABBBBBBB:CDDDDDDD
7336
7337       tlbl = newiTempLabel (NULL);
7338       emitcode ("mov", "c,acc.7");      // c = A
7339
7340       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7341
7342       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7343
7344       emitcode ("anl", "a,#0x%02x",
7345                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7346
7347       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7348       emitcode ("orl", "a,#0x%02x",
7349                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
7350
7351       emitcode ("", "%05d$:", tlbl->key + 100);
7352       break;
7353     default:
7354       break;
7355     }
7356 }
7357 #endif
7358
7359 #ifdef BETTER_LITERAL_SHIFT
7360 static void
7361 _loadLeftIntoAx(char    **lsb, 
7362                 operand *left, 
7363                 operand *result,
7364                 int     offl,
7365                 int     offr)
7366 {
7367   // Get the initial value from left into a pair of registers.
7368   // MSB must be in A, LSB can be any register.
7369   //
7370   // If the result is held in registers, it is an optimization
7371   // if the LSB can be held in the register which will hold the,
7372   // result LSB since this saves us from having to copy it into
7373   // the result following AccAXLsh.
7374   //
7375   // If the result is addressed indirectly, this is not a gain.
7376   if (AOP_NEEDSACC(result))
7377   {
7378        char *leftByte;
7379        
7380        _startLazyDPSEvaluation();
7381       if (AOP_TYPE(left) == AOP_DPTR2)
7382        {
7383            // Get MSB in A.
7384            MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
7385            // get LSB in DP2_RESULT_REG.
7386            leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
7387            assert(!strcmp(leftByte, DP2_RESULT_REG));
7388        }
7389        else
7390        {
7391            // get LSB into DP2_RESULT_REG
7392            leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
7393            if (strcmp(leftByte, DP2_RESULT_REG))
7394            {
7395                TR_AP("#7");
7396                emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7397            }
7398            // And MSB in A.
7399            leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
7400            assert(strcmp(leftByte, DP2_RESULT_REG));
7401            MOVA(leftByte);
7402        }
7403        _endLazyDPSEvaluation();
7404        *lsb = DP2_RESULT_REG;
7405   }
7406   else
7407   {
7408       if (sameRegs (AOP (result), AOP (left)) &&
7409         ((offl + MSB16) == offr))
7410       {
7411           /* don't crash result[offr] */
7412           MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
7413           emitcode ("xch", "a,%s", 
7414                     aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
7415       }
7416       else
7417       {
7418           movLeft2Result (left, offl, result, offr, 0);
7419           MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
7420       }
7421       *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
7422       assert(strcmp(*lsb,"a"));      
7423   }
7424 }
7425
7426 static void
7427 _storeAxResults(char    *lsb,
7428                 operand *result,
7429                 int     offr)
7430 {
7431   _startLazyDPSEvaluation();
7432   if (AOP_NEEDSACC(result))
7433   {
7434       /* We have to explicitly update the result LSB.
7435        */
7436       emitcode("xch","a,%s", lsb);
7437       aopPut(AOP(result), "a", offr);
7438       emitcode("mov","a,%s", lsb);
7439   }
7440   if (getDataSize (result) > 1)
7441   {
7442       aopPut (AOP (result), "a", offr + MSB16);
7443   }
7444   _endLazyDPSEvaluation();
7445 }
7446
7447 /*-----------------------------------------------------------------*/
7448 /* shiftL2Left2Result - shift left two bytes from left to result   */
7449 /*-----------------------------------------------------------------*/
7450 static void
7451 shiftL2Left2Result (operand * left, int offl,
7452                     operand * result, int offr, int shCount)
7453 {
7454   char *lsb;
7455
7456   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7457   
7458   AccAXLsh (lsb, shCount);
7459   
7460   _storeAxResults(lsb, result, offr);
7461 }
7462 #endif
7463
7464 #ifdef BETTER_LITERAL_SHIFT
7465 /*-----------------------------------------------------------------*/
7466 /* shiftR2Left2Result - shift right two bytes from left to result  */
7467 /*-----------------------------------------------------------------*/
7468 static void
7469 shiftR2Left2Result (operand * left, int offl,
7470                     operand * result, int offr,
7471                     int shCount, int sign)
7472 {
7473   char *lsb;
7474   
7475   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7476   
7477   /* a:x >> shCount (x = lsb(result)) */
7478   if (sign)
7479   {
7480      AccAXRshS(lsb, shCount);
7481   }
7482   else
7483   {
7484     AccAXRsh(lsb, shCount);
7485   }
7486   
7487   _storeAxResults(lsb, result, offr);
7488 }
7489 #endif
7490
7491 #if 0
7492 //REMOVE ME!!!
7493 /*-----------------------------------------------------------------*/
7494 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7495 /*-----------------------------------------------------------------*/
7496 static void
7497 shiftLLeftOrResult (operand * left, int offl,
7498                     operand * result, int offr, int shCount)
7499 {
7500   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7501   /* shift left accumulator */
7502   AccLsh (shCount);
7503   /* or with result */
7504   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7505   /* back to result */
7506   aopPut (AOP (result), "a", offr);
7507 }
7508 #endif
7509
7510 #if 0
7511 //REMOVE ME!!!
7512 /*-----------------------------------------------------------------*/
7513 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7514 /*-----------------------------------------------------------------*/
7515 static void
7516 shiftRLeftOrResult (operand * left, int offl,
7517                     operand * result, int offr, int shCount)
7518 {
7519   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7520   /* shift right accumulator */
7521   AccRsh (shCount);
7522   /* or with result */
7523   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7524   /* back to result */
7525   aopPut (AOP (result), "a", offr);
7526 }
7527 #endif
7528
7529 #ifdef BETTER_LITERAL_SHIFT
7530 /*-----------------------------------------------------------------*/
7531 /* genlshOne - left shift a one byte quantity by known count       */
7532 /*-----------------------------------------------------------------*/
7533 static void
7534 genlshOne (operand * result, operand * left, int shCount)
7535 {
7536   D (emitcode (";", "genlshOne "););
7537   shiftL1Left2Result (left, LSB, result, LSB, shCount);
7538 }
7539 #endif
7540
7541 #ifdef BETTER_LITERAL_SHIFT
7542 /*-----------------------------------------------------------------*/
7543 /* genlshTwo - left shift two bytes by known amount != 0           */
7544 /*-----------------------------------------------------------------*/
7545 static void
7546 genlshTwo (operand * result, operand * left, int shCount)
7547 {
7548   int size;
7549
7550   D (emitcode (";", "genlshTwo "););
7551
7552   size = getDataSize (result);
7553
7554   /* if shCount >= 8 */
7555   if (shCount >= 8)
7556   {
7557       shCount -= 8;
7558
7559       _startLazyDPSEvaluation();
7560
7561       if (size > 1)
7562         {
7563           if (shCount)
7564           {
7565             _endLazyDPSEvaluation();
7566             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7567             aopPut (AOP (result), zero, LSB);       
7568           }
7569           else
7570           {
7571             movLeft2Result (left, LSB, result, MSB16, 0);
7572             aopPut (AOP (result), zero, LSB);
7573             _endLazyDPSEvaluation();
7574           }
7575         }
7576         else
7577         {
7578           aopPut (AOP (result), zero, LSB);
7579           _endLazyDPSEvaluation();
7580         }
7581   }
7582
7583   /*  1 <= shCount <= 7 */
7584   else
7585     {
7586       if (size == 1)
7587       {
7588         shiftL1Left2Result (left, LSB, result, LSB, shCount);
7589       }
7590       else
7591       {
7592         shiftL2Left2Result (left, LSB, result, LSB, shCount);
7593       }
7594     }
7595 }
7596 #endif
7597
7598 #if 0
7599 //REMOVE ME!!!
7600 /*-----------------------------------------------------------------*/
7601 /* shiftLLong - shift left one long from left to result            */
7602 /* offl = LSB or MSB16                                             */
7603 /*-----------------------------------------------------------------*/
7604 static void
7605 shiftLLong (operand * left, operand * result, int offr)
7606 {
7607   char *l;
7608   int size = AOP_SIZE (result);
7609
7610   if (size >= LSB + offr)
7611     {
7612       l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
7613       MOVA (l);
7614       emitcode ("add", "a,acc");
7615       if (sameRegs (AOP (left), AOP (result)) &&
7616           size >= MSB16 + offr && offr != LSB)
7617         emitcode ("xch", "a,%s",
7618                   aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
7619       else
7620         aopPut (AOP (result), "a", LSB + offr);
7621     }
7622
7623   if (size >= MSB16 + offr)
7624     {
7625       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7626         {
7627           l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
7628           MOVA (l);
7629         }
7630       emitcode ("rlc", "a");
7631       if (sameRegs (AOP (left), AOP (result)) &&
7632           size >= MSB24 + offr && offr != LSB)
7633         emitcode ("xch", "a,%s",
7634                   aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
7635       else
7636         aopPut (AOP (result), "a", MSB16 + offr);
7637     }
7638
7639   if (size >= MSB24 + offr)
7640     {
7641       if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7642         {
7643           l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
7644           MOVA (l);
7645         }
7646       emitcode ("rlc", "a");
7647       if (sameRegs (AOP (left), AOP (result)) &&
7648           size >= MSB32 + offr && offr != LSB)
7649         emitcode ("xch", "a,%s",
7650                   aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
7651       else
7652         aopPut (AOP (result), "a", MSB24 + offr);
7653     }
7654
7655   if (size > MSB32 + offr)
7656     {
7657       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7658         {
7659           l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
7660           MOVA (l);
7661         }
7662       emitcode ("rlc", "a");
7663       aopPut (AOP (result), "a", MSB32 + offr);
7664     }
7665   if (offr != LSB)
7666     aopPut (AOP (result), zero, LSB);
7667 }
7668 #endif
7669
7670 #if 0
7671 //REMOVE ME!!!
7672 /*-----------------------------------------------------------------*/
7673 /* genlshFour - shift four byte by a known amount != 0             */
7674 /*-----------------------------------------------------------------*/
7675 static void
7676 genlshFour (operand * result, operand * left, int shCount)
7677 {
7678   int size;
7679
7680   D (emitcode (";", "genlshFour ");
7681     );
7682
7683   size = AOP_SIZE (result);
7684
7685   /* if shifting more that 3 bytes */
7686   if (shCount >= 24)
7687     {
7688       shCount -= 24;
7689       if (shCount)
7690         /* lowest order of left goes to the highest
7691            order of the destination */
7692         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7693       else
7694         movLeft2Result (left, LSB, result, MSB32, 0);
7695       aopPut (AOP (result), zero, LSB);
7696       aopPut (AOP (result), zero, MSB16);
7697       aopPut (AOP (result), zero, MSB24);
7698       return;
7699     }
7700
7701   /* more than two bytes */
7702   else if (shCount >= 16)
7703     {
7704       /* lower order two bytes goes to higher order two bytes */
7705       shCount -= 16;
7706       /* if some more remaining */
7707       if (shCount)
7708         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7709       else
7710         {
7711           movLeft2Result (left, MSB16, result, MSB32, 0);
7712           movLeft2Result (left, LSB, result, MSB24, 0);
7713         }
7714       aopPut (AOP (result), zero, MSB16);
7715       aopPut (AOP (result), zero, LSB);
7716       return;
7717     }
7718
7719   /* if more than 1 byte */
7720   else if (shCount >= 8)
7721     {
7722       /* lower order three bytes goes to higher order  three bytes */
7723       shCount -= 8;
7724       if (size == 2)
7725         {
7726           if (shCount)
7727             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7728           else
7729             movLeft2Result (left, LSB, result, MSB16, 0);
7730         }
7731       else
7732         {                       /* size = 4 */
7733           if (shCount == 0)
7734             {
7735               movLeft2Result (left, MSB24, result, MSB32, 0);
7736               movLeft2Result (left, MSB16, result, MSB24, 0);
7737               movLeft2Result (left, LSB, result, MSB16, 0);
7738               aopPut (AOP (result), zero, LSB);
7739             }
7740           else if (shCount == 1)
7741             shiftLLong (left, result, MSB16);
7742           else
7743             {
7744               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7745               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7746               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7747               aopPut (AOP (result), zero, LSB);
7748             }
7749         }
7750     }
7751
7752   /* 1 <= shCount <= 7 */
7753   else if (shCount <= 2)
7754     {
7755       shiftLLong (left, result, LSB);
7756       if (shCount == 2)
7757         shiftLLong (result, result, LSB);
7758     }
7759   /* 3 <= shCount <= 7, optimize */
7760   else
7761     {
7762       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7763       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7764       shiftL2Left2Result (left, LSB, result, LSB, shCount);
7765     }
7766 }
7767 #endif
7768
7769 #ifdef BETTER_LITERAL_SHIFT
7770 /*-----------------------------------------------------------------*/
7771 /* genLeftShiftLiteral - left shifting by known count              */
7772 /*-----------------------------------------------------------------*/
7773 static bool
7774 genLeftShiftLiteral (operand * left,
7775                      operand * right,
7776                      operand * result,
7777                      iCode * ic)
7778 {
7779   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7780   int size;
7781
7782   size = getSize (operandType (result));
7783
7784   D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
7785
7786   /* We only handle certain easy cases so far. */
7787   if ((shCount != 0)
7788    && (shCount < (size * 8))
7789    && (size != 1)
7790    && (size != 2))
7791   {
7792       D(emitcode (";", "genLeftShiftLiteral wimping out"););    
7793       return FALSE;
7794   }
7795
7796   freeAsmop (right, NULL, ic, TRUE);
7797
7798   aopOp(left, ic, FALSE, FALSE);
7799   aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
7800
7801 #if 1 // debug spew
7802   if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
7803   {
7804         emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
7805         if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
7806         {
7807            emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
7808         }
7809   }
7810   if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
7811   {
7812         emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
7813         if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
7814         {
7815            emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
7816         }       
7817   }  
7818 #endif
7819   
7820 #if VIEW_SIZE
7821   emitcode ("; shift left ", "result %d, left %d", size,
7822             AOP_SIZE (left));
7823 #endif
7824
7825   /* I suppose that the left size >= result size */
7826   if (shCount == 0)
7827   {
7828         _startLazyDPSEvaluation();
7829         while (size--)
7830         {
7831           movLeft2Result (left, size, result, size, 0);
7832         }
7833         _endLazyDPSEvaluation();
7834   }
7835   else if (shCount >= (size * 8))
7836   {
7837     _startLazyDPSEvaluation();
7838     while (size--)
7839     {
7840       aopPut (AOP (result), zero, size);
7841     }
7842     _endLazyDPSEvaluation();
7843   }
7844   else
7845   {
7846       switch (size)
7847         {
7848         case 1:
7849           genlshOne (result, left, shCount);
7850           break;
7851
7852         case 2:
7853           genlshTwo (result, left, shCount);
7854           break;
7855 #if 0
7856         case 4:
7857           genlshFour (result, left, shCount);
7858           break;
7859 #endif
7860         default:
7861           fprintf(stderr, "*** ack! mystery literal shift!\n");   
7862           break;
7863         }
7864     }
7865   freeAsmop (left, NULL, ic, TRUE);
7866   freeAsmop (result, NULL, ic, TRUE);
7867   return TRUE;
7868 }
7869 #endif
7870
7871 /*-----------------------------------------------------------------*/
7872 /* genLeftShift - generates code for left shifting                 */
7873 /*-----------------------------------------------------------------*/
7874 static void
7875 genLeftShift (iCode * ic)
7876 {
7877   operand *left, *right, *result;
7878   int size, offset;
7879   char *l;
7880   symbol *tlbl, *tlbl1;
7881
7882   D (emitcode (";", "genLeftShift "););
7883
7884   right = IC_RIGHT (ic);
7885   left = IC_LEFT (ic);
7886   result = IC_RESULT (ic);
7887
7888   aopOp (right, ic, FALSE, FALSE);
7889
7890
7891 #ifdef BETTER_LITERAL_SHIFT
7892   /* if the shift count is known then do it
7893      as efficiently as possible */
7894   if (AOP_TYPE (right) == AOP_LIT)
7895     {
7896       if (genLeftShiftLiteral (left, right, result, ic))
7897       {
7898         return;
7899       }
7900     }
7901 #endif
7902
7903   /* shift count is unknown then we have to form
7904      a loop get the loop count in B : Note: we take
7905      only the lower order byte since shifting
7906      more that 32 bits make no sense anyway, ( the
7907      largest size of an object can be only 32 bits ) */
7908
7909   if (AOP_TYPE (right) == AOP_LIT)
7910   {
7911       /* Really should be handled by genLeftShiftLiteral,
7912        * but since I'm too lazy to fix that today, at least we can make
7913        * some small improvement.
7914        */
7915        emitcode("mov", "b,#0x%02x",
7916                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7917   }
7918   else
7919   {
7920         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7921         emitcode ("inc", "b");
7922   }
7923   freeAsmop (right, NULL, ic, TRUE);
7924   aopOp (left, ic, FALSE, FALSE);
7925   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7926
7927   /* now move the left to the result if they are not the
7928      same */
7929   if (!sameRegs (AOP (left), AOP (result)) &&
7930       AOP_SIZE (result) > 1)
7931     {
7932
7933       size = AOP_SIZE (result);
7934       offset = 0;
7935       _startLazyDPSEvaluation ();
7936       while (size--)
7937         {
7938           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7939           if (*l == '@' && (IS_AOP_PREG (result)))
7940             {
7941
7942               emitcode ("mov", "a,%s", l);
7943               aopPut (AOP (result), "a", offset);
7944             }
7945           else
7946             aopPut (AOP (result), l, offset);
7947           offset++;
7948         }
7949       _endLazyDPSEvaluation ();
7950     }
7951
7952   tlbl = newiTempLabel (NULL);
7953   size = AOP_SIZE (result);
7954   offset = 0;
7955   tlbl1 = newiTempLabel (NULL);
7956
7957   /* if it is only one byte then */
7958   if (size == 1)
7959     {
7960       symbol *tlbl1 = newiTempLabel (NULL);
7961
7962       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7963       MOVA (l);
7964       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7965       emitcode ("", "%05d$:", tlbl->key + 100);
7966       emitcode ("add", "a,acc");
7967       emitcode ("", "%05d$:", tlbl1->key + 100);
7968       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7969       aopPut (AOP (result), "a", 0);
7970       goto release;
7971     }
7972
7973   reAdjustPreg (AOP (result));
7974
7975   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7976   emitcode ("", "%05d$:", tlbl->key + 100);
7977   l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7978   MOVA (l);
7979   emitcode ("add", "a,acc");
7980   aopPut (AOP (result), "a", offset++);
7981   _startLazyDPSEvaluation ();
7982   while (--size)
7983     {
7984       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7985       MOVA (l);
7986       emitcode ("rlc", "a");
7987       aopPut (AOP (result), "a", offset++);
7988     }
7989   _endLazyDPSEvaluation ();
7990   reAdjustPreg (AOP (result));
7991
7992   emitcode ("", "%05d$:", tlbl1->key + 100);
7993   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7994 release:
7995   freeAsmop (left, NULL, ic, TRUE);
7996   freeAsmop (result, NULL, ic, TRUE);
7997 }
7998
7999 #ifdef BETTER_LITERAL_SHIFT
8000 /*-----------------------------------------------------------------*/
8001 /* genrshOne - right shift a one byte quantity by known count      */
8002 /*-----------------------------------------------------------------*/
8003 static void
8004 genrshOne (operand * result, operand * left,
8005            int shCount, int sign)
8006 {
8007   D (emitcode (";", "genrshOne"););
8008   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8009 }
8010 #endif
8011
8012 #ifdef BETTER_LITERAL_SHIFT
8013 /*-----------------------------------------------------------------*/
8014 /* genrshTwo - right shift two bytes by known amount != 0          */
8015 /*-----------------------------------------------------------------*/
8016 static void
8017 genrshTwo (operand * result, operand * left,
8018            int shCount, int sign)
8019 {
8020   D (emitcode (";", "genrshTwo"););
8021
8022   /* if shCount >= 8 */
8023   if (shCount >= 8)
8024     {
8025       shCount -= 8;
8026       _startLazyDPSEvaluation();
8027       if (shCount)
8028       {
8029         shiftR1Left2Result (left, MSB16, result, LSB,
8030                             shCount, sign);
8031       }                     
8032       else
8033       {
8034         movLeft2Result (left, MSB16, result, LSB, sign);
8035       }
8036       addSign (result, MSB16, sign);
8037       _endLazyDPSEvaluation();
8038     }
8039
8040   /*  1 <= shCount <= 7 */
8041   else
8042   {
8043     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8044   }
8045 }
8046 #endif
8047
8048 #if 0
8049 //REMOVE ME!!!
8050 /*-----------------------------------------------------------------*/
8051 /* shiftRLong - shift right one long from left to result           */
8052 /* offl = LSB or MSB16                                             */
8053 /*-----------------------------------------------------------------*/
8054 static void
8055 shiftRLong (operand * left, int offl,
8056             operand * result, int sign)
8057 {
8058   int isSameRegs=sameRegs(AOP(left),AOP(result));
8059
8060   if (isSameRegs && offl>1) {
8061     // we are in big trouble, but this shouldn't happen
8062     werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8063   }
8064
8065   MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
8066   
8067   if (offl==MSB16) {
8068     // shift is > 8
8069     if (sign) {
8070       emitcode ("rlc", "a");
8071       emitcode ("subb", "a,acc");
8072       emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
8073     } else {
8074       aopPut (AOP(result), zero, MSB32);
8075     }
8076   }
8077
8078   if (!sign) {
8079     emitcode ("clr", "c");
8080   } else {
8081     emitcode ("mov", "c,acc.7");
8082   }
8083
8084   emitcode ("rrc", "a");
8085
8086   if (isSameRegs && offl==MSB16) {
8087     emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
8088   } else {
8089     aopPut (AOP (result), "a", MSB32);
8090     MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
8091   }
8092
8093   emitcode ("rrc", "a");
8094   if (isSameRegs && offl==1) {
8095     emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
8096   } else {
8097     aopPut (AOP (result), "a", MSB24);
8098     MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
8099   }
8100   emitcode ("rrc", "a");
8101   aopPut (AOP (result), "a", MSB16 - offl);
8102
8103   if (offl == LSB)
8104     {
8105       MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
8106       emitcode ("rrc", "a");
8107       aopPut (AOP (result), "a", LSB);
8108     }
8109 }
8110 #endif
8111
8112 #if 0
8113 //REMOVE ME!!!
8114 /*-----------------------------------------------------------------*/
8115 /* genrshFour - shift four byte by a known amount != 0             */
8116 /*-----------------------------------------------------------------*/
8117 static void
8118 genrshFour (operand * result, operand * left,
8119             int shCount, int sign)
8120 {
8121   D (emitcode (";", "genrshFour");
8122     );
8123
8124   /* if shifting more that 3 bytes */
8125   if (shCount >= 24)
8126     {
8127       shCount -= 24;
8128       if (shCount)
8129         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8130       else
8131         movLeft2Result (left, MSB32, result, LSB, sign);
8132       addSign (result, MSB16, sign);
8133     }
8134   else if (shCount >= 16)
8135     {
8136       shCount -= 16;
8137       if (shCount)
8138         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8139       else
8140         {
8141           movLeft2Result (left, MSB24, result, LSB, 0);
8142           movLeft2Result (left, MSB32, result, MSB16, sign);
8143         }
8144       addSign (result, MSB24, sign);
8145     }
8146   else if (shCount >= 8)
8147     {
8148       shCount -= 8;
8149       if (shCount == 1)
8150         shiftRLong (left, MSB16, result, sign);
8151       else if (shCount == 0)
8152         {
8153           movLeft2Result (left, MSB16, result, LSB, 0);
8154           movLeft2Result (left, MSB24, result, MSB16, 0);
8155           movLeft2Result (left, MSB32, result, MSB24, sign);
8156           addSign (result, MSB32, sign);
8157         }
8158       else
8159         {
8160           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8161           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8162           /* the last shift is signed */
8163           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8164           addSign (result, MSB32, sign);
8165         }
8166     }
8167   else
8168     {                           /* 1 <= shCount <= 7 */
8169       if (shCount <= 2)
8170         {
8171           shiftRLong (left, LSB, result, sign);
8172           if (shCount == 2)
8173             shiftRLong (result, LSB, result, sign);
8174         }
8175       else
8176         {
8177           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8178           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8179           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8180         }
8181     }
8182 }
8183 #endif
8184
8185 #ifdef BETTER_LITERAL_SHIFT
8186 /*-----------------------------------------------------------------*/
8187 /* genRightShiftLiteral - right shifting by known count            */
8188 /*-----------------------------------------------------------------*/
8189 static bool
8190 genRightShiftLiteral (operand * left,
8191                       operand * right,
8192                       operand * result,
8193                       iCode * ic,
8194                       int sign)
8195 {
8196   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8197   int size;
8198
8199   size = getSize (operandType (result));
8200
8201   D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8202
8203   /* We only handle certain easy cases so far. */
8204   if ((shCount != 0)
8205    && (shCount < (size * 8))
8206    && (size != 1)
8207    && (size != 2))
8208   {
8209       D(emitcode (";", "genRightShiftLiteral wimping out"););   
8210       return FALSE;
8211   }
8212
8213   freeAsmop (right, NULL, ic, TRUE);
8214
8215   aopOp (left, ic, FALSE, FALSE);
8216   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8217
8218 #if VIEW_SIZE
8219   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8220             AOP_SIZE (left));
8221 #endif
8222
8223   /* test the LEFT size !!! */
8224
8225   /* I suppose that the left size >= result size */
8226   if (shCount == 0)
8227   {
8228       size = getDataSize (result);
8229       _startLazyDPSEvaluation();
8230       while (size--)
8231       {
8232         movLeft2Result (left, size, result, size, 0);
8233       }
8234       _endLazyDPSEvaluation();
8235   }
8236   else if (shCount >= (size * 8))
8237     {
8238       if (sign)
8239       {
8240         /* get sign in acc.7 */
8241         MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
8242       }
8243       addSign (result, LSB, sign);
8244     }
8245   else
8246     {
8247       switch (size)
8248         {
8249         case 1:
8250           genrshOne (result, left, shCount, sign);
8251           break;
8252
8253         case 2:
8254           genrshTwo (result, left, shCount, sign);
8255           break;
8256 #if 0
8257         case 4:
8258           genrshFour (result, left, shCount, sign);
8259           break;
8260 #endif    
8261         default:
8262           break;
8263         }
8264
8265       freeAsmop (left, NULL, ic, TRUE);
8266       freeAsmop (result, NULL, ic, TRUE);
8267     }
8268     return TRUE;
8269 }
8270 #endif
8271
8272 /*-----------------------------------------------------------------*/
8273 /* genSignedRightShift - right shift of signed number              */
8274 /*-----------------------------------------------------------------*/
8275 static void
8276 genSignedRightShift (iCode * ic)
8277 {
8278   operand *right, *left, *result;
8279   int size, offset;
8280   char *l;
8281   symbol *tlbl, *tlbl1;
8282
8283   D (emitcode (";", "genSignedRightShift "););
8284
8285   /* we do it the hard way put the shift count in b
8286      and loop thru preserving the sign */
8287
8288   right = IC_RIGHT (ic);
8289   left = IC_LEFT (ic);
8290   result = IC_RESULT (ic);
8291
8292   aopOp (right, ic, FALSE, FALSE);
8293
8294 #ifdef BETTER_LITERAL_SHIFT
8295   if (AOP_TYPE (right) == AOP_LIT)
8296     {
8297       if (genRightShiftLiteral (left, right, result, ic, 1))
8298       {
8299         return;
8300       }
8301     }
8302 #endif
8303   /* shift count is unknown then we have to form
8304      a loop get the loop count in B : Note: we take
8305      only the lower order byte since shifting
8306      more that 32 bits make no sense anyway, ( the
8307      largest size of an object can be only 32 bits ) */
8308
8309   if (AOP_TYPE (right) == AOP_LIT)
8310   {
8311       /* Really should be handled by genRightShiftLiteral,
8312        * but since I'm too lazy to fix that today, at least we can make
8313        * some small improvement.
8314        */
8315        emitcode("mov", "b,#0x%02x",
8316                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8317   }
8318   else
8319   {
8320         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8321         emitcode ("inc", "b");
8322   }
8323   freeAsmop (right, NULL, ic, TRUE);
8324   aopOp (left, ic, FALSE, FALSE);
8325   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8326
8327   /* now move the left to the result if they are not the
8328      same */
8329   if (!sameRegs (AOP (left), AOP (result)) &&
8330       AOP_SIZE (result) > 1)
8331     {
8332
8333       size = AOP_SIZE (result);
8334       offset = 0;
8335       _startLazyDPSEvaluation ();
8336       while (size--)
8337         {
8338           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8339           if (*l == '@' && IS_AOP_PREG (result))
8340             {
8341
8342               emitcode ("mov", "a,%s", l);
8343               aopPut (AOP (result), "a", offset);
8344             }
8345           else
8346             aopPut (AOP (result), l, offset);
8347           offset++;
8348         }
8349       _endLazyDPSEvaluation ();
8350     }
8351
8352   /* mov the highest order bit to OVR */
8353   tlbl = newiTempLabel (NULL);
8354   tlbl1 = newiTempLabel (NULL);
8355
8356   size = AOP_SIZE (result);
8357   offset = size - 1;
8358   emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
8359   emitcode ("rlc", "a");
8360   emitcode ("mov", "ov,c");
8361   /* if it is only one byte then */
8362   if (size == 1)
8363     {
8364       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8365       MOVA (l);
8366       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8367       emitcode ("", "%05d$:", tlbl->key + 100);
8368       emitcode ("mov", "c,ov");
8369       emitcode ("rrc", "a");
8370       emitcode ("", "%05d$:", tlbl1->key + 100);
8371       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8372       aopPut (AOP (result), "a", 0);
8373       goto release;
8374     }
8375
8376   reAdjustPreg (AOP (result));
8377   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8378   emitcode ("", "%05d$:", tlbl->key + 100);
8379   emitcode ("mov", "c,ov");
8380   _startLazyDPSEvaluation ();
8381   while (size--)
8382     {
8383       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8384       MOVA (l);
8385       emitcode ("rrc", "a");
8386       aopPut (AOP (result), "a", offset--);
8387     }
8388   _endLazyDPSEvaluation ();
8389   reAdjustPreg (AOP (result));
8390   emitcode ("", "%05d$:", tlbl1->key + 100);
8391   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8392
8393 release:
8394   freeAsmop (left, NULL, ic, TRUE);
8395   freeAsmop (result, NULL, ic, TRUE);
8396 }
8397
8398 /*-----------------------------------------------------------------*/
8399 /* genRightShift - generate code for right shifting                */
8400 /*-----------------------------------------------------------------*/
8401 static void
8402 genRightShift (iCode * ic)
8403 {
8404   operand *right, *left, *result;
8405   sym_link *retype;
8406   int size, offset;
8407   char *l;
8408   symbol *tlbl, *tlbl1;
8409
8410   D (emitcode (";", "genRightShift "););
8411
8412   /* if signed then we do it the hard way preserve the
8413      sign bit moving it inwards */
8414   retype = getSpec (operandType (IC_RESULT (ic)));
8415
8416   if (!SPEC_USIGN (retype))
8417     {
8418       genSignedRightShift (ic);
8419       return;
8420     }
8421
8422   /* signed & unsigned types are treated the same : i.e. the
8423      signed is NOT propagated inwards : quoting from the
8424      ANSI - standard : "for E1 >> E2, is equivalent to division
8425      by 2**E2 if unsigned or if it has a non-negative value,
8426      otherwise the result is implementation defined ", MY definition
8427      is that the sign does not get propagated */
8428
8429   right = IC_RIGHT (ic);
8430   left = IC_LEFT (ic);
8431   result = IC_RESULT (ic);
8432
8433   aopOp (right, ic, FALSE, FALSE);
8434
8435 #ifdef BETTER_LITERAL_SHIFT
8436   /* if the shift count is known then do it
8437      as efficiently as possible */
8438   if (AOP_TYPE (right) == AOP_LIT)
8439     {
8440       if (genRightShiftLiteral (left, right, result, ic, 0))
8441       {
8442         return;
8443       }
8444     }
8445 #endif
8446
8447   /* shift count is unknown then we have to form
8448      a loop get the loop count in B : Note: we take
8449      only the lower order byte since shifting
8450      more that 32 bits make no sense anyway, ( the
8451      largest size of an object can be only 32 bits ) */
8452   
8453   if (AOP_TYPE (right) == AOP_LIT)
8454   {
8455       /* Really should be handled by genRightShiftLiteral,
8456        * but since I'm too lazy to fix that today, at least we can make
8457        * some small improvement.
8458        */
8459        emitcode("mov", "b,#0x%02x",
8460                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8461   }
8462   else
8463   {
8464         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8465         emitcode ("inc", "b");
8466   }
8467   freeAsmop (right, NULL, ic, TRUE);
8468   aopOp (left, ic, FALSE, FALSE);
8469   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8470
8471   /* now move the left to the result if they are not the
8472      same */
8473   if (!sameRegs (AOP (left), AOP (result)) &&
8474       AOP_SIZE (result) > 1)
8475     {
8476
8477       size = AOP_SIZE (result);
8478       offset = 0;
8479       _startLazyDPSEvaluation ();
8480       while (size--)
8481         {
8482           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8483           if (*l == '@' && IS_AOP_PREG (result))
8484             {
8485
8486               emitcode ("mov", "a,%s", l);
8487               aopPut (AOP (result), "a", offset);
8488             }
8489           else
8490             aopPut (AOP (result), l, offset);
8491           offset++;
8492         }
8493       _endLazyDPSEvaluation ();
8494     }
8495
8496   tlbl = newiTempLabel (NULL);
8497   tlbl1 = newiTempLabel (NULL);
8498   size = AOP_SIZE (result);
8499   offset = size - 1;
8500
8501   /* if it is only one byte then */
8502   if (size == 1)
8503     {
8504       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8505       MOVA (l);
8506       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8507       emitcode ("", "%05d$:", tlbl->key + 100);
8508       CLRC;
8509       emitcode ("rrc", "a");
8510       emitcode ("", "%05d$:", tlbl1->key + 100);
8511       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8512       aopPut (AOP (result), "a", 0);
8513       goto release;
8514     }
8515
8516   reAdjustPreg (AOP (result));
8517   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8518   emitcode ("", "%05d$:", tlbl->key + 100);
8519   CLRC;
8520   _startLazyDPSEvaluation ();
8521   while (size--)
8522     {
8523       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8524       MOVA (l);
8525       emitcode ("rrc", "a");
8526       aopPut (AOP (result), "a", offset--);
8527     }
8528   _endLazyDPSEvaluation ();
8529   reAdjustPreg (AOP (result));
8530
8531   emitcode ("", "%05d$:", tlbl1->key + 100);
8532   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8533
8534 release:
8535   freeAsmop (left, NULL, ic, TRUE);
8536   freeAsmop (result, NULL, ic, TRUE);
8537 }
8538
8539 /*-----------------------------------------------------------------*/
8540 /* genUnpackBits - generates code for unpacking bits               */
8541 /*-----------------------------------------------------------------*/
8542 static void
8543 genUnpackBits (operand * result, char *rname, int ptype)
8544 {
8545   int shCnt;
8546   int rlen = 0;
8547   sym_link *etype;
8548   int offset = 0;
8549
8550   D (emitcode (";", "genUnpackBits ");
8551     );
8552
8553   etype = getSpec (operandType (result));
8554
8555   /* read the first byte  */
8556   switch (ptype)
8557     {
8558
8559     case POINTER:
8560     case IPOINTER:
8561       emitcode ("mov", "a,@%s", rname);
8562       break;
8563
8564     case PPOINTER:
8565       emitcode ("movx", "a,@%s", rname);
8566       break;
8567
8568     case FPOINTER:
8569       emitcode ("movx", "a,@dptr");
8570       break;
8571
8572     case CPOINTER:
8573       emitcode ("clr", "a");
8574       emitcode ("movc", "a,@a+dptr");
8575       break;
8576
8577     case GPOINTER:
8578       emitcode ("lcall", "__gptrget");
8579       break;
8580     }
8581
8582   /* if we have bitdisplacement then it fits   */
8583   /* into this byte completely or if length is */
8584   /* less than a byte                          */
8585   if ((shCnt = SPEC_BSTR (etype)) ||
8586       (SPEC_BLEN (etype) <= 8))
8587     {
8588
8589       /* shift right acc */
8590       AccRsh (shCnt);
8591
8592       emitcode ("anl", "a,#0x%02x",
8593                 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
8594       aopPut (AOP (result), "a", offset);
8595       return;
8596     }
8597
8598   /* bit field did not fit in a byte  */
8599   rlen = SPEC_BLEN (etype) - 8;
8600   aopPut (AOP (result), "a", offset++);
8601
8602   while (1)
8603     {
8604
8605       switch (ptype)
8606         {
8607         case POINTER:
8608         case IPOINTER:
8609           emitcode ("inc", "%s", rname);
8610           emitcode ("mov", "a,@%s", rname);
8611           break;
8612
8613         case PPOINTER:
8614           emitcode ("inc", "%s", rname);
8615           emitcode ("movx", "a,@%s", rname);
8616           break;
8617
8618         case FPOINTER:
8619           emitcode ("inc", "dptr");
8620           emitcode ("movx", "a,@dptr");
8621           break;
8622
8623         case CPOINTER:
8624           emitcode ("clr", "a");
8625           emitcode ("inc", "dptr");
8626           emitcode ("movc", "a,@a+dptr");
8627           break;
8628
8629         case GPOINTER:
8630           emitcode ("inc", "dptr");
8631           emitcode ("lcall", "__gptrget");
8632           break;
8633         }
8634
8635       rlen -= 8;
8636       /* if we are done */
8637       if (rlen < 8)
8638         break;
8639
8640       aopPut (AOP (result), "a", offset++);
8641
8642     }
8643
8644   if (rlen)
8645     {
8646       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
8647       aopPut (AOP (result), "a", offset);
8648     }
8649
8650   return;
8651 }
8652
8653
8654 /*-----------------------------------------------------------------*/
8655 /* genDataPointerGet - generates code when ptr offset is known     */
8656 /*-----------------------------------------------------------------*/
8657 static void
8658 genDataPointerGet (operand * left,
8659                    operand * result,
8660                    iCode * ic)
8661 {
8662   char *l;
8663   char buffer[256];
8664   int size, offset = 0;
8665   aopOp (result, ic, TRUE, FALSE);
8666
8667   /* get the string representation of the name */
8668   l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
8669   size = AOP_SIZE (result);
8670   _startLazyDPSEvaluation ();
8671   while (size--)
8672     {
8673       if (offset)
8674         sprintf (buffer, "(%s + %d)", l + 1, offset);
8675       else
8676         sprintf (buffer, "%s", l + 1);
8677       aopPut (AOP (result), buffer, offset++);
8678     }
8679   _endLazyDPSEvaluation ();
8680
8681   freeAsmop (left, NULL, ic, TRUE);
8682   freeAsmop (result, NULL, ic, TRUE);
8683 }
8684
8685 /*-----------------------------------------------------------------*/
8686 /* genNearPointerGet - emitcode for near pointer fetch             */
8687 /*-----------------------------------------------------------------*/
8688 static void
8689 genNearPointerGet (operand * left,
8690                    operand * result,
8691                    iCode * ic,
8692                    iCode *pi)
8693 {
8694   asmop *aop = NULL;
8695   regs *preg = NULL;
8696   char *rname;
8697   sym_link *rtype, *retype, *letype;
8698   sym_link *ltype = operandType (left);
8699   char buffer[80];
8700
8701   rtype = operandType (result);
8702   retype = getSpec (rtype);
8703   letype = getSpec (ltype);
8704
8705   aopOp (left, ic, FALSE, FALSE);
8706
8707   /* if left is rematerialisable and
8708      result is not bit variable type and
8709      the left is pointer to data space i.e
8710      lower 128 bytes of space */
8711   if (AOP_TYPE (left) == AOP_IMMD &&
8712       !IS_BITVAR (retype) &&
8713       !IS_BITVAR (letype) &&
8714       DCL_TYPE (ltype) == POINTER)
8715     {
8716       genDataPointerGet (left, result, ic);
8717       return;
8718     }
8719
8720   /* if the value is already in a pointer register
8721      then don't need anything more */
8722   if (!AOP_INPREG (AOP (left)))
8723     {
8724       /* otherwise get a free pointer register */
8725       aop = newAsmop (0);
8726       preg = getFreePtr (ic, &aop, FALSE);
8727       emitcode ("mov", "%s,%s",
8728                 preg->name,
8729                 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8730       rname = preg->name;
8731     }
8732   else
8733     rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8734
8735   freeAsmop (left, NULL, ic, TRUE);
8736   aopOp (result, ic, FALSE, FALSE);
8737
8738   /* if bitfield then unpack the bits */
8739   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8740     genUnpackBits (result, rname, POINTER);
8741   else
8742     {
8743       /* we have can just get the values */
8744       int size = AOP_SIZE (result);
8745       int offset = 0;
8746
8747       while (size--)
8748         {
8749           if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8750             {
8751
8752               emitcode ("mov", "a,@%s", rname);
8753               aopPut (AOP (result), "a", offset);
8754             }
8755           else
8756             {
8757               sprintf (buffer, "@%s", rname);
8758               aopPut (AOP (result), buffer, offset);
8759             }
8760           offset++;
8761           if (size || pi)
8762             emitcode ("inc", "%s", rname);
8763         }
8764     }
8765
8766   /* now some housekeeping stuff */
8767   if (aop)
8768     {
8769       /* we had to allocate for this iCode */
8770       if (pi) { /* post increment present */
8771         aopPut(AOP ( left ),rname,0);
8772       }
8773       freeAsmop (NULL, aop, ic, TRUE);
8774     }
8775   else
8776     {
8777       /* we did not allocate which means left
8778          already in a pointer register, then
8779          if size > 0 && this could be used again
8780          we have to point it back to where it
8781          belongs */
8782       if (AOP_SIZE (result) > 1 &&
8783           !OP_SYMBOL (left)->remat &&
8784           (OP_SYMBOL (left)->liveTo > ic->seq ||
8785            ic->depth) &&
8786           !pi)
8787         {
8788           int size = AOP_SIZE (result) - 1;
8789           while (size--)
8790             emitcode ("dec", "%s", rname);
8791         }
8792     }
8793
8794   /* done */
8795   freeAsmop (result, NULL, ic, TRUE);
8796   if (pi) pi->generated = 1;
8797 }
8798
8799 /*-----------------------------------------------------------------*/
8800 /* genPagedPointerGet - emitcode for paged pointer fetch           */
8801 /*-----------------------------------------------------------------*/
8802 static void
8803 genPagedPointerGet (operand * left,
8804                     operand * result,
8805                     iCode * ic,
8806                     iCode * pi)
8807 {
8808   asmop *aop = NULL;
8809   regs *preg = NULL;
8810   char *rname;
8811   sym_link *rtype, *retype, *letype;
8812
8813   rtype = operandType (result);
8814   retype = getSpec (rtype);
8815   letype = getSpec (operandType (left));
8816   aopOp (left, ic, FALSE, FALSE);
8817
8818   /* if the value is already in a pointer register
8819      then don't need anything more */
8820   if (!AOP_INPREG (AOP (left)))
8821     {
8822       /* otherwise get a free pointer register */
8823       aop = newAsmop (0);
8824       preg = getFreePtr (ic, &aop, FALSE);
8825       emitcode ("mov", "%s,%s",
8826                 preg->name,
8827                 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8828       rname = preg->name;
8829     }
8830   else
8831     rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8832
8833   freeAsmop (left, NULL, ic, TRUE);
8834   aopOp (result, ic, FALSE, FALSE);
8835
8836   /* if bitfield then unpack the bits */
8837   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8838     genUnpackBits (result, rname, PPOINTER);
8839   else
8840     {
8841       /* we have can just get the values */
8842       int size = AOP_SIZE (result);
8843       int offset = 0;
8844
8845       while (size--)
8846         {
8847
8848           emitcode ("movx", "a,@%s", rname);
8849           aopPut (AOP (result), "a", offset);
8850
8851           offset++;
8852
8853           if (size || pi)
8854             emitcode ("inc", "%s", rname);
8855         }
8856     }
8857
8858   /* now some housekeeping stuff */
8859   if (aop)
8860     {
8861       /* we had to allocate for this iCode */
8862       if (pi) aopPut ( AOP (left), rname, 0);
8863       freeAsmop (NULL, aop, ic, TRUE);
8864     }
8865   else
8866     {
8867       /* we did not allocate which means left
8868          already in a pointer register, then
8869          if size > 0 && this could be used again
8870          we have to point it back to where it
8871          belongs */
8872       if (AOP_SIZE (result) > 1 &&
8873           !OP_SYMBOL (left)->remat &&
8874           (OP_SYMBOL (left)->liveTo > ic->seq ||
8875            ic->depth) &&
8876           !pi)
8877         {
8878           int size = AOP_SIZE (result) - 1;
8879           while (size--)
8880             emitcode ("dec", "%s", rname);
8881         }
8882     }
8883
8884   /* done */
8885   freeAsmop (result, NULL, ic, TRUE);
8886   if (pi) pi->generated = 1;
8887 }
8888
8889 /*-----------------------------------------------------------------*/
8890 /* genFarPointerGet - gget value from far space                    */
8891 /*-----------------------------------------------------------------*/
8892 static void
8893 genFarPointerGet (operand * left,
8894                   operand * result, iCode * ic, iCode *pi)
8895 {
8896     int size, offset, dopi=1;
8897   sym_link *retype = getSpec (operandType (result));
8898   sym_link *letype = getSpec (operandType (left));
8899   D (emitcode (";", "genFarPointerGet");
8900     );
8901
8902   aopOp (left, ic, FALSE, FALSE);
8903
8904   /* if the operand is already in dptr
8905      then we do nothing else we move the value to dptr */
8906   if (AOP_TYPE (left) != AOP_STR)
8907     {
8908       /* if this is remateriazable */
8909       if (AOP_TYPE (left) == AOP_IMMD)
8910         {
8911           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8912         }
8913       else
8914         {
8915           /* we need to get it byte by byte */
8916           _startLazyDPSEvaluation ();
8917           if (AOP_TYPE (left) != AOP_DPTR)
8918             {
8919               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8920               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8921               if (options.model == MODEL_FLAT24)
8922                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8923             }
8924           else
8925             {
8926               /* We need to generate a load to DPTR indirect through DPTR. */
8927               D (emitcode (";", "genFarPointerGet -- indirection special case.");
8928                 );
8929               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8930               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8931               if (options.model == MODEL_FLAT24)
8932                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8933               emitcode ("pop", "dph");
8934               emitcode ("pop", "dpl");
8935               dopi =0;
8936             }
8937           _endLazyDPSEvaluation ();
8938         }
8939     }
8940   /* so dptr know contains the address */
8941   aopOp (result, ic, FALSE, TRUE);
8942
8943   /* if bit then unpack */
8944   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8945     genUnpackBits (result, "dptr", FPOINTER);
8946   else
8947     {
8948       size = AOP_SIZE (result);
8949       offset = 0;
8950
8951       _startLazyDPSEvaluation ();
8952       while (size--)
8953         {
8954
8955           genSetDPTR (0);
8956           _flushLazyDPS ();
8957
8958           emitcode ("movx", "a,@dptr");
8959           if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
8960             emitcode ("inc", "dptr");
8961
8962           aopPut (AOP (result), "a", offset++);
8963         }
8964       _endLazyDPSEvaluation ();
8965     }
8966   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
8967     aopPut ( AOP (left), "dpl", 0);
8968     aopPut ( AOP (left), "dph", 1);
8969     if (options.model == MODEL_FLAT24)
8970             aopPut ( AOP (left), "dpx", 2);
8971     pi->generated = 1;
8972   } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
8973              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
8974       
8975       size = AOP_SIZE (result) - 1;
8976       while (size--) emitcode ("lcall","__decdptr");
8977   }
8978
8979   freeAsmop (left, NULL, ic, TRUE);
8980   freeAsmop (result, NULL, ic, TRUE);
8981 }
8982
8983 /*-----------------------------------------------------------------*/
8984 /* emitcodePointerGet - gget value from code space                  */
8985 /*-----------------------------------------------------------------*/
8986 static void
8987 emitcodePointerGet (operand * left,
8988                     operand * result, iCode * ic, iCode *pi)
8989 {
8990   int size, offset, dopi=1;
8991   sym_link *retype = getSpec (operandType (result));
8992
8993   aopOp (left, ic, FALSE, FALSE);
8994
8995   /* if the operand is already in dptr
8996      then we do nothing else we move the value to dptr */
8997   if (AOP_TYPE (left) != AOP_STR)
8998     {
8999       /* if this is remateriazable */
9000       if (AOP_TYPE (left) == AOP_IMMD)
9001         {
9002           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9003         }
9004       else
9005         {                       /* we need to get it byte by byte */
9006           _startLazyDPSEvaluation ();
9007           if (AOP_TYPE (left) != AOP_DPTR)
9008             {
9009               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9010               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9011               if (options.model == MODEL_FLAT24)
9012                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9013             }
9014           else
9015             {
9016               /* We need to generate a load to DPTR indirect through DPTR. */
9017               D (emitcode (";", "gencodePointerGet -- indirection special case.");
9018                 );
9019               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
9020               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
9021               if (options.model == MODEL_FLAT24)
9022                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9023               emitcode ("pop", "dph");
9024               emitcode ("pop", "dpl");
9025               dopi=0;
9026             }
9027           _endLazyDPSEvaluation ();
9028         }
9029     }
9030   /* so dptr know contains the address */
9031   aopOp (result, ic, FALSE, TRUE);
9032
9033   /* if bit then unpack */
9034   if (IS_BITVAR (retype))
9035     genUnpackBits (result, "dptr", CPOINTER);
9036   else
9037     {
9038       size = AOP_SIZE (result);
9039       offset = 0;
9040
9041       _startLazyDPSEvaluation ();
9042       while (size--)
9043         {
9044           genSetDPTR (0);
9045           _flushLazyDPS ();
9046
9047           emitcode ("clr", "a");
9048           emitcode ("movc", "a,@a+dptr");
9049           if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9050             emitcode ("inc", "dptr");
9051           aopPut (AOP (result), "a", offset++);
9052         }
9053       _endLazyDPSEvaluation ();
9054     }
9055   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9056       aopPut ( AOP (left), "dpl", 0);
9057       aopPut ( AOP (left), "dph", 1);
9058       if (options.model == MODEL_FLAT24)
9059           aopPut ( AOP (left), "dpx", 2);
9060       pi->generated = 1;
9061   } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9062              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9063       
9064       size = AOP_SIZE (result) - 1;
9065       while (size--) emitcode ("lcall","__decdptr");
9066   }
9067   
9068   freeAsmop (left, NULL, ic, TRUE);
9069   freeAsmop (result, NULL, ic, TRUE);
9070 }
9071
9072 /*-----------------------------------------------------------------*/
9073 /* genGenPointerGet - gget value from generic pointer space        */
9074 /*-----------------------------------------------------------------*/
9075 static void
9076 genGenPointerGet (operand * left,
9077                   operand * result, iCode * ic, iCode * pi)
9078 {
9079   int size, offset;
9080   sym_link *retype = getSpec (operandType (result));
9081   sym_link *letype = getSpec (operandType (left));
9082
9083   D (emitcode (";", "genGenPointerGet "); );
9084
9085   aopOp (left, ic, FALSE, (OP_SYMBOL(left)->ruonly ? FALSE : TRUE));
9086
9087   /* if the operand is already in dptr
9088      then we do nothing else we move the value to dptr */
9089   if (AOP_TYPE (left) != AOP_STR)
9090     {
9091       /* if this is remateriazable */
9092       if (AOP_TYPE (left) == AOP_IMMD)
9093         {
9094           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9095           if (AOP(left)->aopu.aop_immd.from_cast_remat) 
9096                   emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, FALSE));
9097           else
9098                   emitcode ("mov", "b,#%d", pointerCode (retype));
9099         }
9100       else
9101         {                       /* we need to get it byte by byte */
9102           _startLazyDPSEvaluation ();
9103           if (AOP(left)->type==AOP_DPTR2) {
9104             char *l;
9105             l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
9106             genSetDPTR(0);
9107             _flushLazyDPS();
9108             emitcode ("mov", "dpl,%s", l);
9109             l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
9110             genSetDPTR(0);
9111             _flushLazyDPS();
9112             emitcode ("mov", "dph,%s", l);
9113             if (options.model == MODEL_FLAT24) {
9114               l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
9115               genSetDPTR(0);
9116               _flushLazyDPS();
9117               emitcode ("mov", "dpx,%s", l);
9118               emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
9119             } else {
9120               emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9121             }
9122           } else {
9123             emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
9124             emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
9125             if (options.model == MODEL_FLAT24) {
9126               emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9127               emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
9128             } else {
9129               emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9130             }
9131           }
9132           _endLazyDPSEvaluation ();
9133         }
9134     }
9135   /* so dptr know contains the address */
9136   aopOp (result, ic, FALSE, TRUE);
9137
9138   /* if bit then unpack */
9139   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9140     genUnpackBits (result, "dptr", GPOINTER);
9141   else
9142     {
9143       size = AOP_SIZE (result);
9144       offset = 0;
9145
9146       while (size--)
9147         {
9148           emitcode ("lcall", "__gptrget");
9149           aopPut (AOP (result), "a", offset++);
9150           if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9151             emitcode ("inc", "dptr");
9152         }
9153     }
9154
9155   if (pi && AOP_TYPE (left) != AOP_IMMD) {
9156     aopPut ( AOP (left), "dpl", 0);
9157     aopPut ( AOP (left), "dph", 1);
9158     if (options.model == MODEL_FLAT24) {
9159         aopPut ( AOP (left), "dpx", 2);
9160         aopPut ( AOP (left), "b", 3);   
9161     } else  aopPut ( AOP (left), "b", 2);       
9162     pi->generated = 1;
9163   } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9164              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9165       
9166       size = AOP_SIZE (result) - 1;
9167       while (size--) emitcode ("lcall","__decdptr");
9168   }
9169
9170   freeAsmop (left, NULL, ic, TRUE);
9171   freeAsmop (result, NULL, ic, TRUE);
9172 }
9173
9174 /*-----------------------------------------------------------------*/
9175 /* genPointerGet - generate code for pointer get                   */
9176 /*-----------------------------------------------------------------*/
9177 static void
9178 genPointerGet (iCode * ic, iCode *pi)
9179 {
9180   operand *left, *result;
9181   sym_link *type, *etype;
9182   int p_type;
9183
9184   D (emitcode (";", "genPointerGet ");
9185     );
9186
9187   left = IC_LEFT (ic);
9188   result = IC_RESULT (ic);
9189
9190   /* depending on the type of pointer we need to
9191      move it to the correct pointer register */
9192   type = operandType (left);
9193   etype = getSpec (type);
9194   /* if left is of type of pointer then it is simple */
9195   if (IS_PTR (type) && !IS_FUNC (type->next))
9196     p_type = DCL_TYPE (type);
9197   else
9198     {
9199       /* we have to go by the storage class */
9200       p_type = PTR_TYPE (SPEC_OCLS (etype));
9201     }
9202   /* special case when cast remat */
9203   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9204       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9205           left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9206           type =   type = operandType (left);
9207           p_type = DCL_TYPE (type);
9208   }
9209   /* now that we have the pointer type we assign
9210      the pointer values */
9211   switch (p_type)
9212     {
9213
9214     case POINTER:
9215     case IPOINTER:
9216       genNearPointerGet (left, result, ic, pi);
9217       break;
9218
9219     case PPOINTER:
9220       genPagedPointerGet (left, result, ic, pi);
9221       break;
9222
9223     case FPOINTER:
9224       genFarPointerGet (left, result, ic, pi);
9225       break;
9226
9227     case CPOINTER:
9228       emitcodePointerGet (left, result, ic, pi);
9229       break;
9230
9231     case GPOINTER:
9232       genGenPointerGet (left, result, ic, pi);
9233       break;
9234     }
9235
9236 }
9237
9238 /*-----------------------------------------------------------------*/
9239 /* genPackBits - generates code for packed bit storage             */
9240 /*-----------------------------------------------------------------*/
9241 static void
9242 genPackBits (sym_link * etype,
9243              operand * right,
9244              char *rname, int p_type)
9245 {
9246   int shCount = 0;
9247   int offset = 0;
9248   int rLen = 0;
9249   int blen, bstr;
9250   char *l;
9251
9252   blen = SPEC_BLEN (etype);
9253   bstr = SPEC_BSTR (etype);
9254
9255   l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9256   MOVA (l);
9257
9258   /* if the bit lenth is less than or    */
9259   /* it exactly fits a byte then         */
9260   if (SPEC_BLEN (etype) <= 8)
9261     {
9262       shCount = SPEC_BSTR (etype);
9263
9264       /* shift left acc */
9265       AccLsh (shCount);
9266
9267       if (SPEC_BLEN (etype) < 8)
9268         {                       /* if smaller than a byte */
9269
9270
9271           switch (p_type)
9272             {
9273             case POINTER:
9274               emitcode ("mov", "b,a");
9275               emitcode ("mov", "a,@%s", rname);
9276               break;
9277
9278             case FPOINTER:
9279               emitcode ("mov", "b,a");
9280               emitcode ("movx", "a,@dptr");
9281               break;
9282
9283             case GPOINTER:
9284               emitcode ("push", "b");
9285               emitcode ("push", "acc");
9286               emitcode ("lcall", "__gptrget");
9287               emitcode ("pop", "b");
9288               break;
9289             }
9290
9291           emitcode ("anl", "a,#0x%02x", (unsigned char)
9292                     ((unsigned char) (0xFF << (blen + bstr)) |
9293                      (unsigned char) (0xFF >> (8 - bstr))));
9294           emitcode ("orl", "a,b");
9295           if (p_type == GPOINTER)
9296             emitcode ("pop", "b");
9297         }
9298     }
9299
9300   switch (p_type)
9301     {
9302     case POINTER:
9303       emitcode ("mov", "@%s,a", rname);
9304       break;
9305
9306     case FPOINTER:
9307       emitcode ("movx", "@dptr,a");
9308       break;
9309
9310     case GPOINTER:
9311       emitcode ("lcall", "__gptrput");
9312       break;
9313     }
9314
9315   /* if we r done */
9316   if (SPEC_BLEN (etype) <= 8)
9317     return;
9318
9319   emitcode ("inc", "%s", rname);
9320   rLen = SPEC_BLEN (etype);
9321
9322   /* now generate for lengths greater than one byte */
9323   while (1)
9324     {
9325
9326       l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
9327
9328       rLen -= 8;
9329       if (rLen < 8)
9330         break;
9331
9332       switch (p_type)
9333         {
9334         case POINTER:
9335           if (*l == '@')
9336             {
9337               MOVA (l);
9338               emitcode ("mov", "@%s,a", rname);
9339             }
9340           else
9341             emitcode ("mov", "@%s,%s", rname, l);
9342           break;
9343
9344         case FPOINTER:
9345           MOVA (l);
9346           emitcode ("movx", "@dptr,a");
9347           break;
9348
9349         case GPOINTER:
9350           MOVA (l);
9351           emitcode ("lcall", "__gptrput");
9352           break;
9353         }
9354       emitcode ("inc", "%s", rname);
9355     }
9356
9357   MOVA (l);
9358
9359   /* last last was not complete */
9360   if (rLen)
9361     {
9362       /* save the byte & read byte */
9363       switch (p_type)
9364         {
9365         case POINTER:
9366           emitcode ("mov", "b,a");
9367           emitcode ("mov", "a,@%s", rname);
9368           break;
9369
9370         case FPOINTER:
9371           emitcode ("mov", "b,a");
9372           emitcode ("movx", "a,@dptr");
9373           break;
9374
9375         case GPOINTER:
9376           emitcode ("push", "b");
9377           emitcode ("push", "acc");
9378           emitcode ("lcall", "__gptrget");
9379           emitcode ("pop", "b");
9380           break;
9381         }
9382
9383       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
9384       emitcode ("orl", "a,b");
9385     }
9386
9387   if (p_type == GPOINTER)
9388     emitcode ("pop", "b");
9389
9390   switch (p_type)
9391     {
9392
9393     case POINTER:
9394       emitcode ("mov", "@%s,a", rname);
9395       break;
9396
9397     case FPOINTER:
9398       emitcode ("movx", "@dptr,a");
9399       break;
9400
9401     case GPOINTER:
9402       emitcode ("lcall", "__gptrput");
9403       break;
9404     }
9405 }
9406 /*-----------------------------------------------------------------*/
9407 /* genDataPointerSet - remat pointer to data space                 */
9408 /*-----------------------------------------------------------------*/
9409 static void
9410 genDataPointerSet (operand * right,
9411                    operand * result,
9412                    iCode * ic)
9413 {
9414   int size, offset = 0;
9415   char *l, buffer[256];
9416
9417   aopOp (right, ic, FALSE, FALSE);
9418
9419   l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
9420   size = AOP_SIZE (right);
9421   while (size--)
9422     {
9423       if (offset)
9424         sprintf (buffer, "(%s + %d)", l + 1, offset);
9425       else
9426         sprintf (buffer, "%s", l + 1);
9427       emitcode ("mov", "%s,%s", buffer,
9428                 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
9429     }
9430
9431   freeAsmop (right, NULL, ic, TRUE);
9432   freeAsmop (result, NULL, ic, TRUE);
9433 }
9434
9435 /*-----------------------------------------------------------------*/
9436 /* genNearPointerSet - emitcode for near pointer put                */
9437 /*-----------------------------------------------------------------*/
9438 static void
9439 genNearPointerSet (operand * right,
9440                    operand * result,
9441                    iCode * ic,
9442                    iCode * pi)
9443 {
9444   asmop *aop = NULL;
9445   regs *preg = NULL;
9446   char *rname, *l;
9447   sym_link *retype, *letype;
9448   sym_link *ptype = operandType (result);
9449
9450   retype = getSpec (operandType (right));
9451   letype = getSpec (ptype);
9452
9453   aopOp (result, ic, FALSE, FALSE);
9454
9455   /* if the result is rematerializable &
9456      in data space & not a bit variable */
9457   if (AOP_TYPE (result) == AOP_IMMD &&
9458       DCL_TYPE (ptype) == POINTER &&
9459       !IS_BITVAR (retype) &&
9460       !IS_BITVAR (letype))
9461     {
9462       genDataPointerSet (right, result, ic);
9463       return;
9464     }
9465
9466   /* if the value is already in a pointer register
9467      then don't need anything more */
9468   if (!AOP_INPREG (AOP (result)))
9469     {
9470       /* otherwise get a free pointer register */
9471       aop = newAsmop (0);
9472       preg = getFreePtr (ic, &aop, FALSE);
9473       emitcode ("mov", "%s,%s",
9474                 preg->name,
9475                 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9476       rname = preg->name;
9477     }
9478   else
9479     rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9480
9481   aopOp (right, ic, FALSE, FALSE);
9482
9483   /* if bitfield then unpack the bits */
9484   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9485     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
9486   else
9487     {
9488       /* we have can just get the values */
9489       int size = AOP_SIZE (right);
9490       int offset = 0;
9491
9492       while (size--)
9493         {
9494           l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
9495           if (*l == '@')
9496             {
9497               MOVA (l);
9498               emitcode ("mov", "@%s,a", rname);
9499             }
9500           else
9501             emitcode ("mov", "@%s,%s", rname, l);
9502           if (size || pi)
9503             emitcode ("inc", "%s", rname);
9504           offset++;
9505         }
9506     }
9507
9508   /* now some housekeeping stuff */
9509   if (aop)
9510     {
9511       /* we had to allocate for this iCode */
9512       if (pi) aopPut (AOP (result),rname,0);
9513       freeAsmop (NULL, aop, ic, TRUE);
9514     }
9515   else
9516     {
9517       /* we did not allocate which means left
9518          already in a pointer register, then
9519          if size > 0 && this could be used again
9520          we have to point it back to where it
9521          belongs */
9522       if (AOP_SIZE (right) > 1 &&
9523           !OP_SYMBOL (result)->remat &&
9524           (OP_SYMBOL (result)->liveTo > ic->seq ||
9525            ic->depth) &&
9526           !pi)
9527         {
9528           int size = AOP_SIZE (right) - 1;
9529           while (size--)
9530             emitcode ("dec", "%s", rname);
9531         }
9532     }
9533
9534   /* done */
9535   if (pi) pi->generated = 1;
9536   freeAsmop (result, NULL, ic, TRUE);
9537   freeAsmop (right, NULL, ic, TRUE);
9538
9539
9540 }
9541
9542 /*-----------------------------------------------------------------*/
9543 /* genPagedPointerSet - emitcode for Paged pointer put             */
9544 /*-----------------------------------------------------------------*/
9545 static void
9546 genPagedPointerSet (operand * right,
9547                     operand * result,
9548                     iCode * ic,
9549                     iCode *pi)
9550 {
9551   asmop *aop = NULL;
9552   regs *preg = NULL;
9553   char *rname, *l;
9554   sym_link *retype, *letype;
9555
9556   retype = getSpec (operandType (right));
9557   letype = getSpec (operandType (result));
9558
9559   aopOp (result, ic, FALSE, FALSE);
9560
9561   /* if the value is already in a pointer register
9562      then don't need anything more */
9563   if (!AOP_INPREG (AOP (result)))
9564     {
9565       /* otherwise get a free pointer register */
9566       aop = newAsmop (0);
9567       preg = getFreePtr (ic, &aop, FALSE);
9568       emitcode ("mov", "%s,%s",
9569                 preg->name,
9570                 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9571       rname = preg->name;
9572     }
9573   else
9574     rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9575
9576   aopOp (right, ic, FALSE, FALSE);
9577
9578   /* if bitfield then unpack the bits */
9579   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9580     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
9581   else
9582     {
9583       /* we have can just get the values */
9584       int size = AOP_SIZE (right);
9585       int offset = 0;
9586
9587       while (size--)
9588         {
9589           l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
9590
9591           MOVA (l);
9592           emitcode ("movx", "@%s,a", rname);
9593
9594           if (size || pi)
9595             emitcode ("inc", "%s", rname);
9596
9597           offset++;
9598         }
9599     }
9600
9601   /* now some housekeeping stuff */
9602   if (aop)
9603     {
9604       if (pi) aopPut (AOP (result),rname,0);
9605       /* we had to allocate for this iCode */
9606       freeAsmop (NULL, aop, ic, TRUE);
9607     }
9608   else
9609     {
9610       /* we did not allocate which means left
9611          already in a pointer register, then
9612          if size > 0 && this could be used again
9613          we have to point it back to where it
9614          belongs */
9615       if (AOP_SIZE (right) > 1 &&
9616           !OP_SYMBOL (result)->remat &&
9617           (OP_SYMBOL (result)->liveTo > ic->seq ||
9618            ic->depth) &&
9619           !pi)
9620         {
9621           int size = AOP_SIZE (right) - 1;
9622           while (size--)
9623             emitcode ("dec", "%s", rname);
9624         }
9625     }
9626
9627   /* done */
9628   if (pi) pi->generated = 1;
9629   freeAsmop (result, NULL, ic, TRUE);
9630   freeAsmop (right, NULL, ic, TRUE);
9631
9632
9633 }
9634
9635 /*-----------------------------------------------------------------*/
9636 /* genFarPointerSet - set value from far space                     */
9637 /*-----------------------------------------------------------------*/
9638 static void
9639 genFarPointerSet (operand * right,
9640                   operand * result, iCode * ic, iCode *pi)
9641 {
9642   int size, offset, dopi=1;
9643   sym_link *retype = getSpec (operandType (right));
9644   sym_link *letype = getSpec (operandType (result));
9645
9646   aopOp (result, ic, FALSE, FALSE);
9647
9648   /* if the operand is already in dptr
9649      then we do nothing else we move the value to dptr */
9650   if (AOP_TYPE (result) != AOP_STR)
9651     {
9652       /* if this is remateriazable */
9653       if (AOP_TYPE (result) == AOP_IMMD)
9654         emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9655       else
9656         {
9657           /* we need to get it byte by byte */
9658           _startLazyDPSEvaluation ();
9659           if (AOP_TYPE (result) != AOP_DPTR)
9660             {
9661               emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9662               emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9663               if (options.model == MODEL_FLAT24)
9664                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9665             }
9666           else
9667             {
9668               /* We need to generate a load to DPTR indirect through DPTR. */
9669               D (emitcode (";", "genFarPointerSet -- indirection special case.");
9670                 );
9671               emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
9672               emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
9673               if (options.model == MODEL_FLAT24)
9674                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9675               emitcode ("pop", "dph");
9676               emitcode ("pop", "dpl");
9677               dopi=0;
9678             }
9679           _endLazyDPSEvaluation ();
9680         }
9681     }
9682   /* so dptr know contains the address */
9683   aopOp (right, ic, FALSE, TRUE);
9684
9685   /* if bit then unpack */
9686   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9687     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
9688   else
9689     {
9690       size = AOP_SIZE (right);
9691       offset = 0;
9692
9693       _startLazyDPSEvaluation ();
9694       while (size--)
9695         {
9696           char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9697           MOVA (l);
9698
9699           genSetDPTR (0);
9700           _flushLazyDPS ();
9701
9702           emitcode ("movx", "@dptr,a");
9703           if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
9704             emitcode ("inc", "dptr");
9705         }
9706       _endLazyDPSEvaluation ();
9707     }
9708
9709   if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
9710       aopPut (AOP(result),"dpl",0);
9711       aopPut (AOP(result),"dph",1);
9712       if (options.model == MODEL_FLAT24)
9713           aopPut (AOP(result),"dpx",2);
9714       pi->generated=1;
9715   } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
9716              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
9717       
9718       size = AOP_SIZE (right) - 1;
9719       while (size--) emitcode ("lcall","__decdptr");
9720   }
9721   freeAsmop (result, NULL, ic, TRUE);
9722   freeAsmop (right, NULL, ic, TRUE);
9723 }
9724
9725 /*-----------------------------------------------------------------*/
9726 /* genGenPointerSet - set value from generic pointer space         */
9727 /*-----------------------------------------------------------------*/
9728 static void
9729 genGenPointerSet (operand * right,
9730                   operand * result, iCode * ic, iCode *pi)
9731 {
9732   int size, offset;
9733   sym_link *retype = getSpec (operandType (right));
9734   sym_link *letype = getSpec (operandType (result));
9735
9736   aopOp (result, ic, FALSE, OP_SYMBOL(result)->ruonly ? FALSE : TRUE);
9737
9738   /* if the operand is already in dptr
9739      then we do nothing else we move the value to dptr */
9740   if (AOP_TYPE (result) != AOP_STR)
9741     {
9742       _startLazyDPSEvaluation ();
9743       /* if this is remateriazable */
9744       if (AOP_TYPE (result) == AOP_IMMD)
9745         {
9746           emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9747           if (AOP(result)->aopu.aop_immd.from_cast_remat) 
9748                   emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, FALSE));
9749           else
9750                   emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9751         }
9752       else
9753         {                       /* we need to get it byte by byte */
9754           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9755           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9756           if (options.model == MODEL_FLAT24) {
9757             emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9758             emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
9759           } else {
9760             emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9761           }
9762         }
9763       _endLazyDPSEvaluation ();
9764     }
9765   /* so dptr know contains the address */
9766   aopOp (right, ic, FALSE, TRUE);
9767
9768   /* if bit then unpack */
9769   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9770     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
9771   else
9772     {
9773       size = AOP_SIZE (right);
9774       offset = 0;
9775
9776       _startLazyDPSEvaluation ();
9777       while (size--)
9778         {
9779           char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9780           MOVA (l);
9781
9782           genSetDPTR (0);
9783           _flushLazyDPS ();
9784
9785           emitcode ("lcall", "__gptrput");
9786           if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
9787             emitcode ("inc", "dptr");
9788         }
9789       _endLazyDPSEvaluation ();
9790     }
9791
9792   if (pi && AOP_TYPE (result) != AOP_IMMD) {
9793       aopPut (AOP(result),"dpl",0);
9794       aopPut (AOP(result),"dph",1);
9795       if (options.model == MODEL_FLAT24) {
9796           aopPut (AOP(result),"dpx",2);
9797           aopPut (AOP(result),"b",3);
9798       } else {
9799           aopPut (AOP(result),"b",2);
9800       }
9801       pi->generated=1;
9802   } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
9803              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
9804       
9805       size = AOP_SIZE (right) - 1;
9806       while (size--) emitcode ("lcall","__decdptr");
9807   }
9808   freeAsmop (result, NULL, ic, TRUE);
9809   freeAsmop (right, NULL, ic, TRUE);
9810 }
9811
9812 /*-----------------------------------------------------------------*/
9813 /* genPointerSet - stores the value into a pointer location        */
9814 /*-----------------------------------------------------------------*/
9815 static void
9816 genPointerSet (iCode * ic, iCode *pi)
9817 {
9818   operand *right, *result;
9819   sym_link *type, *etype;
9820   int p_type;
9821
9822   D (emitcode (";", "genPointerSet ");
9823     );
9824
9825   right = IC_RIGHT (ic);
9826   result = IC_RESULT (ic);
9827
9828   /* depending on the type of pointer we need to
9829      move it to the correct pointer register */
9830   type = operandType (result);
9831   etype = getSpec (type);
9832   /* if left is of type of pointer then it is simple */
9833   if (IS_PTR (type) && !IS_FUNC (type->next))
9834     {
9835       p_type = DCL_TYPE (type);
9836     }
9837   else
9838     {
9839       /* we have to go by the storage class */
9840       p_type = PTR_TYPE (SPEC_OCLS (etype));
9841     }
9842   /* special case when cast remat */
9843   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
9844       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
9845           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
9846           type =   type = operandType (result);
9847           p_type = DCL_TYPE (type);
9848   }
9849
9850   /* now that we have the pointer type we assign
9851      the pointer values */
9852   switch (p_type)
9853     {
9854
9855     case POINTER:
9856     case IPOINTER:
9857       genNearPointerSet (right, result, ic, pi);
9858       break;
9859
9860     case PPOINTER:
9861       genPagedPointerSet (right, result, ic, pi);
9862       break;
9863
9864     case FPOINTER:
9865       genFarPointerSet (right, result, ic, pi);
9866       break;
9867
9868     case GPOINTER:
9869       genGenPointerSet (right, result, ic, pi);
9870       break;
9871     }
9872
9873 }
9874
9875 /*-----------------------------------------------------------------*/
9876 /* genIfx - generate code for Ifx statement                        */
9877 /*-----------------------------------------------------------------*/
9878 static void
9879 genIfx (iCode * ic, iCode * popIc)
9880 {
9881   operand *cond = IC_COND (ic);
9882   int isbit = 0;
9883
9884   D (emitcode (";", "genIfx "););
9885
9886   aopOp (cond, ic, FALSE, FALSE);
9887
9888   /* get the value into acc */
9889   if (AOP_TYPE (cond) != AOP_CRY)
9890     toBoolean (cond);
9891   else
9892     isbit = 1;
9893   /* the result is now in the accumulator */
9894   freeAsmop (cond, NULL, ic, TRUE);
9895
9896   /* if there was something to be popped then do it */
9897   if (popIc)
9898     genIpop (popIc);
9899
9900   /* if the condition is  a bit variable */
9901   if (isbit && IS_ITEMP (cond) &&
9902       SPIL_LOC (cond))
9903     genIfxJump (ic, SPIL_LOC (cond)->rname);
9904   else if (isbit && !IS_ITEMP (cond))
9905     genIfxJump (ic, OP_SYMBOL (cond)->rname);
9906   else
9907     genIfxJump (ic, "a");
9908
9909   ic->generated = 1;
9910 }
9911
9912 /*-----------------------------------------------------------------*/
9913 /* genAddrOf - generates code for address of                       */
9914 /*-----------------------------------------------------------------*/
9915 static void
9916 genAddrOf (iCode * ic)
9917 {
9918   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
9919   int size, offset;
9920
9921   D (emitcode (";", "genAddrOf ");
9922     );
9923
9924   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9925
9926   /* if the operand is on the stack then we
9927      need to get the stack offset of this
9928      variable */
9929   if (sym->onStack) {
9930       
9931       /* if 10 bit stack */
9932       if (options.stack10bit) {
9933           char buff[10];
9934           sprintf(buff,"#0x%02x",(options.stack_loc >> 16) & 0xff);
9935           /* if it has an offset then we need to compute it */
9936           emitcode ("subb", "a,#0x%02x",
9937                     -((sym->stack < 0) ?
9938                       ((short) (sym->stack - _G.nRegsSaved)) :
9939                       ((short) sym->stack)) & 0xff);
9940           emitcode ("mov","b,a");
9941           emitcode ("mov","a,#0x%02x",(-((sym->stack < 0) ?
9942                                          ((short) (sym->stack - _G.nRegsSaved)) :
9943                                          ((short) sym->stack)) >> 8) & 0xff);
9944           if (sym->stack) {
9945               emitcode ("mov", "a,_bpx");
9946               emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ? 
9947                                              ((char) (sym->stack - _G.nRegsSaved)) :
9948                                              ((char) sym->stack )) & 0xff);
9949               emitcode ("mov", "b,a");
9950               emitcode ("mov", "a,_bpx+1");
9951               emitcode ("addc","a,#0x%02x", (((sym->stack < 0) ? 
9952                                               ((short) (sym->stack - _G.nRegsSaved)) :
9953                                               ((short) sym->stack )) >> 8) & 0xff);
9954               aopPut (AOP (IC_RESULT (ic)), "b", 0);
9955               aopPut (AOP (IC_RESULT (ic)), "a", 1);
9956               aopPut (AOP (IC_RESULT (ic)), buff, 2);
9957           } else {
9958               /* we can just move _bp */
9959               aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
9960               aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
9961               aopPut (AOP (IC_RESULT (ic)), buff, 2);
9962           }       
9963       } else {
9964           /* if it has an offset then we need to compute it */
9965           if (sym->stack) {
9966               emitcode ("mov", "a,_bp");
9967               emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
9968               aopPut (AOP (IC_RESULT (ic)), "a", 0);
9969           } else {
9970               /* we can just move _bp */
9971               aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
9972           }
9973           /* fill the result with zero */
9974           size = AOP_SIZE (IC_RESULT (ic)) - 1;
9975           
9976           
9977           if (options.stack10bit && size < (FPTRSIZE - 1)) {
9978               fprintf (stderr,
9979                        "*** warning: pointer to stack var truncated.\n");
9980           }
9981
9982           offset = 1;
9983           while (size--) {
9984               aopPut (AOP (IC_RESULT (ic)), zero, offset++);
9985           }      
9986       }
9987       goto release;
9988   }
9989
9990   /* object not on stack then we need the name */
9991   size = AOP_SIZE (IC_RESULT (ic));
9992   offset = 0;
9993
9994   while (size--)
9995     {
9996       char s[SDCC_NAME_MAX];
9997       if (offset)
9998         sprintf (s, "#(%s >> %d)",
9999                  sym->rname,
10000                  offset * 8);
10001       else
10002         sprintf (s, "#%s", sym->rname);
10003       aopPut (AOP (IC_RESULT (ic)), s, offset++);
10004     }
10005
10006 release:
10007   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10008
10009 }
10010
10011 /*-----------------------------------------------------------------*/
10012 /* genArrayInit - generates code for address of                       */
10013 /*-----------------------------------------------------------------*/
10014 static void
10015 genArrayInit (iCode * ic)
10016 {
10017     literalList *iLoop;
10018     int         ix, count;
10019     int         elementSize = 0, eIndex;
10020     unsigned    val, lastVal;
10021     sym_link    *type;
10022     operand     *left=IC_LEFT(ic);
10023     
10024     D (emitcode (";", "genArrayInit "););
10025
10026     aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10027     
10028     if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10029     {
10030         // Load immediate value into DPTR.
10031         emitcode("mov", "dptr, %s",
10032              aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, TRUE));
10033     }
10034     else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10035     {
10036 #if 0
10037       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10038               "Unexpected operand to genArrayInit.\n");
10039       exit(1);
10040 #else
10041       // a regression because of SDCCcse.c:1.52
10042       emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
10043       emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
10044       if (options.model == MODEL_FLAT24)
10045         emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
10046 #endif
10047     }
10048     
10049     type = operandType(IC_LEFT(ic));
10050     
10051     if (type && type->next)
10052     {
10053         elementSize = getSize(type->next);
10054     }
10055     else
10056     {
10057         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10058                                 "can't determine element size in genArrayInit.\n");
10059         exit(1);
10060     }
10061     
10062     iLoop = IC_ARRAYILIST(ic);
10063     lastVal = 0xffff;
10064     
10065     while (iLoop)
10066     {
10067         bool firstpass = TRUE;
10068         
10069         emitcode(";", "store %d x 0x%x to DPTR (element size %d)", 
10070                  iLoop->count, (int)iLoop->literalValue, elementSize);
10071         
10072         ix = iLoop->count;
10073         
10074         while (ix)
10075         {
10076             symbol *tlbl = NULL;
10077             
10078             count = ix > 256 ? 256 : ix;
10079             
10080             if (count > 1)
10081             {
10082                 tlbl = newiTempLabel (NULL);
10083                 if (firstpass || (count & 0xff))
10084                 {
10085                     emitcode("mov", "b, #0x%x", count & 0xff);
10086                 }
10087                 
10088                 emitcode ("", "%05d$:", tlbl->key + 100);
10089             }
10090             
10091             firstpass = FALSE;
10092                 
10093             for (eIndex = 0; eIndex < elementSize; eIndex++)
10094             {
10095                 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10096                 if (val != lastVal)
10097                 {
10098                     emitcode("mov", "a, #0x%x", val);
10099                     lastVal = val;
10100                 }
10101                 
10102                 emitcode("movx", "@dptr, a");
10103                 emitcode("inc", "dptr");
10104             }
10105             
10106             if (count > 1)
10107             {
10108                 emitcode("djnz", "b, %05d$", tlbl->key + 100);
10109             }
10110             
10111             ix -= count;
10112         }
10113         
10114         iLoop = iLoop->next;
10115     }
10116     
10117     freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10118 }
10119
10120 /*-----------------------------------------------------------------*/
10121 /* genFarFarAssign - assignment when both are in far space         */
10122 /*-----------------------------------------------------------------*/
10123 static void
10124 genFarFarAssign (operand * result, operand * right, iCode * ic)
10125 {
10126   int size = AOP_SIZE (right);
10127   int offset = 0;
10128   symbol *rSym = NULL;
10129
10130   if (size == 1)
10131   {
10132       /* quick & easy case. */
10133       D(emitcode(";","genFarFarAssign (1 byte case)"););      
10134       MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
10135       freeAsmop (right, NULL, ic, FALSE);
10136       /* now assign DPTR to result */
10137       _G.accInUse++;
10138       aopOp(result, ic, FALSE, FALSE);
10139       _G.accInUse--;
10140       aopPut(AOP(result), "a", 0);
10141       freeAsmop(result, NULL, ic, FALSE);
10142       return;
10143   }
10144   
10145   /* See if we've got an underlying symbol to abuse. */
10146   if (IS_SYMOP(result) && OP_SYMBOL(result))
10147   {
10148       if (IS_TRUE_SYMOP(result))
10149       {
10150           rSym = OP_SYMBOL(result);
10151       }
10152       else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10153       {
10154           rSym = OP_SYMBOL(result)->usl.spillLoc;
10155       }
10156   }
10157              
10158   if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10159   {
10160       /* We can use the '390 auto-toggle feature to good effect here. */
10161       
10162       D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10163       emitcode("mov", "dps, #0x21");    /* Select DPTR2 & auto-toggle. */
10164       emitcode ("mov", "dptr,#%s", rSym->rname); 
10165       /* DP2 = result, DP1 = right, DP1 is current. */
10166       while (size)
10167       {
10168           emitcode("movx", "a,@dptr");
10169           emitcode("movx", "@dptr,a");
10170           if (--size)
10171           {
10172                emitcode("inc", "dptr");
10173                emitcode("inc", "dptr");
10174           }
10175       }
10176       emitcode("mov", "dps, #0");
10177       freeAsmop (right, NULL, ic, FALSE);
10178 #if 0
10179 some alternative code for processors without auto-toggle
10180 no time to test now, so later well put in...kpb
10181         D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10182         emitcode("mov", "dps, #0x01");  /* Select DPTR2. */
10183         emitcode ("mov", "dptr,#%s", rSym->rname); 
10184         /* DP2 = result, DP1 = right, DP1 is current. */
10185         while (size)
10186         {
10187           --size;
10188           emitcode("movx", "a,@dptr");
10189           if (size)
10190             emitcode("inc", "dptr");
10191           emitcode("inc", "dps");
10192           emitcode("movx", "@dptr,a");
10193           if (size)
10194             emitcode("inc", "dptr");
10195           emitcode("inc", "dps");
10196         }
10197         emitcode("mov", "dps, #0");
10198         freeAsmop (right, NULL, ic, FALSE);
10199 #endif
10200   }
10201   else
10202   {
10203       D (emitcode (";", "genFarFarAssign"););
10204       aopOp (result, ic, TRUE, TRUE);
10205
10206       _startLazyDPSEvaluation ();
10207       
10208       while (size--)
10209         {
10210           aopPut (AOP (result),
10211                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
10212           offset++;
10213         }
10214       _endLazyDPSEvaluation ();
10215       freeAsmop (result, NULL, ic, FALSE);
10216       freeAsmop (right, NULL, ic, FALSE);
10217   }
10218 }
10219
10220 /*-----------------------------------------------------------------*/
10221 /* genAssign - generate code for assignment                        */
10222 /*-----------------------------------------------------------------*/
10223 static void
10224 genAssign (iCode * ic)
10225 {
10226   operand *result, *right;
10227   int size, offset;
10228   unsigned long lit = 0L;
10229
10230   D (emitcode (";", "genAssign ");
10231     );
10232
10233   result = IC_RESULT (ic);
10234   right = IC_RIGHT (ic);
10235
10236   /* if they are the same */
10237   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10238     return;
10239
10240   aopOp (right, ic, FALSE, FALSE);
10241
10242   emitcode (";", "genAssign: resultIsFar = %s",
10243             isOperandInFarSpace (result) ?
10244             "TRUE" : "FALSE");
10245
10246   /* special case both in far space */
10247   if ((AOP_TYPE (right) == AOP_DPTR ||
10248        AOP_TYPE (right) == AOP_DPTR2) &&
10249   /* IS_TRUE_SYMOP(result)       && */
10250       isOperandInFarSpace (result))
10251     {
10252       genFarFarAssign (result, right, ic);
10253       return;
10254     }
10255
10256   aopOp (result, ic, TRUE, FALSE);
10257
10258   /* if they are the same registers */
10259   if (sameRegs (AOP (right), AOP (result)))
10260     goto release;
10261
10262   /* if the result is a bit */
10263   if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10264     {
10265       /* if the right size is a literal then
10266          we know what the value is */
10267       if (AOP_TYPE (right) == AOP_LIT)
10268         {
10269           if (((int) operandLitValue (right)))
10270             aopPut (AOP (result), one, 0);
10271           else
10272             aopPut (AOP (result), zero, 0);
10273           goto release;
10274         }
10275
10276       /* the right is also a bit variable */
10277       if (AOP_TYPE (right) == AOP_CRY)
10278         {
10279           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10280           aopPut (AOP (result), "c", 0);
10281           goto release;
10282         }
10283
10284       /* we need to or */
10285       toBoolean (right);
10286       aopPut (AOP (result), "a", 0);
10287       goto release;
10288     }
10289
10290   /* bit variables done */
10291   /* general case */
10292   size = AOP_SIZE (result);
10293   offset = 0;
10294   if (AOP_TYPE (right) == AOP_LIT)
10295     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10296
10297   if ((size > 1) &&
10298       (AOP_TYPE (result) != AOP_REG) &&
10299       (AOP_TYPE (right) == AOP_LIT) &&
10300       !IS_FLOAT (operandType (right)))
10301     {
10302       _startLazyDPSEvaluation ();
10303       while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10304         {
10305           aopPut (AOP (result),
10306                   aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
10307                   offset);
10308           offset++;
10309           size--;
10310         }
10311       /* And now fill the rest with zeros. */
10312       if (size)
10313         {
10314           emitcode ("clr", "a");
10315         }
10316       while (size--)
10317         {
10318           aopPut (AOP (result), "a", offset++);
10319         }
10320       _endLazyDPSEvaluation ();
10321     }
10322   else
10323     {
10324       _startLazyDPSEvaluation ();
10325       while (size--)
10326         {
10327           aopPut (AOP (result),
10328                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10329                   offset);
10330           offset++;
10331         }
10332       _endLazyDPSEvaluation ();
10333     }
10334
10335 release:
10336   freeAsmop (right, NULL, ic, FALSE);
10337   freeAsmop (result, NULL, ic, TRUE);
10338 }
10339
10340 /*-----------------------------------------------------------------*/
10341 /* genJumpTab - generates code for jump table                      */
10342 /*-----------------------------------------------------------------*/
10343 static void
10344 genJumpTab (iCode * ic)
10345 {
10346   symbol *jtab;
10347   char *l;
10348
10349   D (emitcode (";", "genJumpTab ");
10350     );
10351
10352   aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10353   /* get the condition into accumulator */
10354   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
10355   MOVA (l);
10356   /* multiply by four! */
10357   emitcode ("add", "a,acc");
10358   emitcode ("add", "a,acc");
10359   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10360
10361   jtab = newiTempLabel (NULL);
10362   emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
10363   emitcode ("jmp", "@a+dptr");
10364   emitcode ("", "%05d$:", jtab->key + 100);
10365   /* now generate the jump labels */
10366   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10367        jtab = setNextItem (IC_JTLABELS (ic)))
10368     emitcode ("ljmp", "%05d$", jtab->key + 100);
10369
10370 }
10371
10372 /*-----------------------------------------------------------------*/
10373 /* genCast - gen code for casting                                  */
10374 /*-----------------------------------------------------------------*/
10375 static void
10376 genCast (iCode * ic)
10377 {
10378   operand *result = IC_RESULT (ic);
10379   sym_link *ctype = operandType (IC_LEFT (ic));
10380   sym_link *rtype = operandType (IC_RIGHT (ic));
10381   operand *right = IC_RIGHT (ic);
10382   int size, offset;
10383
10384   D (emitcode (";", "genCast ");
10385     );
10386
10387   /* if they are equivalent then do nothing */
10388   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10389     return;
10390
10391   aopOp (right, ic, FALSE, FALSE);
10392   aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
10393
10394   /* if the result is a bit */
10395   // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10396   if (IS_BITVAR(OP_SYMBOL(result)->type))
10397     {
10398       /* if the right size is a literal then
10399          we know what the value is */
10400       if (AOP_TYPE (right) == AOP_LIT)
10401         {
10402           if (((int) operandLitValue (right)))
10403             aopPut (AOP (result), one, 0);
10404           else
10405             aopPut (AOP (result), zero, 0);
10406
10407           goto release;
10408         }
10409
10410       /* the right is also a bit variable */
10411       if (AOP_TYPE (right) == AOP_CRY)
10412         {
10413           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10414           aopPut (AOP (result), "c", 0);
10415           goto release;
10416         }
10417
10418       /* we need to or */
10419       toBoolean (right);
10420       aopPut (AOP (result), "a", 0);
10421       goto release;
10422     }
10423
10424   /* if they are the same size : or less */
10425   if (AOP_SIZE (result) <= AOP_SIZE (right))
10426     {
10427
10428       /* if they are in the same place */
10429       if (sameRegs (AOP (right), AOP (result)))
10430         goto release;
10431
10432       /* if they in different places then copy */
10433       size = AOP_SIZE (result);
10434       offset = 0;
10435       _startLazyDPSEvaluation ();
10436       while (size--)
10437         {
10438           aopPut (AOP (result),
10439                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10440                   offset);
10441           offset++;
10442         }
10443       _endLazyDPSEvaluation ();
10444       goto release;
10445     }
10446
10447
10448   /* if the result is of type pointer */
10449   if (IS_PTR (ctype))
10450     {
10451
10452       int p_type;
10453       sym_link *type = operandType (right);
10454
10455       /* pointer to generic pointer */
10456       if (IS_GENPTR (ctype))
10457         {
10458           char *l = zero;
10459
10460           if (IS_PTR (type))
10461             {
10462               p_type = DCL_TYPE (type);
10463             }
10464           else
10465             {
10466 #if OLD_CAST_BEHAVIOR
10467               /* KV: we are converting a non-pointer type to
10468                * a generic pointer. This (ifdef'd out) code
10469                * says that the resulting generic pointer
10470                * should have the same class as the storage
10471                * location of the non-pointer variable.
10472                *
10473                * For example, converting an int (which happens
10474                * to be stored in DATA space) to a pointer results
10475                * in a DATA generic pointer; if the original int
10476                * in XDATA space, so will be the resulting pointer.
10477                *
10478                * I don't like that behavior, and thus this change:
10479                * all such conversions will be forced to XDATA and
10480                * throw a warning. If you want some non-XDATA
10481                * type, or you want to suppress the warning, you
10482                * must go through an intermediate cast, like so:
10483                *
10484                * char _generic *gp = (char _xdata *)(intVar);
10485                */
10486               sym_link *etype = getSpec (type);
10487
10488               /* we have to go by the storage class */
10489               if (SPEC_OCLS (etype) != generic)
10490                 {
10491                   p_type = PTR_TYPE (SPEC_OCLS (etype));
10492                 }
10493               else
10494 #endif
10495                 {
10496                   /* Converting unknown class (i.e. register variable)
10497                    * to generic pointer. This is not good, but
10498                    * we'll make a guess (and throw a warning).
10499                    */
10500                   p_type = FPOINTER;
10501                   werror (W_INT_TO_GEN_PTR_CAST);
10502                 }
10503             }
10504
10505           /* the first two bytes are known */
10506           size = GPTRSIZE - 1;
10507           offset = 0;
10508           _startLazyDPSEvaluation ();
10509           while (size--)
10510             {
10511               aopPut (AOP (result),
10512                       aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10513                       offset);
10514               offset++;
10515             }
10516           _endLazyDPSEvaluation ();
10517
10518           /* the last byte depending on type */
10519           switch (p_type)
10520             {
10521             case IPOINTER:
10522             case POINTER:
10523               l = zero;
10524               break;
10525             case FPOINTER:
10526               l = one;
10527               break;
10528             case CPOINTER:
10529               l = "#0x02";
10530               break;
10531             case PPOINTER:
10532               l = "#0x03";
10533               break;
10534
10535             default:
10536               /* this should never happen */
10537               werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10538                       "got unknown pointer type");
10539               exit (1);
10540             }
10541           aopPut (AOP (result), l, GPTRSIZE - 1);
10542           goto release;
10543         }
10544
10545       /* just copy the pointers */
10546       size = AOP_SIZE (result);
10547       offset = 0;
10548       _startLazyDPSEvaluation ();
10549       while (size--)
10550         {
10551           aopPut (AOP (result),
10552                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10553                   offset);
10554           offset++;
10555         }
10556       _endLazyDPSEvaluation ();
10557       goto release;
10558     }
10559
10560   /* so we now know that the size of destination is greater
10561      than the size of the source */
10562   /* we move to result for the size of source */
10563   size = AOP_SIZE (right);
10564   offset = 0;
10565   _startLazyDPSEvaluation ();
10566   while (size--)
10567     {
10568       aopPut (AOP (result),
10569               aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10570               offset);
10571       offset++;
10572     }
10573   _endLazyDPSEvaluation ();
10574
10575   /* now depending on the sign of the source && destination */
10576   size = AOP_SIZE (result) - AOP_SIZE (right);
10577   /* if unsigned or not an integral type */
10578   /* also, if the source is a bit, we don't need to sign extend, because
10579    * it can't possibly have set the sign bit.
10580    */
10581   if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
10582     {
10583       while (size--)
10584         {
10585           aopPut (AOP (result), zero, offset++);
10586         }
10587     }
10588   else
10589     {
10590       /* we need to extend the sign :{ */
10591       char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
10592                         FALSE, FALSE, TRUE);
10593       MOVA (l);
10594       emitcode ("rlc", "a");
10595       emitcode ("subb", "a,acc");
10596       while (size--)
10597         aopPut (AOP (result), "a", offset++);
10598     }
10599
10600   /* we are done hurray !!!! */
10601
10602 release:
10603   freeAsmop (right, NULL, ic, TRUE);
10604   freeAsmop (result, NULL, ic, TRUE);
10605
10606 }
10607
10608 /*-----------------------------------------------------------------*/
10609 /* genDjnz - generate decrement & jump if not zero instrucion      */
10610 /*-----------------------------------------------------------------*/
10611 static int
10612 genDjnz (iCode * ic, iCode * ifx)
10613 {
10614   symbol *lbl, *lbl1;
10615   if (!ifx)
10616     return 0;
10617
10618   /* if the if condition has a false label
10619      then we cannot save */
10620   if (IC_FALSE (ifx))
10621     return 0;
10622
10623   /* if the minus is not of the form
10624      a = a - 1 */
10625   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
10626       !IS_OP_LITERAL (IC_RIGHT (ic)))
10627     return 0;
10628
10629   if (operandLitValue (IC_RIGHT (ic)) != 1)
10630     return 0;
10631
10632   /* if the size of this greater than one then no
10633      saving */
10634   if (getSize (operandType (IC_RESULT (ic))) > 1)
10635     return 0;
10636
10637   /* otherwise we can save BIG */
10638   D(emitcode(";", "genDjnz"););
10639
10640   lbl = newiTempLabel (NULL);
10641   lbl1 = newiTempLabel (NULL);
10642
10643   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10644
10645   if (AOP_NEEDSACC(IC_RESULT(ic)))
10646   {
10647       /* If the result is accessed indirectly via
10648        * the accumulator, we must explicitly write
10649        * it back after the decrement.
10650        */
10651       char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
10652       
10653       if (strcmp(rByte, "a"))
10654       {
10655            /* Something is hopelessly wrong */
10656            fprintf(stderr, "*** warning: internal error at %s:%d\n",
10657                    __FILE__, __LINE__);
10658            /* We can just give up; the generated code will be inefficient,
10659             * but what the hey.
10660             */
10661            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10662            return 0;
10663       }
10664       emitcode ("dec", "%s", rByte);
10665       aopPut(AOP(IC_RESULT(ic)), rByte, 0);
10666       emitcode ("jnz", "%05d$", lbl->key + 100);
10667   }
10668   else if (IS_AOP_PREG (IC_RESULT (ic)))
10669     {
10670       emitcode ("dec", "%s",
10671                 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10672       emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10673       emitcode ("jnz", "%05d$", lbl->key + 100);
10674     }
10675   else
10676     {
10677       emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
10678                 lbl->key + 100);
10679     }
10680   emitcode ("sjmp", "%05d$", lbl1->key + 100);
10681   emitcode ("", "%05d$:", lbl->key + 100);
10682   emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
10683   emitcode ("", "%05d$:", lbl1->key + 100);
10684
10685   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10686   ifx->generated = 1;
10687   return 1;
10688 }
10689
10690 /*-----------------------------------------------------------------*/
10691 /* genReceive - generate code for a receive iCode                  */
10692 /*-----------------------------------------------------------------*/
10693 static void
10694 genReceive (iCode * ic)
10695 {
10696
10697   D (emitcode (";", "genReceive ");
10698     );
10699
10700   if (isOperandInFarSpace (IC_RESULT (ic)) &&
10701       (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
10702        IS_TRUE_SYMOP (IC_RESULT (ic))))
10703     {
10704       int size = getSize (operandType (IC_RESULT (ic)));
10705       int offset = fReturnSizeDS390 - size;
10706       while (size--)
10707         {
10708           emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
10709                             fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
10710           offset++;
10711         }
10712       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10713       size = AOP_SIZE (IC_RESULT (ic));
10714       offset = 0;
10715       while (size--)
10716         {
10717           emitcode ("pop", "acc");
10718           aopPut (AOP (IC_RESULT (ic)), "a", offset++);
10719         }
10720
10721     }
10722   else
10723     {
10724       _G.accInUse++;
10725       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10726       _G.accInUse--;
10727       assignResultValue (IC_RESULT (ic));
10728     }
10729
10730   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10731 }
10732
10733 /*-----------------------------------------------------------------*/
10734 /* genMemcpyX2X - gen code for memcpy xdata to xdata               */
10735 /*-----------------------------------------------------------------*/
10736 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
10737 {
10738     operand *from , *to , *count;
10739     symbol *lbl;
10740
10741     /* we know it has to be 3 parameters */
10742     assert (nparms == 3);
10743     
10744     to = parms[0];
10745     from = parms[1];
10746     count = parms[2];
10747
10748     aopOp (from, ic->next, FALSE, FALSE);
10749
10750     /* get from into DPTR1 */
10751     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, TRUE));
10752     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, TRUE));
10753     if (options.model == MODEL_FLAT24) {
10754         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, TRUE));
10755     }
10756
10757     freeAsmop (from, NULL, ic, FALSE);
10758     aopOp (to, ic, FALSE, FALSE);
10759     /* get "to" into DPTR */
10760     /* if the operand is already in dptr
10761        then we do nothing else we move the value to dptr */
10762     if (AOP_TYPE (to) != AOP_STR) {
10763         /* if already in DPTR then we need to push */
10764         if (AOP_TYPE(to) == AOP_DPTR) {
10765             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
10766             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
10767             if (options.model == MODEL_FLAT24)
10768                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
10769             emitcode ("pop", "dph");
10770             emitcode ("pop", "dpl");        
10771         } else {
10772             _startLazyDPSEvaluation ();
10773             /* if this is remateriazable */
10774             if (AOP_TYPE (to) == AOP_IMMD) {
10775                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
10776             } else {                    /* we need to get it byte by byte */
10777                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
10778                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
10779                 if (options.model == MODEL_FLAT24) {
10780                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
10781                 }
10782             }
10783             _endLazyDPSEvaluation ();
10784         }
10785     }
10786     freeAsmop (to, NULL, ic, FALSE);
10787
10788     aopOp (count, ic->next->next, FALSE,FALSE);
10789     lbl =newiTempLabel(NULL);
10790
10791     /* now for the actual copy */
10792     if (AOP_TYPE(count) == AOP_LIT && 
10793         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
10794         emitcode (";","OH! JOY auto increment with djnz (very fast)");
10795         emitcode ("mov", "dps, #0x21");         /* Select DPTR2 & auto-toggle. */
10796         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
10797         emitcode ("","%05d$:",lbl->key+100);
10798         if (fromc) {
10799             emitcode ("clr","a");
10800             emitcode ("movc", "a,@a+dptr");
10801         } else 
10802             emitcode ("movx", "a,@dptr");
10803         emitcode ("movx", "@dptr,a");
10804         emitcode ("inc", "dptr");
10805         emitcode ("inc", "dptr");
10806         emitcode ("djnz","b,%05d$",lbl->key+100);
10807     } else {
10808         symbol *lbl1 = newiTempLabel(NULL);
10809         
10810         emitcode (";"," Auto increment but no djnz");
10811         emitcode ("mov","ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
10812         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
10813         emitcode ("mov", "dps, #0x21");         /* Select DPTR2 & auto-toggle. */
10814         emitcode ("","%05d$:",lbl->key+100);
10815         if (fromc) {
10816             emitcode ("clr","a");
10817             emitcode ("movc", "a,@a+dptr");
10818         } else 
10819             emitcode ("movx", "a,@dptr");
10820         emitcode ("movx", "@dptr,a");
10821         emitcode ("inc", "dptr");
10822         emitcode ("inc", "dptr");
10823         emitcode ("mov","a,b");
10824         emitcode ("orl","a,ap");
10825         emitcode ("jz","%05d$",lbl1->key+100);
10826         emitcode ("mov","a,ap");
10827         emitcode ("add","a,#0xFF");
10828         emitcode ("mov","ap,a");
10829         emitcode ("mov","a,b");
10830         emitcode ("addc","a,#0xFF");
10831         emitcode ("mov","b,a");
10832         emitcode ("sjmp","%05d$",lbl->key+100);
10833         emitcode ("","%05d$:",lbl1->key+100);
10834     }
10835     emitcode ("mov", "dps, #0"); 
10836     freeAsmop (count, NULL, ic, FALSE);
10837
10838 }
10839
10840 /*-----------------------------------------------------------------*/
10841 /* genMemsetX - gencode for memSetX data                           */
10842 /*-----------------------------------------------------------------*/
10843 static void genMemsetX(iCode *ic, int nparms, operand **parms)
10844 {
10845     operand *to , *val , *count;
10846     symbol *lbl;
10847     char *l;
10848     /* we know it has to be 3 parameters */
10849     assert (nparms == 3);
10850     
10851     to = parms[0];
10852     val = parms[1];
10853     count = parms[2];
10854
10855     aopOp (to, ic, FALSE, FALSE);
10856     /* get "to" into DPTR */
10857     /* if the operand is already in dptr
10858        then we do nothing else we move the value to dptr */
10859     if (AOP_TYPE (to) != AOP_STR) {
10860         /* if already in DPTR then we need to push */
10861         if (AOP_TYPE(to) == AOP_DPTR) {
10862             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
10863             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
10864             if (options.model == MODEL_FLAT24)
10865                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
10866             emitcode ("pop", "dph");
10867             emitcode ("pop", "dpl");        
10868         } else {
10869             _startLazyDPSEvaluation ();
10870             /* if this is remateriazable */
10871             if (AOP_TYPE (to) == AOP_IMMD) {
10872                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
10873             } else {                    /* we need to get it byte by byte */
10874                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
10875                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
10876                 if (options.model == MODEL_FLAT24) {
10877                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
10878                 }
10879             }
10880             _endLazyDPSEvaluation ();
10881         }
10882     }
10883     freeAsmop (to, NULL, ic, FALSE);
10884
10885     aopOp (val, ic->next->next, FALSE,FALSE);
10886     aopOp (count, ic->next->next, FALSE,FALSE);    
10887     lbl =newiTempLabel(NULL);
10888     /* now for the actual copy */
10889     if (AOP_TYPE(count) == AOP_LIT && 
10890         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
10891         l = aopGet(AOP (val), 0, FALSE, FALSE, TRUE);
10892         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
10893         MOVA(l);
10894         emitcode ("","%05d$:",lbl->key+100);
10895         emitcode ("movx", "@dptr,a");
10896         emitcode ("inc", "dptr");
10897         emitcode ("djnz","b,%05d$",lbl->key+100);
10898     } else {
10899         symbol *lbl1 = newiTempLabel(NULL);
10900         
10901         emitcode ("mov","ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
10902         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
10903         emitcode ("","%05d$:",lbl->key+100);
10904         l = aopGet(AOP (val), 0, FALSE, FALSE, TRUE);
10905         MOVA(l);
10906         emitcode ("movx", "a,@dptr");
10907         emitcode ("inc", "dptr");
10908         emitcode ("mov","a,b");
10909         emitcode ("orl","a,ap");
10910         emitcode ("jz","%05d$",lbl1->key+100);
10911         emitcode ("mov","a,ap");
10912         emitcode ("add","a,#0xFF");
10913         emitcode ("mov","ap,a");
10914         emitcode ("mov","a,b");
10915         emitcode ("addc","a,#0xFF");
10916         emitcode ("mov","b,a");
10917         emitcode ("sjmp","%05d$",lbl->key+100);
10918         emitcode ("","%05d$:",lbl1->key+100);
10919     }
10920     freeAsmop (count, NULL, ic, FALSE);
10921 }
10922
10923 /*-----------------------------------------------------------------*/
10924 /* genBuiltIn - calls the appropriate function to  generating code */
10925 /* for a built in function                                         */
10926 /*-----------------------------------------------------------------*/
10927 static void genBuiltIn (iCode *ic)
10928 {
10929     operand *bi_parms[MAX_BUILTIN_ARGS];
10930     int nbi_parms;
10931     iCode *bi_iCode;
10932     symbol *bif;
10933
10934     /* get all the arguments for a built in function */
10935     bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
10936
10937     /* which function is it */
10938     bif = OP_SYMBOL(IC_LEFT(bi_iCode));
10939     if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
10940         genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
10941     } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
10942         genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
10943     } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
10944         genMemsetX(bi_iCode,nbi_parms,bi_parms);
10945     } else {
10946         werror(E_INTERNAL_ERROR,"unknown builtin function encountered\n");
10947         return ;
10948     }
10949     return ;    
10950 }
10951
10952 /*-----------------------------------------------------------------*/
10953 /* gen390Code - generate code for Dallas 390 based controllers     */
10954 /*-----------------------------------------------------------------*/
10955 void
10956 gen390Code (iCode * lic)
10957 {
10958   iCode *ic;
10959   int cln = 0;
10960
10961   lineHead = lineCurr = NULL;
10962
10963   if (options.model == MODEL_FLAT24) {
10964     fReturnSizeDS390 = 5;
10965     fReturn = fReturn24;
10966   } else {
10967     fReturnSizeDS390 = 4;
10968     fReturn = fReturn16;
10969     options.stack10bit=0;
10970   }
10971 #if 0
10972   //REMOVE ME!!!
10973   /* print the allocation information */
10974   if (allocInfo)
10975     printAllocInfo (currFunc, codeOutFile);
10976 #endif
10977   /* if debug information required */
10978   if (options.debug && currFunc)
10979     {
10980       cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
10981       _G.debugLine = 1;
10982       if (IS_STATIC (currFunc->etype))
10983         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
10984       else
10985         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
10986       _G.debugLine = 0;
10987     }
10988   /* stack pointer name */
10989   if (options.useXstack)
10990     spname = "_spx";
10991   else
10992     spname = "sp";
10993
10994
10995   for (ic = lic; ic; ic = ic->next)
10996     {
10997
10998       if (cln != ic->lineno)
10999         {
11000           if (options.debug)
11001             {
11002               _G.debugLine = 1;
11003               emitcode ("", "C$%s$%d$%d$%d ==.",
11004                         FileBaseName (ic->filename), ic->lineno,
11005                         ic->level, ic->block);
11006               _G.debugLine = 0;
11007             }
11008           emitcode (";", "%s %d", ic->filename, ic->lineno);
11009           cln = ic->lineno;
11010         }
11011       /* if the result is marked as
11012          spilt and rematerializable or code for
11013          this has already been generated then
11014          do nothing */
11015       if (resultRemat (ic) || ic->generated)
11016         continue;
11017
11018       /* depending on the operation */
11019       switch (ic->op)
11020         {
11021         case '!':
11022           genNot (ic);
11023           break;
11024
11025         case '~':
11026           genCpl (ic);
11027           break;
11028
11029         case UNARYMINUS:
11030           genUminus (ic);
11031           break;
11032
11033         case IPUSH:
11034           genIpush (ic);
11035           break;
11036
11037         case IPOP:
11038           /* IPOP happens only when trying to restore a
11039              spilt live range, if there is an ifx statement
11040              following this pop then the if statement might
11041              be using some of the registers being popped which
11042              would destory the contents of the register so
11043              we need to check for this condition and handle it */
11044           if (ic->next &&
11045               ic->next->op == IFX &&
11046               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11047             genIfx (ic->next, ic);
11048           else
11049             genIpop (ic);
11050           break;
11051
11052         case CALL:
11053           genCall (ic);
11054           break;
11055
11056         case PCALL:
11057           genPcall (ic);
11058           break;
11059
11060         case FUNCTION:
11061           genFunction (ic);
11062           break;
11063
11064         case ENDFUNCTION:
11065           genEndFunction (ic);
11066           break;
11067
11068         case RETURN:
11069           genRet (ic);
11070           break;
11071
11072         case LABEL:
11073           genLabel (ic);
11074           break;
11075
11076         case GOTO:
11077           genGoto (ic);
11078           break;
11079
11080         case '+':
11081           genPlus (ic);
11082           break;
11083
11084         case '-':
11085           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11086             genMinus (ic);
11087           break;
11088
11089         case '*':
11090           genMult (ic);
11091           break;
11092
11093         case '/':
11094           genDiv (ic);
11095           break;
11096
11097         case '%':
11098           genMod (ic);
11099           break;
11100
11101         case '>':
11102           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11103           break;
11104
11105         case '<':
11106           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11107           break;
11108
11109         case LE_OP:
11110         case GE_OP:
11111         case NE_OP:
11112
11113           /* note these two are xlated by algebraic equivalence
11114              during parsing SDCC.y */
11115           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11116                   "got '>=' or '<=' shouldn't have come here");
11117           break;
11118
11119         case EQ_OP:
11120           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11121           break;
11122
11123         case AND_OP:
11124           genAndOp (ic);
11125           break;
11126
11127         case OR_OP:
11128           genOrOp (ic);
11129           break;
11130
11131         case '^':
11132           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11133           break;
11134
11135         case '|':
11136           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11137           break;
11138
11139         case BITWISEAND:
11140           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
11141           break;
11142
11143         case INLINEASM:
11144           genInline (ic);
11145           break;
11146
11147         case RRC:
11148           genRRC (ic);
11149           break;
11150
11151         case RLC:
11152           genRLC (ic);
11153           break;
11154
11155         case GETHBIT:
11156           genGetHbit (ic);
11157           break;
11158
11159         case LEFT_OP:
11160           genLeftShift (ic);
11161           break;
11162
11163         case RIGHT_OP:
11164           genRightShift (ic);
11165           break;
11166
11167         case GET_VALUE_AT_ADDRESS:
11168           genPointerGet (ic,hasInc(IC_LEFT(ic),ic));
11169           break;
11170
11171         case '=':
11172           if (POINTER_SET (ic))
11173             genPointerSet (ic,hasInc(IC_RESULT(ic),ic));
11174           else
11175             genAssign (ic);
11176           break;
11177
11178         case IFX:
11179           genIfx (ic, NULL);
11180           break;
11181
11182         case ADDRESS_OF:
11183           genAddrOf (ic);
11184           break;
11185
11186         case JUMPTABLE:
11187           genJumpTab (ic);
11188           break;
11189
11190         case CAST:
11191           genCast (ic);
11192           break;
11193
11194         case RECEIVE:
11195           genReceive (ic);
11196           break;
11197
11198         case SEND:
11199           if (ic->builtinSEND) genBuiltIn(ic);
11200           else addSet (&_G.sendSet, ic);
11201           break;
11202
11203         case ARRAYINIT:
11204             genArrayInit(ic);
11205             break;
11206             
11207         default:
11208           ic = ic;
11209         }
11210     }
11211
11212
11213   /* now we are ready to call the
11214      peep hole optimizer */
11215   if (!options.nopeep)
11216     peepHole (&lineHead);
11217
11218   /* now do the actual printing */
11219   printLine (lineHead, codeOutFile);
11220   return;
11221 }