]> git.gag.com Git - fw/sdcc/blob - src/ds390/gen.c
e110942ee7b82423f78badd79f62d517c0a64b82
[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 static char *javaRet[] = { "r0","r1","r2","r3"};
83 static short rbank = -1;
84
85 static struct
86   {
87     short r0Pushed;
88     short r1Pushed;
89     short accInUse;
90     short bInUse;
91     short inLine;
92     short debugLine;
93     short nRegsSaved;
94     set *sendSet;
95   }
96 _G;
97
98 static void saveRBank (int, iCode *, bool);
99
100 #define RESULTONSTACK(x) \
101                          (IC_RESULT(x) && IC_RESULT(x)->aop && \
102                          IC_RESULT(x)->aop->type == AOP_STK )
103
104 /* #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x); */
105 #define MOVA(x) { char *_mova_tmp = strdup(x); \
106                  if (strcmp(_mova_tmp,"a") && strcmp(_mova_tmp,"acc")) \
107                  { \
108                     emitcode("mov","a,%s",_mova_tmp); \
109                  } \
110                  free(_mova_tmp); \
111                 }
112 #define CLRC    emitcode("clr","c")
113 #define SETC    emitcode("setb","c")
114
115 // A scratch register which will be used to hold
116 // result bytes from operands in far space via DPTR2.
117 #define DP2_RESULT_REG  "_ap"
118
119 static lineNode *lineHead = NULL;
120 static lineNode *lineCurr = NULL;
121
122 static unsigned char SLMask[] =
123 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
124  0xE0, 0xC0, 0x80, 0x00};
125 static unsigned char SRMask[] =
126 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
127  0x07, 0x03, 0x01, 0x00};
128
129 #define LSB     0
130 #define MSB16   1
131 #define MSB24   2
132 #define MSB32   3
133
134 /*-----------------------------------------------------------------*/
135 /* emitcode - writes the code into a file : for now it is simple    */
136 /*-----------------------------------------------------------------*/
137 static void
138 emitcode (char *inst, char *fmt,...)
139 {
140   va_list ap;
141   char lb[INITIAL_INLINEASM];
142   char *lbp = lb;
143
144   va_start (ap, fmt);
145
146   if (inst && *inst)
147     {
148       if (fmt && *fmt)
149         sprintf (lb, "%s\t", inst);
150       else
151         sprintf (lb, "%s", inst);
152       tvsprintf (lb + (strlen (lb)), fmt, ap);
153     }
154   else
155     tvsprintf (lb, fmt, ap);
156
157   while (isspace (*lbp))
158     lbp++;
159
160   if (lbp && *lbp)
161     lineCurr = (lineCurr ?
162                 connectLine (lineCurr, newLineNode (lb)) :
163                 (lineHead = newLineNode (lb)));
164   lineCurr->isInline = _G.inLine;
165   lineCurr->isDebug = _G.debugLine;
166   va_end (ap);
167 }
168
169 /*-----------------------------------------------------------------*/
170 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
171 /*-----------------------------------------------------------------*/
172 static regs *
173 getFreePtr (iCode * ic, asmop ** aopp, bool result)
174 {
175   bool r0iu = FALSE, r1iu = FALSE;
176   bool r0ou = FALSE, r1ou = FALSE;
177
178   /* the logic: if r0 & r1 used in the instruction
179      then we are in trouble otherwise */
180
181   /* first check if r0 & r1 are used by this
182      instruction, in which case we are in trouble */
183   r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
184   r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
185   if (r0iu && r1iu) {
186       goto endOfWorld;
187     }
188
189   r0ou = bitVectBitValue (ic->rMask, R0_IDX);
190   r1ou = bitVectBitValue (ic->rMask, R1_IDX);
191
192   /* if no usage of r0 then return it */
193   if (!r0iu && !r0ou)
194     {
195       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
196       (*aopp)->type = AOP_R0;
197
198       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
199     }
200
201   /* if no usage of r1 then return it */
202   if (!r1iu && !r1ou)
203     {
204       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
205       (*aopp)->type = AOP_R1;
206
207       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R1_IDX);
208     }
209
210   /* now we know they both have usage */
211   /* if r0 not used in this instruction */
212   if (!r0iu)
213     {
214       /* push it if not already pushed */
215       if (!_G.r0Pushed)
216         {
217           emitcode ("push", "%s",
218                     ds390_regWithIdx (R0_IDX)->dname);
219           _G.r0Pushed++;
220         }
221
222       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
223       (*aopp)->type = AOP_R0;
224
225       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
226     }
227
228   /* if r1 not used then */
229
230   if (!r1iu)
231     {
232       /* push it if not already pushed */
233       if (!_G.r1Pushed)
234         {
235           emitcode ("push", "%s",
236                     ds390_regWithIdx (R1_IDX)->dname);
237           _G.r1Pushed++;
238         }
239
240       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
241       (*aopp)->type = AOP_R1;
242       return ds390_regWithIdx (R1_IDX);
243     }
244
245 endOfWorld:
246   /* I said end of world but not quite end of world yet */
247   /* if this is a result then we can push it on the stack */
248   if (result)
249     {
250       (*aopp)->type = AOP_STK;
251       return NULL;
252     }
253
254   /* other wise this is true end of the world */
255   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
256           "getFreePtr should never reach here");
257   exit (1);
258 }
259
260 /*-----------------------------------------------------------------*/
261 /* newAsmop - creates a new asmOp                                  */
262 /*-----------------------------------------------------------------*/
263 static asmop *
264 newAsmop (short type)
265 {
266   asmop *aop;
267
268   aop = Safe_calloc (1, sizeof (asmop));
269   aop->type = type;
270   return aop;
271 }
272
273 static int _currentDPS;         /* Current processor DPS. */
274 static int _desiredDPS;         /* DPS value compiler thinks we should be using. */
275 static int _lazyDPS = 0;        /* if non-zero, we are doing lazy evaluation of DPS changes. */
276
277 /*-----------------------------------------------------------------*/
278 /* genSetDPTR: generate code to select which DPTR is in use (zero  */
279 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390     */
280 /* alternate DPTR (DPL1/DPH1/DPX1).          */
281 /*-----------------------------------------------------------------*/
282 static void
283 genSetDPTR (int n)
284 {
285
286   /* If we are doing lazy evaluation, simply note the desired
287    * change, but don't emit any code yet.
288    */
289   if (_lazyDPS)
290     {
291       _desiredDPS = n;
292       return;
293     }
294
295   if (!n)
296     {
297       emitcode ("mov", "dps,#0");
298     }
299   else
300     {
301       TR_DPTR("#1");
302       emitcode ("mov", "dps,#1");
303     }
304 }
305
306 /*-----------------------------------------------------------------*/
307 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
308 /*                   */
309 /* Any code that operates on DPTR (NB: not on the individual     */
310 /* components, like DPH) *must* call _flushLazyDPS() before using  */
311 /* DPTR within a lazy DPS evaluation block.        */
312 /*                   */
313 /* Note that aopPut and aopGet already contain the proper calls to */
314 /* _flushLazyDPS, so it is safe to use these calls within a lazy   */
315 /* DPS evaluation block.             */
316 /*                   */
317 /* Also, _flushLazyDPS must be called before any flow control      */
318 /* operations that could potentially branch out of the block.    */
319 /*                         */
320 /* Lazy DPS evaluation is simply an optimization (though an      */
321 /* important one), so if in doubt, leave it out.       */
322 /*-----------------------------------------------------------------*/
323 static void
324 _startLazyDPSEvaluation (void)
325 {
326   _currentDPS = 0;
327   _desiredDPS = 0;
328 #ifdef BETTER_LITERAL_SHIFT  
329   _lazyDPS++;
330 #else
331   _lazyDPS = 1;
332 #endif  
333 }
334
335 /*-----------------------------------------------------------------*/
336 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
337 /* desired one. Call before using DPTR within a lazy DPS evaluation */
338 /* block.                */
339 /*-----------------------------------------------------------------*/
340 static void
341 _flushLazyDPS (void)
342 {
343   if (!_lazyDPS)
344     {
345       /* nothing to do. */
346       return;
347     }
348
349   if (_desiredDPS != _currentDPS)
350     {
351       if (_desiredDPS)
352         {
353           emitcode ("inc", "dps");
354         }
355       else
356         {
357           emitcode ("dec", "dps");
358         }
359       _currentDPS = _desiredDPS;
360     }
361 }
362
363 /*-----------------------------------------------------------------*/
364 /* _endLazyDPSEvaluation: end lazy DPS evaluation block.     */
365 /*                   */
366 /* Forces us back to the safe state (standard DPTR selected).    */
367 /*-----------------------------------------------------------------*/
368 static void
369 _endLazyDPSEvaluation (void)
370 {
371 #ifdef BETTER_LITERAL_SHIFT  
372   _lazyDPS--;
373 #else
374   _lazyDPS = 0;
375 #endif    
376   if (!_lazyDPS)
377   {
378     if (_currentDPS)
379     {
380       genSetDPTR (0);
381       _flushLazyDPS ();
382     }
383     _currentDPS = 0;
384     _desiredDPS = 0;
385   }
386 }
387
388
389
390 /*-----------------------------------------------------------------*/
391 /* pointerCode - returns the code for a pointer type               */
392 /*-----------------------------------------------------------------*/
393 static int
394 pointerCode (sym_link * etype)
395 {
396
397   return PTR_TYPE (SPEC_OCLS (etype));
398
399 }
400
401 /*-----------------------------------------------------------------*/
402 /* aopForSym - for a true symbol                                   */
403 /*-----------------------------------------------------------------*/
404 static asmop *
405 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
406 {
407   asmop *aop;
408   memmap *space = SPEC_OCLS (sym->etype);
409
410   /* if already has one */
411   if (sym->aop)
412     return sym->aop;
413
414   /* assign depending on the storage class */
415   /* if it is on the stack or indirectly addressable */
416   /* space we need to assign either r0 or r1 to it   */
417   if ((sym->onStack && !options.stack10bit) || sym->iaccess)
418     {
419       sym->aop = aop = newAsmop (0);
420       aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
421       aop->size = getSize (sym->type);
422
423       /* now assign the address of the variable to
424          the pointer register */
425       if (aop->type != AOP_STK)
426         {
427
428           if (sym->onStack)
429             {
430               if (_G.accInUse)
431                 emitcode ("push", "acc");
432
433               if (_G.bInUse)
434                 emitcode ("push", "b");
435
436               emitcode ("mov", "a,_bp");
437               emitcode ("add", "a,#!constbyte",
438                         ((sym->stack < 0) ?
439                          ((char) (sym->stack - _G.nRegsSaved)) :
440                          ((char) sym->stack)) & 0xff);
441               emitcode ("mov", "%s,a",
442                         aop->aopu.aop_ptr->name);
443
444               if (_G.bInUse)
445                 emitcode ("pop", "b");
446
447               if (_G.accInUse)
448                 emitcode ("pop", "acc");
449             }
450           else
451             emitcode ("mov", "%s,#%s",
452                       aop->aopu.aop_ptr->name,
453                       sym->rname);
454           aop->paged = space->paged;
455         }
456       else
457         aop->aopu.aop_stk = sym->stack;
458       return aop;
459     }
460
461   if (sym->onStack && options.stack10bit)
462     {
463       /* It's on the 10 bit stack, which is located in
464        * far data space.
465        */
466
467       if (_G.accInUse)
468         emitcode ("push", "acc");
469
470       if (_G.bInUse)
471         emitcode ("push", "b");
472
473       emitcode ("mov", "a,_bpx");
474       emitcode ("clr","c");
475       emitcode ("subb", "a,#!constbyte",
476                 -((sym->stack < 0) ?
477                   ((short) (sym->stack - _G.nRegsSaved)) :
478                   ((short) sym->stack)) & 0xff);
479       emitcode ("mov","b,a");
480       emitcode ("mov","a,_bpx+1");
481       emitcode ("subb","a,#!constbyte",(-((sym->stack < 0) ?
482                                      ((short) (sym->stack - _G.nRegsSaved)) :
483                                      ((short) sym->stack)) >> 8) & 0xff);
484       if (useDP2) {
485           if (options.model == MODEL_FLAT24)
486               emitcode ("mov", "dpx1,#!constbyte", (options.stack_loc >> 16) & 0xff);
487           TR_DPTR("#2");
488           emitcode ("mov", "dph1,a");
489           emitcode ("mov", "dpl1,b");
490       } else {
491           if (options.model == MODEL_FLAT24)
492               emitcode ("mov", "dpx,#!constbyte", (options.stack_loc >> 16) & 0xff);
493           emitcode ("mov", "dph,a");
494           emitcode ("mov", "dpl,b");
495       }
496
497       if (_G.bInUse)
498         emitcode ("pop", "b");
499
500       if (_G.accInUse)
501         emitcode ("pop", "acc");
502
503       sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
504       aop->size = getSize (sym->type);
505       return aop;
506     }
507
508   /* if in bit space */
509   if (IN_BITSPACE (space))
510     {
511       sym->aop = aop = newAsmop (AOP_CRY);
512       aop->aopu.aop_dir = sym->rname;
513       aop->size = getSize (sym->type);
514       return aop;
515     }
516   /* if it is in direct space */
517   if (IN_DIRSPACE (space))
518     {
519       sym->aop = aop = newAsmop (AOP_DIR);
520       aop->aopu.aop_dir = sym->rname;
521       aop->size = getSize (sym->type);
522       return aop;
523     }
524
525   /* special case for a function */
526   if (IS_FUNC (sym->type))
527     {
528       sym->aop = aop = newAsmop (AOP_IMMD);
529       aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
530       strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
531       aop->size = FPTRSIZE;
532       return aop;
533     }
534
535   /* only remaining is far space */
536   /* in which case DPTR gets the address */
537   sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
538   if (useDP2)
539     {
540       genSetDPTR (1);
541       _flushLazyDPS ();
542       emitcode ("mov", "dptr,#%s", sym->rname);
543       genSetDPTR (0);
544     }
545   else
546     {
547       emitcode ("mov", "dptr,#%s", sym->rname);
548     }
549   aop->size = getSize (sym->type);
550
551   /* if it is in code space */
552   if (IN_CODESPACE (space))
553     aop->code = 1;
554
555   return aop;
556 }
557
558 /*-----------------------------------------------------------------*/
559 /* aopForRemat - rematerialzes an object                           */
560 /*-----------------------------------------------------------------*/
561 static asmop *
562 aopForRemat (symbol * sym)
563 {
564   iCode *ic = sym->rematiCode;
565   asmop *aop = newAsmop (AOP_IMMD);
566   int ptr_type =0;
567   int val = 0;
568
569   for (;;)
570     {
571       if (ic->op == '+')
572         val += (int) operandLitValue (IC_RIGHT (ic));
573       else if (ic->op == '-')
574         val -= (int) operandLitValue (IC_RIGHT (ic));
575       else if (IS_CAST_ICODE(ic)) {
576               sym_link *from_type = operandType(IC_RIGHT(ic));
577               aop->aopu.aop_immd.from_cast_remat = 1;
578               ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
579               ptr_type = DCL_TYPE(from_type);
580               if (ptr_type == IPOINTER) {
581                 // bug #481053
582                 ptr_type = POINTER;
583               }
584               continue ;
585       } else break;
586       
587       ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
588     }
589
590   if (val)
591     sprintf (buffer, "(%s %c 0x%04x)",
592              OP_SYMBOL (IC_LEFT (ic))->rname,
593              val >= 0 ? '+' : '-',
594              abs (val) & 0xffff);
595   else
596     strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
597
598   aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
599   strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
600   /* set immd2 field if required */
601   if (aop->aopu.aop_immd.from_cast_remat) {
602           tsprintf(buffer,"#!constbyte",ptr_type);
603           aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
604           strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
605   }
606
607   return aop;
608 }
609
610 /*-----------------------------------------------------------------*/
611 /* aopHasRegs - returns true if aop has regs between from-to       */
612 /*-----------------------------------------------------------------*/
613 static int aopHasRegs(asmop *aop, int from, int to)
614 {
615     int size =0;
616
617     if (aop->type != AOP_REG) return 0; /* if not assigned to regs */
618
619     for (; size < aop->size ; size++) {
620         int reg;
621         for (reg = from ; reg <= to ; reg++)
622             if (aop->aopu.aop_reg[size] == ds390_regWithIdx(reg)) return 1;
623     }
624     return 0;
625 }
626
627 /*-----------------------------------------------------------------*/
628 /* regsInCommon - two operands have some registers in common       */
629 /*-----------------------------------------------------------------*/
630 static bool
631 regsInCommon (operand * op1, operand * op2)
632 {
633   symbol *sym1, *sym2;
634   int i;
635
636   /* if they have registers in common */
637   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
638     return FALSE;
639
640   sym1 = OP_SYMBOL (op1);
641   sym2 = OP_SYMBOL (op2);
642
643   if (sym1->nRegs == 0 || sym2->nRegs == 0)
644     return FALSE;
645
646   for (i = 0; i < sym1->nRegs; i++)
647     {
648       int j;
649       if (!sym1->regs[i])
650         continue;
651
652       for (j = 0; j < sym2->nRegs; j++)
653         {
654           if (!sym2->regs[j])
655             continue;
656
657           if (sym2->regs[j] == sym1->regs[i])
658             return TRUE;
659         }
660     }
661
662   return FALSE;
663 }
664
665 /*-----------------------------------------------------------------*/
666 /* operandsEqu - equivalent                                        */
667 /*-----------------------------------------------------------------*/
668 static bool
669 operandsEqu (operand * op1, operand * op2)
670 {
671   symbol *sym1, *sym2;
672
673   /* if they not symbols */
674   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
675     return FALSE;
676
677   sym1 = OP_SYMBOL (op1);
678   sym2 = OP_SYMBOL (op2);
679
680   /* if both are itemps & one is spilt
681      and the other is not then false */
682   if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
683       sym1->isspilt != sym2->isspilt)
684     return FALSE;
685
686   /* if they are the same */
687   if (sym1 == sym2)
688     return TRUE;
689
690   if (strcmp (sym1->rname, sym2->rname) == 0)
691     return TRUE;
692
693
694   /* if left is a tmp & right is not */
695   if (IS_ITEMP (op1) &&
696       !IS_ITEMP (op2) &&
697       sym1->isspilt &&
698       (sym1->usl.spillLoc == sym2))
699     return TRUE;
700
701   if (IS_ITEMP (op2) &&
702       !IS_ITEMP (op1) &&
703       sym2->isspilt &&
704       sym1->level > 0 &&
705       (sym2->usl.spillLoc == sym1))
706     return TRUE;
707
708   return FALSE;
709 }
710
711 /*-----------------------------------------------------------------*/
712 /* sameRegs - two asmops have the same registers                   */
713 /*-----------------------------------------------------------------*/
714 static bool
715 sameRegs (asmop * aop1, asmop * aop2)
716 {
717   int i;
718
719   if (aop1 == aop2)
720     {
721       if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
722         {
723           return FALSE;
724         }
725       return TRUE;
726     }
727
728   if (aop1->type != AOP_REG ||
729       aop2->type != AOP_REG)
730     return FALSE;
731
732   if (aop1->size != aop2->size)
733     return FALSE;
734
735   for (i = 0; i < aop1->size; i++)
736     if (aop1->aopu.aop_reg[i] !=
737         aop2->aopu.aop_reg[i])
738       return FALSE;
739
740   return TRUE;
741 }
742
743 /*-----------------------------------------------------------------*/
744 /* aopOp - allocates an asmop for an operand  :                    */
745 /*-----------------------------------------------------------------*/
746 static void
747 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
748 {
749   asmop *aop;
750   symbol *sym;
751   int i;
752
753   if (!op)
754     return;
755
756   /* if this a literal */
757   if (IS_OP_LITERAL (op))
758     {
759       op->aop = aop = newAsmop (AOP_LIT);
760       aop->aopu.aop_lit = op->operand.valOperand;
761       aop->size = getSize (operandType (op));
762       return;
763     }
764
765   /* if already has a asmop then continue */
766   if (op->aop)
767     return;
768
769   /* if the underlying symbol has a aop */
770   if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
771     {
772       op->aop = OP_SYMBOL (op)->aop;
773       return;
774     }
775
776   /* if this is a true symbol */
777   if (IS_TRUE_SYMOP (op))
778     {
779       op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
780       return;
781     }
782
783   /* this is a temporary : this has
784      only four choices :
785      a) register
786      b) spillocation
787      c) rematerialize
788      d) conditional
789      e) can be a return use only */
790
791   sym = OP_SYMBOL (op);
792
793
794   /* if the type is a conditional */
795   if (sym->regType == REG_CND)
796     {
797       aop = op->aop = sym->aop = newAsmop (AOP_CRY);
798       aop->size = 0;
799       return;
800     }
801
802   /* if it is spilt then two situations
803      a) is rematerialize
804      b) has a spill location */
805   if (sym->isspilt || sym->nRegs == 0)
806     {
807
808       /* rematerialize it NOW */
809       if (sym->remat)
810         {
811           sym->aop = op->aop = aop =
812             aopForRemat (sym);
813           aop->size = getSize (sym->type);
814           return;
815         }
816
817       if (sym->accuse)
818         {
819           int i;
820           aop = op->aop = sym->aop = newAsmop (AOP_ACC);
821           aop->size = getSize (sym->type);
822           for (i = 0; i < 2; i++)
823             aop->aopu.aop_str[i] = accUse[i];
824           return;
825         }
826
827       if (sym->ruonly)
828         {
829           int i;
830
831           if (useDP2)
832             {
833               /* a AOP_STR uses DPTR, but DPTR is already in use;
834                * we're just hosed.
835                */
836               fprintf (stderr, "*** Internal error: AOP_STR with DPTR in use! for operand %s\n",sym->name);
837             }
838
839           aop = op->aop = sym->aop = newAsmop (AOP_STR);
840           aop->size = getSize (sym->type);
841           for (i = 0; i < (int) fReturnSizeDS390; i++)
842             aop->aopu.aop_str[i] = fReturn[i];
843           return;
844         }
845
846       /* else spill location  */
847       if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
848           /* force a new aop if sizes differ */
849           sym->usl.spillLoc->aop = NULL;
850       }
851       sym->aop = op->aop = aop =
852         aopForSym (ic, sym->usl.spillLoc, result, useDP2);
853       aop->size = getSize (sym->type);
854       return;
855     }
856
857   /* must be in a register */
858   sym->aop = op->aop = aop = newAsmop (AOP_REG);
859   aop->size = sym->nRegs;
860   for (i = 0; i < sym->nRegs; i++)
861     aop->aopu.aop_reg[i] = sym->regs[i];
862 }
863
864 /*-----------------------------------------------------------------*/
865 /* freeAsmop - free up the asmop given to an operand               */
866 /*----------------------------------------------------------------*/
867 static void
868 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
869 {
870   asmop *aop;
871
872   if (!op)
873     aop = aaop;
874   else
875     aop = op->aop;
876
877   if (!aop)
878     return;
879
880   if (aop->freed)
881     goto dealloc;
882
883   aop->freed = 1;
884
885   /* depending on the asmop type only three cases need work AOP_RO
886      , AOP_R1 && AOP_STK */
887   switch (aop->type)
888     {
889     case AOP_R0:
890       if (_G.r0Pushed)
891         {
892           if (pop)
893             {
894               emitcode ("pop", "ar0");
895               _G.r0Pushed--;
896             }
897         }
898       bitVectUnSetBit (ic->rUsed, R0_IDX);
899       break;
900
901     case AOP_R1:
902       if (_G.r1Pushed)
903         {
904           if (pop)
905             {
906               emitcode ("pop", "ar1");
907               _G.r1Pushed--;
908             }
909         }
910       bitVectUnSetBit (ic->rUsed, R1_IDX);
911       break;
912
913     case AOP_STK:
914       {
915         int sz = aop->size;
916         int stk = aop->aopu.aop_stk + aop->size;
917         bitVectUnSetBit (ic->rUsed, R0_IDX);
918         bitVectUnSetBit (ic->rUsed, R1_IDX);
919
920         getFreePtr (ic, &aop, FALSE);
921
922         if (options.stack10bit)
923           {
924             /* I'm not sure what to do here yet... */
925             /* #STUB */
926             fprintf (stderr,
927                      "*** Warning: probably generating bad code for "
928                      "10 bit stack mode.\n");
929           }
930
931         if (stk)
932           {
933             emitcode ("mov", "a,_bp");
934             emitcode ("add", "a,#!constbyte", ((char) stk) & 0xff);
935             emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
936           }
937         else
938           {
939             emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
940           }
941
942         while (sz--)
943           {
944             emitcode ("pop", "acc");
945             emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
946             if (!sz)
947               break;
948             emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
949           }
950         op->aop = aop;
951         freeAsmop (op, NULL, ic, TRUE);
952         if (_G.r0Pushed)
953           {
954             emitcode ("pop", "ar0");
955             _G.r0Pushed--;
956           }
957
958         if (_G.r1Pushed)
959           {
960             emitcode ("pop", "ar1");
961             _G.r1Pushed--;
962           }
963       }
964     }
965
966 dealloc:
967   /* all other cases just dealloc */
968   if (op)
969     {
970       op->aop = NULL;
971       if (IS_SYMOP (op))
972         {
973           OP_SYMBOL (op)->aop = NULL;
974           /* if the symbol has a spill */
975           if (SPIL_LOC (op))
976             SPIL_LOC (op)->aop = NULL;
977         }
978     }
979 }
980
981 /*------------------------------------------------------------------*/
982 /* aopGet - for fetching value of the aop                           */
983 /*                    */
984 /* Set canClobberACC if you are sure it is OK to clobber the value  */
985 /* in the accumulator. Set it FALSE otherwise; FALSE is always safe, */
986 /* just less efficient.               */
987 /*------------------------------------------------------------------*/
988
989 static char *
990 aopGet (asmop * aop,
991         int offset,
992         bool bit16,
993         bool dname,
994         bool canClobberACC)
995 {
996   char *s = buffer;
997   char *rs;
998
999   /* offset is greater than
1000      size then zero */
1001   if (offset > (aop->size - 1) &&
1002       aop->type != AOP_LIT)
1003     return zero;
1004
1005   /* depending on type */
1006   switch (aop->type)
1007     {
1008
1009     case AOP_R0:
1010     case AOP_R1:
1011       /* if we need to increment it */
1012       while (offset > aop->coff)
1013         {
1014           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1015           aop->coff++;
1016         }
1017
1018       while (offset < aop->coff)
1019         {
1020           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1021           aop->coff--;
1022         }
1023
1024       aop->coff = offset;
1025       if (aop->paged)
1026         {
1027           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1028           return (dname ? "acc" : "a");
1029         }
1030       sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1031       rs = Safe_calloc (1, strlen (s) + 1);
1032       strcpy (rs, s);
1033       return rs;
1034
1035     case AOP_DPTR:
1036     case AOP_DPTR2:
1037
1038       if (aop->type == AOP_DPTR2)
1039         {
1040           genSetDPTR (1);
1041           if (!canClobberACC)
1042             {
1043                     TR_AP("#1");
1044                     emitcode ("xch", "a, %s", DP2_RESULT_REG);
1045             }
1046         }
1047
1048       _flushLazyDPS ();
1049
1050       while (offset > aop->coff)
1051         {
1052           emitcode ("inc", "dptr");
1053           aop->coff++;
1054         }
1055
1056       while (offset < aop->coff)
1057         {
1058           emitcode ("lcall", "__decdptr");
1059           aop->coff--;
1060         }
1061
1062       aop->coff = offset;
1063       if (aop->code)
1064         {
1065           emitcode ("clr", "a");
1066           emitcode ("movc", "a,@a+dptr");
1067         }
1068       else
1069         {
1070           emitcode ("movx", "a,@dptr");
1071         }
1072
1073       if (aop->type == AOP_DPTR2)
1074         {
1075           genSetDPTR (0);
1076           if (!canClobberACC)
1077             {
1078        TR_AP("#2");
1079               emitcode ("xch", "a, %s", DP2_RESULT_REG);
1080               return DP2_RESULT_REG;
1081             }
1082         }
1083       return (dname ? "acc" : "a");
1084
1085     case AOP_IMMD:
1086       if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
1087               sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
1088       } else if (bit16)
1089         sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
1090       else if (offset) {
1091           switch (offset) {
1092           case 1:
1093               tsprintf(s,"#!his",aop->aopu.aop_immd.aop_immd1);
1094               break;
1095           case 2:
1096               tsprintf(s,"#!hihis",aop->aopu.aop_immd.aop_immd1);
1097               break;
1098           case 3:
1099               tsprintf(s,"#!hihihis",aop->aopu.aop_immd.aop_immd1);
1100               break;
1101           default: /* should not need this (just in case) */
1102               sprintf (s, "#(%s >> %d)",
1103                        aop->aopu.aop_immd.aop_immd1,
1104                        offset * 8);
1105           }
1106       }
1107       else
1108         sprintf (s, "#%s",
1109                  aop->aopu.aop_immd.aop_immd1);
1110       rs = Safe_calloc (1, strlen (s) + 1);
1111       strcpy (rs, s);
1112       return rs;
1113
1114     case AOP_DIR:
1115       if (offset)
1116         sprintf (s, "(%s + %d)",
1117                  aop->aopu.aop_dir,
1118                  offset);
1119       else
1120         sprintf (s, "%s", aop->aopu.aop_dir);
1121       rs = Safe_calloc (1, strlen (s) + 1);
1122       strcpy (rs, s);
1123       return rs;
1124
1125     case AOP_REG:
1126       if (dname)
1127         return aop->aopu.aop_reg[offset]->dname;
1128       else
1129         return aop->aopu.aop_reg[offset]->name;
1130
1131     case AOP_CRY:
1132       emitcode ("clr", "a");
1133       emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1134       emitcode ("rlc", "a");
1135       return (dname ? "acc" : "a");
1136
1137     case AOP_ACC:
1138       if (!offset && dname)
1139         return "acc";
1140       return aop->aopu.aop_str[offset];
1141
1142     case AOP_LIT:
1143       return aopLiteral (aop->aopu.aop_lit, offset);
1144
1145     case AOP_STR:
1146       aop->coff = offset;
1147       if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1148           dname)
1149         return "acc";
1150
1151       return aop->aopu.aop_str[offset];
1152
1153     }
1154
1155   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1156           "aopget got unsupported aop->type");
1157   exit (1);
1158 }
1159 /*-----------------------------------------------------------------*/
1160 /* aopPut - puts a string for a aop                                */
1161 /*-----------------------------------------------------------------*/
1162 static void
1163 aopPut (asmop * aop, char *s, int offset)
1164 {
1165   char *d = buffer;
1166
1167   if (aop->size && offset > (aop->size - 1))
1168     {
1169       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1170               "aopPut got offset > aop->size");
1171       exit (1);
1172     }
1173
1174   /* will assign value to value */
1175   /* depending on where it is ofcourse */
1176   switch (aop->type)
1177     {
1178     case AOP_DIR:
1179       if (offset)
1180         sprintf (d, "(%s + %d)",
1181                  aop->aopu.aop_dir, offset);
1182       else
1183         sprintf (d, "%s", aop->aopu.aop_dir);
1184
1185       if (strcmp (d, s))
1186         emitcode ("mov", "%s,%s", d, s);
1187
1188       break;
1189
1190     case AOP_REG:
1191       if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1192           strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1193         {
1194           if (*s == '@' ||
1195               strcmp (s, "r0") == 0 ||
1196               strcmp (s, "r1") == 0 ||
1197               strcmp (s, "r2") == 0 ||
1198               strcmp (s, "r3") == 0 ||
1199               strcmp (s, "r4") == 0 ||
1200               strcmp (s, "r5") == 0 ||
1201               strcmp (s, "r6") == 0 ||
1202               strcmp (s, "r7") == 0)
1203             emitcode ("mov", "%s,%s",
1204                       aop->aopu.aop_reg[offset]->dname, s);
1205           else
1206             emitcode ("mov", "%s,%s",
1207                       aop->aopu.aop_reg[offset]->name, s);
1208         }
1209       break;
1210
1211     case AOP_DPTR:
1212     case AOP_DPTR2:
1213
1214       if (aop->type == AOP_DPTR2)
1215         {
1216           genSetDPTR (1);
1217         }
1218       _flushLazyDPS ();
1219
1220       if (aop->code)
1221         {
1222           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1223                   "aopPut writting to code space");
1224           exit (1);
1225         }
1226
1227       while (offset > aop->coff)
1228         {
1229           aop->coff++;
1230           emitcode ("inc", "dptr");
1231         }
1232
1233       while (offset < aop->coff)
1234         {
1235           aop->coff--;
1236           emitcode ("lcall", "__decdptr");
1237         }
1238
1239       aop->coff = offset;
1240
1241       /* if not in accumulater */
1242       MOVA (s);
1243
1244       emitcode ("movx", "@dptr,a");
1245
1246       if (aop->type == AOP_DPTR2)
1247         {
1248           genSetDPTR (0);
1249         }
1250       break;
1251
1252     case AOP_R0:
1253     case AOP_R1:
1254       while (offset > aop->coff)
1255         {
1256           aop->coff++;
1257           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1258         }
1259       while (offset < aop->coff)
1260         {
1261           aop->coff--;
1262           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1263         }
1264       aop->coff = offset;
1265
1266       if (aop->paged)
1267         {
1268           MOVA (s);
1269           emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1270
1271         }
1272       else if (*s == '@')
1273         {
1274           MOVA (s);
1275           emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1276         }
1277       else if (strcmp (s, "r0") == 0 ||
1278                strcmp (s, "r1") == 0 ||
1279                strcmp (s, "r2") == 0 ||
1280                strcmp (s, "r3") == 0 ||
1281                strcmp (s, "r4") == 0 ||
1282                strcmp (s, "r5") == 0 ||
1283                strcmp (s, "r6") == 0 ||
1284                strcmp (s, "r7") == 0)
1285         {
1286           char buffer[10];
1287           sprintf (buffer, "a%s", s);
1288           emitcode ("mov", "@%s,%s",
1289                     aop->aopu.aop_ptr->name, buffer);
1290         }
1291       else
1292         emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1293
1294       break;
1295
1296     case AOP_STK:
1297       if (strcmp (s, "a") == 0)
1298         emitcode ("push", "acc");
1299       else
1300         if (*s=='@') {
1301           MOVA(s);
1302           emitcode ("push", "acc");
1303         } else {
1304           emitcode ("push", s);
1305         }
1306
1307       break;
1308
1309     case AOP_CRY:
1310       /* if bit variable */
1311       if (!aop->aopu.aop_dir)
1312         {
1313           emitcode ("clr", "a");
1314           emitcode ("rlc", "a");
1315         }
1316       else
1317         {
1318           if (s == zero)
1319             emitcode ("clr", "%s", aop->aopu.aop_dir);
1320           else if (s == one)
1321             emitcode ("setb", "%s", aop->aopu.aop_dir);
1322           else if (!strcmp (s, "c"))
1323             emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1324           else
1325             {
1326               if (strcmp (s, "a"))
1327                 {
1328                   MOVA (s);
1329                 }
1330               {
1331                 symbol *lbl = newiTempLabel (NULL);
1332                 emitcode ("clr", "c");
1333                 emitcode ("jz", "!tlabel", lbl->key + 100);
1334                 emitcode ("cpl", "c");
1335                 emitcode ("", "!tlabeldef", lbl->key + 100);
1336                 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1337               }
1338             }
1339         }
1340       break;
1341
1342     case AOP_STR:
1343       aop->coff = offset;
1344       if (strcmp (aop->aopu.aop_str[offset], s))
1345         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1346       break;
1347
1348     case AOP_ACC:
1349       aop->coff = offset;
1350       if (!offset && (strcmp (s, "acc") == 0))
1351         break;
1352
1353       if (strcmp (aop->aopu.aop_str[offset], s))
1354         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1355       break;
1356
1357     default:
1358       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1359               "aopPut got unsupported aop->type");
1360       exit (1);
1361     }
1362
1363 }
1364
1365
1366 /*--------------------------------------------------------------------*/
1367 /* reAdjustPreg - points a register back to where it should (coff==0) */
1368 /*--------------------------------------------------------------------*/
1369 static void
1370 reAdjustPreg (asmop * aop)
1371 {
1372   if ((aop->coff==0) || (aop->size <= 1)) {
1373     return;
1374   }
1375
1376   switch (aop->type)
1377     {
1378     case AOP_R0:
1379     case AOP_R1:
1380       while (aop->coff--)
1381         emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1382       break;
1383     case AOP_DPTR:
1384     case AOP_DPTR2:
1385       if (aop->type == AOP_DPTR2)
1386         {
1387           genSetDPTR (1);
1388           _flushLazyDPS ();
1389         }
1390       while (aop->coff--)
1391         {
1392           emitcode ("lcall", "__decdptr");
1393         }
1394
1395       if (aop->type == AOP_DPTR2)
1396         {
1397           genSetDPTR (0);
1398         }
1399       break;
1400
1401     }
1402   aop->coff=0;
1403 }
1404
1405 #define AOP(op) op->aop
1406 #define AOP_TYPE(op) AOP(op)->type
1407 #define AOP_SIZE(op) AOP(op)->size
1408 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1409                        AOP_TYPE(x) == AOP_R0))
1410
1411 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
1412                         AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1413                          AOP(x)->paged))
1414
1415 #define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
1416                       (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1417                       x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1418
1419 /* Workaround for DS80C390 bug: div ab may return bogus results
1420  * if A is accessed in instruction immediately before the div.
1421  *
1422  * Will be fixed in B4 rev of processor, Dallas claims.
1423  */
1424
1425 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L)       \
1426     if (!AOP_NEEDSACC(RIGHT))         \
1427     {               \
1428       /* We can load A first, then B, since     \
1429        * B (the RIGHT operand) won't clobber A,   \
1430        * thus avoiding touching A right before the div. \
1431        */             \
1432       D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1433       L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE);     \
1434       MOVA(L);            \
1435       emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1436     }               \
1437     else              \
1438     {               \
1439       /* Just stuff in a nop after loading A. */    \
1440       emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1441       L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE);   \
1442       MOVA(L);            \
1443       emitcode("nop", "; workaround for DS80C390 div bug.");  \
1444     }
1445
1446 /*-----------------------------------------------------------------*/
1447 /* genNotFloat - generates not for float operations              */
1448 /*-----------------------------------------------------------------*/
1449 static void
1450 genNotFloat (operand * op, operand * res)
1451 {
1452   int size, offset;
1453   char *l;
1454   symbol *tlbl;
1455
1456   D (emitcode (";", "genNotFloat ");
1457     );
1458
1459   /* we will put 127 in the first byte of
1460      the result */
1461   aopPut (AOP (res), "#127", 0);
1462   size = AOP_SIZE (op) - 1;
1463   offset = 1;
1464
1465   _startLazyDPSEvaluation ();
1466   l = aopGet (op->aop, offset++, FALSE, FALSE, TRUE);
1467   MOVA (l);
1468
1469   while (size--)
1470     {
1471       emitcode ("orl", "a,%s",
1472                 aopGet (op->aop,
1473                         offset++, FALSE, FALSE, FALSE));
1474     }
1475   _endLazyDPSEvaluation ();
1476
1477   tlbl = newiTempLabel (NULL);
1478   aopPut (res->aop, one, 1);
1479   emitcode ("jz", "!tlabel", (tlbl->key + 100));
1480   aopPut (res->aop, zero, 1);
1481   emitcode ("", "!tlabeldef", (tlbl->key + 100));
1482
1483   size = res->aop->size - 2;
1484   offset = 2;
1485   /* put zeros in the rest */
1486   while (size--)
1487     aopPut (res->aop, zero, offset++);
1488 }
1489
1490 /*-----------------------------------------------------------------*/
1491 /* opIsGptr: returns non-zero if the passed operand is       */
1492 /* a generic pointer type.             */
1493 /*-----------------------------------------------------------------*/
1494 static int
1495 opIsGptr (operand * op)
1496 {
1497   sym_link *type = operandType (op);
1498
1499   if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1500     {
1501       return 1;
1502     }
1503   return 0;
1504 }
1505
1506 /*-----------------------------------------------------------------*/
1507 /* getDataSize - get the operand data size                         */
1508 /*-----------------------------------------------------------------*/
1509 static int
1510 getDataSize (operand * op)
1511 {
1512   int size;
1513   size = AOP_SIZE (op);
1514   if (size == GPTRSIZE)
1515     {
1516       sym_link *type = operandType (op);
1517       if (IS_GENPTR (type))
1518         {
1519           /* generic pointer; arithmetic operations
1520            * should ignore the high byte (pointer type).
1521            */
1522           size--;
1523         }
1524     }
1525   return size;
1526 }
1527
1528 /*-----------------------------------------------------------------*/
1529 /* outAcc - output Acc                                             */
1530 /*-----------------------------------------------------------------*/
1531 static void
1532 outAcc (operand * result)
1533 {
1534   int size, offset;
1535   size = getDataSize (result);
1536   if (size)
1537     {
1538       aopPut (AOP (result), "a", 0);
1539       size--;
1540       offset = 1;
1541       /* unsigned or positive */
1542       while (size--)
1543         {
1544           aopPut (AOP (result), zero, offset++);
1545         }
1546     }
1547 }
1548
1549 /*-----------------------------------------------------------------*/
1550 /* outBitC - output a bit C                                        */
1551 /*-----------------------------------------------------------------*/
1552 static void
1553 outBitC (operand * result)
1554 {
1555   /* if the result is bit */
1556   if (AOP_TYPE (result) == AOP_CRY)
1557     {
1558       aopPut (AOP (result), "c", 0);
1559     }
1560   else
1561     {
1562       emitcode ("clr", "a");
1563       emitcode ("rlc", "a");
1564       outAcc (result);
1565     }
1566 }
1567
1568 /*-----------------------------------------------------------------*/
1569 /* toBoolean - emit code for orl a,operator(sizeop)                */
1570 /*-----------------------------------------------------------------*/
1571 static void
1572 toBoolean (operand * oper)
1573 {
1574   int   size = AOP_SIZE (oper) - 1;
1575   int   offset = 1;
1576   bool usedB = FALSE;
1577
1578   /* The generic part of a generic pointer should
1579    * not participate in it's truth value.
1580    *
1581    * i.e. 0x10000000 is zero.
1582    */
1583   if (opIsGptr (oper))
1584     {
1585       D (emitcode (";", "toBoolean: generic ptr special case.");
1586         );
1587       size--;
1588     }
1589
1590   _startLazyDPSEvaluation ();
1591   if (AOP_NEEDSACC (oper) && size)
1592     {
1593       usedB = TRUE;
1594       emitcode ("push", "b");
1595       emitcode ("mov", "b, %s", aopGet (AOP (oper), 0, FALSE, FALSE, FALSE));
1596     }
1597   else
1598     {
1599       MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, TRUE));
1600     }
1601   while (size--)
1602     {
1603       if (usedB)
1604         {
1605           emitcode ("orl", "b,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1606         }
1607       else
1608         {
1609           emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1610         }
1611     }
1612   _endLazyDPSEvaluation ();
1613
1614   if (usedB)
1615     {
1616       emitcode ("mov", "a,b");
1617       emitcode ("pop", "b");
1618     }
1619 }
1620
1621
1622 /*-----------------------------------------------------------------*/
1623 /* genNot - generate code for ! operation                          */
1624 /*-----------------------------------------------------------------*/
1625 static void
1626 genNot (iCode * ic)
1627 {
1628   symbol *tlbl;
1629   sym_link *optype = operandType (IC_LEFT (ic));
1630
1631   D (emitcode (";", "genNot ");
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 in bit space then a special case */
1639   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1640     {
1641       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1642       emitcode ("cpl", "c");
1643       outBitC (IC_RESULT (ic));
1644       goto release;
1645     }
1646
1647   /* if type float then do float */
1648   if (IS_FLOAT (optype))
1649     {
1650       genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1651       goto release;
1652     }
1653
1654   toBoolean (IC_LEFT (ic));
1655
1656   tlbl = newiTempLabel (NULL);
1657   emitcode ("cjne", "a,#1,!tlabel", tlbl->key + 100);
1658   emitcode ("", "!tlabeldef", tlbl->key + 100);
1659   outBitC (IC_RESULT (ic));
1660
1661 release:
1662   /* release the aops */
1663   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1664   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1665 }
1666
1667
1668 /*-----------------------------------------------------------------*/
1669 /* genCpl - generate code for complement                           */
1670 /*-----------------------------------------------------------------*/
1671 static void
1672 genCpl (iCode * ic)
1673 {
1674   int offset = 0;
1675   int size;
1676
1677   D (emitcode (";", "genCpl ");
1678     );
1679
1680
1681   /* assign asmOps to operand & result */
1682   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1683   aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1684
1685   /* if both are in bit space then
1686      a special case */
1687   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1688       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1689     {
1690
1691       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1692       emitcode ("cpl", "c");
1693       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1694       goto release;
1695     }
1696
1697   size = AOP_SIZE (IC_RESULT (ic));
1698   _startLazyDPSEvaluation ();
1699   while (size--)
1700     {
1701       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1702       MOVA (l);
1703       emitcode ("cpl", "a");
1704       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1705     }
1706   _endLazyDPSEvaluation ();
1707
1708
1709 release:
1710   /* release the aops */
1711   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1712   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1713 }
1714
1715 /*-----------------------------------------------------------------*/
1716 /* genUminusFloat - unary minus for floating points                */
1717 /*-----------------------------------------------------------------*/
1718 static void
1719 genUminusFloat (operand * op, operand * result)
1720 {
1721   int size, offset = 0;
1722   char *l;
1723   /* for this we just need to flip the
1724      first it then copy the rest in place */
1725   D (emitcode (";", "genUminusFloat");
1726     );
1727
1728   _startLazyDPSEvaluation ();
1729   size = AOP_SIZE (op) - 1;
1730   l = aopGet (AOP (op), 3, FALSE, FALSE, TRUE);
1731   MOVA (l);
1732
1733   emitcode ("cpl", "acc.7");
1734   aopPut (AOP (result), "a", 3);
1735
1736   while (size--)
1737     {
1738       aopPut (AOP (result),
1739               aopGet (AOP (op), offset, FALSE, FALSE, FALSE),
1740               offset);
1741       offset++;
1742     }
1743   _endLazyDPSEvaluation ();
1744 }
1745
1746 /*-----------------------------------------------------------------*/
1747 /* genUminus - unary minus code generation                         */
1748 /*-----------------------------------------------------------------*/
1749 static void
1750 genUminus (iCode * ic)
1751 {
1752   int offset, size;
1753   sym_link *optype, *rtype;
1754
1755   D (emitcode (";", "genUminus ");
1756     );
1757
1758
1759   /* assign asmops */
1760   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1761   aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1762
1763   /* if both in bit space then special
1764      case */
1765   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1766       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1767     {
1768
1769       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1770       emitcode ("cpl", "c");
1771       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1772       goto release;
1773     }
1774
1775   optype = operandType (IC_LEFT (ic));
1776   rtype = operandType (IC_RESULT (ic));
1777
1778   /* if float then do float stuff */
1779   if (IS_FLOAT (optype))
1780     {
1781       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1782       goto release;
1783     }
1784
1785   /* otherwise subtract from zero */
1786   size = AOP_SIZE (IC_LEFT (ic));
1787   offset = 0;
1788   _startLazyDPSEvaluation ();
1789   while (size--)
1790     {
1791       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1792       if (!strcmp (l, "a"))
1793         {
1794           if (offset == 0)
1795             SETC;
1796           emitcode ("cpl", "a");
1797           emitcode ("addc", "a,#0");
1798         }
1799       else
1800         {
1801           if (offset == 0)
1802             CLRC;
1803           emitcode ("clr", "a");
1804           emitcode ("subb", "a,%s", l);
1805         }
1806       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1807     }
1808   _endLazyDPSEvaluation ();
1809
1810   /* if any remaining bytes in the result */
1811   /* we just need to propagate the sign   */
1812   if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1813     {
1814       emitcode ("rlc", "a");
1815       emitcode ("subb", "a,acc");
1816       while (size--)
1817         aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1818     }
1819
1820 release:
1821   /* release the aops */
1822   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1823   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1824 }
1825
1826 /*-----------------------------------------------------------------*/
1827 /* savermask - saves registers in the mask                         */
1828 /*-----------------------------------------------------------------*/
1829 static void savermask(bitVect *rs_mask)
1830 {
1831     int i;
1832     if (options.useXstack) {
1833         if (bitVectBitValue (rs_mask, R0_IDX))
1834             emitcode ("mov", "b,r0");
1835         emitcode ("mov", "r0,%s", spname);
1836         for (i = 0; i < ds390_nRegs; i++) {
1837             if (bitVectBitValue (rs_mask, i)) {
1838                 if (i == R0_IDX)
1839                     emitcode ("mov", "a,b");
1840                 else
1841                     emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
1842                 emitcode ("movx", "@r0,a");
1843                 emitcode ("inc", "r0");
1844             }
1845         }
1846         emitcode ("mov", "%s,r0", spname);
1847         if (bitVectBitValue (rs_mask, R0_IDX))
1848             emitcode ("mov", "r0,b");
1849     } else {
1850         for (i = 0; i < ds390_nRegs; i++) {
1851             if (bitVectBitValue (rs_mask, i))
1852                 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
1853         }
1854     }
1855 }
1856
1857 /*-----------------------------------------------------------------*/
1858 /* saveRegisters - will look for a call and save the registers     */
1859 /*-----------------------------------------------------------------*/
1860 static void
1861 saveRegisters (iCode * lic)
1862 {
1863   iCode *ic;
1864   bitVect *rsave;
1865
1866   /* look for call */
1867   for (ic = lic; ic; ic = ic->next)
1868     if (ic->op == CALL || ic->op == PCALL)
1869       break;
1870
1871   if (!ic)
1872     {
1873       fprintf (stderr, "found parameter push with no function call\n");
1874       return;
1875     }
1876
1877   /* if the registers have been saved already then
1878      do nothing */
1879   if (ic->regsSaved || IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic)))) return ;
1880
1881   /* special case if DPTR alive across a function call then must save it 
1882      even though callee saves */
1883   if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
1884       int i =0;
1885       rsave = newBitVect(ic->rMask->size);
1886       for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
1887           if (bitVectBitValue(ic->rMask,i))
1888               rsave = bitVectSetBit(rsave,i);
1889       }
1890   } else {
1891     /* safe the registers in use at this time but skip the
1892        ones for the result */
1893     rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1894                            ds390_rUmaskForOp (IC_RESULT(ic)));
1895   }
1896   ic->regsSaved = 1;
1897   savermask(rsave);
1898 }
1899
1900 /*-----------------------------------------------------------------*/
1901 /* usavermask - restore registers with mask                        */
1902 /*-----------------------------------------------------------------*/
1903 static void unsavermask(bitVect *rs_mask)
1904 {
1905     int i;
1906     if (options.useXstack) {
1907         emitcode ("mov", "r0,%s", spname);
1908         for (i = ds390_nRegs; i >= 0; i--) {
1909             if (bitVectBitValue (rs_mask, i)) {
1910                 emitcode ("dec", "r0");
1911                 emitcode ("movx", "a,@r0");
1912                 if (i == R0_IDX)
1913                     emitcode ("mov", "b,a");
1914                 else
1915                     emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
1916             }       
1917         }
1918         emitcode ("mov", "%s,r0", spname);
1919         if (bitVectBitValue (rs_mask, R0_IDX))
1920             emitcode ("mov", "r0,b");
1921     } else {
1922         for (i = ds390_nRegs; i >= 0; i--) {
1923             if (bitVectBitValue (rs_mask, i))
1924                 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
1925         }
1926     }
1927 }
1928
1929 /*-----------------------------------------------------------------*/
1930 /* unsaveRegisters - pop the pushed registers                      */
1931 /*-----------------------------------------------------------------*/
1932 static void
1933 unsaveRegisters (iCode * ic)
1934 {
1935   bitVect *rsave;
1936
1937   if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
1938       int i =0;
1939       rsave = newBitVect(ic->rMask->size);
1940       for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
1941           if (bitVectBitValue(ic->rMask,i))
1942               rsave = bitVectSetBit(rsave,i);
1943       }
1944   } else {
1945     /* restore the registers in use at this time but skip the
1946        ones for the result */
1947     rsave = bitVectCplAnd (bitVectCopy (ic->rMask), 
1948                            ds390_rUmaskForOp (IC_RESULT(ic)));
1949   }
1950   unsavermask(rsave);
1951 }
1952
1953
1954 /*-----------------------------------------------------------------*/
1955 /* pushSide -                */
1956 /*-----------------------------------------------------------------*/
1957 static void
1958 pushSide (operand * oper, int size)
1959 {
1960   int offset = 0;
1961   _startLazyDPSEvaluation ();
1962   while (size--)
1963     {
1964       char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, FALSE);
1965       if (AOP_TYPE (oper) != AOP_REG &&
1966           AOP_TYPE (oper) != AOP_DIR &&
1967           strcmp (l, "a"))
1968         {
1969           emitcode ("mov", "a,%s", l);
1970           emitcode ("push", "acc");
1971         }
1972       else
1973         emitcode ("push", "%s", l);
1974     }
1975   _endLazyDPSEvaluation ();
1976 }
1977
1978 /*-----------------------------------------------------------------*/
1979 /* assignResultValue -               */
1980 /*-----------------------------------------------------------------*/
1981 static void
1982 assignResultValue (operand * oper)
1983 {
1984   int offset = 0;
1985   int size = AOP_SIZE (oper);
1986
1987   _startLazyDPSEvaluation ();
1988   while (size--)
1989     {
1990       aopPut (AOP (oper), fReturn[offset], offset);
1991       offset++;
1992     }
1993   _endLazyDPSEvaluation ();
1994 }
1995
1996
1997 /*-----------------------------------------------------------------*/
1998 /* genXpush - pushes onto the external stack                       */
1999 /*-----------------------------------------------------------------*/
2000 static void
2001 genXpush (iCode * ic)
2002 {
2003   asmop *aop = newAsmop (0);
2004   regs *r;
2005   int size, offset = 0;
2006
2007   D (emitcode (";", "genXpush ");
2008     );
2009
2010   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2011   r = getFreePtr (ic, &aop, FALSE);
2012
2013
2014   emitcode ("mov", "%s,_spx", r->name);
2015
2016   size = AOP_SIZE (IC_LEFT (ic));
2017   _startLazyDPSEvaluation ();
2018   while (size--)
2019     {
2020
2021       char *l = aopGet (AOP (IC_LEFT (ic)),
2022                         offset++, FALSE, FALSE, TRUE);
2023       MOVA (l);
2024       emitcode ("movx", "@%s,a", r->name);
2025       emitcode ("inc", "%s", r->name);
2026
2027     }
2028   _endLazyDPSEvaluation ();
2029
2030
2031   emitcode ("mov", "_spx,%s", r->name);
2032
2033   freeAsmop (NULL, aop, ic, TRUE);
2034   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2035 }
2036
2037 /*-----------------------------------------------------------------*/
2038 /* genIpush - genrate code for pushing this gets a little complex  */
2039 /*-----------------------------------------------------------------*/
2040 static void
2041 genIpush (iCode * ic)
2042 {
2043   int size, offset = 0;
2044   char *l;
2045
2046   D (emitcode (";", "genIpush ");
2047     );
2048
2049   /* if this is not a parm push : ie. it is spill push
2050      and spill push is always done on the local stack */
2051   if (!ic->parmPush)
2052     {
2053
2054       /* and the item is spilt then do nothing */
2055       if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2056         return;
2057
2058       aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2059       size = AOP_SIZE (IC_LEFT (ic));
2060       /* push it on the stack */
2061       _startLazyDPSEvaluation ();
2062       while (size--)
2063         {
2064           l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, TRUE);
2065           if (*l == '#')
2066             {
2067               MOVA (l);
2068               l = "acc";
2069             }
2070           emitcode ("push", "%s", l);
2071         }
2072       _endLazyDPSEvaluation ();
2073       return;
2074     }
2075
2076   /* this is a paramter push: in this case we call
2077      the routine to find the call and save those
2078      registers that need to be saved */
2079   saveRegisters (ic);
2080
2081   /* if use external stack then call the external
2082      stack pushing routine */
2083   if (options.useXstack)
2084     {
2085       genXpush (ic);
2086       return;
2087     }
2088
2089   /* then do the push */
2090   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2091
2092   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2093   size = AOP_SIZE (IC_LEFT (ic));
2094
2095   _startLazyDPSEvaluation ();
2096   while (size--)
2097     {
2098       l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, FALSE);
2099       if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2100           AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2101           strcmp (l, "a"))
2102         {
2103           emitcode ("mov", "a,%s", l);
2104           emitcode ("push", "acc");
2105         }
2106       else
2107         emitcode ("push", "%s", l);
2108     }
2109   _endLazyDPSEvaluation ();
2110
2111   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2112 }
2113
2114 /*-----------------------------------------------------------------*/
2115 /* genIpop - recover the registers: can happen only for spilling   */
2116 /*-----------------------------------------------------------------*/
2117 static void
2118 genIpop (iCode * ic)
2119 {
2120   int size, offset;
2121
2122   D (emitcode (";", "genIpop ");
2123     );
2124
2125
2126   /* if the temp was not pushed then */
2127   if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2128     return;
2129
2130   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2131   size = AOP_SIZE (IC_LEFT (ic));
2132   offset = (size - 1);
2133   _startLazyDPSEvaluation ();
2134   while (size--)
2135     {
2136       emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2137                                      FALSE, TRUE, TRUE));
2138     }
2139   _endLazyDPSEvaluation ();
2140
2141   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2142 }
2143
2144 /*-----------------------------------------------------------------*/
2145 /* unsaveRBank - restores the resgister bank from stack            */
2146 /*-----------------------------------------------------------------*/
2147 static void
2148 unsaveRBank (int bank, iCode * ic, bool popPsw)
2149 {
2150   int i;
2151   asmop *aop = NULL;
2152   regs *r = NULL;
2153
2154   if (options.useXstack)
2155   {
2156       if (!ic)
2157       {
2158           /* Assume r0 is available for use. */
2159           r = ds390_regWithIdx (R0_IDX);;          
2160       } 
2161       else
2162       {
2163           aop = newAsmop (0);
2164           r = getFreePtr (ic, &aop, FALSE);
2165       }
2166       emitcode ("mov", "%s,_spx", r->name);      
2167   }
2168   
2169   if (popPsw)
2170     {
2171       if (options.useXstack)
2172       {
2173           emitcode ("movx", "a,@%s", r->name);
2174           emitcode ("mov", "psw,a");
2175           emitcode ("dec", "%s", r->name);
2176         }
2177       else
2178       {
2179         emitcode ("pop", "psw");
2180       }
2181     }
2182
2183   for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2184     {
2185       if (options.useXstack)
2186         {
2187           emitcode ("movx", "a,@%s", r->name);
2188           emitcode ("mov", "(%s+%d),a",
2189                     regs390[i].base, 8 * bank + regs390[i].offset);
2190           emitcode ("dec", "%s", r->name);
2191
2192         }
2193       else
2194         emitcode ("pop", "(%s+%d)",
2195                   regs390[i].base, 8 * bank + regs390[i].offset);
2196     }
2197
2198   if (options.useXstack)
2199     {
2200       emitcode ("mov", "_spx,%s", r->name);
2201     }
2202     
2203   if (aop)
2204   {
2205       freeAsmop (NULL, aop, ic, TRUE);  
2206   }    
2207 }
2208
2209 /*-----------------------------------------------------------------*/
2210 /* saveRBank - saves an entire register bank on the stack          */
2211 /*-----------------------------------------------------------------*/
2212 static void
2213 saveRBank (int bank, iCode * ic, bool pushPsw)
2214 {
2215   int i;
2216   asmop *aop = NULL;
2217   regs *r = NULL;
2218
2219   if (options.useXstack)
2220     {
2221         if (!ic)
2222         {
2223           /* Assume r0 is available for use. */
2224                   r = ds390_regWithIdx (R0_IDX);;
2225         }
2226         else
2227         {
2228           aop = newAsmop (0);
2229           r = getFreePtr (ic, &aop, FALSE);
2230         }
2231         emitcode ("mov", "%s,_spx", r->name);    
2232     }
2233
2234   for (i = 0; i < 8 ; i++) /* only R0-R7 needs saving */
2235     {
2236       if (options.useXstack)
2237         {
2238           emitcode ("inc", "%s", r->name);
2239           emitcode ("mov", "a,(%s+%d)",
2240                     regs390[i].base, 8 * bank + regs390[i].offset);
2241           emitcode ("movx", "@%s,a", r->name);
2242         }
2243       else
2244         emitcode ("push", "(%s+%d)",
2245                   regs390[i].base, 8 * bank + regs390[i].offset);
2246     }
2247
2248   if (pushPsw)
2249     {
2250       if (options.useXstack)
2251         {
2252           emitcode ("mov", "a,psw");
2253           emitcode ("movx", "@%s,a", r->name);
2254           emitcode ("inc", "%s", r->name);
2255           emitcode ("mov", "_spx,%s", r->name);
2256         }
2257       else
2258       {
2259         emitcode ("push", "psw");
2260       }
2261
2262       emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2263     }
2264   
2265   if (aop)
2266   {
2267        freeAsmop (NULL, aop, ic, TRUE);
2268   }    
2269     
2270   if (ic)
2271   {  
2272       ic->bankSaved = 1;
2273   }
2274 }
2275
2276 /*-----------------------------------------------------------------*/
2277 /* genCall - generates a call statement                            */
2278 /*-----------------------------------------------------------------*/
2279 static void
2280 genCall (iCode * ic)
2281 {
2282   sym_link *dtype;
2283   bool restoreBank = FALSE;
2284   bool swapBanks = FALSE;
2285
2286   D (emitcode (";", "genCall "););
2287
2288   /* if we are calling a not _naked function that is not using
2289      the same register bank then we need to save the
2290      destination registers on the stack */
2291   dtype = operandType (IC_LEFT (ic));
2292   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2293       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2294       IFFUNC_ISISR (currFunc->type))
2295   {
2296       if (!ic->bankSaved) 
2297       {
2298            /* This is unexpected; the bank should have been saved in
2299             * genFunction.
2300             */
2301            saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2302            restoreBank = TRUE;
2303       }
2304       swapBanks = TRUE;
2305   }
2306   
2307     /* if caller saves & we have not saved then */
2308     if (!ic->regsSaved)
2309       saveRegisters (ic);
2310   
2311   /* if send set is not empty the assign */
2312   /* We've saved all the registers we care about;
2313   * therefore, we may clobber any register not used
2314   * in the calling convention (i.e. anything not in
2315   * fReturn.
2316   */
2317   if (_G.sendSet)
2318     {
2319       iCode *sic;
2320
2321       for (sic = setFirstItem (_G.sendSet); sic;
2322            sic = setNextItem (_G.sendSet))
2323         {
2324           int size, offset = 0;
2325
2326 #if 0
2327           aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2328           size = AOP_SIZE (IC_LEFT (sic));
2329
2330           _startLazyDPSEvaluation ();
2331           while (size--)
2332             {
2333               char *l = aopGet (AOP(IC_LEFT(sic)), offset,
2334                                 FALSE, FALSE, TRUE);
2335                 if ((AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR) && size)
2336                 {
2337                     emitcode("mov", "%s,%s", regs390[offset].name, l);
2338                 }
2339                 else if (strcmp (l, fReturn[offset]))
2340                 {
2341                     emitcode ("mov", "%s,%s",
2342                               fReturn[offset],
2343                               l);
2344                 }
2345               offset++;
2346             }
2347           _endLazyDPSEvaluation ();
2348           if (AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR)
2349           {
2350               size = AOP_SIZE (IC_LEFT (sic));
2351               if (size)
2352               {
2353                  size--;
2354               }
2355               while (size)
2356               {
2357                    size--;
2358                    emitcode("mov", "%s,%s",
2359                                     fReturn[size], regs390[size].name);
2360               }
2361           }
2362 #else
2363           // we know that dpl(hxb) is the result, so
2364           _startLazyDPSEvaluation ();
2365           size=getSize(operandType(IC_LEFT(sic)));
2366           if (size>1) {
2367             aopOp (IC_LEFT (sic), sic, FALSE, 
2368                    (IS_SYMOP(IC_LEFT(sic)) && OP_SYMBOL(IC_LEFT(sic))->ruonly ? FALSE : TRUE));
2369           } else {
2370             aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2371           }
2372           while (size--)
2373             {
2374               char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2375                                 FALSE, FALSE, TRUE);
2376               if (strcmp (l, fReturn[offset]))
2377                 {
2378                   emitcode ("mov", "%s,%s",
2379                             fReturn[offset],
2380                             l);
2381                 }
2382               offset++;
2383             }
2384           _endLazyDPSEvaluation ();
2385 #endif
2386           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2387         }
2388       _G.sendSet = NULL;
2389     }  
2390     
2391   if (swapBanks)
2392   {
2393         emitcode ("mov", "psw,#!constbyte", 
2394            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2395   }
2396
2397   /* make the call */
2398   emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2399                             OP_SYMBOL (IC_LEFT (ic))->rname :
2400                             OP_SYMBOL (IC_LEFT (ic))->name));
2401
2402   if (swapBanks)
2403   {
2404        emitcode ("mov", "psw,#!constbyte", 
2405           ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2406   }
2407
2408   /* if we need assign a result value */
2409   if ((IS_ITEMP (IC_RESULT (ic)) &&
2410        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2411         OP_SYMBOL (IC_RESULT (ic))->accuse ||
2412         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2413       IS_TRUE_SYMOP (IC_RESULT (ic)))
2414     {
2415       if (isOperandInFarSpace (IC_RESULT (ic))
2416           && getSize (operandType (IC_RESULT (ic))) <= 2)
2417         {
2418           int size = getSize (operandType (IC_RESULT (ic)));
2419
2420           /* Special case for 1 or 2 byte return in far space. */
2421           MOVA (fReturn[0]);
2422           if (size > 1)
2423             {
2424               emitcode ("mov", "b,%s", fReturn[1]);
2425             }
2426
2427           aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2428           aopPut (AOP (IC_RESULT (ic)), "a", 0);
2429
2430           if (size > 1)
2431             {
2432               aopPut (AOP (IC_RESULT (ic)), "b", 1);
2433             }
2434           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2435         }
2436       else
2437         {
2438           _G.accInUse++;
2439           aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2440           _G.accInUse--;
2441
2442           assignResultValue (IC_RESULT (ic));
2443
2444           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2445         }
2446     }
2447
2448   /* adjust the stack for parameters if
2449      required */
2450   if (ic->parmBytes) {
2451       if (options.stack10bit) {
2452           emitcode ("clr","c");
2453           emitcode ("mov","a,sp");
2454           emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2455           emitcode ("mov","sp,a");
2456           emitcode ("mov","a,esp");
2457           emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2458           emitcode ("mov","esp,a");       
2459       } else {
2460           int i;
2461           if (ic->parmBytes > 3) {
2462               emitcode ("mov", "a,%s", spname);
2463               emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2464               emitcode ("mov", "%s,a", spname);
2465           } else
2466               for (i = 0; i < ic->parmBytes; i++)
2467                   emitcode ("dec", "%s", spname);
2468       }
2469   }
2470
2471   /* if we hade saved some registers then unsave them */
2472   if (ic->regsSaved)
2473     unsaveRegisters (ic);
2474
2475   /* if register bank was saved then pop them */
2476   if (restoreBank)
2477     unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2478 }
2479
2480 /*-----------------------------------------------------------------*/
2481 /* genPcall - generates a call by pointer statement                */
2482 /*-----------------------------------------------------------------*/
2483 static void
2484 genPcall (iCode * ic)
2485 {
2486   sym_link *dtype;
2487   symbol *rlbl = newiTempLabel (NULL);
2488   bool restoreBank=FALSE;
2489
2490   D (emitcode (";", "genPcall ");
2491     );
2492
2493
2494   /* if caller saves & we have not saved then */
2495   if (!ic->regsSaved)
2496     saveRegisters (ic);
2497
2498   /* if we are calling a function that is not using
2499      the same register bank then we need to save the
2500      destination registers on the stack */
2501   dtype = operandType (IC_LEFT (ic));
2502   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2503       IFFUNC_ISISR (currFunc->type) &&
2504       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2505     saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2506     restoreBank=TRUE;
2507   }
2508
2509   /* push the return address on to the stack */
2510   emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
2511   emitcode ("push", "acc");
2512   emitcode ("mov", "a,#!hil", (rlbl->key + 100));
2513   emitcode ("push", "acc");
2514
2515   if (options.model == MODEL_FLAT24)
2516     {
2517       emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
2518       emitcode ("push", "acc");
2519     }
2520
2521   /* now push the calling address */
2522   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2523
2524   pushSide (IC_LEFT (ic), FPTRSIZE);
2525
2526   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2527
2528   /* if send set is not empty the assign */
2529   if (_G.sendSet)
2530     {
2531       iCode *sic;
2532
2533       for (sic = setFirstItem (_G.sendSet); sic;
2534            sic = setNextItem (_G.sendSet))
2535         {
2536           int size, offset = 0;
2537
2538           // we know that dpl(hxb) is the result, so
2539           _startLazyDPSEvaluation ();
2540           size=getSize(operandType(IC_LEFT(sic)));
2541           if (size>1) {
2542             aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2543           } else {
2544             aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2545           }
2546           while (size--)
2547             {
2548               char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2549                                 FALSE, FALSE, TRUE);
2550               if (strcmp (l, fReturn[offset]))
2551                 {
2552                   emitcode ("mov", "%s,%s",
2553                             fReturn[offset],
2554                             l);
2555                 }
2556               offset++;
2557             }
2558           _endLazyDPSEvaluation ();
2559           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2560         }
2561       _G.sendSet = NULL;
2562     }
2563
2564   emitcode ("ret", "");
2565   emitcode ("", "!tlabeldef", (rlbl->key + 100));
2566
2567
2568   /* if we need assign a result value */
2569   if ((IS_ITEMP (IC_RESULT (ic)) &&
2570        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2571         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2572       IS_TRUE_SYMOP (IC_RESULT (ic)))
2573     {
2574
2575       _G.accInUse++;
2576       aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2577       _G.accInUse--;
2578
2579       assignResultValue (IC_RESULT (ic));
2580
2581       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2582     }
2583
2584   /* adjust the stack for parameters if
2585      required */
2586   if (ic->parmBytes)
2587     {
2588       int i;
2589       if (ic->parmBytes > 3)
2590         {
2591           emitcode ("mov", "a,%s", spname);
2592           emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2593           emitcode ("mov", "%s,a", spname);
2594         }
2595       else
2596         for (i = 0; i < ic->parmBytes; i++)
2597           emitcode ("dec", "%s", spname);
2598
2599     }
2600
2601   /* if register bank was saved then unsave them */
2602   if (restoreBank)
2603     unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2604   
2605   /* if we hade saved some registers then
2606      unsave them */
2607   if (ic->regsSaved)
2608     unsaveRegisters (ic);
2609
2610 }
2611
2612 /*-----------------------------------------------------------------*/
2613 /* resultRemat - result  is rematerializable                       */
2614 /*-----------------------------------------------------------------*/
2615 static int
2616 resultRemat (iCode * ic)
2617 {
2618   if (SKIP_IC (ic) || ic->op == IFX)
2619     return 0;
2620
2621   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2622     {
2623       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2624       if (sym->remat && !POINTER_SET (ic))
2625         return 1;
2626     }
2627
2628   return 0;
2629 }
2630
2631 #if defined(__BORLANDC__) || defined(_MSC_VER)
2632 #define STRCASECMP stricmp
2633 #else
2634 #define STRCASECMP strcasecmp
2635 #endif
2636
2637 /*-----------------------------------------------------------------*/
2638 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2639 /*-----------------------------------------------------------------*/
2640 static bool
2641 inExcludeList (char *s)
2642 {
2643   int i = 0;
2644
2645   if (options.excludeRegs[i] &&
2646       STRCASECMP (options.excludeRegs[i], "none") == 0)
2647     return FALSE;
2648
2649   for (i = 0; options.excludeRegs[i]; i++)
2650     {
2651       if (options.excludeRegs[i] &&
2652           STRCASECMP (s, options.excludeRegs[i]) == 0)
2653         return TRUE;
2654     }
2655   return FALSE;
2656 }
2657
2658 /*-----------------------------------------------------------------*/
2659 /* genFunction - generated code for function entry                 */
2660 /*-----------------------------------------------------------------*/
2661 static void
2662 genFunction (iCode * ic)
2663 {
2664   symbol *sym;
2665   sym_link *ftype;
2666   bool   switchedPSW = FALSE;
2667
2668   D (emitcode (";", "genFunction "););
2669
2670   _G.nRegsSaved = 0;
2671   /* create the function header */
2672   emitcode (";", "-----------------------------------------");
2673   emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2674   emitcode (";", "-----------------------------------------");
2675
2676   emitcode ("", "%s:", sym->rname);
2677   ftype = operandType (IC_LEFT (ic));
2678
2679   if (IFFUNC_ISNAKED(ftype))
2680   {
2681       emitcode(";", "naked function: no prologue.");
2682       return;
2683   }
2684   
2685   if (options.stack_probe) 
2686       emitcode ("lcall","__stack_probe");
2687   /* if critical function then turn interrupts off */
2688   if (IFFUNC_ISCRITICAL (ftype))
2689     emitcode ("clr", "ea");
2690
2691   /* here we need to generate the equates for the
2692      register bank if required */
2693   if (FUNC_REGBANK (ftype) != rbank)
2694     {
2695       int i;
2696
2697       rbank = FUNC_REGBANK (ftype);
2698       for (i = 0; i < ds390_nRegs; i++)
2699         {
2700           if (regs390[i].print) {
2701               if (strcmp (regs390[i].base, "0") == 0)
2702                   emitcode ("", "%s !equ !constbyte",
2703                             regs390[i].dname,
2704                             8 * rbank + regs390[i].offset);
2705               else
2706                   emitcode ("", "%s !equ %s + !constbyte",
2707                             regs390[i].dname,
2708                             regs390[i].base,
2709                             8 * rbank + regs390[i].offset);
2710           }
2711         }
2712     }
2713
2714   /* if this is an interrupt service routine then
2715      save acc, b, dpl, dph  */
2716   if (IFFUNC_ISISR (sym->type))
2717     {
2718
2719       if (!inExcludeList ("acc"))
2720         emitcode ("push", "acc");
2721       if (!inExcludeList ("b"))
2722         emitcode ("push", "b");
2723       if (!inExcludeList ("dpl"))
2724         emitcode ("push", "dpl");
2725       if (!inExcludeList ("dph"))
2726         emitcode ("push", "dph");
2727       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2728         {
2729           emitcode ("push", "dpx");
2730           /* Make sure we're using standard DPTR */
2731           emitcode ("push", "dps");
2732           emitcode ("mov", "dps,#0");
2733           if (options.stack10bit)
2734             {
2735               /* This ISR could conceivably use DPTR2. Better save it. */
2736               emitcode ("push", "dpl1");
2737               emitcode ("push", "dph1");
2738               emitcode ("push", "dpx1");
2739               emitcode ("push",  DP2_RESULT_REG);
2740             }
2741         }
2742       /* if this isr has no bank i.e. is going to
2743          run with bank 0 , then we need to save more
2744          registers :-) */
2745       if (!FUNC_REGBANK (sym->type))
2746         {
2747
2748           /* if this function does not call any other
2749              function then we can be economical and
2750              save only those registers that are used */
2751           if (!IFFUNC_HASFCALL(sym->type))
2752             {
2753               int i;
2754
2755               /* if any registers used */
2756               if (sym->regsUsed)
2757                 {
2758                   /* save the registers used */
2759                   for (i = 0; i < sym->regsUsed->size; i++)
2760                     {
2761                       if (bitVectBitValue (sym->regsUsed, i) ||
2762                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2763                         emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2764                     }
2765                 }
2766
2767             }
2768           else
2769             {
2770               /* this function has  a function call cannot
2771                  determines register usage so we will have to push the
2772                  entire bank */
2773               saveRBank (0, ic, FALSE);
2774             }
2775         }
2776         else
2777         {
2778             /* This ISR uses a non-zero bank.
2779              *
2780              * We assume that the bank is available for our
2781              * exclusive use.
2782              *
2783              * However, if this ISR calls a function which uses some
2784              * other bank, we must save that bank entirely.
2785              */
2786             unsigned long banksToSave = 0;
2787             
2788             if (IFFUNC_HASFCALL(sym->type))
2789             {
2790
2791 #define MAX_REGISTER_BANKS 4
2792
2793                 iCode *i;
2794                 int ix;
2795
2796                 for (i = ic; i; i = i->next)
2797                 {
2798                     if (i->op == ENDFUNCTION)
2799                     {
2800                         /* we got to the end OK. */
2801                         break;
2802                     }
2803                     
2804                     if (i->op == CALL)
2805                     {
2806                         sym_link *dtype;
2807                         
2808                         dtype = operandType (IC_LEFT(i));
2809                         if (dtype 
2810                          && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2811                         {
2812                              /* Mark this bank for saving. */
2813                              if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2814                              {
2815                                  werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2816                              }
2817                              else
2818                              {
2819                                  banksToSave |= (1 << FUNC_REGBANK(dtype));
2820                              }
2821                              
2822                              /* And note that we don't need to do it in 
2823                               * genCall.
2824                               */
2825                              i->bankSaved = 1;
2826                         }
2827                     }
2828                     if (i->op == PCALL)
2829                     {
2830                         /* This is a mess; we have no idea what
2831                          * register bank the called function might
2832                          * use.
2833                          *
2834                          * The only thing I can think of to do is
2835                          * throw a warning and hope.
2836                          */
2837                         werror(W_FUNCPTR_IN_USING_ISR);   
2838                     }
2839                 }
2840
2841                 if (banksToSave && options.useXstack)
2842                 {
2843                     /* Since we aren't passing it an ic, 
2844                      * saveRBank will assume r0 is available to abuse.
2845                      *
2846                      * So switch to our (trashable) bank now, so
2847                      * the caller's R0 isn't trashed.
2848                      */
2849                     emitcode ("push", "psw");
2850                     emitcode ("mov", "psw,#!constbyte", 
2851                               (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2852                     switchedPSW = TRUE;
2853                 }
2854                 
2855                 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2856                 {
2857                      if (banksToSave & (1 << ix))
2858                      {
2859                          saveRBank(ix, NULL, FALSE);
2860                      }
2861                 }
2862             }
2863             // jwk: this needs a closer look
2864             SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2865         }
2866     }
2867   else
2868     {
2869       /* if callee-save to be used for this function
2870          then save the registers being used in this function */
2871       if (IFFUNC_CALLEESAVES(sym->type))
2872         {
2873           int i;
2874
2875           /* if any registers used */
2876           if (sym->regsUsed)
2877             {
2878               /* save the registers used */
2879               for (i = 0; i < sym->regsUsed->size; i++)
2880                 {
2881                   if (bitVectBitValue (sym->regsUsed, i) ||
2882                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2883                     {
2884                       emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2885                       _G.nRegsSaved++;
2886                     }
2887                 }
2888             }
2889         }
2890     }
2891
2892   /* set the register bank to the desired value */
2893   if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
2894    && !switchedPSW)
2895     {
2896       emitcode ("push", "psw");
2897       emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2898     }
2899
2900   if ( (IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
2901        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
2902       if (options.stack10bit) {
2903           emitcode ("push","_bpx");
2904           emitcode ("push","_bpx+1");
2905           emitcode ("mov","_bpx,%s",spname);
2906           emitcode ("mov","_bpx+1,esp");
2907           emitcode ("anl","_bpx+1,#3");
2908       } else {
2909           if (options.useXstack) {
2910               emitcode ("mov", "r0,%s", spname);
2911               emitcode ("mov", "a,_bp");
2912               emitcode ("movx", "@r0,a");
2913               emitcode ("inc", "%s", spname);
2914           } else {
2915               /* set up the stack */
2916               emitcode ("push", "_bp"); /* save the callers stack  */
2917           }
2918           emitcode ("mov", "_bp,%s", spname);
2919       }
2920   }
2921
2922   /* adjust the stack for the function */
2923   if (sym->stack) {
2924       int i = sym->stack;
2925       if (options.stack10bit) {
2926           if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);
2927           assert (sym->recvSize <= 4);
2928           emitcode ("mov","a,sp");
2929           emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
2930           emitcode ("mov","sp,a");
2931           emitcode ("mov","a,esp");
2932           emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
2933           emitcode ("mov","esp,a");
2934       } else {
2935           if (i > 256)
2936               werror (W_STACK_OVERFLOW, sym->name);
2937           
2938           if (i > 3 && sym->recvSize < 4) {
2939               
2940               emitcode ("mov", "a,sp");
2941               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
2942               emitcode ("mov", "sp,a");
2943               
2944           } else
2945               while (i--)
2946                   emitcode ("inc", "sp");
2947       }
2948   }
2949
2950   if (sym->xstack)
2951     {
2952
2953       emitcode ("mov", "a,_spx");
2954       emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
2955       emitcode ("mov", "_spx,a");
2956     }
2957
2958 }
2959
2960 /*-----------------------------------------------------------------*/
2961 /* genEndFunction - generates epilogue for functions               */
2962 /*-----------------------------------------------------------------*/
2963 static void
2964 genEndFunction (iCode * ic)
2965 {
2966   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2967
2968   D (emitcode (";", "genEndFunction "););
2969
2970   if (IFFUNC_ISNAKED(sym->type))
2971   {
2972       emitcode(";", "naked function: no epilogue.");
2973       return;
2974   }
2975
2976   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
2977        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
2978
2979       if (options.stack10bit) {
2980           emitcode ("mov", "sp,_bpx", spname);
2981           emitcode ("mov", "esp,_bpx+1", spname);
2982       } else {
2983           emitcode ("mov", "%s,_bp", spname);
2984       }
2985   }
2986
2987   /* if use external stack but some variables were
2988      added to the local stack then decrement the
2989      local stack */
2990   if (options.useXstack && sym->stack) {
2991       emitcode ("mov", "a,sp");
2992       emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
2993       emitcode ("mov", "sp,a");
2994   }
2995
2996
2997   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
2998        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
2999
3000       if (options.useXstack) {
3001           emitcode ("mov", "r0,%s", spname);
3002           emitcode ("movx", "a,@r0");
3003           emitcode ("mov", "_bp,a");
3004           emitcode ("dec", "%s", spname);
3005       } else {
3006           if (options.stack10bit) {
3007               emitcode ("pop", "_bpx+1");
3008               emitcode ("pop", "_bpx");
3009           } else {
3010               emitcode ("pop", "_bp");
3011           }
3012       }
3013   }
3014
3015   /* restore the register bank  */
3016   if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3017   {
3018     if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3019      || !options.useXstack)
3020     {
3021         /* Special case of ISR using non-zero bank with useXstack
3022          * is handled below.
3023          */
3024         emitcode ("pop", "psw");
3025     }
3026   }
3027
3028   if (IFFUNC_ISISR (sym->type))
3029     {
3030
3031       /* now we need to restore the registers */
3032       /* if this isr has no bank i.e. is going to
3033          run with bank 0 , then we need to save more
3034          registers :-) */
3035       if (!FUNC_REGBANK (sym->type))
3036         {
3037           /* if this function does not call any other
3038              function then we can be economical and
3039              save only those registers that are used */
3040           if (!IFFUNC_HASFCALL(sym->type))
3041             {
3042               int i;
3043
3044               /* if any registers used */
3045               if (sym->regsUsed)
3046                 {
3047                   /* save the registers used */
3048                   for (i = sym->regsUsed->size; i >= 0; i--)
3049                     {
3050                       if (bitVectBitValue (sym->regsUsed, i) ||
3051                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3052                         emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3053                     }
3054                 }
3055
3056             }
3057           else
3058             {
3059               /* this function has  a function call cannot
3060                  determines register usage so we will have to pop the
3061                  entire bank */
3062               unsaveRBank (0, ic, FALSE);
3063             }
3064         }
3065         else
3066         {
3067             /* This ISR uses a non-zero bank.
3068              *
3069              * Restore any register banks saved by genFunction
3070              * in reverse order.
3071              */
3072           // jwk: this needs a closer look
3073             unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3074             int ix;
3075           
3076             for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3077             {
3078                 if (savedBanks & (1 << ix))
3079                 {
3080                     unsaveRBank(ix, NULL, FALSE);
3081                 }
3082             }
3083             
3084             if (options.useXstack)
3085             {
3086                 /* Restore bank AFTER calling unsaveRBank,
3087                  * since it can trash r0.
3088                  */
3089                 emitcode ("pop", "psw");
3090             }
3091         }
3092
3093       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3094         {
3095           if (options.stack10bit)
3096             {
3097               emitcode ("pop", DP2_RESULT_REG);
3098               emitcode ("pop", "dpx1");
3099               emitcode ("pop", "dph1");
3100               emitcode ("pop", "dpl1");
3101             }
3102           emitcode ("pop", "dps");
3103           emitcode ("pop", "dpx");
3104         }
3105       if (!inExcludeList ("dph"))
3106         emitcode ("pop", "dph");
3107       if (!inExcludeList ("dpl"))
3108         emitcode ("pop", "dpl");
3109       if (!inExcludeList ("b"))
3110         emitcode ("pop", "b");
3111       if (!inExcludeList ("acc"))
3112         emitcode ("pop", "acc");
3113
3114       if (IFFUNC_ISCRITICAL (sym->type))
3115         emitcode ("setb", "ea");
3116
3117       /* if debug then send end of function */
3118       if (options.debug && currFunc) {
3119           _G.debugLine = 1;
3120           emitcode ("", "C$%s$%d$%d$%d ==.",
3121                     FileBaseName (ic->filename), currFunc->lastLine,
3122                     ic->level, ic->block);
3123           if (IS_STATIC (currFunc->etype))
3124             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3125           else
3126             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3127           _G.debugLine = 0;
3128         }
3129
3130       emitcode ("reti", "");
3131     }
3132   else
3133     {
3134       if (IFFUNC_ISCRITICAL (sym->type))
3135         emitcode ("setb", "ea");
3136
3137       if (IFFUNC_CALLEESAVES(sym->type))
3138         {
3139           int i;
3140
3141           /* if any registers used */
3142           if (sym->regsUsed)
3143             {
3144               /* save the registers used */
3145               for (i = sym->regsUsed->size; i >= 0; i--)
3146                 {
3147                   if (bitVectBitValue (sym->regsUsed, i) ||
3148                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3149                     emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3150                 }
3151             }
3152
3153         }
3154
3155       /* if debug then send end of function */
3156       if (options.debug && currFunc)
3157         {
3158           _G.debugLine = 1;
3159           emitcode ("", "C$%s$%d$%d$%d ==.",
3160                     FileBaseName (ic->filename), currFunc->lastLine,
3161                     ic->level, ic->block);
3162           if (IS_STATIC (currFunc->etype))
3163             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3164           else
3165             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3166           _G.debugLine = 0;
3167         }
3168
3169       emitcode ("ret", "");
3170     }
3171
3172 }
3173
3174 /*-----------------------------------------------------------------*/
3175 /* genJavaNativeRet - generate code for return JavaNative          */
3176 /*-----------------------------------------------------------------*/
3177 static void genJavaNativeRet(iCode *ic)
3178 {
3179     int i, size;
3180
3181     aopOp (IC_LEFT (ic), ic, FALSE, 
3182            (IS_SYMOP(IC_LEFT(ic)) && OP_SYMBOL(IC_LEFT(ic))->ruonly ? FALSE :TRUE));
3183     size = AOP_SIZE (IC_LEFT (ic));
3184
3185     assert (size <= 4);
3186
3187     /* it is assigned to GPR0-R3 then push them */
3188     if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3189         aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3190         for (i = 0 ; i < size ; i++ ) {
3191             emitcode ("push","%s",aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,FALSE));     
3192         }
3193         for (i = (size-1) ; i >= 0 ; i--) {
3194             emitcode ("pop","a%s",javaRet[i]);
3195         }
3196     } else {
3197         for (i = 0 ; i < size ; i++) 
3198             emitcode ("mov","%s,%s",javaRet[i],aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,FALSE));
3199     }
3200     for (i = size ; i < 4 ; i++ )
3201             emitcode ("mov","%s,#0",javaRet[i]);
3202     return;
3203 }
3204
3205 /*-----------------------------------------------------------------*/
3206 /* genRet - generate code for return statement                     */
3207 /*-----------------------------------------------------------------*/
3208 static void
3209 genRet (iCode * ic)
3210 {
3211   int size, offset = 0, pushed = 0;
3212
3213   D (emitcode (";", "genRet ");
3214     );
3215
3216   /* if we have no return value then
3217      just generate the "ret" */
3218   if (!IC_LEFT (ic))
3219     goto jumpret;
3220
3221   /* if this is a JavaNative function then return 
3222      value in different register */
3223   if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3224       genJavaNativeRet(ic);
3225       goto jumpret;
3226   }
3227   /* we have something to return then
3228      move the return value into place */
3229   aopOp (IC_LEFT (ic), ic, FALSE, 
3230          (IS_SYMOP(IC_LEFT(ic)) && OP_SYMBOL(IC_LEFT(ic))->ruonly ? FALSE :TRUE));
3231   size = AOP_SIZE (IC_LEFT (ic));
3232
3233   _startLazyDPSEvaluation ();
3234   while (size--)
3235     {
3236       char *l;
3237       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3238         {
3239           l = aopGet (AOP (IC_LEFT (ic)), offset++,
3240                       FALSE, TRUE, FALSE);
3241           emitcode ("push", "%s", l);
3242           pushed++;
3243         }
3244       else
3245         {
3246           /* Since A is the last element of fReturn,
3247            * is is OK to clobber it in the aopGet.
3248            */
3249           l = aopGet (AOP (IC_LEFT (ic)), offset,
3250                       FALSE, FALSE, TRUE);
3251           if (strcmp (fReturn[offset], l))
3252             emitcode ("mov", "%s,%s", fReturn[offset++], l);
3253         }
3254     }
3255   _endLazyDPSEvaluation ();
3256
3257   if (pushed)
3258     {
3259       while (pushed)
3260         {
3261           pushed--;
3262           if (strcmp (fReturn[pushed], "a"))
3263             emitcode ("pop", fReturn[pushed]);
3264           else
3265             emitcode ("pop", "acc");
3266         }
3267     }
3268   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3269
3270 jumpret:
3271   /* generate a jump to the return label
3272      if the next is not the return statement */
3273   if (!(ic->next && ic->next->op == LABEL &&
3274         IC_LABEL (ic->next) == returnLabel))
3275
3276     emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3277
3278 }
3279
3280 /*-----------------------------------------------------------------*/
3281 /* genLabel - generates a label                                    */
3282 /*-----------------------------------------------------------------*/
3283 static void
3284 genLabel (iCode * ic)
3285 {
3286   /* special case never generate */
3287   if (IC_LABEL (ic) == entryLabel)
3288     return;
3289
3290   D (emitcode (";", "genLabel ");
3291     );
3292
3293   emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3294 }
3295
3296 /*-----------------------------------------------------------------*/
3297 /* genGoto - generates a ljmp                                      */
3298 /*-----------------------------------------------------------------*/
3299 static void
3300 genGoto (iCode * ic)
3301 {
3302   D (emitcode (";", "genGoto ");
3303     );
3304   emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3305 }
3306
3307 /*-----------------------------------------------------------------*/
3308 /* findLabelBackwards: walks back through the iCode chain looking  */
3309 /* for the given label. Returns number of iCode instructions     */
3310 /* between that label and given ic.          */
3311 /* Returns zero if label not found.          */
3312 /*-----------------------------------------------------------------*/
3313 static int
3314 findLabelBackwards (iCode * ic, int key)
3315 {
3316   int count = 0;
3317
3318   while (ic->prev)
3319     {
3320       ic = ic->prev;
3321       count++;
3322
3323       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3324         {
3325           /* printf("findLabelBackwards = %d\n", count); */
3326           return count;
3327         }
3328     }
3329
3330   return 0;
3331 }
3332
3333 /*-----------------------------------------------------------------*/
3334 /* genPlusIncr :- does addition with increment if possible         */
3335 /*-----------------------------------------------------------------*/
3336 static bool
3337 genPlusIncr (iCode * ic)
3338 {
3339   unsigned int icount;
3340   unsigned int size = getDataSize (IC_RESULT (ic));
3341
3342   /* will try to generate an increment */
3343   /* if the right side is not a literal
3344      we cannot */
3345   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3346     return FALSE;
3347
3348   /* if the literal value of the right hand side
3349      is greater than 4 then it is not worth it */
3350   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3351     return FALSE;
3352
3353   /* if increment 16 bits in register */
3354   if (
3355        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3356        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3357        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3358        (size > 1) &&
3359        (icount == 1))
3360     {
3361       symbol *tlbl;
3362       int emitTlbl;
3363       int labelRange;
3364
3365       /* If the next instruction is a goto and the goto target
3366        * is <= 5 instructions previous to this, we can generate
3367        * jumps straight to that target.
3368        */
3369       if (ic->next && ic->next->op == GOTO
3370           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3371           && labelRange <= 5)
3372         {
3373           emitcode (";", "tail increment optimized (range %d)", labelRange);
3374           tlbl = IC_LABEL (ic->next);
3375           emitTlbl = 0;
3376         }
3377       else
3378         {
3379           tlbl = newiTempLabel (NULL);
3380           emitTlbl = 1;
3381         }
3382       emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3383       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3384           IS_AOP_PREG (IC_RESULT (ic)))
3385         emitcode ("cjne", "%s,#0,!tlabel"
3386                   ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3387                   ,tlbl->key + 100);
3388       else
3389         {
3390           emitcode ("clr", "a");
3391           emitcode ("cjne", "a,%s,!tlabel"
3392                     ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3393                     ,tlbl->key + 100);
3394         }
3395
3396       emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3397       if (size > 2)
3398         {
3399           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3400               IS_AOP_PREG (IC_RESULT (ic)))
3401             emitcode ("cjne", "%s,#0,!tlabel"
3402                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3403                       ,tlbl->key + 100);
3404           else
3405             emitcode ("cjne", "a,%s,!tlabel"
3406                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3407                       ,tlbl->key + 100);
3408
3409           emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3410         }
3411       if (size > 3)
3412         {
3413           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3414               IS_AOP_PREG (IC_RESULT (ic)))
3415             emitcode ("cjne", "%s,#0,!tlabel"
3416                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3417                       ,tlbl->key + 100);
3418           else
3419             {
3420               emitcode ("cjne", "a,%s,!tlabel"
3421                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3422                         ,tlbl->key + 100);
3423             }
3424           emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3425         }
3426
3427       if (emitTlbl)
3428         {
3429           emitcode ("", "!tlabeldef", tlbl->key + 100);
3430         }
3431       return TRUE;
3432     }
3433
3434   /* if the sizes are greater than 1 then we cannot */
3435   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3436       AOP_SIZE (IC_LEFT (ic)) > 1)
3437     return FALSE;
3438
3439   /* we can if the aops of the left & result match or
3440      if they are in registers and the registers are the
3441      same */
3442   if (
3443        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3444        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3445        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3446     {
3447
3448       if (icount > 3)
3449         {
3450           MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3451           emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3452           aopPut (AOP (IC_RESULT (ic)), "a", 0);
3453         }
3454       else
3455         {
3456
3457           _startLazyDPSEvaluation ();
3458           while (icount--)
3459             {
3460               emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3461             }
3462           _endLazyDPSEvaluation ();
3463         }
3464
3465       return TRUE;
3466     }
3467
3468   return FALSE;
3469 }
3470
3471 /*-----------------------------------------------------------------*/
3472 /* outBitAcc - output a bit in acc                                 */
3473 /*-----------------------------------------------------------------*/
3474 static void
3475 outBitAcc (operand * result)
3476 {
3477   symbol *tlbl = newiTempLabel (NULL);
3478   /* if the result is a bit */
3479   if (AOP_TYPE (result) == AOP_CRY)
3480     {
3481       aopPut (AOP (result), "a", 0);
3482     }
3483   else
3484     {
3485       emitcode ("jz", "!tlabel", tlbl->key + 100);
3486       emitcode ("mov", "a,%s", one);
3487       emitcode ("", "!tlabeldef", tlbl->key + 100);
3488       outAcc (result);
3489     }
3490 }
3491
3492 /*-----------------------------------------------------------------*/
3493 /* genPlusBits - generates code for addition of two bits           */
3494 /*-----------------------------------------------------------------*/
3495 static void
3496 genPlusBits (iCode * ic)
3497 {
3498   D (emitcode (";", "genPlusBits ");
3499     );
3500   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3501     {
3502       symbol *lbl = newiTempLabel (NULL);
3503       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3504       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3505       emitcode ("cpl", "c");
3506       emitcode ("", "!tlabeldef", (lbl->key + 100));
3507       outBitC (IC_RESULT (ic));
3508     }
3509   else
3510     {
3511       emitcode ("clr", "a");
3512       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3513       emitcode ("rlc", "a");
3514       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3515       emitcode ("addc", "a,#0");
3516       outAcc (IC_RESULT (ic));
3517     }
3518 }
3519
3520 static void
3521 adjustArithmeticResult (iCode * ic)
3522 {
3523   if (opIsGptr (IC_RESULT (ic)) &&
3524       opIsGptr (IC_LEFT (ic)) &&
3525       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3526     {
3527       aopPut (AOP (IC_RESULT (ic)),
3528               aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3529               GPTRSIZE - 1);
3530     }
3531
3532   if (opIsGptr (IC_RESULT (ic)) &&
3533       opIsGptr (IC_RIGHT (ic)) &&
3534       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3535     {
3536       aopPut (AOP (IC_RESULT (ic)),
3537             aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3538               GPTRSIZE - 1);
3539     }
3540
3541   if (opIsGptr (IC_RESULT (ic)) &&
3542       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3543       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3544       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3545       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3546     {
3547       char buffer[5];
3548       sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3549       aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3550     }
3551 }
3552
3553 #if 0 // AOP_OP_3 is deprecated; nobody likes Ack errors.
3554       // Please don't bring it back without a really good reason.
3555 // Macro to aopOp all three operands of an ic. Will fatal if this cannot be done
3556 // (because all three operands are in far space).
3557 #define AOP_OP_3(ic) \
3558     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3559     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3560     aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3561               (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3562     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3563         AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3564     { \
3565         /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3566         fprintf(stderr,                                  \
3567                "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno);   \
3568     }
3569 #endif
3570
3571 // Macro to aopOp all three operands of an ic. If this cannot be done, 
3572 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3573 // will be set TRUE. The caller must then handle the case specially, noting
3574 // that the IC_RESULT operand is not aopOp'd.
3575 #define AOP_OP_3_NOFATAL(ic, rc) \
3576     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3577     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR) || \
3578                                   (OP_SYMBOL(IC_RESULT(ic))->ruonly)); \
3579     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3580         (isOperandInFarSpace(IC_RESULT(ic)) || OP_SYMBOL(IC_RESULT(ic))->ruonly )) \
3581     { \
3582        /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3583        rc = TRUE; \
3584     }  \
3585     else \
3586     { \
3587        aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3588                                      (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3589        rc = FALSE; \
3590        if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3591            AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3592        { \
3593             /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3594             fprintf(stderr,                                  \
3595                     "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno);   \
3596        } \
3597     }
3598
3599 // aopOp the left & right operands of an ic.
3600 #define AOP_OP_2(ic) \
3601     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3602     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3603
3604 // convienience macro.
3605 #define AOP_SET_LOCALS(ic) \
3606     left = IC_LEFT(ic); \
3607     right = IC_RIGHT(ic); \
3608     result = IC_RESULT(ic);
3609
3610
3611 // Given an integer value of pushedSize bytes on the stack,
3612 // adjust it to be resultSize bytes, either by discarding
3613 // the most significant bytes or by zero-padding.
3614 //
3615 // On exit from this macro, pushedSize will have been adjusted to
3616 // equal resultSize, and ACC may be trashed.
3617 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize)            \
3618       /* If the pushed data is bigger than the result,          \
3619        * simply discard unused bytes. Icky, but works.          \
3620        */                                                       \
3621       while (pushedSize > resultSize)                           \
3622       {                                                         \
3623           D (emitcode (";", "discarding unused result byte."););\
3624           emitcode ("pop", "acc");                              \
3625           pushedSize--;                                         \
3626       }                                                         \
3627       if (pushedSize < resultSize)                              \
3628       {                                                         \
3629           emitcode ("clr", "a");                                \
3630           /* Conversly, we haven't pushed enough here.          \
3631            * just zero-pad, and all is well.                    \
3632            */                                                   \
3633           while (pushedSize < resultSize)                       \
3634           {                                                     \
3635               emitcode("push", "acc");                          \
3636               pushedSize++;                                     \
3637           }                                                     \
3638       }                                                         \
3639       assert(pushedSize == resultSize);
3640
3641 /*-----------------------------------------------------------------*/
3642 /* genPlus - generates code for addition                           */
3643 /*-----------------------------------------------------------------*/
3644 static void
3645 genPlus (iCode * ic)
3646 {
3647   int size, offset = 0;
3648   bool pushResult = FALSE;
3649   int rSize;
3650
3651   D (emitcode (";", "genPlus "););
3652
3653   /* special cases :- */
3654   if ( IS_SYMOP(IC_LEFT(ic)) && OP_SYMBOL(IC_LEFT(ic))->ruonly &&
3655       isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
3656       aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
3657       size = floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
3658       if (size <= 9) {
3659           while (size--) emitcode ("inc","dptr");
3660       } else {
3661           emitcode ("mov","a,dpl");
3662           emitcode ("add","a,#!constbyte",size & 0xff);
3663           emitcode ("mov","dpl,a");
3664           emitcode ("mov","a,dph");
3665           emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
3666           emitcode ("mov","dph,a");
3667           emitcode ("mov","a,dpx");
3668           emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
3669           emitcode ("mov","dpx,a");
3670       }
3671       freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
3672       return ;
3673   }
3674   if ( IS_SYMOP(IC_LEFT(ic)) && 
3675        OP_SYMBOL(IC_LEFT(ic))->remat &&
3676        isOperandInFarSpace(IC_RIGHT(ic))) {
3677       operand *op = IC_RIGHT(ic);
3678       IC_RIGHT(ic) = IC_LEFT(ic);
3679       IC_LEFT(ic) = op;
3680   }
3681                 
3682   AOP_OP_3_NOFATAL (ic, pushResult);
3683   if (pushResult)
3684     {
3685       D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3686     }
3687
3688   if (!pushResult)
3689     {
3690       /* if literal, literal on the right or
3691          if left requires ACC or right is already
3692          in ACC */
3693       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3694        || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3695           || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3696         {
3697           operand *t = IC_RIGHT (ic);
3698           IC_RIGHT (ic) = IC_LEFT (ic);
3699           IC_LEFT (ic) = t;
3700           emitcode (";", "Swapped plus args.");
3701         }
3702
3703       /* if both left & right are in bit
3704          space */
3705       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3706           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3707         {
3708           genPlusBits (ic);
3709           goto release;
3710         }
3711
3712       /* if left in bit space & right literal */
3713       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3714           AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3715         {
3716           emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3717           /* if result in bit space */
3718           if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3719             {
3720               if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3721                 emitcode ("cpl", "c");
3722               outBitC (IC_RESULT (ic));
3723             }
3724           else
3725             {
3726               size = getDataSize (IC_RESULT (ic));
3727               _startLazyDPSEvaluation ();
3728               while (size--)
3729                 {
3730                   MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3731                   emitcode ("addc", "a,#0");
3732                   aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3733                 }
3734               _endLazyDPSEvaluation ();
3735             }
3736           goto release;
3737         }
3738
3739       /* if I can do an increment instead
3740          of add then GOOD for ME */
3741       if (genPlusIncr (ic) == TRUE)
3742         {
3743           emitcode (";", "did genPlusIncr");
3744           goto release;
3745         }
3746
3747     }
3748   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3749
3750   _startLazyDPSEvaluation ();
3751   while (size--)
3752     {
3753       if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
3754         {
3755           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3756           if (offset == 0)
3757             emitcode ("add", "a,%s",
3758                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3759           else
3760             emitcode ("addc", "a,%s",
3761                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3762         }
3763       else
3764         {
3765           if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
3766           {
3767               /* right is going to use ACC or we would have taken the
3768                * above branch.
3769                */
3770               assert(AOP_NEEDSACC(IC_RIGHT(ic)));
3771        TR_AP("#3");
3772               D(emitcode(";", "+ AOP_ACC special case."););
3773               emitcode("xch", "a, %s", DP2_RESULT_REG);
3774           }
3775           MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3776           if (offset == 0)
3777           {
3778             if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
3779             {
3780          TR_AP("#4");
3781                 emitcode("add", "a, %s", DP2_RESULT_REG); 
3782             }
3783             else
3784             {
3785                 emitcode ("add", "a,%s",
3786                         aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE, FALSE));
3787             }
3788           }
3789           else
3790           {
3791             emitcode ("addc", "a,%s",
3792                   aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3793           }
3794         }
3795       if (!pushResult)
3796         {
3797           aopPut (AOP (IC_RESULT (ic)), "a", offset);
3798         }
3799       else
3800         {
3801           emitcode ("push", "acc");
3802         }
3803       offset++;
3804     }
3805   _endLazyDPSEvaluation ();
3806
3807   if (pushResult)
3808     {
3809       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3810
3811       size = getDataSize (IC_LEFT (ic));
3812       rSize = getDataSize (IC_RESULT (ic));
3813
3814       ADJUST_PUSHED_RESULT(size, rSize);
3815
3816       _startLazyDPSEvaluation ();
3817       while (size--)
3818         {
3819           emitcode ("pop", "acc");
3820           aopPut (AOP (IC_RESULT (ic)), "a", size);
3821         }
3822       _endLazyDPSEvaluation ();
3823     }
3824
3825   adjustArithmeticResult (ic);
3826
3827 release:
3828   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3829   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3830   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3831 }
3832
3833 /*-----------------------------------------------------------------*/
3834 /* genMinusDec :- does subtraction with deccrement if possible     */
3835 /*-----------------------------------------------------------------*/
3836 static bool
3837 genMinusDec (iCode * ic)
3838 {
3839   unsigned int icount;
3840   unsigned int size = getDataSize (IC_RESULT (ic));
3841
3842   /* will try to generate an increment */
3843   /* if the right side is not a literal
3844      we cannot */
3845   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3846     return FALSE;
3847
3848   /* if the literal value of the right hand side
3849      is greater than 4 then it is not worth it */
3850   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3851     return FALSE;
3852
3853   /* if decrement 16 bits in register */
3854   if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3855       AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3856       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3857       (size > 1) &&
3858       (icount == 1))
3859     {
3860       symbol *tlbl;
3861       int emitTlbl;
3862       int labelRange;
3863
3864       /* If the next instruction is a goto and the goto target
3865          * is <= 5 instructions previous to this, we can generate
3866          * jumps straight to that target.
3867        */
3868       if (ic->next && ic->next->op == GOTO
3869           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3870           && labelRange <= 5)
3871         {
3872           emitcode (";", "tail decrement optimized (range %d)", labelRange);
3873           tlbl = IC_LABEL (ic->next);
3874           emitTlbl = 0;
3875         }
3876       else
3877         {
3878           tlbl = newiTempLabel (NULL);
3879           emitTlbl = 1;
3880         }
3881
3882       emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3883       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3884           AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3885           IS_AOP_PREG (IC_RESULT (ic)))
3886         emitcode ("cjne", "%s,#!constbyte,!tlabel"
3887                   ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE), 0xff
3888                   ,tlbl->key + 100);
3889       else
3890         {
3891           emitcode ("mov", "a,#!constbyte",0xff);
3892           emitcode ("cjne", "a,%s,!tlabel"
3893                     ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3894                     ,tlbl->key + 100);
3895         }
3896       emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3897       if (size > 2)
3898         {
3899           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3900               AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3901               IS_AOP_PREG (IC_RESULT (ic)))
3902             emitcode ("cjne", "%s,#!constbyte,!tlabel"
3903                       ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE),0xff
3904                       ,tlbl->key + 100);
3905           else
3906             {
3907               emitcode ("cjne", "a,%s,!tlabel"
3908                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3909                         ,tlbl->key + 100);
3910             }
3911           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3912         }
3913       if (size > 3)
3914         {
3915           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3916               AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3917               IS_AOP_PREG (IC_RESULT (ic)))
3918             emitcode ("cjne", "%s,#!constbyte,!tlabel"
3919                       ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE),0xff
3920                       ,tlbl->key + 100);
3921           else
3922             {
3923               emitcode ("cjne", "a,%s,!tlabel"
3924                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3925                         ,tlbl->key + 100);
3926             }
3927           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3928         }
3929       if (emitTlbl)
3930         {
3931           emitcode ("", "!tlabeldef", tlbl->key + 100);
3932         }
3933       return TRUE;
3934     }
3935
3936   /* if the sizes are greater than 1 then we cannot */
3937   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3938       AOP_SIZE (IC_LEFT (ic)) > 1)
3939     return FALSE;
3940
3941   /* we can if the aops of the left & result match or
3942      if they are in registers and the registers are the
3943      same */
3944   if (
3945        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3946        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3947        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3948     {
3949
3950       _startLazyDPSEvaluation ();
3951       while (icount--)
3952         {
3953           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
3954         }
3955       _endLazyDPSEvaluation ();
3956
3957       return TRUE;
3958     }
3959
3960   return FALSE;
3961 }
3962
3963 /*-----------------------------------------------------------------*/
3964 /* addSign - complete with sign                                    */
3965 /*-----------------------------------------------------------------*/
3966 static void
3967 addSign (operand * result, int offset, int sign)
3968 {
3969   int size = (getDataSize (result) - offset);
3970   if (size > 0)
3971     {
3972       _startLazyDPSEvaluation();
3973       if (sign)
3974         {
3975           emitcode ("rlc", "a");
3976           emitcode ("subb", "a,acc");
3977           while (size--)
3978           {
3979             aopPut (AOP (result), "a", offset++);
3980           }
3981         }
3982       else
3983       {
3984         while (size--)
3985         {
3986           aopPut (AOP (result), zero, offset++);
3987         }
3988       }
3989       _endLazyDPSEvaluation();
3990     }
3991 }
3992
3993 /*-----------------------------------------------------------------*/
3994 /* genMinusBits - generates code for subtraction  of two bits      */
3995 /*-----------------------------------------------------------------*/
3996 static void
3997 genMinusBits (iCode * ic)
3998 {
3999   symbol *lbl = newiTempLabel (NULL);
4000
4001   D (emitcode (";", "genMinusBits "););
4002
4003   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4004     {
4005       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4006       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4007       emitcode ("cpl", "c");
4008       emitcode ("", "!tlabeldef", (lbl->key + 100));
4009       outBitC (IC_RESULT (ic));
4010     }
4011   else
4012     {
4013       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4014       emitcode ("subb", "a,acc");
4015       emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4016       emitcode ("inc", "a");
4017       emitcode ("", "!tlabeldef", (lbl->key + 100));
4018       aopPut (AOP (IC_RESULT (ic)), "a", 0);
4019       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4020     }
4021 }
4022
4023 /*-----------------------------------------------------------------*/
4024 /* genMinus - generates code for subtraction                       */
4025 /*-----------------------------------------------------------------*/
4026 static void
4027 genMinus (iCode * ic)
4028 {
4029   int size, offset = 0;
4030   int rSize;
4031   unsigned long lit = 0L;
4032   bool pushResult = FALSE;
4033
4034   D (emitcode (";", "genMinus "););
4035
4036   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
4037   aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
4038   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
4039       (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
4040     {
4041       pushResult = TRUE;
4042     }
4043   else
4044     {
4045       aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
4046
4047       /* special cases :- */
4048       /* if both left & right are in bit space */
4049       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4050           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4051         {
4052           genMinusBits (ic);
4053           goto release;
4054         }
4055
4056       /* if I can do an decrement instead
4057          of subtract then GOOD for ME */
4058       if (genMinusDec (ic) == TRUE)
4059         goto release;
4060
4061     }
4062
4063   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4064
4065   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4066     {
4067       CLRC;
4068     }
4069   else
4070     {
4071       lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4072       lit = -(long) lit;
4073     }
4074
4075
4076   /* if literal, add a,#-lit, else normal subb */
4077   _startLazyDPSEvaluation ();
4078   while (size--)
4079     {
4080       MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
4081       if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4082         emitcode ("subb", "a,%s",
4083                   aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
4084       else
4085         {
4086           /* first add without previous c */
4087           if (!offset) {
4088             if (!size && lit==-1) {
4089               emitcode ("dec", "a");
4090             } else {
4091               emitcode ("add", "a,#!constbyte",
4092                         (unsigned int) (lit & 0x0FFL));
4093             }
4094           } else {
4095             emitcode ("addc", "a,#!constbyte",
4096                       (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4097           }
4098         }
4099
4100       if (pushResult)
4101         {
4102           emitcode ("push", "acc");
4103         }
4104       else
4105         {
4106           aopPut (AOP (IC_RESULT (ic)), "a", offset);
4107         }
4108       offset++;
4109     }
4110   _endLazyDPSEvaluation ();
4111
4112   if (pushResult)
4113     {
4114       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4115
4116       size = getDataSize (IC_LEFT (ic));
4117       rSize = getDataSize (IC_RESULT (ic));
4118
4119       ADJUST_PUSHED_RESULT(size, rSize);
4120
4121       _startLazyDPSEvaluation ();
4122       while (size--)
4123         {
4124           emitcode ("pop", "acc");
4125           aopPut (AOP (IC_RESULT (ic)), "a", size);
4126         }
4127       _endLazyDPSEvaluation ();
4128     }
4129
4130   adjustArithmeticResult (ic);
4131
4132 release:
4133   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4134   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4135   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4136 }
4137
4138
4139 /*-----------------------------------------------------------------*/
4140 /* genMultbits :- multiplication of bits                           */
4141 /*-----------------------------------------------------------------*/
4142 static void
4143 genMultbits (operand * left,
4144              operand * right,
4145              operand * result,
4146              iCode   * ic)
4147 {
4148   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4149   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4150   aopOp(result, ic, TRUE, FALSE);
4151   outBitC (result);
4152 }
4153
4154
4155 /*-----------------------------------------------------------------*/
4156 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
4157 /*-----------------------------------------------------------------*/
4158 static void
4159 genMultOneByte (operand * left,
4160                 operand * right,
4161                 operand * result,
4162                 iCode   * ic)
4163 {
4164   sym_link *opetype = operandType (result);
4165   symbol *lbl;
4166
4167
4168   /* (if two literals: the value is computed before) */
4169   /* if one literal, literal on the right */
4170   if (AOP_TYPE (left) == AOP_LIT)
4171     {
4172       operand *t = right;
4173       right = left;
4174       left = t;
4175       emitcode (";", "swapped left and right");
4176     }
4177
4178   if (SPEC_USIGN(opetype)
4179       // ignore the sign of left and right, what else can we do?
4180       || (SPEC_USIGN(operandType(left)) && 
4181           SPEC_USIGN(operandType(right)))) {
4182     // just an unsigned 8*8=8/16 multiply
4183     //emitcode (";","unsigned");
4184     emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4185     MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4186     emitcode ("mul", "ab");
4187    
4188     _G.accInUse++; _G.bInUse++;
4189     aopOp(result, ic, TRUE, FALSE);
4190       
4191       if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4192       {
4193           // this should never happen
4194           fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4195                    AOP_SIZE(result), __FILE__, lineno);
4196           exit (1);
4197       }      
4198       
4199     aopPut (AOP (result), "a", 0);
4200     _G.accInUse--; _G.bInUse--;
4201     if (AOP_SIZE(result)==2) 
4202     {
4203       aopPut (AOP (result), "b", 1);
4204     }
4205     return;
4206   }
4207
4208   // we have to do a signed multiply
4209
4210   emitcode (";", "signed");
4211   emitcode ("clr", "F0"); // reset sign flag
4212   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4213
4214   lbl=newiTempLabel(NULL);
4215   emitcode ("jnb", "acc.7,!tlabel",  lbl->key+100);
4216   // left side is negative, 8-bit two's complement, this fails for -128
4217   emitcode ("setb", "F0"); // set sign flag
4218   emitcode ("cpl", "a");
4219   emitcode ("inc", "a");
4220
4221   emitcode ("", "!tlabeldef", lbl->key+100);
4222
4223   /* if literal */
4224   if (AOP_TYPE(right)==AOP_LIT) {
4225     signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
4226     /* AND literal negative */
4227     if ((int) val < 0) {
4228       emitcode ("cpl", "F0"); // complement sign flag
4229       emitcode ("mov", "b,#!constbyte", -val);
4230     } else {
4231       emitcode ("mov", "b,#!constbyte", val);
4232     }
4233   } else {
4234     lbl=newiTempLabel(NULL);
4235     emitcode ("mov", "b,a");
4236     emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4237     emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4238     // right side is negative, 8-bit two's complement
4239     emitcode ("cpl", "F0"); // complement sign flag
4240     emitcode ("cpl", "a");
4241     emitcode ("inc", "a");
4242     emitcode ("", "!tlabeldef", lbl->key+100);
4243   }
4244   emitcode ("mul", "ab");
4245     
4246   _G.accInUse++;_G.bInUse++;
4247   aopOp(result, ic, TRUE, FALSE);
4248     
4249   if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4250   {
4251     // this should never happen
4252       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4253                AOP_SIZE(result), __FILE__, lineno);
4254       exit (1);
4255   }    
4256     
4257   lbl=newiTempLabel(NULL);
4258   emitcode ("jnb", "F0,!tlabel", lbl->key+100);
4259   // only ONE op was negative, we have to do a 8/16-bit two's complement
4260   emitcode ("cpl", "a"); // lsb
4261   if (AOP_SIZE(result)==1) {
4262     emitcode ("inc", "a");
4263   } else {
4264     emitcode ("add", "a,#1");
4265     emitcode ("xch", "a,b");
4266     emitcode ("cpl", "a"); // msb
4267     emitcode ("addc", "a,#0");
4268     emitcode ("xch", "a,b");
4269   }
4270
4271   emitcode ("", "!tlabeldef", lbl->key+100);
4272   aopPut (AOP (result), "a", 0);
4273   _G.accInUse--;_G.bInUse--;
4274   if (AOP_SIZE(result)==2) {
4275     aopPut (AOP (result), "b", 1);
4276   }
4277 }
4278
4279 /*-----------------------------------------------------------------*/
4280 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply    */
4281 /*-----------------------------------------------------------------*/
4282 static void genMultTwoByte (operand *left, operand *right, 
4283                             operand *result, iCode *ic)
4284 {
4285         sym_link *retype = getSpec(operandType(right));
4286         sym_link *letype = getSpec(operandType(left));
4287         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4288         symbol *lbl;
4289
4290         if (AOP_TYPE (left) == AOP_LIT) {
4291                 operand *t = right;
4292                 right = left;
4293                 left = t;
4294         }
4295         /* save EA bit in F1 */
4296         lbl = newiTempLabel(NULL);
4297         emitcode ("setb","F1");
4298         emitcode ("jbc","EA,!tlabel",lbl->key+100);
4299         emitcode ("clr","F1");
4300         emitcode("","!tlabeldef",lbl->key+100);
4301
4302         /* load up MB with right */
4303         if (!umult) {
4304                 emitcode("clr","F0");
4305                 if (AOP_TYPE(right) == AOP_LIT) {
4306                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
4307                         if (val < 0) {
4308                                 emitcode("setb","F0");
4309                                 val = -val;
4310                         }
4311                         emitcode ("mov","mb,#!constbyte",val & 0xff);
4312                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
4313                 } else {
4314                         lbl = newiTempLabel(NULL);
4315                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4316                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4317                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
4318                         emitcode ("xch", "a,b");
4319                         emitcode ("cpl","a");
4320                         emitcode ("add", "a,#1");
4321                         emitcode ("xch", "a,b");
4322                         emitcode ("cpl", "a"); // msb
4323                         emitcode ("addc", "a,#0");
4324                         emitcode ("setb","F0");
4325                         emitcode ("","!tlabeldef",lbl->key+100);
4326                         emitcode ("mov","mb,b");
4327                         emitcode ("mov","mb,a");
4328                 }
4329         } else {
4330                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4331                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4332         }
4333         /* load up MA with left */
4334         if (!umult) {
4335                 lbl = newiTempLabel(NULL);
4336                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4337                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4338                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4339                 emitcode ("xch", "a,b");
4340                 emitcode ("cpl","a");
4341                 emitcode ("add", "a,#1");
4342                 emitcode ("xch", "a,b");
4343                 emitcode ("cpl", "a"); // msb
4344                 emitcode ("addc","a,#0");
4345                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4346                 emitcode ("setb","F0");
4347                 emitcode ("","!tlabeldef",lbl->key+100);
4348                 emitcode ("mov","ma,b");
4349                 emitcode ("mov","ma,a");
4350         } else {
4351                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4352                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4353         }
4354         /* wait for multiplication to finish */
4355         lbl = newiTempLabel(NULL);
4356         emitcode("","!tlabeldef", lbl->key+100);
4357         emitcode("mov","a,mcnt1");
4358         emitcode("anl","a,#!constbyte",0x80);
4359         emitcode("jnz","!tlabel",lbl->key+100);
4360         
4361         freeAsmop (left, NULL, ic, TRUE);
4362         freeAsmop (right, NULL, ic,TRUE);
4363         aopOp(result, ic, TRUE, FALSE);
4364
4365         /* if unsigned then simple */   
4366         if (umult) {
4367                 emitcode ("mov","a,ma");
4368                 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4369                 emitcode ("mov","a,ma");
4370                 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4371                 aopPut(AOP(result),"ma",1);
4372                 aopPut(AOP(result),"ma",0);
4373         } else {
4374                 emitcode("push","ma");
4375                 emitcode("push","ma");
4376                 emitcode("push","ma");
4377                 MOVA("ma");
4378                 /* negate result if needed */
4379                 lbl = newiTempLabel(NULL);      
4380                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4381                 emitcode("cpl","a");
4382                 emitcode("add","a,#1");
4383                 emitcode("","!tlabeldef", lbl->key+100);
4384                 if (AOP_TYPE(result) == AOP_ACC)
4385                 {
4386                     D(emitcode(";", "ACC special case."););
4387                     /* We know result is the only live aop, and 
4388                      * it's obviously not a DPTR2, so AP is available.
4389                      */
4390                     emitcode("mov", "%s,acc", DP2_RESULT_REG);
4391                 }
4392                 else
4393                 {
4394                     aopPut(AOP(result),"a",0);
4395                 }
4396             
4397                 emitcode("pop","acc");
4398                 lbl = newiTempLabel(NULL);      
4399                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4400                 emitcode("cpl","a");
4401                 emitcode("addc","a,#0");
4402                 emitcode("","!tlabeldef", lbl->key+100);
4403                 aopPut(AOP(result),"a",1);
4404                 emitcode("pop","acc");
4405                 if (AOP_SIZE(result) >= 3) {
4406                         lbl = newiTempLabel(NULL);      
4407                         emitcode("jnb","F0,!tlabel",lbl->key+100);
4408                         emitcode("cpl","a");
4409                         emitcode("addc","a,#0");                        
4410                         emitcode("","!tlabeldef", lbl->key+100);
4411                         aopPut(AOP(result),"a",2);
4412                 }
4413                 emitcode("pop","acc");
4414                 if (AOP_SIZE(result) >= 4) {
4415                         lbl = newiTempLabel(NULL);      
4416                         emitcode("jnb","F0,!tlabel",lbl->key+100);
4417                         emitcode("cpl","a");
4418                         emitcode("addc","a,#0");                        
4419                         emitcode("","!tlabeldef", lbl->key+100);
4420                         aopPut(AOP(result),"a",3);
4421                 }
4422                 if (AOP_TYPE(result) == AOP_ACC)
4423                 {
4424                     /* We stashed the result away above. */
4425                     emitcode("mov", "acc,%s", DP2_RESULT_REG);
4426                 }           
4427                 
4428         }
4429         freeAsmop (result, NULL, ic, TRUE);
4430
4431         /* restore EA bit in F1 */
4432         lbl = newiTempLabel(NULL);
4433         emitcode ("jnb","F1,!tlabel",lbl->key+100);
4434         emitcode ("setb","EA");
4435         emitcode("","!tlabeldef",lbl->key+100);
4436         return ;
4437 }
4438
4439 /*-----------------------------------------------------------------*/
4440 /* genMult - generates code for multiplication                     */
4441 /*-----------------------------------------------------------------*/
4442 static void
4443 genMult (iCode * ic)
4444 {
4445   operand *left = IC_LEFT (ic);
4446   operand *right = IC_RIGHT (ic);
4447   operand *result = IC_RESULT (ic);
4448
4449   D (emitcode (";", "genMult "););
4450
4451   /* assign the amsops */
4452   AOP_OP_2 (ic);
4453
4454   /* special cases first */
4455   /* both are bits */
4456   if (AOP_TYPE (left) == AOP_CRY &&
4457       AOP_TYPE (right) == AOP_CRY)
4458     {
4459       genMultbits (left, right, result, ic);
4460       goto release;
4461     }
4462
4463   /* if both are of size == 1 */
4464   if (AOP_SIZE (left) == 1 &&
4465       AOP_SIZE (right) == 1)
4466     {
4467       genMultOneByte (left, right, result, ic);
4468       goto release;
4469     }
4470
4471   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4472           /* use the ds390 ARITHMETIC accel UNIT */
4473           genMultTwoByte (left, right, result, ic);
4474           return ;
4475   }
4476   /* should have been converted to function call */
4477   assert (0);
4478
4479 release:
4480   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4481   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4482   freeAsmop (result, NULL, ic, TRUE);
4483 }
4484
4485 /*-----------------------------------------------------------------*/
4486 /* genDivbits :- division of bits                                  */
4487 /*-----------------------------------------------------------------*/
4488 static void
4489 genDivbits (operand * left,
4490             operand * right,
4491             operand * result,
4492             iCode   * ic)
4493 {
4494
4495   char *l;
4496
4497   /* the result must be bit */
4498   LOAD_AB_FOR_DIV (left, right, l);
4499   emitcode ("div", "ab");
4500   emitcode ("rrc", "a");
4501   aopOp(result, ic, TRUE, FALSE);
4502     
4503   aopPut (AOP (result), "c", 0);
4504 }
4505
4506 /*-----------------------------------------------------------------*/
4507 /* genDivOneByte : 8 bit division                                  */
4508 /*-----------------------------------------------------------------*/
4509 static void
4510 genDivOneByte (operand * left,
4511                operand * right,
4512                operand * result,
4513                iCode   * ic)
4514 {
4515   sym_link *opetype = operandType (result);
4516   char *l;
4517   symbol *lbl;
4518   int size, offset;
4519
4520   offset = 1;
4521   /* signed or unsigned */
4522   if (SPEC_USIGN (opetype))
4523     {
4524         /* unsigned is easy */
4525         LOAD_AB_FOR_DIV (left, right, l);
4526         emitcode ("div", "ab");
4527
4528         _G.accInUse++;
4529         aopOp(result, ic, TRUE, FALSE);
4530         aopPut (AOP (result), "a", 0);
4531         _G.accInUse--;
4532
4533         size = AOP_SIZE (result) - 1;
4534         
4535         while (size--)
4536         {
4537             aopPut (AOP (result), zero, offset++);
4538         }
4539       return;
4540     }
4541
4542   /* signed is a little bit more difficult */
4543
4544   /* save the signs of the operands */
4545   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4546   MOVA (l);
4547   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4548   emitcode ("push", "acc");     /* save it on the stack */
4549
4550   /* now sign adjust for both left & right */
4551   l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4552   MOVA (l);
4553   lbl = newiTempLabel (NULL);
4554   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4555   emitcode ("cpl", "a");
4556   emitcode ("inc", "a");
4557   emitcode ("", "!tlabeldef", (lbl->key + 100));
4558   emitcode ("mov", "b,a");
4559
4560   /* sign adjust left side */
4561   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4562   MOVA (l);
4563
4564   lbl = newiTempLabel (NULL);
4565   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4566   emitcode ("cpl", "a");
4567   emitcode ("inc", "a");
4568   emitcode ("", "!tlabeldef", (lbl->key + 100));
4569
4570   /* now the division */
4571   emitcode ("nop", "; workaround for DS80C390 div bug.");
4572   emitcode ("div", "ab");
4573   /* we are interested in the lower order
4574      only */
4575   emitcode ("mov", "b,a");
4576   lbl = newiTempLabel (NULL);
4577   emitcode ("pop", "acc");
4578   /* if there was an over flow we don't
4579      adjust the sign of the result */
4580   emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4581   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4582   CLRC;
4583   emitcode ("clr", "a");
4584   emitcode ("subb", "a,b");
4585   emitcode ("mov", "b,a");
4586   emitcode ("", "!tlabeldef", (lbl->key + 100));
4587
4588   /* now we are done */
4589   _G.accInUse++;     _G.bInUse++;
4590     aopOp(result, ic, TRUE, FALSE);
4591     
4592     aopPut (AOP (result), "b", 0);
4593     
4594     size = AOP_SIZE (result) - 1;
4595     
4596     if (size > 0)
4597     {
4598       emitcode ("mov", "c,b.7");
4599       emitcode ("subb", "a,acc");
4600     }
4601     while (size--)
4602     {
4603         aopPut (AOP (result), "a", offset++);
4604     }
4605     _G.accInUse--;     _G.bInUse--;
4606
4607 }
4608
4609 /*-----------------------------------------------------------------*/
4610 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide       */
4611 /*-----------------------------------------------------------------*/
4612 static void genDivTwoByte (operand *left, operand *right, 
4613                             operand *result, iCode *ic)
4614 {
4615         sym_link *retype = getSpec(operandType(right));
4616         sym_link *letype = getSpec(operandType(left));
4617         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4618         symbol *lbl;
4619
4620         /* save EA bit in F1 */
4621         lbl = newiTempLabel(NULL);
4622         emitcode ("setb","F1");
4623         emitcode ("jbc","EA,!tlabel",lbl->key+100);
4624         emitcode ("clr","F1");
4625         emitcode("","!tlabeldef",lbl->key+100);
4626
4627         /* load up MA with left */
4628         if (!umult) {
4629                 emitcode("clr","F0");
4630                 lbl = newiTempLabel(NULL);
4631                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4632                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4633                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4634                 emitcode ("xch", "a,b");
4635                 emitcode ("cpl","a");
4636                 emitcode ("add", "a,#1");
4637                 emitcode ("xch", "a,b");
4638                 emitcode ("cpl", "a"); // msb
4639                 emitcode ("addc","a,#0");
4640                 emitcode ("setb","F0");
4641                 emitcode ("","!tlabeldef",lbl->key+100);
4642                 emitcode ("mov","ma,b");
4643                 emitcode ("mov","ma,a");
4644         } else {
4645                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4646                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4647         }
4648
4649         /* load up MB with right */
4650         if (!umult) {
4651                 if (AOP_TYPE(right) == AOP_LIT) {
4652                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
4653                         if (val < 0) {
4654                                 lbl = newiTempLabel(NULL);
4655                                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4656                                 emitcode("setb","F0");
4657                                 emitcode ("","!tlabeldef",lbl->key+100);
4658                                 val = -val;
4659                         } 
4660                         emitcode ("mov","mb,#!constbyte",val & 0xff);               
4661                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4662                 } else {
4663                         lbl = newiTempLabel(NULL);
4664                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4665                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4666                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
4667                         emitcode ("xch", "a,b");
4668                         emitcode ("cpl","a");
4669                         emitcode ("add", "a,#1");
4670                         emitcode ("xch", "a,b");
4671                         emitcode ("cpl", "a"); // msb
4672                         emitcode ("addc", "a,#0");
4673                         emitcode ("jbc","F0,!tlabel",lbl->key+100);
4674                         emitcode ("setb","F0");
4675                         emitcode ("","!tlabeldef",lbl->key+100);
4676                         emitcode ("mov","mb,b");
4677                         emitcode ("mov","mb,a");
4678                 }
4679         } else {
4680                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4681                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4682         }
4683
4684         /* wait for multiplication to finish */
4685         lbl = newiTempLabel(NULL);
4686         emitcode("","!tlabeldef", lbl->key+100);
4687         emitcode("mov","a,mcnt1");
4688         emitcode("anl","a,#!constbyte",0x80);
4689         emitcode("jnz","!tlabel",lbl->key+100);
4690         
4691         freeAsmop (left, NULL, ic, TRUE);
4692         freeAsmop (right, NULL, ic,TRUE);
4693         aopOp(result, ic, TRUE, FALSE);
4694
4695         /* if unsigned then simple */   
4696         if (umult) {
4697                 aopPut(AOP(result),"ma",1);
4698                 aopPut(AOP(result),"ma",0);
4699         } else {
4700                 emitcode("push","ma");
4701                 MOVA("ma");
4702                 /* negate result if needed */
4703                 lbl = newiTempLabel(NULL);      
4704                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4705                 emitcode("cpl","a");
4706                 emitcode("add","a,#1");
4707                 emitcode("","!tlabeldef", lbl->key+100);
4708                 aopPut(AOP(result),"a",0);
4709                 emitcode("pop","acc");
4710                 lbl = newiTempLabel(NULL);      
4711                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4712                 emitcode("cpl","a");
4713                 emitcode("addc","a,#0");
4714                 emitcode("","!tlabeldef", lbl->key+100);
4715                 aopPut(AOP(result),"a",1);
4716         }
4717         freeAsmop (result, NULL, ic, TRUE);
4718         /* restore EA bit in F1 */
4719         lbl = newiTempLabel(NULL);
4720         emitcode ("jnb","F1,!tlabel",lbl->key+100);
4721         emitcode ("setb","EA");
4722         emitcode("","!tlabeldef",lbl->key+100);
4723         return ;
4724 }
4725
4726 /*-----------------------------------------------------------------*/
4727 /* genDiv - generates code for division                            */
4728 /*-----------------------------------------------------------------*/
4729 static void
4730 genDiv (iCode * ic)
4731 {
4732   operand *left = IC_LEFT (ic);
4733   operand *right = IC_RIGHT (ic);
4734   operand *result = IC_RESULT (ic);
4735
4736   D (emitcode (";", "genDiv "););
4737
4738   /* assign the amsops */
4739   AOP_OP_2 (ic);
4740
4741   /* special cases first */
4742   /* both are bits */
4743   if (AOP_TYPE (left) == AOP_CRY &&
4744       AOP_TYPE (right) == AOP_CRY)
4745     {
4746       genDivbits (left, right, result, ic);
4747       goto release;
4748     }
4749
4750   /* if both are of size == 1 */
4751   if (AOP_SIZE (left) == 1 &&
4752       AOP_SIZE (right) == 1)
4753     {
4754       genDivOneByte (left, right, result, ic);
4755       goto release;
4756     }
4757
4758   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4759           /* use the ds390 ARITHMETIC accel UNIT */
4760           genDivTwoByte (left, right, result, ic);
4761           return ;
4762   }
4763   /* should have been converted to function call */
4764   assert (0);
4765 release:
4766   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4767   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4768   freeAsmop (result, NULL, ic, TRUE);
4769 }
4770
4771 /*-----------------------------------------------------------------*/
4772 /* genModbits :- modulus of bits                                   */
4773 /*-----------------------------------------------------------------*/
4774 static void
4775 genModbits (operand * left,
4776             operand * right,
4777             operand * result,
4778             iCode   * ic)
4779 {
4780
4781   char *l;
4782
4783   /* the result must be bit */
4784   LOAD_AB_FOR_DIV (left, right, l);
4785   emitcode ("div", "ab");
4786   emitcode ("mov", "a,b");
4787   emitcode ("rrc", "a");
4788   aopOp(result, ic, TRUE, FALSE);
4789   aopPut (AOP (result), "c", 0);
4790 }
4791
4792 /*-----------------------------------------------------------------*/
4793 /* genModOneByte : 8 bit modulus                                   */
4794 /*-----------------------------------------------------------------*/
4795 static void
4796 genModOneByte (operand * left,
4797                operand * right,
4798                operand * result,
4799                iCode   * ic)
4800 {
4801   sym_link *opetype = operandType (result);
4802   char *l;
4803   symbol *lbl;
4804
4805   /* signed or unsigned */
4806   if (SPEC_USIGN (opetype))
4807     {
4808       /* unsigned is easy */
4809       LOAD_AB_FOR_DIV (left, right, l);
4810       emitcode ("div", "ab");
4811       aopOp(result, ic, TRUE, FALSE);   
4812       aopPut (AOP (result), "b", 0);
4813       return;
4814     }
4815
4816   /* signed is a little bit more difficult */
4817
4818   /* save the signs of the operands */
4819   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4820   MOVA (l);
4821
4822   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4823   emitcode ("push", "acc");     /* save it on the stack */
4824
4825   /* now sign adjust for both left & right */
4826   l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4827   MOVA (l);
4828
4829   lbl = newiTempLabel (NULL);
4830   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4831   emitcode ("cpl", "a");
4832   emitcode ("inc", "a");
4833   emitcode ("", "!tlabeldef", (lbl->key + 100));
4834   emitcode ("mov", "b,a");
4835
4836   /* sign adjust left side */
4837   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4838   MOVA (l);
4839
4840   lbl = newiTempLabel (NULL);
4841   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4842   emitcode ("cpl", "a");
4843   emitcode ("inc", "a");
4844   emitcode ("", "!tlabeldef", (lbl->key + 100));
4845
4846   /* now the multiplication */
4847   emitcode ("nop", "; workaround for DS80C390 div bug.");
4848   emitcode ("div", "ab");
4849   /* we are interested in the lower order
4850      only */
4851   lbl = newiTempLabel (NULL);
4852   emitcode ("pop", "acc");
4853   /* if there was an over flow we don't
4854      adjust the sign of the result */
4855   emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4856   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4857   CLRC;
4858   emitcode ("clr", "a");
4859   emitcode ("subb", "a,b");
4860   emitcode ("mov", "b,a");
4861   emitcode ("", "!tlabeldef", (lbl->key + 100));
4862   
4863   _G.bInUse++;
4864   /* now we are done */
4865   aopOp(result, ic, TRUE, FALSE);    
4866   aopPut (AOP (result), "b", 0);
4867   _G.bInUse--;
4868
4869 }
4870
4871 /*-----------------------------------------------------------------*/
4872 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus      */
4873 /*-----------------------------------------------------------------*/
4874 static void genModTwoByte (operand *left, operand *right, 
4875                             operand *result, iCode *ic)
4876 {
4877         sym_link *retype = getSpec(operandType(right));
4878         sym_link *letype = getSpec(operandType(left));
4879         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4880         symbol *lbl;
4881
4882         /* load up MA with left */
4883         /* save EA bit in F1 */
4884         lbl = newiTempLabel(NULL);
4885         emitcode ("setb","F1");
4886         emitcode ("jbc","EA,!tlabel",lbl->key+100);
4887         emitcode ("clr","F1");
4888         emitcode("","!tlabeldef",lbl->key+100);
4889
4890         if (!umult) {
4891                 lbl = newiTempLabel(NULL);
4892                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4893                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4894                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4895                 emitcode ("xch", "a,b");
4896                 emitcode ("cpl","a");
4897                 emitcode ("add", "a,#1");
4898                 emitcode ("xch", "a,b");
4899                 emitcode ("cpl", "a"); // msb
4900                 emitcode ("addc","a,#0");
4901                 emitcode ("","!tlabeldef",lbl->key+100);
4902                 emitcode ("mov","ma,b");
4903                 emitcode ("mov","ma,a");
4904         } else {
4905                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4906                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4907         }
4908
4909         /* load up MB with right */
4910         if (!umult) {
4911                 if (AOP_TYPE(right) == AOP_LIT) {
4912                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
4913                         if (val < 0) {
4914                                 val = -val;
4915                         } 
4916                         emitcode ("mov","mb,#!constbyte",val & 0xff);
4917                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
4918                 } else {
4919                         lbl = newiTempLabel(NULL);
4920                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4921                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4922                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
4923                         emitcode ("xch", "a,b");
4924                         emitcode ("cpl","a");
4925                         emitcode ("add", "a,#1");
4926                         emitcode ("xch", "a,b");
4927                         emitcode ("cpl", "a"); // msb
4928                         emitcode ("addc", "a,#0");
4929                         emitcode ("","!tlabeldef",lbl->key+100);
4930                         emitcode ("mov","mb,b");
4931                         emitcode ("mov","mb,a");
4932                 }
4933         } else {
4934                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4935                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4936         }
4937
4938         /* wait for multiplication to finish */
4939         lbl = newiTempLabel(NULL);
4940         emitcode("","!tlabeldef", lbl->key+100);
4941         emitcode("mov","a,mcnt1");
4942         emitcode("anl","a,#!constbyte",0x80);
4943         emitcode("jnz","!tlabel",lbl->key+100);
4944         
4945         freeAsmop (left, NULL, ic, TRUE);
4946         freeAsmop (right, NULL, ic,TRUE);
4947         aopOp(result, ic, TRUE, FALSE);
4948
4949         aopPut(AOP(result),"mb",1);
4950         aopPut(AOP(result),"mb",0);
4951         freeAsmop (result, NULL, ic, TRUE);
4952
4953         /* restore EA bit in F1 */
4954         lbl = newiTempLabel(NULL);
4955         emitcode ("jnb","F1,!tlabel",lbl->key+100);
4956         emitcode ("setb","EA");
4957         emitcode("","!tlabeldef",lbl->key+100);
4958         return ;
4959 }
4960
4961 /*-----------------------------------------------------------------*/
4962 /* genMod - generates code for division                            */
4963 /*-----------------------------------------------------------------*/
4964 static void
4965 genMod (iCode * ic)
4966 {
4967   operand *left = IC_LEFT (ic);
4968   operand *right = IC_RIGHT (ic);
4969   operand *result = IC_RESULT (ic);
4970
4971   D (emitcode (";", "genMod "); );
4972
4973   /* assign the amsops */
4974   AOP_OP_2 (ic);
4975
4976   /* special cases first */
4977   /* both are bits */
4978   if (AOP_TYPE (left) == AOP_CRY &&
4979       AOP_TYPE (right) == AOP_CRY)
4980     {
4981       genModbits (left, right, result, ic);
4982       goto release;
4983     }
4984
4985   /* if both are of size == 1 */
4986   if (AOP_SIZE (left) == 1 &&
4987       AOP_SIZE (right) == 1)
4988     {
4989       genModOneByte (left, right, result, ic);
4990       goto release;
4991     }
4992
4993   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4994           /* use the ds390 ARITHMETIC accel UNIT */
4995           genModTwoByte (left, right, result, ic);
4996           return ;
4997   }
4998
4999   /* should have been converted to function call */
5000   assert (0);
5001
5002 release:
5003   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5004   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5005   freeAsmop (result, NULL, ic, TRUE);
5006 }
5007
5008 /*-----------------------------------------------------------------*/
5009 /* genIfxJump :- will create a jump depending on the ifx           */
5010 /*-----------------------------------------------------------------*/
5011 static void
5012 genIfxJump (iCode * ic, char *jval)
5013 {
5014   symbol *jlbl;
5015   symbol *tlbl = newiTempLabel (NULL);
5016   char *inst;
5017
5018   D (emitcode (";", "genIfxJump ");
5019     );
5020
5021   /* if true label then we jump if condition
5022      supplied is true */
5023   if (IC_TRUE (ic))
5024     {
5025       jlbl = IC_TRUE (ic);
5026       inst = ((strcmp (jval, "a") == 0 ? "jz" :
5027                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5028     }
5029   else
5030     {
5031       /* false label is present */
5032       jlbl = IC_FALSE (ic);
5033       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5034                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5035     }
5036   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5037     emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5038   else
5039     emitcode (inst, "!tlabel", tlbl->key + 100);
5040   emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5041   emitcode ("", "!tlabeldef", tlbl->key + 100);
5042
5043   /* mark the icode as generated */
5044   ic->generated = 1;
5045 }
5046
5047 /*-----------------------------------------------------------------*/
5048 /* genCmp :- greater or less than comparison                       */
5049 /*-----------------------------------------------------------------*/
5050 static void
5051 genCmp (operand * left, operand * right,
5052         iCode * ic, iCode * ifx, int sign)
5053 {
5054   int size, offset = 0;
5055   unsigned long lit = 0L;
5056   operand *result;
5057
5058   D (emitcode (";", "genCmp");
5059     );
5060
5061   result = IC_RESULT (ic);
5062
5063   /* if left & right are bit variables */
5064   if (AOP_TYPE (left) == AOP_CRY &&
5065       AOP_TYPE (right) == AOP_CRY)
5066     {
5067       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5068       emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
5069     }
5070   else
5071     {
5072       /* subtract right from left if at the
5073          end the carry flag is set then we know that
5074          left is greater than right */
5075       size = max (AOP_SIZE (left), AOP_SIZE (right));
5076
5077       /* if unsigned char cmp with lit, do cjne left,#right,zz */
5078       if ((size == 1) && !sign &&
5079           (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5080         {
5081           symbol *lbl = newiTempLabel (NULL);
5082           emitcode ("cjne", "%s,%s,!tlabel",
5083                     aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5084                     aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
5085                     lbl->key + 100);
5086           emitcode ("", "!tlabeldef", lbl->key + 100);
5087         }
5088       else
5089         {
5090           if (AOP_TYPE (right) == AOP_LIT)
5091             {
5092               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5093               /* optimize if(x < 0) or if(x >= 0) */
5094               if (lit == 0L)
5095                 {
5096                   if (!sign)
5097                     {
5098                       CLRC;
5099                     }
5100                   else
5101                     {
5102                       MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
5103
5104                       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5105                       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5106
5107                       aopOp (result, ic, FALSE, FALSE);
5108
5109                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5110                         {
5111                           freeAsmop (result, NULL, ic, TRUE);
5112                           genIfxJump (ifx, "acc.7");
5113                           return;
5114                         }
5115                       else
5116                         {
5117                           emitcode ("rlc", "a");
5118                         }
5119                       goto release_freedLR;
5120                     }
5121                   goto release;
5122                 }
5123             }
5124           CLRC;
5125           while (size--)
5126             {
5127               //emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5128               MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5129               //emitcode (";", "genCmp #2");
5130               if (sign && (size == 0))
5131                 {
5132                     //emitcode (";", "genCmp #3");
5133                   emitcode ("xrl", "a,#!constbyte",0x80);
5134                   if (AOP_TYPE (right) == AOP_LIT)
5135                     {
5136                       unsigned long lit = (unsigned long)
5137                       floatFromVal (AOP (right)->aopu.aop_lit);
5138                       //emitcode (";", "genCmp #3.1");
5139                       emitcode ("subb", "a,#!constbyte",
5140                                 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5141                     }
5142                   else
5143                     {
5144                       //emitcode (";", "genCmp #3.2");
5145                       if (AOP_NEEDSACC (right))
5146                         {
5147                           emitcode ("push", "acc");
5148                         }
5149                       emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
5150                                                        FALSE, FALSE, FALSE));
5151                       emitcode ("xrl", "b,#!constbyte",0x80);
5152                       if (AOP_NEEDSACC (right))
5153                         {
5154                           emitcode ("pop", "acc");
5155                         }
5156                       emitcode ("subb", "a,b");
5157                     }
5158                 }
5159               else
5160                 {
5161                   const char *s;
5162
5163                   //emitcode (";", "genCmp #4");
5164                   if (AOP_NEEDSACC (right))
5165                     {
5166                       /* Yuck!! */
5167                       //emitcode (";", "genCmp #4.1");
5168                       emitcode ("xch", "a, b");
5169                       MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
5170                       emitcode ("xch", "a, b");
5171                       s = "b";
5172                     }
5173                   else
5174                     {
5175                       //emitcode (";", "genCmp #4.2");
5176                       s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
5177                     }
5178
5179                   emitcode ("subb", "a,%s", s);
5180                 }
5181             }
5182         }
5183     }
5184
5185 release:
5186 /* Don't need the left & right operands any more; do need the result. */
5187   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5188   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5189
5190   aopOp (result, ic, FALSE, FALSE);
5191
5192 release_freedLR:
5193
5194   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5195     {
5196       outBitC (result);
5197     }
5198   else
5199     {
5200       /* if the result is used in the next
5201          ifx conditional branch then generate
5202          code a little differently */
5203       if (ifx)
5204         {
5205           genIfxJump (ifx, "c");
5206         }
5207       else
5208         {
5209           outBitC (result);
5210         }
5211       /* leave the result in acc */
5212     }
5213   freeAsmop (result, NULL, ic, TRUE);
5214 }
5215
5216 /*-----------------------------------------------------------------*/
5217 /* genCmpGt :- greater than comparison                             */
5218 /*-----------------------------------------------------------------*/
5219 static void
5220 genCmpGt (iCode * ic, iCode * ifx)
5221 {
5222   operand *left, *right;
5223   sym_link *letype, *retype;
5224   int sign;
5225
5226   D (emitcode (";", "genCmpGt ");
5227     );
5228
5229   left = IC_LEFT (ic);
5230   right = IC_RIGHT (ic);
5231
5232   letype = getSpec (operandType (left));
5233   retype = getSpec (operandType (right));
5234   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5235
5236   /* assign the left & right amsops */
5237   AOP_OP_2 (ic);
5238
5239   genCmp (right, left, ic, ifx, sign);
5240 }
5241
5242 /*-----------------------------------------------------------------*/
5243 /* genCmpLt - less than comparisons                                */
5244 /*-----------------------------------------------------------------*/
5245 static void
5246 genCmpLt (iCode * ic, iCode * ifx)
5247 {
5248   operand *left, *right;
5249   sym_link *letype, *retype;
5250   int sign;
5251
5252   D (emitcode (";", "genCmpLt "););
5253
5254   left = IC_LEFT (ic);
5255   right = IC_RIGHT (ic);
5256
5257   letype = getSpec (operandType (left));
5258   retype = getSpec (operandType (right));
5259   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5260
5261   /* assign the left & right amsops */
5262   AOP_OP_2 (ic);
5263
5264   genCmp (left, right, ic, ifx, sign);
5265 }
5266
5267 /*-----------------------------------------------------------------*/
5268 /* gencjneshort - compare and jump if not equal                    */
5269 /*-----------------------------------------------------------------*/
5270 static void
5271 gencjneshort (operand * left, operand * right, symbol * lbl)
5272 {
5273   int size = max (AOP_SIZE (left), AOP_SIZE (right));
5274   int offset = 0;
5275   unsigned long lit = 0L;
5276
5277   D (emitcode (";", "gencjneshort");
5278     );
5279
5280   /* if the left side is a literal or
5281      if the right is in a pointer register and left
5282      is not */
5283   if ((AOP_TYPE (left) == AOP_LIT) ||
5284       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5285     {
5286       operand *t = right;
5287       right = left;
5288       left = t;
5289     }
5290
5291   if (AOP_TYPE (right) == AOP_LIT)
5292     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5293
5294   if (opIsGptr (left) || opIsGptr (right))
5295     {
5296       /* We are comparing a generic pointer to something.
5297        * Exclude the generic type byte from the comparison.
5298        */
5299       size--;
5300       D (emitcode (";", "cjneshort: generic ptr special case.");
5301         )
5302     }
5303
5304
5305   /* if the right side is a literal then anything goes */
5306   if (AOP_TYPE (right) == AOP_LIT &&
5307       AOP_TYPE (left) != AOP_DIR)
5308     {
5309       while (size--)
5310         {
5311           char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5312           MOVA (l);
5313           emitcode ("cjne", "a,%s,!tlabel",
5314                     aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
5315                     lbl->key + 100);
5316           offset++;
5317         }
5318     }
5319
5320   /* if the right side is in a register or in direct space or
5321      if the left is a pointer register & right is not */
5322   else if (AOP_TYPE (right) == AOP_REG ||
5323            AOP_TYPE (right) == AOP_DIR ||
5324            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5325            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5326     {
5327       while (size--)
5328         {
5329           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5330           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5331               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5332             emitcode ("jnz", "!tlabel", lbl->key + 100);
5333           else
5334             emitcode ("cjne", "a,%s,!tlabel",
5335                       aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
5336                       lbl->key + 100);
5337           offset++;
5338         }
5339     }
5340   else
5341     {
5342       /* right is a pointer reg need both a & b */
5343       while (size--)
5344         {
5345           char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5346           if (strcmp (l, "b"))
5347             emitcode ("mov", "b,%s", l);
5348           MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5349           emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
5350           offset++;
5351         }
5352     }
5353 }
5354
5355 /*-----------------------------------------------------------------*/
5356 /* gencjne - compare and jump if not equal                         */
5357 /*-----------------------------------------------------------------*/
5358 static void
5359 gencjne (operand * left, operand * right, symbol * lbl)
5360 {
5361   symbol *tlbl = newiTempLabel (NULL);
5362
5363   D (emitcode (";", "gencjne");
5364     );
5365
5366   gencjneshort (left, right, lbl);
5367
5368   emitcode ("mov", "a,%s", one);
5369   emitcode ("sjmp", "!tlabel", tlbl->key + 100);
5370   emitcode ("", "!tlabeldef", lbl->key + 100);
5371   emitcode ("clr", "a");
5372   emitcode ("", "!tlabeldef", tlbl->key + 100);
5373 }
5374
5375 /*-----------------------------------------------------------------*/
5376 /* genCmpEq - generates code for equal to                          */
5377 /*-----------------------------------------------------------------*/
5378 static void
5379 genCmpEq (iCode * ic, iCode * ifx)
5380 {
5381   operand *left, *right, *result;
5382
5383   D (emitcode (";", "genCmpEq ");
5384     );
5385
5386   AOP_OP_2 (ic);
5387   AOP_SET_LOCALS (ic);
5388
5389   /* if literal, literal on the right or
5390      if the right is in a pointer register and left
5391      is not */
5392   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5393       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5394     {
5395       operand *t = IC_RIGHT (ic);
5396       IC_RIGHT (ic) = IC_LEFT (ic);
5397       IC_LEFT (ic) = t;
5398     }
5399
5400   if (ifx &&                    /* !AOP_SIZE(result) */
5401       OP_SYMBOL (result) &&
5402       OP_SYMBOL (result)->regType == REG_CND)
5403     {
5404       symbol *tlbl;
5405       /* if they are both bit variables */
5406       if (AOP_TYPE (left) == AOP_CRY &&
5407           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5408         {
5409           if (AOP_TYPE (right) == AOP_LIT)
5410             {
5411               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5412               if (lit == 0L)
5413                 {
5414                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5415                   emitcode ("cpl", "c");
5416                 }
5417               else if (lit == 1L)
5418                 {
5419                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5420                 }
5421               else
5422                 {
5423                   emitcode ("clr", "c");
5424                 }
5425               /* AOP_TYPE(right) == AOP_CRY */
5426             }
5427           else
5428             {
5429               symbol *lbl = newiTempLabel (NULL);
5430               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5431               emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5432               emitcode ("cpl", "c");
5433               emitcode ("", "!tlabeldef", (lbl->key + 100));
5434             }
5435           /* if true label then we jump if condition
5436              supplied is true */
5437           tlbl = newiTempLabel (NULL);
5438           if (IC_TRUE (ifx))
5439             {
5440               emitcode ("jnc", "!tlabel", tlbl->key + 100);
5441               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5442             }
5443           else
5444             {
5445               emitcode ("jc", "!tlabel", tlbl->key + 100);
5446               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5447             }
5448           emitcode ("", "!tlabeldef", tlbl->key + 100);
5449         }
5450       else
5451         {
5452           tlbl = newiTempLabel (NULL);
5453           gencjneshort (left, right, tlbl);
5454           if (IC_TRUE (ifx))
5455             {
5456               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5457               emitcode ("", "!tlabeldef", tlbl->key + 100);
5458             }
5459           else
5460             {
5461               symbol *lbl = newiTempLabel (NULL);
5462               emitcode ("sjmp", "!tlabel", lbl->key + 100);
5463               emitcode ("", "!tlabeldef", tlbl->key + 100);
5464               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5465               emitcode ("", "!tlabeldef", lbl->key + 100);
5466             }
5467         }
5468       /* mark the icode as generated */
5469       ifx->generated = 1;
5470
5471       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5472       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5473       return;
5474     }
5475
5476   /* if they are both bit variables */
5477   if (AOP_TYPE (left) == AOP_CRY &&
5478       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5479     {
5480       if (AOP_TYPE (right) == AOP_LIT)
5481         {
5482           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5483           if (lit == 0L)
5484             {
5485               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5486               emitcode ("cpl", "c");
5487             }
5488           else if (lit == 1L)
5489             {
5490               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5491             }
5492           else
5493             {
5494               emitcode ("clr", "c");
5495             }
5496           /* AOP_TYPE(right) == AOP_CRY */
5497         }
5498       else
5499         {
5500           symbol *lbl = newiTempLabel (NULL);
5501           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5502           emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5503           emitcode ("cpl", "c");
5504           emitcode ("", "!tlabeldef", (lbl->key + 100));
5505         }
5506
5507       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5508       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5509
5510       aopOp (result, ic, TRUE, FALSE);
5511
5512       /* c = 1 if egal */
5513       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5514         {
5515           outBitC (result);
5516           goto release;
5517         }
5518       if (ifx)
5519         {
5520           genIfxJump (ifx, "c");
5521           goto release;
5522         }
5523       /* if the result is used in an arithmetic operation
5524          then put the result in place */
5525       outBitC (result);
5526     }
5527   else
5528     {
5529       gencjne (left, right, newiTempLabel (NULL));
5530
5531       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5532       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5533
5534       aopOp (result, ic, TRUE, FALSE);
5535
5536       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5537         {
5538           aopPut (AOP (result), "a", 0);
5539           goto release;
5540         }
5541       if (ifx)
5542         {
5543           genIfxJump (ifx, "a");
5544           goto release;
5545         }
5546       /* if the result is used in an arithmetic operation
5547          then put the result in place */
5548       if (AOP_TYPE (result) != AOP_CRY)
5549         outAcc (result);
5550       /* leave the result in acc */
5551     }
5552
5553 release:
5554   freeAsmop (result, NULL, ic, TRUE);
5555 }
5556
5557 /*-----------------------------------------------------------------*/
5558 /* ifxForOp - returns the icode containing the ifx for operand     */
5559 /*-----------------------------------------------------------------*/
5560 static iCode *
5561 ifxForOp (operand * op, iCode * ic)
5562 {
5563   /* if true symbol then needs to be assigned */
5564   if (IS_TRUE_SYMOP (op))
5565     return NULL;
5566
5567   /* if this has register type condition and
5568      the next instruction is ifx with the same operand
5569      and live to of the operand is upto the ifx only then */
5570   if (ic->next &&
5571       ic->next->op == IFX &&
5572       IC_COND (ic->next)->key == op->key &&
5573       OP_SYMBOL (op)->liveTo <= ic->next->seq)
5574     return ic->next;
5575
5576   return NULL;
5577 }
5578 /*-----------------------------------------------------------------*/
5579 /* hasInc - operand is incremented before any other use            */
5580 /*-----------------------------------------------------------------*/
5581 static iCode *
5582 hasInc (operand *op, iCode *ic)
5583 {
5584   sym_link *type = operandType(op);
5585   sym_link *retype = getSpec (type);
5586   iCode *lic = ic->next;
5587   int isize ;
5588   
5589   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5590   if (!IS_SYMOP(op)) return NULL;
5591
5592   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5593   isize = getSize(type->next);
5594   while (lic) {
5595       /* if operand of the form op = op + <sizeof *op> */
5596       if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5597           isOperandEqual(IC_RESULT(lic),op) && 
5598           isOperandLiteral(IC_RIGHT(lic)) &&
5599           operandLitValue(IC_RIGHT(lic)) == isize) {
5600           return lic;
5601       }
5602       /* if the operand used or deffed */
5603       if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5604           return NULL;
5605       }
5606       /* if GOTO or IFX */
5607       if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5608       lic = lic->next;
5609   }
5610   return NULL;
5611 }
5612
5613 /*-----------------------------------------------------------------*/
5614 /* genAndOp - for && operation                                     */
5615 /*-----------------------------------------------------------------*/
5616 static void
5617 genAndOp (iCode * ic)
5618 {
5619   operand *left, *right, *result;
5620   symbol *tlbl;
5621
5622   D (emitcode (";", "genAndOp "););
5623
5624   /* note here that && operations that are in an
5625      if statement are taken away by backPatchLabels
5626      only those used in arthmetic operations remain */
5627   AOP_OP_2 (ic);
5628   AOP_SET_LOCALS (ic);
5629
5630   /* if both are bit variables */
5631   if (AOP_TYPE (left) == AOP_CRY &&
5632       AOP_TYPE (right) == AOP_CRY)
5633     {
5634       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5635       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5636       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5637       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5638   
5639       aopOp (result,ic,FALSE, FALSE);
5640       outBitC (result);
5641     }
5642   else
5643     {
5644       tlbl = newiTempLabel (NULL);
5645       toBoolean (left);
5646       emitcode ("jz", "!tlabel", tlbl->key + 100);
5647       toBoolean (right);
5648       emitcode ("", "!tlabeldef", tlbl->key + 100);
5649       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5650       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5651   
5652       aopOp (result,ic,FALSE, FALSE);
5653       outBitAcc (result);
5654     }
5655     freeAsmop (result, NULL, ic, TRUE);
5656 }
5657
5658
5659 /*-----------------------------------------------------------------*/
5660 /* genOrOp - for || operation                                      */
5661 /*-----------------------------------------------------------------*/
5662 static void
5663 genOrOp (iCode * ic)
5664 {
5665   operand *left, *right, *result;
5666   symbol *tlbl;
5667
5668   D (emitcode (";", "genOrOp "););
5669
5670   /* note here that || operations that are in an
5671      if statement are taken away by backPatchLabels
5672      only those used in arthmetic operations remain */
5673   AOP_OP_2 (ic);
5674   AOP_SET_LOCALS (ic);
5675
5676   /* if both are bit variables */
5677   if (AOP_TYPE (left) == AOP_CRY &&
5678       AOP_TYPE (right) == AOP_CRY)
5679     {
5680       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5681       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5682       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5683       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5684   
5685       aopOp (result,ic,FALSE, FALSE);
5686       
5687       outBitC (result);
5688     }
5689   else
5690     {
5691       tlbl = newiTempLabel (NULL);
5692       toBoolean (left);
5693       emitcode ("jnz", "!tlabel", tlbl->key + 100);
5694       toBoolean (right);
5695       emitcode ("", "!tlabeldef", tlbl->key + 100);
5696       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5697       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5698   
5699       aopOp (result,ic,FALSE, FALSE);
5700       
5701       outBitAcc (result);
5702     }
5703
5704   freeAsmop (result, NULL, ic, TRUE);
5705 }
5706
5707 /*-----------------------------------------------------------------*/
5708 /* isLiteralBit - test if lit == 2^n                               */
5709 /*-----------------------------------------------------------------*/
5710 static int
5711 isLiteralBit (unsigned long lit)
5712 {
5713   unsigned long pw[32] =
5714   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5715    0x100L, 0x200L, 0x400L, 0x800L,
5716    0x1000L, 0x2000L, 0x4000L, 0x8000L,
5717    0x10000L, 0x20000L, 0x40000L, 0x80000L,
5718    0x100000L, 0x200000L, 0x400000L, 0x800000L,
5719    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5720    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5721   int idx;
5722
5723   for (idx = 0; idx < 32; idx++)
5724     if (lit == pw[idx])
5725       return idx + 1;
5726   return 0;
5727 }
5728
5729 /*-----------------------------------------------------------------*/
5730 /* continueIfTrue -                                                */
5731 /*-----------------------------------------------------------------*/
5732 static void
5733 continueIfTrue (iCode * ic)
5734 {
5735   if (IC_TRUE (ic))
5736     emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
5737   ic->generated = 1;
5738 }
5739
5740 /*-----------------------------------------------------------------*/
5741 /* jmpIfTrue -                                                     */
5742 /*-----------------------------------------------------------------*/
5743 static void
5744 jumpIfTrue (iCode * ic)
5745 {
5746   if (!IC_TRUE (ic))
5747     emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
5748   ic->generated = 1;
5749 }
5750
5751 /*-----------------------------------------------------------------*/
5752 /* jmpTrueOrFalse -                                                */
5753 /*-----------------------------------------------------------------*/
5754 static void
5755 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
5756 {
5757   // ugly but optimized by peephole
5758   if (IC_TRUE (ic))
5759     {
5760       symbol *nlbl = newiTempLabel (NULL);
5761       emitcode ("sjmp", "!tlabel", nlbl->key + 100);
5762       emitcode ("", "!tlabeldef", tlbl->key + 100);
5763       emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
5764       emitcode ("", "!tlabeldef", nlbl->key + 100);
5765     }
5766   else
5767     {
5768       emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
5769       emitcode ("", "!tlabeldef", tlbl->key + 100);
5770     }
5771   ic->generated = 1;
5772 }
5773
5774 // Generate code to perform a bit-wise logic operation
5775 // on two operands in far space (assumed to already have been 
5776 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
5777 // in far space. This requires pushing the result on the stack
5778 // then popping it into the result.
5779 static void
5780 genFarFarLogicOp(iCode *ic, char *logicOp)
5781 {
5782       int size, resultSize, compSize;
5783       int offset = 0;
5784       
5785       TR_AP("#5");
5786       D(emitcode(";", "%s special case for 3 far operands.", logicOp););
5787       compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ? 
5788                   AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
5789       
5790       _startLazyDPSEvaluation();
5791       for (size = compSize; (size--); offset++)
5792       {
5793           MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
5794           emitcode ("mov", "%s, acc", DP2_RESULT_REG);
5795           MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
5796           
5797           emitcode (logicOp, "a,%s", DP2_RESULT_REG);
5798           emitcode ("push", "acc");
5799       }
5800       _endLazyDPSEvaluation();
5801      
5802       freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5803       freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5804       aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
5805      
5806       resultSize = AOP_SIZE(IC_RESULT(ic));
5807
5808       ADJUST_PUSHED_RESULT(compSize, resultSize);
5809
5810       _startLazyDPSEvaluation();
5811       while (compSize--)
5812       {
5813           emitcode ("pop", "acc");
5814           aopPut (AOP (IC_RESULT (ic)), "a", compSize);
5815       }
5816       _endLazyDPSEvaluation();
5817       freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
5818 }
5819
5820
5821 /*-----------------------------------------------------------------*/
5822 /* genAnd  - code for and                                          */
5823 /*-----------------------------------------------------------------*/
5824 static void
5825 genAnd (iCode * ic, iCode * ifx)
5826 {
5827   operand *left, *right, *result;
5828   int size, offset = 0;
5829   unsigned long lit = 0L;
5830   int bytelit = 0;
5831   char buffer[10];
5832   bool pushResult;
5833
5834   D (emitcode (";", "genAnd "););
5835
5836   AOP_OP_3_NOFATAL (ic, pushResult);
5837   AOP_SET_LOCALS (ic);
5838
5839   if (pushResult)
5840   {
5841       genFarFarLogicOp(ic, "anl");
5842       return;
5843   }  
5844
5845 #ifdef DEBUG_TYPE
5846   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5847             AOP_TYPE (result),
5848             AOP_TYPE (left), AOP_TYPE (right));
5849   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5850             AOP_SIZE (result),
5851             AOP_SIZE (left), AOP_SIZE (right));
5852 #endif
5853
5854   /* if left is a literal & right is not then exchange them */
5855   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5856 #ifdef LOGIC_OPS_BROKEN      
5857     ||  AOP_NEEDSACC (left)
5858 #endif
5859     )
5860     {
5861       operand *tmp = right;
5862       right = left;
5863       left = tmp;
5864     }
5865
5866   /* if result = right then exchange them */
5867   if (sameRegs (AOP (result), AOP (right)))
5868     {
5869       operand *tmp = right;
5870       right = left;
5871       left = tmp;
5872     }
5873
5874   /* if right is bit then exchange them */
5875   if (AOP_TYPE (right) == AOP_CRY &&
5876       AOP_TYPE (left) != AOP_CRY)
5877     {
5878       operand *tmp = right;
5879       right = left;
5880       left = tmp;
5881     }
5882   if (AOP_TYPE (right) == AOP_LIT)
5883     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5884
5885   size = AOP_SIZE (result);
5886
5887   // if(bit & yy)
5888   // result = bit & yy;
5889   if (AOP_TYPE (left) == AOP_CRY)
5890     {
5891       // c = bit & literal;
5892       if (AOP_TYPE (right) == AOP_LIT)
5893         {
5894           if (lit & 1)
5895             {
5896               if (size && sameRegs (AOP (result), AOP (left)))
5897                 // no change
5898                 goto release;
5899               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5900             }
5901           else
5902             {
5903               // bit(result) = 0;
5904               if (size && (AOP_TYPE (result) == AOP_CRY))
5905                 {
5906                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5907                   goto release;
5908                 }
5909               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5910                 {
5911                   jumpIfTrue (ifx);
5912                   goto release;
5913                 }
5914               emitcode ("clr", "c");
5915             }
5916         }
5917       else
5918         {
5919           if (AOP_TYPE (right) == AOP_CRY)
5920             {
5921               // c = bit & bit;
5922               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5923               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5924             }
5925           else
5926             {
5927               // c = bit & val;
5928               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
5929               // c = lsb
5930               emitcode ("rrc", "a");
5931               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5932             }
5933         }
5934       // bit = c
5935       // val = c
5936       if (size)
5937         outBitC (result);
5938       // if(bit & ...)
5939       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5940         genIfxJump (ifx, "c");
5941       goto release;
5942     }
5943
5944   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5945   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5946   if ((AOP_TYPE (right) == AOP_LIT) &&
5947       (AOP_TYPE (result) == AOP_CRY) &&
5948       (AOP_TYPE (left) != AOP_CRY))
5949     {
5950       int posbit = isLiteralBit (lit);
5951       /* left &  2^n */
5952       if (posbit)
5953         {
5954           posbit--;
5955           MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
5956           // bit = left & 2^n
5957           if (size)
5958             emitcode ("mov", "c,acc.%d", posbit & 0x07);
5959           // if(left &  2^n)
5960           else
5961             {
5962               if (ifx)
5963                 {
5964                   sprintf (buffer, "acc.%d", posbit & 0x07);
5965                   genIfxJump (ifx, buffer);
5966                 }
5967               goto release;
5968             }
5969         }
5970       else
5971         {
5972           symbol *tlbl = newiTempLabel (NULL);
5973           int sizel = AOP_SIZE (left);
5974           if (size)
5975             emitcode ("setb", "c");
5976           while (sizel--)
5977             {
5978               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5979                 {
5980                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5981                   // byte ==  2^n ?
5982                   if ((posbit = isLiteralBit (bytelit)) != 0)
5983                     emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
5984                   else
5985                     {
5986                       if (bytelit != 0x0FFL)
5987                         emitcode ("anl", "a,%s",
5988                           aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
5989                       emitcode ("jnz", "!tlabel", tlbl->key + 100);
5990                     }
5991                 }
5992               offset++;
5993             }
5994           // bit = left & literal
5995           if (size)
5996             {
5997               emitcode ("clr", "c");
5998               emitcode ("", "!tlabeldef", tlbl->key + 100);
5999             }
6000           // if(left & literal)
6001           else
6002             {
6003               if (ifx)
6004                 jmpTrueOrFalse (ifx, tlbl);
6005               goto release;
6006             }
6007         }
6008       outBitC (result);
6009       goto release;
6010     }
6011
6012   /* if left is same as result */
6013   if (sameRegs (AOP (result), AOP (left)))
6014     {
6015       for (; size--; offset++)
6016         {
6017           if (AOP_TYPE (right) == AOP_LIT)
6018             {
6019               if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6020                 continue;
6021               else if (bytelit == 0)
6022                 aopPut (AOP (result), zero, offset);
6023               else if (IS_AOP_PREG (result))
6024                 {
6025                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6026                   emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6027                   aopPut (AOP (result), "a", offset);
6028                 }
6029               else
6030                 emitcode ("anl", "%s,%s",
6031                           aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6032                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6033             }
6034           else
6035             {
6036               if (AOP_TYPE (left) == AOP_ACC)
6037                 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6038               else
6039                 {
6040                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6041                   if (IS_AOP_PREG (result))
6042                     {
6043                       emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6044                       aopPut (AOP (result), "a", offset);
6045
6046                     }
6047                   else
6048                     emitcode ("anl", "%s,a",
6049                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6050                 }
6051             }
6052         }
6053     }
6054   else
6055     {
6056       // left & result in different registers
6057       if (AOP_TYPE (result) == AOP_CRY)
6058         {
6059           // result = bit
6060           // if(size), result in bit
6061           // if(!size && ifx), conditional oper: if(left & right)
6062           symbol *tlbl = newiTempLabel (NULL);
6063           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6064           if (size)
6065             emitcode ("setb", "c");
6066           while (sizer--)
6067             {
6068               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6069                 emitcode ("anl", "a,%s",
6070                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6071               } else {
6072                 if (AOP_TYPE(left)==AOP_ACC) {
6073                   emitcode("mov", "b,a");
6074                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6075                   emitcode("anl", "a,b");
6076                 }else {
6077                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6078                   emitcode ("anl", "a,%s",
6079                             aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6080                 }
6081               }
6082               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6083               offset++;
6084             }
6085           if (size)
6086             {
6087               CLRC;
6088               emitcode ("", "!tlabeldef", tlbl->key + 100);
6089               outBitC (result);
6090             }
6091           else if (ifx)
6092             jmpTrueOrFalse (ifx, tlbl);
6093         }
6094       else
6095         {
6096           for (; (size--); offset++)
6097             {
6098               // normal case
6099               // result = left & right
6100               if (AOP_TYPE (right) == AOP_LIT)
6101                 {
6102                   if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6103                     {
6104                       aopPut (AOP (result),
6105                            aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6106                               offset);
6107                       continue;
6108                     }
6109                   else if (bytelit == 0)
6110                     {
6111                       aopPut (AOP (result), zero, offset);
6112                       continue;
6113                     }
6114                   D (emitcode (";", "better literal AND."););
6115                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6116                   emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6117                                                     FALSE, FALSE, FALSE));
6118
6119                 }
6120               else
6121                 {
6122                   // faster than result <- left, anl result,right
6123                   // and better if result is SFR
6124                   if (AOP_TYPE (left) == AOP_ACC)
6125                     {
6126                       emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
6127                                                        FALSE, FALSE, FALSE));
6128                     }
6129                   else
6130                     {
6131                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6132                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6133                       {
6134                           emitcode("mov", "b,a");
6135                           rOp = "b";
6136                       }
6137                         
6138                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6139                       emitcode ("anl", "a,%s", rOp);
6140                     }                   
6141                 }
6142               aopPut (AOP (result), "a", offset);
6143             }
6144         }
6145     }
6146
6147 release:
6148   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6149   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6150   freeAsmop (result, NULL, ic, TRUE);
6151 }
6152
6153
6154 /*-----------------------------------------------------------------*/
6155 /* genOr  - code for or                                            */
6156 /*-----------------------------------------------------------------*/
6157 static void
6158 genOr (iCode * ic, iCode * ifx)
6159 {
6160   operand *left, *right, *result;
6161   int size, offset = 0;
6162   unsigned long lit = 0L;
6163   bool     pushResult;
6164
6165   D (emitcode (";", "genOr "););
6166
6167   AOP_OP_3_NOFATAL (ic, pushResult);
6168   AOP_SET_LOCALS (ic);
6169
6170   if (pushResult)
6171   {
6172       genFarFarLogicOp(ic, "orl");
6173       return;
6174   }
6175
6176
6177 #ifdef DEBUG_TYPE
6178   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6179             AOP_TYPE (result),
6180             AOP_TYPE (left), AOP_TYPE (right));
6181   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6182             AOP_SIZE (result),
6183             AOP_SIZE (left), AOP_SIZE (right));
6184 #endif
6185
6186   /* if left is a literal & right is not then exchange them */
6187   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6188 #ifdef LOGIC_OPS_BROKEN
6189    || AOP_NEEDSACC (left) // I think this is a net loss now.
6190 #endif      
6191       )
6192     {
6193       operand *tmp = right;
6194       right = left;
6195       left = tmp;
6196     }
6197
6198   /* if result = right then exchange them */
6199   if (sameRegs (AOP (result), AOP (right)))
6200     {
6201       operand *tmp = right;
6202       right = left;
6203       left = tmp;
6204     }
6205
6206   /* if right is bit then exchange them */
6207   if (AOP_TYPE (right) == AOP_CRY &&
6208       AOP_TYPE (left) != AOP_CRY)
6209     {
6210       operand *tmp = right;
6211       right = left;
6212       left = tmp;
6213     }
6214   if (AOP_TYPE (right) == AOP_LIT)
6215     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6216
6217   size = AOP_SIZE (result);
6218
6219   // if(bit | yy)
6220   // xx = bit | yy;
6221   if (AOP_TYPE (left) == AOP_CRY)
6222     {
6223       if (AOP_TYPE (right) == AOP_LIT)
6224         {
6225           // c = bit & literal;
6226           if (lit)
6227             {
6228               // lit != 0 => result = 1
6229               if (AOP_TYPE (result) == AOP_CRY)
6230                 {
6231                   if (size)
6232                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6233                   else if (ifx)
6234                     continueIfTrue (ifx);
6235                   goto release;
6236                 }
6237               emitcode ("setb", "c");
6238             }
6239           else
6240             {
6241               // lit == 0 => result = left
6242               if (size && sameRegs (AOP (result), AOP (left)))
6243                 goto release;
6244               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6245             }
6246         }
6247       else
6248         {
6249           if (AOP_TYPE (right) == AOP_CRY)
6250             {
6251               // c = bit | bit;
6252               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6253               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6254             }
6255           else
6256             {
6257               // c = bit | val;
6258               symbol *tlbl = newiTempLabel (NULL);
6259               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6260                 emitcode ("setb", "c");
6261               emitcode ("jb", "%s,!tlabel",
6262                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
6263               toBoolean (right);
6264               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6265               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6266                 {
6267                   jmpTrueOrFalse (ifx, tlbl);
6268                   goto release;
6269                 }
6270               else
6271                 {
6272                   CLRC;
6273                   emitcode ("", "!tlabeldef", tlbl->key + 100);
6274                 }
6275             }
6276         }
6277       // bit = c
6278       // val = c
6279       if (size)
6280         outBitC (result);
6281       // if(bit | ...)
6282       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6283         genIfxJump (ifx, "c");
6284       goto release;
6285     }
6286
6287   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6288   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6289   if ((AOP_TYPE (right) == AOP_LIT) &&
6290       (AOP_TYPE (result) == AOP_CRY) &&
6291       (AOP_TYPE (left) != AOP_CRY))
6292     {
6293       if (lit)
6294         {
6295           // result = 1
6296           if (size)
6297             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6298           else
6299             continueIfTrue (ifx);
6300           goto release;
6301         }
6302       else
6303         {
6304           // lit = 0, result = boolean(left)
6305           if (size)
6306             emitcode ("setb", "c");
6307           toBoolean (right);
6308           if (size)
6309             {
6310               symbol *tlbl = newiTempLabel (NULL);
6311               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6312               CLRC;
6313               emitcode ("", "!tlabeldef", tlbl->key + 100);
6314             }
6315           else
6316             {
6317               genIfxJump (ifx, "a");
6318               goto release;
6319             }
6320         }
6321       outBitC (result);
6322       goto release;
6323     }
6324
6325   /* if left is same as result */
6326   if (sameRegs (AOP (result), AOP (left)))
6327     {
6328       for (; size--; offset++)
6329         {
6330           if (AOP_TYPE (right) == AOP_LIT)
6331             {
6332               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6333                 {
6334                   continue;
6335                 }
6336               else
6337                 {
6338                   if (IS_AOP_PREG (left))
6339                     {
6340                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6341                       emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6342                       aopPut (AOP (result), "a", offset);
6343                     }
6344                   else
6345                     {
6346                       emitcode ("orl", "%s,%s",
6347                             aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6348                          aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6349                     }
6350                 }
6351             }
6352           else
6353             {
6354               if (AOP_TYPE (left) == AOP_ACC)
6355                 {
6356                   emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6357                 }
6358               else
6359                 {
6360                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6361                   if (IS_AOP_PREG (left))
6362                     {
6363                       emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6364                       aopPut (AOP (result), "a", offset);
6365                     }
6366                   else
6367                     {
6368                       emitcode ("orl", "%s,a",
6369                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6370                     }
6371                 }
6372             }
6373         }
6374     }
6375   else
6376     {
6377       // left & result in different registers
6378       if (AOP_TYPE (result) == AOP_CRY)
6379         {
6380           // result = bit
6381           // if(size), result in bit
6382           // if(!size && ifx), conditional oper: if(left | right)
6383           symbol *tlbl = newiTempLabel (NULL);
6384           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6385           if (size)
6386             emitcode ("setb", "c");
6387           while (sizer--)
6388             {
6389               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6390                 emitcode ("orl", "a,%s",
6391                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6392               } else {
6393                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6394                 emitcode ("orl", "a,%s",
6395                           aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6396               }
6397               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6398               offset++;
6399             }
6400           if (size)
6401             {
6402               CLRC;
6403               emitcode ("", "!tlabeldef", tlbl->key + 100);
6404               outBitC (result);
6405             }
6406           else if (ifx)
6407             jmpTrueOrFalse (ifx, tlbl);
6408         }
6409       else
6410         {
6411             _startLazyDPSEvaluation();
6412           for (; (size--); offset++)
6413             {
6414               // normal case
6415               // result = left & right
6416               if (AOP_TYPE (right) == AOP_LIT)
6417                 {
6418                   if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6419                     {
6420                       aopPut (AOP (result),
6421                            aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6422                               offset);
6423                       continue;
6424                     }
6425                   D (emitcode (";", "better literal OR."););
6426                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6427                   emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
6428                                                     FALSE, FALSE, FALSE));
6429
6430                 }
6431               else
6432                 {
6433                   // faster than result <- left, anl result,right
6434                   // and better if result is SFR
6435                   if (AOP_TYPE (left) == AOP_ACC)
6436                     {
6437                       emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
6438                                                        FALSE, FALSE, FALSE));
6439                     }
6440                   else
6441                     {
6442                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6443                         
6444                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6445                       {
6446                           emitcode("mov", "b,a");
6447                           rOp = "b";
6448                       }
6449                         
6450                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6451                       emitcode ("orl", "a,%s", rOp);
6452                     }
6453                 }
6454               aopPut (AOP (result), "a", offset);
6455             }
6456             _endLazyDPSEvaluation();
6457         }
6458     }
6459
6460 release:
6461   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6462   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6463   freeAsmop (result, NULL, ic, TRUE);
6464 }
6465
6466 /*-----------------------------------------------------------------*/
6467 /* genXor - code for xclusive or                                   */
6468 /*-----------------------------------------------------------------*/
6469 static void
6470 genXor (iCode * ic, iCode * ifx)
6471 {
6472   operand *left, *right, *result;
6473   int size, offset = 0;
6474   unsigned long lit = 0L;
6475   bool pushResult;
6476
6477   D (emitcode (";", "genXor "););
6478
6479   AOP_OP_3_NOFATAL (ic, pushResult);
6480   AOP_SET_LOCALS (ic);
6481
6482   if (pushResult)
6483   {
6484       genFarFarLogicOp(ic, "xrl");
6485       return;
6486   }  
6487
6488 #ifdef DEBUG_TYPE
6489   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6490             AOP_TYPE (result),
6491             AOP_TYPE (left), AOP_TYPE (right));
6492   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6493             AOP_SIZE (result),
6494             AOP_SIZE (left), AOP_SIZE (right));
6495 #endif
6496
6497   /* if left is a literal & right is not ||
6498      if left needs acc & right does not */
6499   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) 
6500 #ifdef LOGIC_OPS_BROKEN      
6501       || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6502 #endif
6503      )
6504     {
6505       operand *tmp = right;
6506       right = left;
6507       left = tmp;
6508     }
6509
6510   /* if result = right then exchange them */
6511   if (sameRegs (AOP (result), AOP (right)))
6512     {
6513       operand *tmp = right;
6514       right = left;
6515       left = tmp;
6516     }
6517
6518   /* if right is bit then exchange them */
6519   if (AOP_TYPE (right) == AOP_CRY &&
6520       AOP_TYPE (left) != AOP_CRY)
6521     {
6522       operand *tmp = right;
6523       right = left;
6524       left = tmp;
6525     }
6526   if (AOP_TYPE (right) == AOP_LIT)
6527     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6528
6529   size = AOP_SIZE (result);
6530
6531   // if(bit ^ yy)
6532   // xx = bit ^ yy;
6533   if (AOP_TYPE (left) == AOP_CRY)
6534     {
6535       if (AOP_TYPE (right) == AOP_LIT)
6536         {
6537           // c = bit & literal;
6538           if (lit >> 1)
6539             {
6540               // lit>>1  != 0 => result = 1
6541               if (AOP_TYPE (result) == AOP_CRY)
6542                 {
6543                   if (size)
6544                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6545                   else if (ifx)
6546                     continueIfTrue (ifx);
6547                   goto release;
6548                 }
6549               emitcode ("setb", "c");
6550             }
6551           else
6552             {
6553               // lit == (0 or 1)
6554               if (lit == 0)
6555                 {
6556                   // lit == 0, result = left
6557                   if (size && sameRegs (AOP (result), AOP (left)))
6558                     goto release;
6559                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6560                 }
6561               else
6562                 {
6563                   // lit == 1, result = not(left)
6564                   if (size && sameRegs (AOP (result), AOP (left)))
6565                     {
6566                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6567                       goto release;
6568                     }
6569                   else
6570                     {
6571                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6572                       emitcode ("cpl", "c");
6573                     }
6574                 }
6575             }
6576
6577         }
6578       else
6579         {
6580           // right != literal
6581           symbol *tlbl = newiTempLabel (NULL);
6582           if (AOP_TYPE (right) == AOP_CRY)
6583             {
6584               // c = bit ^ bit;
6585               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6586             }
6587           else
6588             {
6589               int sizer = AOP_SIZE (right);
6590               // c = bit ^ val
6591               // if val>>1 != 0, result = 1
6592               emitcode ("setb", "c");
6593               while (sizer)
6594                 {
6595                   MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
6596                   if (sizer == 1)
6597                     // test the msb of the lsb
6598                     emitcode ("anl", "a,#!constbyte",0xfe);
6599                   emitcode ("jnz", "!tlabel", tlbl->key + 100);
6600                   sizer--;
6601                 }
6602               // val = (0,1)
6603               emitcode ("rrc", "a");
6604             }
6605           emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6606           emitcode ("cpl", "c");
6607           emitcode ("", "!tlabeldef", (tlbl->key + 100));
6608         }
6609       // bit = c
6610       // val = c
6611       if (size)
6612         outBitC (result);
6613       // if(bit | ...)
6614       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6615         genIfxJump (ifx, "c");
6616       goto release;
6617     }
6618
6619   if (sameRegs (AOP (result), AOP (left)))
6620     {
6621       /* if left is same as result */
6622       for (; size--; offset++)
6623         {
6624           if (AOP_TYPE (right) == AOP_LIT)
6625             {
6626               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6627                 continue;
6628               else if (IS_AOP_PREG (left))
6629                 {
6630                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6631                   emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6632                   aopPut (AOP (result), "a", offset);
6633                 }
6634               else
6635                 emitcode ("xrl", "%s,%s",
6636                           aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6637                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6638             }
6639           else
6640             {
6641               if (AOP_TYPE (left) == AOP_ACC)
6642                 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6643               else
6644                 {
6645                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6646                   if (IS_AOP_PREG (left))
6647                     {
6648                       emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6649                       aopPut (AOP (result), "a", offset);
6650                     }
6651                   else
6652                     emitcode ("xrl", "%s,a",
6653                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6654                 }
6655             }
6656         }
6657     }
6658   else
6659     {
6660       // left & result in different registers
6661       if (AOP_TYPE (result) == AOP_CRY)
6662         {
6663           // result = bit
6664           // if(size), result in bit
6665           // if(!size && ifx), conditional oper: if(left ^ right)
6666           symbol *tlbl = newiTempLabel (NULL);
6667           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6668                   
6669           if (size)
6670             emitcode ("setb", "c");
6671           while (sizer--)
6672             {
6673               if ((AOP_TYPE (right) == AOP_LIT) &&
6674                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6675                 {
6676                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6677                 }
6678               else
6679                 {
6680                   if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6681                     emitcode ("xrl", "a,%s",
6682                               aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6683                   } else {
6684                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6685                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6686                       {
6687                           emitcode("mov", "b,a");
6688                           rOp = "b";
6689                       }
6690                         
6691                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6692                       emitcode ("xrl", "a,%s", rOp);                  
6693                   }
6694                 }
6695               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6696               offset++;
6697             }
6698           if (size)
6699             {
6700               CLRC;
6701               emitcode ("", "!tlabeldef", tlbl->key + 100);
6702               outBitC (result);
6703             }
6704           else if (ifx)
6705             jmpTrueOrFalse (ifx, tlbl);
6706         }
6707       else
6708         {
6709         for (; (size--); offset++)
6710           {
6711             // normal case
6712             // result = left & right
6713             if (AOP_TYPE (right) == AOP_LIT)
6714               {
6715                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6716                   {
6717                     aopPut (AOP (result),
6718                             aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6719                             offset);
6720                     continue;
6721                   }
6722                 D (emitcode (";", "better literal XOR."););
6723                 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6724                 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
6725                                                   FALSE, FALSE, FALSE));
6726               }
6727             else
6728               {
6729                 // faster than result <- left, anl result,right
6730                 // and better if result is SFR
6731                 if (AOP_TYPE (left) == AOP_ACC)
6732                   {
6733                     emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
6734                                                      FALSE, FALSE, FALSE));
6735                   }
6736                 else
6737                   {
6738                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6739                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6740                       {
6741                           emitcode("mov", "b,a");
6742                           rOp = "b";
6743                       }
6744                         
6745                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6746                       emitcode ("xrl", "a,%s", rOp);
6747                   }
6748               }
6749             aopPut (AOP (result), "a", offset);
6750           }
6751         }
6752         
6753     }
6754
6755 release:
6756   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6757   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6758   freeAsmop (result, NULL, ic, TRUE);
6759 }
6760
6761 /*-----------------------------------------------------------------*/
6762 /* genInline - write the inline code out                           */
6763 /*-----------------------------------------------------------------*/
6764 static void
6765 genInline (iCode * ic)
6766 {
6767   char *buffer, *bp, *bp1;
6768
6769   D (emitcode (";", "genInline ");
6770     );
6771
6772   _G.inLine += (!options.asmpeep);
6773
6774   buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6775   strcpy (buffer, IC_INLINE (ic));
6776
6777   /* emit each line as a code */
6778   while (*bp)
6779     {
6780       if (*bp == '\n')
6781         {
6782           *bp++ = '\0';
6783           emitcode (bp1, "");
6784           bp1 = bp;
6785         }
6786       else
6787         {
6788           if (*bp == ':')
6789             {
6790               bp++;
6791               *bp = '\0';
6792               bp++;
6793               emitcode (bp1, "");
6794               bp1 = bp;
6795             }
6796           else
6797             bp++;
6798         }
6799     }
6800   if (bp1 != bp)
6801     emitcode (bp1, "");
6802   /*     emitcode("",buffer); */
6803   _G.inLine -= (!options.asmpeep);
6804 }
6805
6806 /*-----------------------------------------------------------------*/
6807 /* genRRC - rotate right with carry                                */
6808 /*-----------------------------------------------------------------*/
6809 static void
6810 genRRC (iCode * ic)
6811 {
6812   operand *left, *result;
6813   int size, offset = 0;
6814   char *l;
6815
6816   D (emitcode (";", "genRRC ");
6817     );
6818
6819   /* rotate right with carry */
6820   left = IC_LEFT (ic);
6821   result = IC_RESULT (ic);
6822   aopOp (left, ic, FALSE, FALSE);
6823   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6824
6825   /* move it to the result */
6826   size = AOP_SIZE (result);
6827   offset = size - 1;
6828   CLRC;
6829
6830   _startLazyDPSEvaluation ();
6831   while (size--)
6832     {
6833       l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6834       MOVA (l);
6835       emitcode ("rrc", "a");
6836       if (AOP_SIZE (result) > 1)
6837         aopPut (AOP (result), "a", offset--);
6838     }
6839   _endLazyDPSEvaluation ();
6840
6841   /* now we need to put the carry into the
6842      highest order byte of the result */
6843   if (AOP_SIZE (result) > 1)
6844     {
6845       l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
6846       MOVA (l);
6847     }
6848   emitcode ("mov", "acc.7,c");
6849   aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
6850   freeAsmop (left, NULL, ic, TRUE);
6851   freeAsmop (result, NULL, ic, TRUE);
6852 }
6853
6854 /*-----------------------------------------------------------------*/
6855 /* genRLC - generate code for rotate left with carry               */
6856 /*-----------------------------------------------------------------*/
6857 static void
6858 genRLC (iCode * ic)
6859 {
6860   operand *left, *result;
6861   int size, offset = 0;
6862   char *l;
6863
6864   D (emitcode (";", "genRLC ");
6865     );
6866
6867   /* rotate right with carry */
6868   left = IC_LEFT (ic);
6869   result = IC_RESULT (ic);
6870   aopOp (left, ic, FALSE, FALSE);
6871   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6872
6873   /* move it to the result */
6874   size = AOP_SIZE (result);
6875   offset = 0;
6876   if (size--)
6877     {
6878       l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6879       MOVA (l);
6880       emitcode ("add", "a,acc");
6881       if (AOP_SIZE (result) > 1)
6882         {
6883           aopPut (AOP (result), "a", offset++);
6884         }
6885
6886       _startLazyDPSEvaluation ();
6887       while (size--)
6888         {
6889           l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6890           MOVA (l);
6891           emitcode ("rlc", "a");
6892           if (AOP_SIZE (result) > 1)
6893             aopPut (AOP (result), "a", offset++);
6894         }
6895       _endLazyDPSEvaluation ();
6896     }
6897   /* now we need to put the carry into the
6898      highest order byte of the result */
6899   if (AOP_SIZE (result) > 1)
6900     {
6901       l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
6902       MOVA (l);
6903     }
6904   emitcode ("mov", "acc.0,c");
6905   aopPut (AOP (result), "a", 0);
6906   freeAsmop (left, NULL, ic, TRUE);
6907   freeAsmop (result, NULL, ic, TRUE);
6908 }
6909
6910 /*-----------------------------------------------------------------*/
6911 /* genGetHbit - generates code get highest order bit               */
6912 /*-----------------------------------------------------------------*/
6913 static void
6914 genGetHbit (iCode * ic)
6915 {
6916   operand *left, *result;
6917   left = IC_LEFT (ic);
6918   result = IC_RESULT (ic);
6919   aopOp (left, ic, FALSE, FALSE);
6920   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6921
6922   D (emitcode (";", "genGetHbit ");
6923     );
6924
6925   /* get the highest order byte into a */
6926   MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
6927   if (AOP_TYPE (result) == AOP_CRY)
6928     {
6929       emitcode ("rlc", "a");
6930       outBitC (result);
6931     }
6932   else
6933     {
6934       emitcode ("rl", "a");
6935       emitcode ("anl", "a,#1");
6936       outAcc (result);
6937     }
6938
6939
6940   freeAsmop (left, NULL, ic, TRUE);
6941   freeAsmop (result, NULL, ic, TRUE);
6942 }
6943
6944 /*-----------------------------------------------------------------*/
6945 /* AccRol - rotate left accumulator by known count                 */
6946 /*-----------------------------------------------------------------*/
6947 static void
6948 AccRol (int shCount)
6949 {
6950   shCount &= 0x0007;            // shCount : 0..7
6951
6952   switch (shCount)
6953     {
6954     case 0:
6955       break;
6956     case 1:
6957       emitcode ("rl", "a");
6958       break;
6959     case 2:
6960       emitcode ("rl", "a");
6961       emitcode ("rl", "a");
6962       break;
6963     case 3:
6964       emitcode ("swap", "a");
6965       emitcode ("rr", "a");
6966       break;
6967     case 4:
6968       emitcode ("swap", "a");
6969       break;
6970     case 5:
6971       emitcode ("swap", "a");
6972       emitcode ("rl", "a");
6973       break;
6974     case 6:
6975       emitcode ("rr", "a");
6976       emitcode ("rr", "a");
6977       break;
6978     case 7:
6979       emitcode ("rr", "a");
6980       break;
6981     }
6982 }
6983
6984 /*-----------------------------------------------------------------*/
6985 /* AccLsh - left shift accumulator by known count                  */
6986 /*-----------------------------------------------------------------*/
6987 static void
6988 AccLsh (int shCount)
6989 {
6990   if (shCount != 0)
6991     {
6992       if (shCount == 1)
6993         emitcode ("add", "a,acc");
6994       else if (shCount == 2)
6995         {
6996           emitcode ("add", "a,acc");
6997           emitcode ("add", "a,acc");
6998         }
6999       else
7000         {
7001           /* rotate left accumulator */
7002           AccRol (shCount);
7003           /* and kill the lower order bits */
7004           emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7005         }
7006     }
7007 }
7008
7009 /*-----------------------------------------------------------------*/
7010 /* AccRsh - right shift accumulator by known count                 */
7011 /*-----------------------------------------------------------------*/
7012 static void
7013 AccRsh (int shCount)
7014 {
7015   if (shCount != 0)
7016     {
7017       if (shCount == 1)
7018         {
7019           CLRC;
7020           emitcode ("rrc", "a");
7021         }
7022       else
7023         {
7024           /* rotate right accumulator */
7025           AccRol (8 - shCount);
7026           /* and kill the higher order bits */
7027           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7028         }
7029     }
7030 }
7031
7032 #ifdef BETTER_LITERAL_SHIFT
7033 /*-----------------------------------------------------------------*/
7034 /* AccSRsh - signed right shift accumulator by known count                 */
7035 /*-----------------------------------------------------------------*/
7036 static void
7037 AccSRsh (int shCount)
7038 {
7039   symbol *tlbl;
7040   if (shCount != 0)
7041     {
7042       if (shCount == 1)
7043         {
7044           emitcode ("mov", "c,acc.7");
7045           emitcode ("rrc", "a");
7046         }
7047       else if (shCount == 2)
7048         {
7049           emitcode ("mov", "c,acc.7");
7050           emitcode ("rrc", "a");
7051           emitcode ("mov", "c,acc.7");
7052           emitcode ("rrc", "a");
7053         }
7054       else
7055         {
7056           tlbl = newiTempLabel (NULL);
7057           /* rotate right accumulator */
7058           AccRol (8 - shCount);
7059           /* and kill the higher order bits */
7060           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7061           emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7062           emitcode ("orl", "a,#!constbyte",
7063                     (unsigned char) ~SRMask[shCount]);
7064           emitcode ("", "!tlabeldef", tlbl->key + 100);
7065         }
7066     }
7067 }
7068 #endif
7069
7070 #ifdef BETTER_LITERAL_SHIFT
7071 /*-----------------------------------------------------------------*/
7072 /* shiftR1Left2Result - shift right one byte from left to result   */
7073 /*-----------------------------------------------------------------*/
7074 static void
7075 shiftR1Left2Result (operand * left, int offl,
7076                     operand * result, int offr,
7077                     int shCount, int sign)
7078 {
7079   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7080   /* shift right accumulator */
7081   if (sign)
7082     AccSRsh (shCount);
7083   else
7084     AccRsh (shCount);
7085   aopPut (AOP (result), "a", offr);
7086 }
7087 #endif
7088
7089 #ifdef BETTER_LITERAL_SHIFT
7090 /*-----------------------------------------------------------------*/
7091 /* shiftL1Left2Result - shift left one byte from left to result    */
7092 /*-----------------------------------------------------------------*/
7093 static void
7094 shiftL1Left2Result (operand * left, int offl,
7095                     operand * result, int offr, int shCount)
7096 {
7097   MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7098   /* shift left accumulator */
7099   AccLsh (shCount);
7100   aopPut (AOP (result), "a", offr);
7101 }
7102 #endif
7103
7104 #ifdef BETTER_LITERAL_SHIFT
7105 /*-----------------------------------------------------------------*/
7106 /* movLeft2Result - move byte from left to result                  */
7107 /*-----------------------------------------------------------------*/
7108 static void
7109 movLeft2Result (operand * left, int offl,
7110                 operand * result, int offr, int sign)
7111 {
7112   char *l;
7113   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7114   {
7115       l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
7116
7117       if (*l == '@' && (IS_AOP_PREG (result)))
7118       {
7119           emitcode ("mov", "a,%s", l);
7120           aopPut (AOP (result), "a", offr);
7121       }
7122       else
7123       {
7124           if (!sign)
7125           {
7126             aopPut (AOP (result), l, offr);
7127           }
7128           else
7129             {
7130               /* MSB sign in acc.7 ! */
7131               if (getDataSize (left) == offl + 1)
7132                 {
7133                   emitcode ("mov", "a,%s", l);
7134                   aopPut (AOP (result), "a", offr);
7135                 }
7136             }
7137       }
7138   }
7139 }
7140 #endif
7141
7142 #ifdef BETTER_LITERAL_SHIFT
7143 /*-----------------------------------------------------------------*/
7144 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
7145 /*-----------------------------------------------------------------*/
7146 static void
7147 AccAXRrl1 (char *x)
7148 {
7149   emitcode ("rrc", "a");
7150   emitcode ("xch", "a,%s", x);
7151   emitcode ("rrc", "a");
7152   emitcode ("xch", "a,%s", x);
7153 }
7154 #endif
7155
7156 #ifdef BETTER_LITERAL_SHIFT
7157 //REMOVE ME!!!
7158 /*-----------------------------------------------------------------*/
7159 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
7160 /*-----------------------------------------------------------------*/
7161 static void
7162 AccAXLrl1 (char *x)
7163 {
7164   emitcode ("xch", "a,%s", x);
7165   emitcode ("rlc", "a");
7166   emitcode ("xch", "a,%s", x);
7167   emitcode ("rlc", "a");
7168 }
7169 #endif
7170
7171 #ifdef BETTER_LITERAL_SHIFT
7172 /*-----------------------------------------------------------------*/
7173 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
7174 /*-----------------------------------------------------------------*/
7175 static void
7176 AccAXLsh1 (char *x)
7177 {
7178   emitcode ("xch", "a,%s", x);
7179   emitcode ("add", "a,acc");
7180   emitcode ("xch", "a,%s", x);
7181   emitcode ("rlc", "a");
7182 }
7183 #endif
7184
7185 #ifdef BETTER_LITERAL_SHIFT
7186 /*-----------------------------------------------------------------*/
7187 /* AccAXLsh - left shift a:x by known count (0..7)                 */
7188 /*-----------------------------------------------------------------*/
7189 static void
7190 AccAXLsh (char *x, int shCount)
7191 {
7192   switch (shCount)
7193     {
7194     case 0:
7195       break;
7196     case 1:
7197       AccAXLsh1 (x);
7198       break;
7199     case 2:
7200       AccAXLsh1 (x);
7201       AccAXLsh1 (x);
7202       break;
7203     case 3:
7204     case 4:
7205     case 5:                     // AAAAABBB:CCCCCDDD
7206
7207       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
7208
7209       emitcode ("anl", "a,#!constbyte",
7210                 SLMask[shCount]);       // BBB00000:CCCCCDDD
7211
7212       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
7213
7214       AccRol (shCount);         // DDDCCCCC:BBB00000
7215
7216       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
7217
7218       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
7219
7220       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
7221
7222       emitcode ("anl", "a,#!constbyte",
7223                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
7224
7225       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
7226
7227       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
7228
7229       break;
7230     case 6:                     // AAAAAABB:CCCCCCDD
7231       emitcode ("anl", "a,#!constbyte",
7232                 SRMask[shCount]);       // 000000BB:CCCCCCDD
7233       emitcode ("mov", "c,acc.0");      // c = B
7234       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
7235 #if 0
7236       AccAXRrl1 (x);            // BCCCCCCD:D000000B
7237       AccAXRrl1 (x);            // BBCCCCCC:DD000000
7238 #else
7239       emitcode("rrc","a"); 
7240       emitcode("xch","a,%s", x); 
7241       emitcode("rrc","a"); 
7242       emitcode("mov","c,acc.0"); //<< get correct bit 
7243       emitcode("xch","a,%s", x); 
7244
7245       emitcode("rrc","a"); 
7246       emitcode("xch","a,%s", x); 
7247       emitcode("rrc","a"); 
7248       emitcode("xch","a,%s", x); 
7249 #endif
7250       break;
7251     case 7:                     // a:x <<= 7
7252
7253       emitcode ("anl", "a,#!constbyte",
7254                 SRMask[shCount]);       // 0000000B:CCCCCCCD
7255
7256       emitcode ("mov", "c,acc.0");      // c = B
7257
7258       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
7259
7260       AccAXRrl1 (x);            // BCCCCCCC:D0000000
7261
7262       break;
7263     default:
7264       break;
7265     }
7266 }
7267 #endif
7268
7269 #ifdef BETTER_LITERAL_SHIFT
7270 //REMOVE ME!!!
7271 /*-----------------------------------------------------------------*/
7272 /* AccAXRsh - right shift a:x known count (0..7)                   */
7273 /*-----------------------------------------------------------------*/
7274 static void
7275 AccAXRsh (char *x, int shCount)
7276 {
7277   switch (shCount)
7278     {
7279     case 0:
7280       break;
7281     case 1:
7282       CLRC;
7283       AccAXRrl1 (x);            // 0->a:x
7284
7285       break;
7286     case 2:
7287       CLRC;
7288       AccAXRrl1 (x);            // 0->a:x
7289
7290       CLRC;
7291       AccAXRrl1 (x);            // 0->a:x
7292
7293       break;
7294     case 3:
7295     case 4:
7296     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7297
7298       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
7299
7300       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7301
7302       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7303
7304       emitcode ("anl", "a,#!constbyte",
7305                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7306
7307       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7308
7309       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7310
7311       emitcode ("anl", "a,#!constbyte",
7312                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7313
7314       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7315
7316       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7317
7318       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
7319
7320       break;
7321     case 6:                     // AABBBBBB:CCDDDDDD
7322
7323       emitcode ("mov", "c,acc.7");
7324       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7325
7326       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7327
7328       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7329
7330       emitcode ("anl", "a,#!constbyte",
7331                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7332
7333       break;
7334     case 7:                     // ABBBBBBB:CDDDDDDD
7335
7336       emitcode ("mov", "c,acc.7");      // c = A
7337
7338       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7339
7340       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7341
7342       emitcode ("anl", "a,#!constbyte",
7343                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7344
7345       break;
7346     default:
7347       break;
7348     }
7349 }
7350 #endif
7351
7352 #ifdef BETTER_LITERAL_SHIFT
7353 /*-----------------------------------------------------------------*/
7354 /* AccAXRshS - right shift signed a:x known count (0..7)           */
7355 /*-----------------------------------------------------------------*/
7356 static void
7357 AccAXRshS (char *x, int shCount)
7358 {
7359   symbol *tlbl;
7360   switch (shCount)
7361     {
7362     case 0:
7363       break;
7364     case 1:
7365       emitcode ("mov", "c,acc.7");
7366       AccAXRrl1 (x);            // s->a:x
7367
7368       break;
7369     case 2:
7370       emitcode ("mov", "c,acc.7");
7371       AccAXRrl1 (x);            // s->a:x
7372
7373       emitcode ("mov", "c,acc.7");
7374       AccAXRrl1 (x);            // s->a:x
7375
7376       break;
7377     case 3:
7378     case 4:
7379     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7380
7381       tlbl = newiTempLabel (NULL);
7382       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
7383
7384       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7385
7386       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7387
7388       emitcode ("anl", "a,#!constbyte",
7389                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7390
7391       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7392
7393       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7394
7395       emitcode ("anl", "a,#!constbyte",
7396                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7397
7398       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7399
7400       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7401
7402       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
7403
7404       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7405       emitcode ("orl", "a,#!constbyte",
7406                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
7407
7408       emitcode ("", "!tlabeldef", tlbl->key + 100);
7409       break;                    // SSSSAAAA:BBBCCCCC
7410
7411     case 6:                     // AABBBBBB:CCDDDDDD
7412
7413       tlbl = newiTempLabel (NULL);
7414       emitcode ("mov", "c,acc.7");
7415       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7416
7417       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7418
7419       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7420
7421       emitcode ("anl", "a,#!constbyte",
7422                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7423
7424       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7425       emitcode ("orl", "a,#!constbyte",
7426                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
7427
7428       emitcode ("", "!tlabeldef", tlbl->key + 100);
7429       break;
7430     case 7:                     // ABBBBBBB:CDDDDDDD
7431
7432       tlbl = newiTempLabel (NULL);
7433       emitcode ("mov", "c,acc.7");      // c = A
7434
7435       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7436
7437       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7438
7439       emitcode ("anl", "a,#!constbyte",
7440                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7441
7442       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7443       emitcode ("orl", "a,#!constbyte",
7444                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
7445
7446       emitcode ("", "!tlabeldef", tlbl->key + 100);
7447       break;
7448     default:
7449       break;
7450     }
7451 }
7452 #endif
7453
7454 #ifdef BETTER_LITERAL_SHIFT
7455 static void
7456 _loadLeftIntoAx(char    **lsb, 
7457                 operand *left, 
7458                 operand *result,
7459                 int     offl,
7460                 int     offr)
7461 {
7462   // Get the initial value from left into a pair of registers.
7463   // MSB must be in A, LSB can be any register.
7464   //
7465   // If the result is held in registers, it is an optimization
7466   // if the LSB can be held in the register which will hold the,
7467   // result LSB since this saves us from having to copy it into
7468   // the result following AccAXLsh.
7469   //
7470   // If the result is addressed indirectly, this is not a gain.
7471   if (AOP_NEEDSACC(result))
7472   {
7473        char *leftByte;
7474        
7475        _startLazyDPSEvaluation();
7476       if (AOP_TYPE(left) == AOP_DPTR2)
7477        {
7478            // Get MSB in A.
7479            MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
7480            // get LSB in DP2_RESULT_REG.
7481            leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
7482            assert(!strcmp(leftByte, DP2_RESULT_REG));
7483        }
7484        else
7485        {
7486            // get LSB into DP2_RESULT_REG
7487            leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
7488            if (strcmp(leftByte, DP2_RESULT_REG))
7489            {
7490                TR_AP("#7");
7491                emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7492            }
7493            // And MSB in A.
7494            leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
7495            assert(strcmp(leftByte, DP2_RESULT_REG));
7496            MOVA(leftByte);
7497        }
7498        _endLazyDPSEvaluation();
7499        *lsb = DP2_RESULT_REG;
7500   }
7501   else
7502   {
7503       if (sameRegs (AOP (result), AOP (left)) &&
7504         ((offl + MSB16) == offr))
7505       {
7506           /* don't crash result[offr] */
7507           MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
7508           emitcode ("xch", "a,%s", 
7509                     aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
7510       }
7511       else
7512       {
7513           movLeft2Result (left, offl, result, offr, 0);
7514           MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
7515       }
7516       *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
7517       assert(strcmp(*lsb,"a"));      
7518   }
7519 }
7520
7521 static void
7522 _storeAxResults(char    *lsb,
7523                 operand *result,
7524                 int     offr)
7525 {
7526   _startLazyDPSEvaluation();
7527   if (AOP_NEEDSACC(result))
7528   {
7529       /* We have to explicitly update the result LSB.
7530        */
7531       emitcode("xch","a,%s", lsb);
7532       aopPut(AOP(result), "a", offr);
7533       emitcode("mov","a,%s", lsb);
7534   }
7535   if (getDataSize (result) > 1)
7536   {
7537       aopPut (AOP (result), "a", offr + MSB16);
7538   }
7539   _endLazyDPSEvaluation();
7540 }
7541
7542 /*-----------------------------------------------------------------*/
7543 /* shiftL2Left2Result - shift left two bytes from left to result   */
7544 /*-----------------------------------------------------------------*/
7545 static void
7546 shiftL2Left2Result (operand * left, int offl,
7547                     operand * result, int offr, int shCount)
7548 {
7549   char *lsb;
7550
7551   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7552   
7553   AccAXLsh (lsb, shCount);
7554   
7555   _storeAxResults(lsb, result, offr);
7556 }
7557 #endif
7558
7559 #ifdef BETTER_LITERAL_SHIFT
7560 /*-----------------------------------------------------------------*/
7561 /* shiftR2Left2Result - shift right two bytes from left to result  */
7562 /*-----------------------------------------------------------------*/
7563 static void
7564 shiftR2Left2Result (operand * left, int offl,
7565                     operand * result, int offr,
7566                     int shCount, int sign)
7567 {
7568   char *lsb;
7569   
7570   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7571   
7572   /* a:x >> shCount (x = lsb(result)) */
7573   if (sign)
7574   {
7575      AccAXRshS(lsb, shCount);
7576   }
7577   else
7578   {
7579     AccAXRsh(lsb, shCount);
7580   }
7581   
7582   _storeAxResults(lsb, result, offr);
7583 }
7584 #endif
7585
7586 #if 0
7587 //REMOVE ME!!!
7588 /*-----------------------------------------------------------------*/
7589 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7590 /*-----------------------------------------------------------------*/
7591 static void
7592 shiftLLeftOrResult (operand * left, int offl,
7593                     operand * result, int offr, int shCount)
7594 {
7595   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7596   /* shift left accumulator */
7597   AccLsh (shCount);
7598   /* or with result */
7599   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7600   /* back to result */
7601   aopPut (AOP (result), "a", offr);
7602 }
7603 #endif
7604
7605 #if 0
7606 //REMOVE ME!!!
7607 /*-----------------------------------------------------------------*/
7608 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7609 /*-----------------------------------------------------------------*/
7610 static void
7611 shiftRLeftOrResult (operand * left, int offl,
7612                     operand * result, int offr, int shCount)
7613 {
7614   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7615   /* shift right accumulator */
7616   AccRsh (shCount);
7617   /* or with result */
7618   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7619   /* back to result */
7620   aopPut (AOP (result), "a", offr);
7621 }
7622 #endif
7623
7624 #ifdef BETTER_LITERAL_SHIFT
7625 /*-----------------------------------------------------------------*/
7626 /* genlshOne - left shift a one byte quantity by known count       */
7627 /*-----------------------------------------------------------------*/
7628 static void
7629 genlshOne (operand * result, operand * left, int shCount)
7630 {
7631   D (emitcode (";", "genlshOne "););
7632   shiftL1Left2Result (left, LSB, result, LSB, shCount);
7633 }
7634 #endif
7635
7636 #ifdef BETTER_LITERAL_SHIFT
7637 /*-----------------------------------------------------------------*/
7638 /* genlshTwo - left shift two bytes by known amount != 0           */
7639 /*-----------------------------------------------------------------*/
7640 static void
7641 genlshTwo (operand * result, operand * left, int shCount)
7642 {
7643   int size;
7644
7645   D (emitcode (";", "genlshTwo "););
7646
7647   size = getDataSize (result);
7648
7649   /* if shCount >= 8 */
7650   if (shCount >= 8)
7651   {
7652       shCount -= 8;
7653
7654       _startLazyDPSEvaluation();
7655
7656       if (size > 1)
7657         {
7658           if (shCount)
7659           {
7660             _endLazyDPSEvaluation();
7661             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7662             aopPut (AOP (result), zero, LSB);       
7663           }
7664           else
7665           {
7666             movLeft2Result (left, LSB, result, MSB16, 0);
7667             aopPut (AOP (result), zero, LSB);
7668             _endLazyDPSEvaluation();
7669           }
7670         }
7671         else
7672         {
7673           aopPut (AOP (result), zero, LSB);
7674           _endLazyDPSEvaluation();
7675         }
7676   }
7677
7678   /*  1 <= shCount <= 7 */
7679   else
7680     {
7681       if (size == 1)
7682       {
7683         shiftL1Left2Result (left, LSB, result, LSB, shCount);
7684       }
7685       else
7686       {
7687         shiftL2Left2Result (left, LSB, result, LSB, shCount);
7688       }
7689     }
7690 }
7691 #endif
7692
7693 #if 0
7694 //REMOVE ME!!!
7695 /*-----------------------------------------------------------------*/
7696 /* shiftLLong - shift left one long from left to result            */
7697 /* offl = LSB or MSB16                                             */
7698 /*-----------------------------------------------------------------*/
7699 static void
7700 shiftLLong (operand * left, operand * result, int offr)
7701 {
7702   char *l;
7703   int size = AOP_SIZE (result);
7704
7705   if (size >= LSB + offr)
7706     {
7707       l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
7708       MOVA (l);
7709       emitcode ("add", "a,acc");
7710       if (sameRegs (AOP (left), AOP (result)) &&
7711           size >= MSB16 + offr && offr != LSB)
7712         emitcode ("xch", "a,%s",
7713                   aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
7714       else
7715         aopPut (AOP (result), "a", LSB + offr);
7716     }
7717
7718   if (size >= MSB16 + offr)
7719     {
7720       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7721         {
7722           l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
7723           MOVA (l);
7724         }
7725       emitcode ("rlc", "a");
7726       if (sameRegs (AOP (left), AOP (result)) &&
7727           size >= MSB24 + offr && offr != LSB)
7728         emitcode ("xch", "a,%s",
7729                   aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
7730       else
7731         aopPut (AOP (result), "a", MSB16 + offr);
7732     }
7733
7734   if (size >= MSB24 + offr)
7735     {
7736       if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7737         {
7738           l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
7739           MOVA (l);
7740         }
7741       emitcode ("rlc", "a");
7742       if (sameRegs (AOP (left), AOP (result)) &&
7743           size >= MSB32 + offr && offr != LSB)
7744         emitcode ("xch", "a,%s",
7745                   aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
7746       else
7747         aopPut (AOP (result), "a", MSB24 + offr);
7748     }
7749
7750   if (size > MSB32 + offr)
7751     {
7752       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7753         {
7754           l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
7755           MOVA (l);
7756         }
7757       emitcode ("rlc", "a");
7758       aopPut (AOP (result), "a", MSB32 + offr);
7759     }
7760   if (offr != LSB)
7761     aopPut (AOP (result), zero, LSB);
7762 }
7763 #endif
7764
7765 #if 0
7766 //REMOVE ME!!!
7767 /*-----------------------------------------------------------------*/
7768 /* genlshFour - shift four byte by a known amount != 0             */
7769 /*-----------------------------------------------------------------*/
7770 static void
7771 genlshFour (operand * result, operand * left, int shCount)
7772 {
7773   int size;
7774
7775   D (emitcode (";", "genlshFour ");
7776     );
7777
7778   size = AOP_SIZE (result);
7779
7780   /* if shifting more that 3 bytes */
7781   if (shCount >= 24)
7782     {
7783       shCount -= 24;
7784       if (shCount)
7785         /* lowest order of left goes to the highest
7786            order of the destination */
7787         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7788       else
7789         movLeft2Result (left, LSB, result, MSB32, 0);
7790       aopPut (AOP (result), zero, LSB);
7791       aopPut (AOP (result), zero, MSB16);
7792       aopPut (AOP (result), zero, MSB24);
7793       return;
7794     }
7795
7796   /* more than two bytes */
7797   else if (shCount >= 16)
7798     {
7799       /* lower order two bytes goes to higher order two bytes */
7800       shCount -= 16;
7801       /* if some more remaining */
7802       if (shCount)
7803         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7804       else
7805         {
7806           movLeft2Result (left, MSB16, result, MSB32, 0);
7807           movLeft2Result (left, LSB, result, MSB24, 0);
7808         }
7809       aopPut (AOP (result), zero, MSB16);
7810       aopPut (AOP (result), zero, LSB);
7811       return;
7812     }
7813
7814   /* if more than 1 byte */
7815   else if (shCount >= 8)
7816     {
7817       /* lower order three bytes goes to higher order  three bytes */
7818       shCount -= 8;
7819       if (size == 2)
7820         {
7821           if (shCount)
7822             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7823           else
7824             movLeft2Result (left, LSB, result, MSB16, 0);
7825         }
7826       else
7827         {                       /* size = 4 */
7828           if (shCount == 0)
7829             {
7830               movLeft2Result (left, MSB24, result, MSB32, 0);
7831               movLeft2Result (left, MSB16, result, MSB24, 0);
7832               movLeft2Result (left, LSB, result, MSB16, 0);
7833               aopPut (AOP (result), zero, LSB);
7834             }
7835           else if (shCount == 1)
7836             shiftLLong (left, result, MSB16);
7837           else
7838             {
7839               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7840               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7841               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7842               aopPut (AOP (result), zero, LSB);
7843             }
7844         }
7845     }
7846
7847   /* 1 <= shCount <= 7 */
7848   else if (shCount <= 2)
7849     {
7850       shiftLLong (left, result, LSB);
7851       if (shCount == 2)
7852         shiftLLong (result, result, LSB);
7853     }
7854   /* 3 <= shCount <= 7, optimize */
7855   else
7856     {
7857       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7858       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7859       shiftL2Left2Result (left, LSB, result, LSB, shCount);
7860     }
7861 }
7862 #endif
7863
7864 #ifdef BETTER_LITERAL_SHIFT
7865 /*-----------------------------------------------------------------*/
7866 /* genLeftShiftLiteral - left shifting by known count              */
7867 /*-----------------------------------------------------------------*/
7868 static bool
7869 genLeftShiftLiteral (operand * left,
7870                      operand * right,
7871                      operand * result,
7872                      iCode * ic)
7873 {
7874   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7875   int size;
7876
7877   size = getSize (operandType (result));
7878
7879   D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
7880
7881   /* We only handle certain easy cases so far. */
7882   if ((shCount != 0)
7883    && (shCount < (size * 8))
7884    && (size != 1)
7885    && (size != 2))
7886   {
7887       D(emitcode (";", "genLeftShiftLiteral wimping out"););    
7888       return FALSE;
7889   }
7890
7891   freeAsmop (right, NULL, ic, TRUE);
7892
7893   aopOp(left, ic, FALSE, FALSE);
7894   aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
7895
7896 #if 0 // debug spew
7897   if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
7898   {
7899         emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
7900         if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
7901         {
7902            emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
7903         }
7904   }
7905   if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
7906   {
7907         emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
7908         if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
7909         {
7910            emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
7911         }       
7912   }  
7913 #endif
7914   
7915 #if VIEW_SIZE
7916   emitcode ("; shift left ", "result %d, left %d", size,
7917             AOP_SIZE (left));
7918 #endif
7919
7920   /* I suppose that the left size >= result size */
7921   if (shCount == 0)
7922   {
7923         _startLazyDPSEvaluation();
7924         while (size--)
7925         {
7926           movLeft2Result (left, size, result, size, 0);
7927         }
7928         _endLazyDPSEvaluation();
7929   }
7930   else if (shCount >= (size * 8))
7931   {
7932     _startLazyDPSEvaluation();
7933     while (size--)
7934     {
7935       aopPut (AOP (result), zero, size);
7936     }
7937     _endLazyDPSEvaluation();
7938   }
7939   else
7940   {
7941       switch (size)
7942         {
7943         case 1:
7944           genlshOne (result, left, shCount);
7945           break;
7946
7947         case 2:
7948           genlshTwo (result, left, shCount);
7949           break;
7950 #if 0
7951         case 4:
7952           genlshFour (result, left, shCount);
7953           break;
7954 #endif
7955         default:
7956           fprintf(stderr, "*** ack! mystery literal shift!\n");   
7957           break;
7958         }
7959     }
7960   freeAsmop (left, NULL, ic, TRUE);
7961   freeAsmop (result, NULL, ic, TRUE);
7962   return TRUE;
7963 }
7964 #endif
7965
7966 /*-----------------------------------------------------------------*/
7967 /* genLeftShift - generates code for left shifting                 */
7968 /*-----------------------------------------------------------------*/
7969 static void
7970 genLeftShift (iCode * ic)
7971 {
7972   operand *left, *right, *result;
7973   int size, offset;
7974   char *l;
7975   symbol *tlbl, *tlbl1;
7976
7977   D (emitcode (";", "genLeftShift "););
7978
7979   right = IC_RIGHT (ic);
7980   left = IC_LEFT (ic);
7981   result = IC_RESULT (ic);
7982
7983   aopOp (right, ic, FALSE, FALSE);
7984
7985
7986 #ifdef BETTER_LITERAL_SHIFT
7987   /* if the shift count is known then do it
7988      as efficiently as possible */
7989   if (AOP_TYPE (right) == AOP_LIT)
7990     {
7991       if (genLeftShiftLiteral (left, right, result, ic))
7992       {
7993         return;
7994       }
7995     }
7996 #endif
7997
7998   /* shift count is unknown then we have to form
7999      a loop get the loop count in B : Note: we take
8000      only the lower order byte since shifting
8001      more that 32 bits make no sense anyway, ( the
8002      largest size of an object can be only 32 bits ) */
8003
8004   if (AOP_TYPE (right) == AOP_LIT)
8005   {
8006       /* Really should be handled by genLeftShiftLiteral,
8007        * but since I'm too lazy to fix that today, at least we can make
8008        * some small improvement.
8009        */
8010        emitcode("mov", "b,#!constbyte",
8011                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8012   }
8013   else
8014   {
8015         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8016         emitcode ("inc", "b");
8017   }
8018   freeAsmop (right, NULL, ic, TRUE);
8019   aopOp (left, ic, FALSE, FALSE);
8020   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8021
8022   /* now move the left to the result if they are not the
8023      same */
8024   if (!sameRegs (AOP (left), AOP (result)) &&
8025       AOP_SIZE (result) > 1)
8026     {
8027
8028       size = AOP_SIZE (result);
8029       offset = 0;
8030       _startLazyDPSEvaluation ();
8031       while (size--)
8032         {
8033           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8034           if (*l == '@' && (IS_AOP_PREG (result)))
8035             {
8036
8037               emitcode ("mov", "a,%s", l);
8038               aopPut (AOP (result), "a", offset);
8039             }
8040           else
8041             aopPut (AOP (result), l, offset);
8042           offset++;
8043         }
8044       _endLazyDPSEvaluation ();
8045     }
8046
8047   tlbl = newiTempLabel (NULL);
8048   size = AOP_SIZE (result);
8049   offset = 0;
8050   tlbl1 = newiTempLabel (NULL);
8051
8052   /* if it is only one byte then */
8053   if (size == 1)
8054     {
8055       symbol *tlbl1 = newiTempLabel (NULL);
8056
8057       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8058       MOVA (l);
8059       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8060       emitcode ("", "!tlabeldef", tlbl->key + 100);
8061       emitcode ("add", "a,acc");
8062       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8063       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8064       aopPut (AOP (result), "a", 0);
8065       goto release;
8066     }
8067
8068   reAdjustPreg (AOP (result));
8069
8070   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8071   emitcode ("", "!tlabeldef", tlbl->key + 100);
8072   l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8073   MOVA (l);
8074   emitcode ("add", "a,acc");
8075   aopPut (AOP (result), "a", offset++);
8076   _startLazyDPSEvaluation ();
8077   while (--size)
8078     {
8079       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8080       MOVA (l);
8081       emitcode ("rlc", "a");
8082       aopPut (AOP (result), "a", offset++);
8083     }
8084   _endLazyDPSEvaluation ();
8085   reAdjustPreg (AOP (result));
8086
8087   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8088   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8089 release:
8090   freeAsmop (left, NULL, ic, TRUE);
8091   freeAsmop (result, NULL, ic, TRUE);
8092 }
8093
8094 #ifdef BETTER_LITERAL_SHIFT
8095 /*-----------------------------------------------------------------*/
8096 /* genrshOne - right shift a one byte quantity by known count      */
8097 /*-----------------------------------------------------------------*/
8098 static void
8099 genrshOne (operand * result, operand * left,
8100            int shCount, int sign)
8101 {
8102   D (emitcode (";", "genrshOne"););
8103   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8104 }
8105 #endif
8106
8107 #ifdef BETTER_LITERAL_SHIFT
8108 /*-----------------------------------------------------------------*/
8109 /* genrshTwo - right shift two bytes by known amount != 0          */
8110 /*-----------------------------------------------------------------*/
8111 static void
8112 genrshTwo (operand * result, operand * left,
8113            int shCount, int sign)
8114 {
8115   D (emitcode (";", "genrshTwo"););
8116
8117   /* if shCount >= 8 */
8118   if (shCount >= 8)
8119     {
8120       shCount -= 8;
8121       _startLazyDPSEvaluation();
8122       if (shCount)
8123       {
8124         shiftR1Left2Result (left, MSB16, result, LSB,
8125                             shCount, sign);
8126       }                     
8127       else
8128       {
8129         movLeft2Result (left, MSB16, result, LSB, sign);
8130       }
8131       addSign (result, MSB16, sign);
8132       _endLazyDPSEvaluation();
8133     }
8134
8135   /*  1 <= shCount <= 7 */
8136   else
8137   {
8138     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8139   }
8140 }
8141 #endif
8142
8143 #if 0
8144 //REMOVE ME!!!
8145 /*-----------------------------------------------------------------*/
8146 /* shiftRLong - shift right one long from left to result           */
8147 /* offl = LSB or MSB16                                             */
8148 /*-----------------------------------------------------------------*/
8149 static void
8150 shiftRLong (operand * left, int offl,
8151             operand * result, int sign)
8152 {
8153   int isSameRegs=sameRegs(AOP(left),AOP(result));
8154
8155   if (isSameRegs && offl>1) {
8156     // we are in big trouble, but this shouldn't happen
8157     werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8158   }
8159
8160   MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
8161   
8162   if (offl==MSB16) {
8163     // shift is > 8
8164     if (sign) {
8165       emitcode ("rlc", "a");
8166       emitcode ("subb", "a,acc");
8167       emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
8168     } else {
8169       aopPut (AOP(result), zero, MSB32);
8170     }
8171   }
8172
8173   if (!sign) {
8174     emitcode ("clr", "c");
8175   } else {
8176     emitcode ("mov", "c,acc.7");
8177   }
8178
8179   emitcode ("rrc", "a");
8180
8181   if (isSameRegs && offl==MSB16) {
8182     emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
8183   } else {
8184     aopPut (AOP (result), "a", MSB32);
8185     MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
8186   }
8187
8188   emitcode ("rrc", "a");
8189   if (isSameRegs && offl==1) {
8190     emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
8191   } else {
8192     aopPut (AOP (result), "a", MSB24);
8193     MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
8194   }
8195   emitcode ("rrc", "a");
8196   aopPut (AOP (result), "a", MSB16 - offl);
8197
8198   if (offl == LSB)
8199     {
8200       MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
8201       emitcode ("rrc", "a");
8202       aopPut (AOP (result), "a", LSB);
8203     }
8204 }
8205 #endif
8206
8207 #if 0
8208 //REMOVE ME!!!
8209 /*-----------------------------------------------------------------*/
8210 /* genrshFour - shift four byte by a known amount != 0             */
8211 /*-----------------------------------------------------------------*/
8212 static void
8213 genrshFour (operand * result, operand * left,
8214             int shCount, int sign)
8215 {
8216   D (emitcode (";", "genrshFour");
8217     );
8218
8219   /* if shifting more that 3 bytes */
8220   if (shCount >= 24)
8221     {
8222       shCount -= 24;
8223       if (shCount)
8224         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8225       else
8226         movLeft2Result (left, MSB32, result, LSB, sign);
8227       addSign (result, MSB16, sign);
8228     }
8229   else if (shCount >= 16)
8230     {
8231       shCount -= 16;
8232       if (shCount)
8233         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8234       else
8235         {
8236           movLeft2Result (left, MSB24, result, LSB, 0);
8237           movLeft2Result (left, MSB32, result, MSB16, sign);
8238         }
8239       addSign (result, MSB24, sign);
8240     }
8241   else if (shCount >= 8)
8242     {
8243       shCount -= 8;
8244       if (shCount == 1)
8245         shiftRLong (left, MSB16, result, sign);
8246       else if (shCount == 0)
8247         {
8248           movLeft2Result (left, MSB16, result, LSB, 0);
8249           movLeft2Result (left, MSB24, result, MSB16, 0);
8250           movLeft2Result (left, MSB32, result, MSB24, sign);
8251           addSign (result, MSB32, sign);
8252         }
8253       else
8254         {
8255           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8256           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8257           /* the last shift is signed */
8258           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8259           addSign (result, MSB32, sign);
8260         }
8261     }
8262   else
8263     {                           /* 1 <= shCount <= 7 */
8264       if (shCount <= 2)
8265         {
8266           shiftRLong (left, LSB, result, sign);
8267           if (shCount == 2)
8268             shiftRLong (result, LSB, result, sign);
8269         }
8270       else
8271         {
8272           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8273           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8274           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8275         }
8276     }
8277 }
8278 #endif
8279
8280 #ifdef BETTER_LITERAL_SHIFT
8281 /*-----------------------------------------------------------------*/
8282 /* genRightShiftLiteral - right shifting by known count            */
8283 /*-----------------------------------------------------------------*/
8284 static bool
8285 genRightShiftLiteral (operand * left,
8286                       operand * right,
8287                       operand * result,
8288                       iCode * ic,
8289                       int sign)
8290 {
8291   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8292   int size;
8293
8294   size = getSize (operandType (result));
8295
8296   D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8297
8298   /* We only handle certain easy cases so far. */
8299   if ((shCount != 0)
8300    && (shCount < (size * 8))
8301    && (size != 1)
8302    && (size != 2))
8303   {
8304       D(emitcode (";", "genRightShiftLiteral wimping out"););   
8305       return FALSE;
8306   }
8307
8308   freeAsmop (right, NULL, ic, TRUE);
8309
8310   aopOp (left, ic, FALSE, FALSE);
8311   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8312
8313 #if VIEW_SIZE
8314   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8315             AOP_SIZE (left));
8316 #endif
8317
8318   /* test the LEFT size !!! */
8319
8320   /* I suppose that the left size >= result size */
8321   if (shCount == 0)
8322   {
8323       size = getDataSize (result);
8324       _startLazyDPSEvaluation();
8325       while (size--)
8326       {
8327         movLeft2Result (left, size, result, size, 0);
8328       }
8329       _endLazyDPSEvaluation();
8330   }
8331   else if (shCount >= (size * 8))
8332     {
8333       if (sign)
8334       {
8335         /* get sign in acc.7 */
8336         MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
8337       }
8338       addSign (result, LSB, sign);
8339     }
8340   else
8341     {
8342       switch (size)
8343         {
8344         case 1:
8345           genrshOne (result, left, shCount, sign);
8346           break;
8347
8348         case 2:
8349           genrshTwo (result, left, shCount, sign);
8350           break;
8351 #if 0
8352         case 4:
8353           genrshFour (result, left, shCount, sign);
8354           break;
8355 #endif    
8356         default:
8357           break;
8358         }
8359
8360       freeAsmop (left, NULL, ic, TRUE);
8361       freeAsmop (result, NULL, ic, TRUE);
8362     }
8363     return TRUE;
8364 }
8365 #endif
8366
8367 /*-----------------------------------------------------------------*/
8368 /* genSignedRightShift - right shift of signed number              */
8369 /*-----------------------------------------------------------------*/
8370 static void
8371 genSignedRightShift (iCode * ic)
8372 {
8373   operand *right, *left, *result;
8374   int size, offset;
8375   char *l;
8376   symbol *tlbl, *tlbl1;
8377
8378   D (emitcode (";", "genSignedRightShift "););
8379
8380   /* we do it the hard way put the shift count in b
8381      and loop thru preserving the sign */
8382
8383   right = IC_RIGHT (ic);
8384   left = IC_LEFT (ic);
8385   result = IC_RESULT (ic);
8386
8387   aopOp (right, ic, FALSE, FALSE);
8388
8389 #ifdef BETTER_LITERAL_SHIFT
8390   if (AOP_TYPE (right) == AOP_LIT)
8391     {
8392       if (genRightShiftLiteral (left, right, result, ic, 1))
8393       {
8394         return;
8395       }
8396     }
8397 #endif
8398   /* shift count is unknown then we have to form
8399      a loop get the loop count in B : Note: we take
8400      only the lower order byte since shifting
8401      more that 32 bits make no sense anyway, ( the
8402      largest size of an object can be only 32 bits ) */
8403
8404   if (AOP_TYPE (right) == AOP_LIT)
8405   {
8406       /* Really should be handled by genRightShiftLiteral,
8407        * but since I'm too lazy to fix that today, at least we can make
8408        * some small improvement.
8409        */
8410        emitcode("mov", "b,#!constbyte",
8411                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8412   }
8413   else
8414   {
8415         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8416         emitcode ("inc", "b");
8417   }
8418   freeAsmop (right, NULL, ic, TRUE);
8419   aopOp (left, ic, FALSE, FALSE);
8420   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8421
8422   /* now move the left to the result if they are not the
8423      same */
8424   if (!sameRegs (AOP (left), AOP (result)) &&
8425       AOP_SIZE (result) > 1)
8426     {
8427
8428       size = AOP_SIZE (result);
8429       offset = 0;
8430       _startLazyDPSEvaluation ();
8431       while (size--)
8432         {
8433           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8434           if (*l == '@' && IS_AOP_PREG (result))
8435             {
8436
8437               emitcode ("mov", "a,%s", l);
8438               aopPut (AOP (result), "a", offset);
8439             }
8440           else
8441             aopPut (AOP (result), l, offset);
8442           offset++;
8443         }
8444       _endLazyDPSEvaluation ();
8445     }
8446
8447   /* mov the highest order bit to OVR */
8448   tlbl = newiTempLabel (NULL);
8449   tlbl1 = newiTempLabel (NULL);
8450
8451   size = AOP_SIZE (result);
8452   offset = size - 1;
8453   emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
8454   emitcode ("rlc", "a");
8455   emitcode ("mov", "ov,c");
8456   /* if it is only one byte then */
8457   if (size == 1)
8458     {
8459       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8460       MOVA (l);
8461       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8462       emitcode ("", "!tlabeldef", tlbl->key + 100);
8463       emitcode ("mov", "c,ov");
8464       emitcode ("rrc", "a");
8465       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8466       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8467       aopPut (AOP (result), "a", 0);
8468       goto release;
8469     }
8470
8471   reAdjustPreg (AOP (result));
8472   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8473   emitcode ("", "!tlabeldef", tlbl->key + 100);
8474   emitcode ("mov", "c,ov");
8475   _startLazyDPSEvaluation ();
8476   while (size--)
8477     {
8478       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8479       MOVA (l);
8480       emitcode ("rrc", "a");
8481       aopPut (AOP (result), "a", offset--);
8482     }
8483   _endLazyDPSEvaluation ();
8484   reAdjustPreg (AOP (result));
8485   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8486   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8487
8488 release:
8489   freeAsmop (left, NULL, ic, TRUE);
8490   freeAsmop (result, NULL, ic, TRUE);
8491 }
8492
8493 /*-----------------------------------------------------------------*/
8494 /* genRightShift - generate code for right shifting                */
8495 /*-----------------------------------------------------------------*/
8496 static void
8497 genRightShift (iCode * ic)
8498 {
8499   operand *right, *left, *result;
8500   sym_link *retype;
8501   int size, offset;
8502   char *l;
8503   symbol *tlbl, *tlbl1;
8504
8505   D (emitcode (";", "genRightShift "););
8506
8507   /* if signed then we do it the hard way preserve the
8508      sign bit moving it inwards */
8509   retype = getSpec (operandType (IC_RESULT (ic)));
8510
8511   if (!SPEC_USIGN (retype))
8512     {
8513       genSignedRightShift (ic);
8514       return;
8515     }
8516
8517   /* signed & unsigned types are treated the same : i.e. the
8518      signed is NOT propagated inwards : quoting from the
8519      ANSI - standard : "for E1 >> E2, is equivalent to division
8520      by 2**E2 if unsigned or if it has a non-negative value,
8521      otherwise the result is implementation defined ", MY definition
8522      is that the sign does not get propagated */
8523
8524   right = IC_RIGHT (ic);
8525   left = IC_LEFT (ic);
8526   result = IC_RESULT (ic);
8527
8528   aopOp (right, ic, FALSE, FALSE);
8529
8530 #ifdef BETTER_LITERAL_SHIFT
8531   /* if the shift count is known then do it
8532      as efficiently as possible */
8533   if (AOP_TYPE (right) == AOP_LIT)
8534     {
8535       if (genRightShiftLiteral (left, right, result, ic, 0))
8536       {
8537         return;
8538       }
8539     }
8540 #endif
8541
8542   /* shift count is unknown then we have to form
8543      a loop get the loop count in B : Note: we take
8544      only the lower order byte since shifting
8545      more that 32 bits make no sense anyway, ( the
8546      largest size of an object can be only 32 bits ) */
8547   
8548   if (AOP_TYPE (right) == AOP_LIT)
8549   {
8550       /* Really should be handled by genRightShiftLiteral,
8551        * but since I'm too lazy to fix that today, at least we can make
8552        * some small improvement.
8553        */
8554        emitcode("mov", "b,#!constbyte",
8555                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8556   }
8557   else
8558   {
8559         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8560         emitcode ("inc", "b");
8561   }
8562   freeAsmop (right, NULL, ic, TRUE);
8563   aopOp (left, ic, FALSE, FALSE);
8564   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8565
8566   /* now move the left to the result if they are not the
8567      same */
8568   if (!sameRegs (AOP (left), AOP (result)) &&
8569       AOP_SIZE (result) > 1)
8570     {
8571
8572       size = AOP_SIZE (result);
8573       offset = 0;
8574       _startLazyDPSEvaluation ();
8575       while (size--)
8576         {
8577           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8578           if (*l == '@' && IS_AOP_PREG (result))
8579             {
8580
8581               emitcode ("mov", "a,%s", l);
8582               aopPut (AOP (result), "a", offset);
8583             }
8584           else
8585             aopPut (AOP (result), l, offset);
8586           offset++;
8587         }
8588       _endLazyDPSEvaluation ();
8589     }
8590
8591   tlbl = newiTempLabel (NULL);
8592   tlbl1 = newiTempLabel (NULL);
8593   size = AOP_SIZE (result);
8594   offset = size - 1;
8595
8596   /* if it is only one byte then */
8597   if (size == 1)
8598     {
8599       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8600       MOVA (l);
8601       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8602       emitcode ("", "!tlabeldef", tlbl->key + 100);
8603       CLRC;
8604       emitcode ("rrc", "a");
8605       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8606       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8607       aopPut (AOP (result), "a", 0);
8608       goto release;
8609     }
8610
8611   reAdjustPreg (AOP (result));
8612   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8613   emitcode ("", "!tlabeldef", tlbl->key + 100);
8614   CLRC;
8615   _startLazyDPSEvaluation ();
8616   while (size--)
8617     {
8618       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8619       MOVA (l);
8620       emitcode ("rrc", "a");
8621       aopPut (AOP (result), "a", offset--);
8622     }
8623   _endLazyDPSEvaluation ();
8624   reAdjustPreg (AOP (result));
8625
8626   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8627   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8628
8629 release:
8630   freeAsmop (left, NULL, ic, TRUE);
8631   freeAsmop (result, NULL, ic, TRUE);
8632 }
8633
8634 /*-----------------------------------------------------------------*/
8635 /* genUnpackBits - generates code for unpacking bits               */
8636 /*-----------------------------------------------------------------*/
8637 static void
8638 genUnpackBits (operand * result, char *rname, int ptype)
8639 {
8640   int shCnt;
8641   int rlen = 0;
8642   sym_link *etype;
8643   int offset = 0;
8644
8645   D (emitcode (";", "genUnpackBits ");
8646     );
8647
8648   etype = getSpec (operandType (result));
8649
8650   /* read the first byte  */
8651   switch (ptype)
8652     {
8653
8654     case POINTER:
8655     case IPOINTER:
8656       emitcode ("mov", "a,@%s", rname);
8657       break;
8658
8659     case PPOINTER:
8660       emitcode ("movx", "a,@%s", rname);
8661       break;
8662
8663     case FPOINTER:
8664       emitcode ("movx", "a,@dptr");
8665       break;
8666
8667     case CPOINTER:
8668       emitcode ("clr", "a");
8669       emitcode ("movc", "a,@a+dptr");
8670       break;
8671
8672     case GPOINTER:
8673       emitcode ("lcall", "__gptrget");
8674       break;
8675     }
8676
8677   /* if we have bitdisplacement then it fits   */
8678   /* into this byte completely or if length is */
8679   /* less than a byte                          */
8680   if ((shCnt = SPEC_BSTR (etype)) ||
8681       (SPEC_BLEN (etype) <= 8))
8682     {
8683
8684       /* shift right acc */
8685       AccRsh (shCnt);
8686
8687       emitcode ("anl", "a,#!constbyte",
8688                 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
8689       aopPut (AOP (result), "a", offset);
8690       return;
8691     }
8692
8693   /* bit field did not fit in a byte  */
8694   rlen = SPEC_BLEN (etype) - 8;
8695   aopPut (AOP (result), "a", offset++);
8696
8697   while (1)
8698     {
8699
8700       switch (ptype)
8701         {
8702         case POINTER:
8703         case IPOINTER:
8704           emitcode ("inc", "%s", rname);
8705           emitcode ("mov", "a,@%s", rname);
8706           break;
8707
8708         case PPOINTER:
8709           emitcode ("inc", "%s", rname);
8710           emitcode ("movx", "a,@%s", rname);
8711           break;
8712
8713         case FPOINTER:
8714           emitcode ("inc", "dptr");
8715           emitcode ("movx", "a,@dptr");
8716           break;
8717
8718         case CPOINTER:
8719           emitcode ("clr", "a");
8720           emitcode ("inc", "dptr");
8721           emitcode ("movc", "a,@a+dptr");
8722           break;
8723
8724         case GPOINTER:
8725           emitcode ("inc", "dptr");
8726           emitcode ("lcall", "__gptrget");
8727           break;
8728         }
8729
8730       rlen -= 8;
8731       /* if we are done */
8732       if (rlen < 8)
8733         break;
8734
8735       aopPut (AOP (result), "a", offset++);
8736
8737     }
8738
8739   if (rlen)
8740     {
8741       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (rlen));
8742       aopPut (AOP (result), "a", offset);
8743     }
8744
8745   return;
8746 }
8747
8748
8749 /*-----------------------------------------------------------------*/
8750 /* genDataPointerGet - generates code when ptr offset is known     */
8751 /*-----------------------------------------------------------------*/
8752 static void
8753 genDataPointerGet (operand * left,
8754                    operand * result,
8755                    iCode * ic)
8756 {
8757   char *l;
8758   char buffer[256];
8759   int size, offset = 0;
8760   aopOp (result, ic, TRUE, FALSE);
8761
8762   /* get the string representation of the name */
8763   l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
8764   size = AOP_SIZE (result);
8765   _startLazyDPSEvaluation ();
8766   while (size--)
8767     {
8768       if (offset)
8769         sprintf (buffer, "(%s + %d)", l + 1, offset);
8770       else
8771         sprintf (buffer, "%s", l + 1);
8772       aopPut (AOP (result), buffer, offset++);
8773     }
8774   _endLazyDPSEvaluation ();
8775
8776   freeAsmop (left, NULL, ic, TRUE);
8777   freeAsmop (result, NULL, ic, TRUE);
8778 }
8779
8780 /*-----------------------------------------------------------------*/
8781 /* genNearPointerGet - emitcode for near pointer fetch             */
8782 /*-----------------------------------------------------------------*/
8783 static void
8784 genNearPointerGet (operand * left,
8785                    operand * result,
8786                    iCode * ic,
8787                    iCode *pi)
8788 {
8789   asmop *aop = NULL;
8790   regs *preg = NULL;
8791   char *rname;
8792   sym_link *rtype, *retype, *letype;
8793   sym_link *ltype = operandType (left);
8794   char buffer[80];
8795
8796   rtype = operandType (result);
8797   retype = getSpec (rtype);
8798   letype = getSpec (ltype);
8799
8800   aopOp (left, ic, FALSE, FALSE);
8801
8802   /* if left is rematerialisable and
8803      result is not bit variable type and
8804      the left is pointer to data space i.e
8805      lower 128 bytes of space */
8806   if (AOP_TYPE (left) == AOP_IMMD &&
8807       !IS_BITVAR (retype) &&
8808       !IS_BITVAR (letype) &&
8809       DCL_TYPE (ltype) == POINTER)
8810     {
8811       genDataPointerGet (left, result, ic);
8812       return;
8813     }
8814
8815   /* if the value is already in a pointer register
8816      then don't need anything more */
8817   if (!AOP_INPREG (AOP (left)))
8818     {
8819       /* otherwise get a free pointer register */
8820       aop = newAsmop (0);
8821       preg = getFreePtr (ic, &aop, FALSE);
8822       emitcode ("mov", "%s,%s",
8823                 preg->name,
8824                 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8825       rname = preg->name;
8826     }
8827   else
8828     rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8829
8830   freeAsmop (left, NULL, ic, TRUE);
8831   aopOp (result, ic, FALSE, FALSE);
8832
8833   /* if bitfield then unpack the bits */
8834   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8835     genUnpackBits (result, rname, POINTER);
8836   else
8837     {
8838       /* we have can just get the values */
8839       int size = AOP_SIZE (result);
8840       int offset = 0;
8841
8842       while (size--)
8843         {
8844           if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8845             {
8846
8847               emitcode ("mov", "a,@%s", rname);
8848               aopPut (AOP (result), "a", offset);
8849             }
8850           else
8851             {
8852               sprintf (buffer, "@%s", rname);
8853               aopPut (AOP (result), buffer, offset);
8854             }
8855           offset++;
8856           if (size || pi)
8857             emitcode ("inc", "%s", rname);
8858         }
8859     }
8860
8861   /* now some housekeeping stuff */
8862   if (aop)
8863     {
8864       /* we had to allocate for this iCode */
8865       if (pi) { /* post increment present */
8866         aopPut(AOP ( left ),rname,0);
8867       }
8868       freeAsmop (NULL, aop, ic, TRUE);
8869     }
8870   else
8871     {
8872       /* we did not allocate which means left
8873          already in a pointer register, then
8874          if size > 0 && this could be used again
8875          we have to point it back to where it
8876          belongs */
8877       if (AOP_SIZE (result) > 1 &&
8878           !OP_SYMBOL (left)->remat &&
8879           (OP_SYMBOL (left)->liveTo > ic->seq ||
8880            ic->depth) &&
8881           !pi)
8882         {
8883           int size = AOP_SIZE (result) - 1;
8884           while (size--)
8885             emitcode ("dec", "%s", rname);
8886         }
8887     }
8888
8889   /* done */
8890   freeAsmop (result, NULL, ic, TRUE);
8891   if (pi) pi->generated = 1;
8892 }
8893
8894 /*-----------------------------------------------------------------*/
8895 /* genPagedPointerGet - emitcode for paged pointer fetch           */
8896 /*-----------------------------------------------------------------*/
8897 static void
8898 genPagedPointerGet (operand * left,
8899                     operand * result,
8900                     iCode * ic,
8901                     iCode * pi)
8902 {
8903   asmop *aop = NULL;
8904   regs *preg = NULL;
8905   char *rname;
8906   sym_link *rtype, *retype, *letype;
8907
8908   rtype = operandType (result);
8909   retype = getSpec (rtype);
8910   letype = getSpec (operandType (left));
8911   aopOp (left, ic, FALSE, FALSE);
8912
8913   /* if the value is already in a pointer register
8914      then don't need anything more */
8915   if (!AOP_INPREG (AOP (left)))
8916     {
8917       /* otherwise get a free pointer register */
8918       aop = newAsmop (0);
8919       preg = getFreePtr (ic, &aop, FALSE);
8920       emitcode ("mov", "%s,%s",
8921                 preg->name,
8922                 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8923       rname = preg->name;
8924     }
8925   else
8926     rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8927
8928   freeAsmop (left, NULL, ic, TRUE);
8929   aopOp (result, ic, FALSE, FALSE);
8930
8931   /* if bitfield then unpack the bits */
8932   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8933     genUnpackBits (result, rname, PPOINTER);
8934   else
8935     {
8936       /* we have can just get the values */
8937       int size = AOP_SIZE (result);
8938       int offset = 0;
8939
8940       while (size--)
8941         {
8942
8943           emitcode ("movx", "a,@%s", rname);
8944           aopPut (AOP (result), "a", offset);
8945
8946           offset++;
8947
8948           if (size || pi)
8949             emitcode ("inc", "%s", rname);
8950         }
8951     }
8952
8953   /* now some housekeeping stuff */
8954   if (aop)
8955     {
8956       /* we had to allocate for this iCode */
8957       if (pi) aopPut ( AOP (left), rname, 0);
8958       freeAsmop (NULL, aop, ic, TRUE);
8959     }
8960   else
8961     {
8962       /* we did not allocate which means left
8963          already in a pointer register, then
8964          if size > 0 && this could be used again
8965          we have to point it back to where it
8966          belongs */
8967       if (AOP_SIZE (result) > 1 &&
8968           !OP_SYMBOL (left)->remat &&
8969           (OP_SYMBOL (left)->liveTo > ic->seq ||
8970            ic->depth) &&
8971           !pi)
8972         {
8973           int size = AOP_SIZE (result) - 1;
8974           while (size--)
8975             emitcode ("dec", "%s", rname);
8976         }
8977     }
8978
8979   /* done */
8980   freeAsmop (result, NULL, ic, TRUE);
8981   if (pi) pi->generated = 1;
8982 }
8983
8984 /*-----------------------------------------------------------------*/
8985 /* genFarPointerGet - gget value from far space                    */
8986 /*-----------------------------------------------------------------*/
8987 static void
8988 genFarPointerGet (operand * left,
8989                   operand * result, iCode * ic, iCode *pi)
8990 {
8991     int size, offset, dopi=1;
8992   sym_link *retype = getSpec (operandType (result));
8993   sym_link *letype = getSpec (operandType (left));
8994   D (emitcode (";", "genFarPointerGet");
8995     );
8996
8997   aopOp (left, ic, FALSE, FALSE);
8998
8999   /* if the operand is already in dptr
9000      then we do nothing else we move the value to dptr */
9001   if (AOP_TYPE (left) != AOP_STR)
9002     {
9003       /* if this is remateriazable */
9004       if (AOP_TYPE (left) == AOP_IMMD)
9005         {
9006           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9007         }
9008       else
9009         {
9010           /* we need to get it byte by byte */
9011           _startLazyDPSEvaluation ();
9012           if (AOP_TYPE (left) != AOP_DPTR)
9013             {
9014               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9015               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9016               if (options.model == MODEL_FLAT24)
9017                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9018             }
9019           else
9020             {
9021               /* We need to generate a load to DPTR indirect through DPTR. */
9022               D (emitcode (";", "genFarPointerGet -- indirection special case.");
9023                 );
9024               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
9025               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
9026               if (options.model == MODEL_FLAT24)
9027                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9028               emitcode ("pop", "dph");
9029               emitcode ("pop", "dpl");
9030               dopi =0;
9031             }
9032           _endLazyDPSEvaluation ();
9033         }
9034     }
9035   /* so dptr know contains the address */
9036   aopOp (result, ic, FALSE, TRUE);
9037
9038   /* if bit then unpack */
9039   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9040     genUnpackBits (result, "dptr", FPOINTER);
9041   else
9042     {
9043       size = AOP_SIZE (result);
9044       offset = 0;
9045
9046       _startLazyDPSEvaluation ();
9047       while (size--)
9048         {
9049
9050           genSetDPTR (0);
9051           _flushLazyDPS ();
9052
9053           emitcode ("movx", "a,@dptr");
9054           if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9055             emitcode ("inc", "dptr");
9056
9057           aopPut (AOP (result), "a", offset++);
9058         }
9059       _endLazyDPSEvaluation ();
9060     }
9061   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9062     aopPut ( AOP (left), "dpl", 0);
9063     aopPut ( AOP (left), "dph", 1);
9064     if (options.model == MODEL_FLAT24)
9065             aopPut ( AOP (left), "dpx", 2);
9066     pi->generated = 1;
9067   } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9068              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9069       
9070       size = AOP_SIZE (result) - 1;
9071       while (size--) emitcode ("lcall","__decdptr");
9072   }
9073
9074   freeAsmop (left, NULL, ic, TRUE);
9075   freeAsmop (result, NULL, ic, TRUE);
9076 }
9077
9078 /*-----------------------------------------------------------------*/
9079 /* emitcodePointerGet - gget value from code space                  */
9080 /*-----------------------------------------------------------------*/
9081 static void
9082 emitcodePointerGet (operand * left,
9083                     operand * result, iCode * ic, iCode *pi)
9084 {
9085   int size, offset, dopi=1;
9086   sym_link *retype = getSpec (operandType (result));
9087
9088   aopOp (left, ic, FALSE, FALSE);
9089
9090   /* if the operand is already in dptr
9091      then we do nothing else we move the value to dptr */
9092   if (AOP_TYPE (left) != AOP_STR)
9093     {
9094       /* if this is remateriazable */
9095       if (AOP_TYPE (left) == AOP_IMMD)
9096         {
9097           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9098         }
9099       else
9100         {                       /* we need to get it byte by byte */
9101           _startLazyDPSEvaluation ();
9102           if (AOP_TYPE (left) != AOP_DPTR)
9103             {
9104               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9105               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9106               if (options.model == MODEL_FLAT24)
9107                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9108             }
9109           else
9110             {
9111               /* We need to generate a load to DPTR indirect through DPTR. */
9112               D (emitcode (";", "gencodePointerGet -- indirection special case.");
9113                 );
9114               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
9115               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
9116               if (options.model == MODEL_FLAT24)
9117                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9118               emitcode ("pop", "dph");
9119               emitcode ("pop", "dpl");
9120               dopi=0;
9121             }
9122           _endLazyDPSEvaluation ();
9123         }
9124     }
9125   /* so dptr know contains the address */
9126   aopOp (result, ic, FALSE, TRUE);
9127
9128   /* if bit then unpack */
9129   if (IS_BITVAR (retype))
9130     genUnpackBits (result, "dptr", CPOINTER);
9131   else
9132     {
9133       size = AOP_SIZE (result);
9134       offset = 0;
9135
9136       _startLazyDPSEvaluation ();
9137       while (size--)
9138         {
9139           genSetDPTR (0);
9140           _flushLazyDPS ();
9141
9142           emitcode ("clr", "a");
9143           emitcode ("movc", "a,@a+dptr");
9144           if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9145             emitcode ("inc", "dptr");
9146           aopPut (AOP (result), "a", offset++);
9147         }
9148       _endLazyDPSEvaluation ();
9149     }
9150   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9151       aopPut ( AOP (left), "dpl", 0);
9152       aopPut ( AOP (left), "dph", 1);
9153       if (options.model == MODEL_FLAT24)
9154           aopPut ( AOP (left), "dpx", 2);
9155       pi->generated = 1;
9156   } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9157              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9158       
9159       size = AOP_SIZE (result) - 1;
9160       while (size--) emitcode ("lcall","__decdptr");
9161   }
9162   
9163   freeAsmop (left, NULL, ic, TRUE);
9164   freeAsmop (result, NULL, ic, TRUE);
9165 }
9166
9167 /*-----------------------------------------------------------------*/
9168 /* genGenPointerGet - gget value from generic pointer space        */
9169 /*-----------------------------------------------------------------*/
9170 static void
9171 genGenPointerGet (operand * left,
9172                   operand * result, iCode * ic, iCode * pi)
9173 {
9174   int size, offset;
9175   sym_link *retype = getSpec (operandType (result));
9176   sym_link *letype = getSpec (operandType (left));
9177
9178   D (emitcode (";", "genGenPointerGet "); );
9179
9180   aopOp (left, ic, FALSE, (OP_SYMBOL(left)->ruonly ? FALSE : TRUE));
9181
9182   /* if the operand is already in dptr
9183      then we do nothing else we move the value to dptr */
9184   if (AOP_TYPE (left) != AOP_STR)
9185     {
9186       /* if this is remateriazable */
9187       if (AOP_TYPE (left) == AOP_IMMD)
9188         {
9189           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9190           if (AOP(left)->aopu.aop_immd.from_cast_remat) 
9191                   emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, FALSE));
9192           else
9193                   emitcode ("mov", "b,#%d", pointerCode (retype));
9194         }
9195       else
9196         {                       /* we need to get it byte by byte */
9197           _startLazyDPSEvaluation ();
9198           if (AOP(left)->type==AOP_DPTR2) {
9199             char *l;
9200             l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
9201             genSetDPTR(0);
9202             _flushLazyDPS();
9203             emitcode ("mov", "dpl,%s", l);
9204             l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
9205             genSetDPTR(0);
9206             _flushLazyDPS();
9207             emitcode ("mov", "dph,%s", l);
9208             if (options.model == MODEL_FLAT24) {
9209               l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
9210               genSetDPTR(0);
9211               _flushLazyDPS();
9212               emitcode ("mov", "dpx,%s", l);
9213               emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
9214             } else {
9215               emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9216             }
9217           } else {
9218             emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
9219             emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
9220             if (options.model == MODEL_FLAT24) {
9221               emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9222               emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
9223             } else {
9224               emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9225             }
9226           }
9227           _endLazyDPSEvaluation ();
9228         }
9229     }
9230   /* so dptr know contains the address */
9231   aopOp (result, ic, FALSE, TRUE);
9232
9233   /* if bit then unpack */
9234   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9235     genUnpackBits (result, "dptr", GPOINTER);
9236   else
9237     {
9238       size = AOP_SIZE (result);
9239       offset = 0;
9240
9241       while (size--)
9242         {
9243           emitcode ("lcall", "__gptrget");
9244           aopPut (AOP (result), "a", offset++);
9245           if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9246             emitcode ("inc", "dptr");
9247         }
9248     }
9249
9250   if (pi && AOP_TYPE (left) != AOP_IMMD) {
9251     aopPut ( AOP (left), "dpl", 0);
9252     aopPut ( AOP (left), "dph", 1);
9253     if (options.model == MODEL_FLAT24) {
9254         aopPut ( AOP (left), "dpx", 2);
9255         aopPut ( AOP (left), "b", 3);   
9256     } else  aopPut ( AOP (left), "b", 2);       
9257     pi->generated = 1;
9258   } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9259              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9260       
9261       size = AOP_SIZE (result) - 1;
9262       while (size--) emitcode ("lcall","__decdptr");
9263   }
9264
9265   freeAsmop (left, NULL, ic, TRUE);
9266   freeAsmop (result, NULL, ic, TRUE);
9267 }
9268
9269 /*-----------------------------------------------------------------*/
9270 /* genPointerGet - generate code for pointer get                   */
9271 /*-----------------------------------------------------------------*/
9272 static void
9273 genPointerGet (iCode * ic, iCode *pi)
9274 {
9275   operand *left, *result;
9276   sym_link *type, *etype;
9277   int p_type;
9278
9279   D (emitcode (";", "genPointerGet ");
9280     );
9281
9282   left = IC_LEFT (ic);
9283   result = IC_RESULT (ic);
9284
9285   /* depending on the type of pointer we need to
9286      move it to the correct pointer register */
9287   type = operandType (left);
9288   etype = getSpec (type);
9289   /* if left is of type of pointer then it is simple */
9290   if (IS_PTR (type) && !IS_FUNC (type->next))
9291     p_type = DCL_TYPE (type);
9292   else
9293     {
9294       /* we have to go by the storage class */
9295       p_type = PTR_TYPE (SPEC_OCLS (etype));
9296     }
9297   /* special case when cast remat */
9298   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9299       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9300           left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9301           type =   type = operandType (left);
9302           p_type = DCL_TYPE (type);
9303   }
9304   /* now that we have the pointer type we assign
9305      the pointer values */
9306   switch (p_type)
9307     {
9308
9309     case POINTER:
9310     case IPOINTER:
9311       genNearPointerGet (left, result, ic, pi);
9312       break;
9313
9314     case PPOINTER:
9315       genPagedPointerGet (left, result, ic, pi);
9316       break;
9317
9318     case FPOINTER:
9319       genFarPointerGet (left, result, ic, pi);
9320       break;
9321
9322     case CPOINTER:
9323       emitcodePointerGet (left, result, ic, pi);
9324       break;
9325
9326     case GPOINTER:
9327       genGenPointerGet (left, result, ic, pi);
9328       break;
9329     }
9330
9331 }
9332
9333 /*-----------------------------------------------------------------*/
9334 /* genPackBits - generates code for packed bit storage             */
9335 /*-----------------------------------------------------------------*/
9336 static void
9337 genPackBits (sym_link * etype,
9338              operand * right,
9339              char *rname, int p_type)
9340 {
9341   int shCount = 0;
9342   int offset = 0;
9343   int rLen = 0;
9344   int blen, bstr;
9345   char *l;
9346
9347   blen = SPEC_BLEN (etype);
9348   bstr = SPEC_BSTR (etype);
9349
9350   l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9351   MOVA (l);
9352
9353   /* if the bit lenth is less than or    */
9354   /* it exactly fits a byte then         */
9355   if (SPEC_BLEN (etype) <= 8)
9356     {
9357       shCount = SPEC_BSTR (etype);
9358
9359       /* shift left acc */
9360       AccLsh (shCount);
9361
9362       if (SPEC_BLEN (etype) < 8)
9363         {                       /* if smaller than a byte */
9364
9365
9366           switch (p_type)
9367             {
9368             case POINTER:
9369               emitcode ("mov", "b,a");
9370               emitcode ("mov", "a,@%s", rname);
9371               break;
9372
9373             case FPOINTER:
9374               emitcode ("mov", "b,a");
9375               emitcode ("movx", "a,@dptr");
9376               break;
9377
9378             case GPOINTER:
9379               emitcode ("push", "b");
9380               emitcode ("push", "acc");
9381               emitcode ("lcall", "__gptrget");
9382               emitcode ("pop", "b");
9383               break;
9384             }
9385
9386           emitcode ("anl", "a,#!constbyte", (unsigned char)
9387                     ((unsigned char) (0xFF << (blen + bstr)) |
9388                      (unsigned char) (0xFF >> (8 - bstr))));
9389           emitcode ("orl", "a,b");
9390           if (p_type == GPOINTER)
9391             emitcode ("pop", "b");
9392         }
9393     }
9394
9395   switch (p_type)
9396     {
9397     case POINTER:
9398       emitcode ("mov", "@%s,a", rname);
9399       break;
9400
9401     case FPOINTER:
9402       emitcode ("movx", "@dptr,a");
9403       break;
9404
9405     case GPOINTER:
9406       emitcode ("lcall", "__gptrput");
9407       break;
9408     }
9409
9410   /* if we r done */
9411   if (SPEC_BLEN (etype) <= 8)
9412     return;
9413
9414   emitcode ("inc", "%s", rname);
9415   rLen = SPEC_BLEN (etype);
9416
9417   /* now generate for lengths greater than one byte */
9418   while (1)
9419     {
9420
9421       l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
9422
9423       rLen -= 8;
9424       if (rLen < 8)
9425         break;
9426
9427       switch (p_type)
9428         {
9429         case POINTER:
9430           if (*l == '@')
9431             {
9432               MOVA (l);
9433               emitcode ("mov", "@%s,a", rname);
9434             }
9435           else
9436             emitcode ("mov", "@%s,%s", rname, l);
9437           break;
9438
9439         case FPOINTER:
9440           MOVA (l);
9441           emitcode ("movx", "@dptr,a");
9442           break;
9443
9444         case GPOINTER:
9445           MOVA (l);
9446           emitcode ("lcall", "__gptrput");
9447           break;
9448         }
9449       emitcode ("inc", "%s", rname);
9450     }
9451
9452   MOVA (l);
9453
9454   /* last last was not complete */
9455   if (rLen)
9456     {
9457       /* save the byte & read byte */
9458       switch (p_type)
9459         {
9460         case POINTER:
9461           emitcode ("mov", "b,a");
9462           emitcode ("mov", "a,@%s", rname);
9463           break;
9464
9465         case FPOINTER:
9466           emitcode ("mov", "b,a");
9467           emitcode ("movx", "a,@dptr");
9468           break;
9469
9470         case GPOINTER:
9471           emitcode ("push", "b");
9472           emitcode ("push", "acc");
9473           emitcode ("lcall", "__gptrget");
9474           emitcode ("pop", "b");
9475           break;
9476         }
9477
9478       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1 << rLen));
9479       emitcode ("orl", "a,b");
9480     }
9481
9482   if (p_type == GPOINTER)
9483     emitcode ("pop", "b");
9484
9485   switch (p_type)
9486     {
9487
9488     case POINTER:
9489       emitcode ("mov", "@%s,a", rname);
9490       break;
9491
9492     case FPOINTER:
9493       emitcode ("movx", "@dptr,a");
9494       break;
9495
9496     case GPOINTER:
9497       emitcode ("lcall", "__gptrput");
9498       break;
9499     }
9500 }
9501 /*-----------------------------------------------------------------*/
9502 /* genDataPointerSet - remat pointer to data space                 */
9503 /*-----------------------------------------------------------------*/
9504 static void
9505 genDataPointerSet (operand * right,
9506                    operand * result,
9507                    iCode * ic)
9508 {
9509   int size, offset = 0;
9510   char *l, buffer[256];
9511
9512   aopOp (right, ic, FALSE, FALSE);
9513
9514   l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
9515   size = AOP_SIZE (right);
9516   while (size--)
9517     {
9518       if (offset)
9519         sprintf (buffer, "(%s + %d)", l + 1, offset);
9520       else
9521         sprintf (buffer, "%s", l + 1);
9522       emitcode ("mov", "%s,%s", buffer,
9523                 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
9524     }
9525
9526   freeAsmop (right, NULL, ic, TRUE);
9527   freeAsmop (result, NULL, ic, TRUE);
9528 }
9529
9530 /*-----------------------------------------------------------------*/
9531 /* genNearPointerSet - emitcode for near pointer put                */
9532 /*-----------------------------------------------------------------*/
9533 static void
9534 genNearPointerSet (operand * right,
9535                    operand * result,
9536                    iCode * ic,
9537                    iCode * pi)
9538 {
9539   asmop *aop = NULL;
9540   regs *preg = NULL;
9541   char *rname, *l;
9542   sym_link *retype, *letype;
9543   sym_link *ptype = operandType (result);
9544
9545   retype = getSpec (operandType (right));
9546   letype = getSpec (ptype);
9547
9548   aopOp (result, ic, FALSE, FALSE);
9549
9550   /* if the result is rematerializable &
9551      in data space & not a bit variable */
9552   if (AOP_TYPE (result) == AOP_IMMD &&
9553       DCL_TYPE (ptype) == POINTER &&
9554       !IS_BITVAR (retype) &&
9555       !IS_BITVAR (letype))
9556     {
9557       genDataPointerSet (right, result, ic);
9558       return;
9559     }
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, POINTER);
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, FALSE);
9590           if (*l == '@')
9591             {
9592               MOVA (l);
9593               emitcode ("mov", "@%s,a", rname);
9594             }
9595           else
9596             emitcode ("mov", "@%s,%s", rname, l);
9597           if (size || pi)
9598             emitcode ("inc", "%s", rname);
9599           offset++;
9600         }
9601     }
9602
9603   /* now some housekeeping stuff */
9604   if (aop)
9605     {
9606       /* we had to allocate for this iCode */
9607       if (pi) aopPut (AOP (result),rname,0);
9608       freeAsmop (NULL, aop, ic, TRUE);
9609     }
9610   else
9611     {
9612       /* we did not allocate which means left
9613          already in a pointer register, then
9614          if size > 0 && this could be used again
9615          we have to point it back to where it
9616          belongs */
9617       if (AOP_SIZE (right) > 1 &&
9618           !OP_SYMBOL (result)->remat &&
9619           (OP_SYMBOL (result)->liveTo > ic->seq ||
9620            ic->depth) &&
9621           !pi)
9622         {
9623           int size = AOP_SIZE (right) - 1;
9624           while (size--)
9625             emitcode ("dec", "%s", rname);
9626         }
9627     }
9628
9629   /* done */
9630   if (pi) pi->generated = 1;
9631   freeAsmop (result, NULL, ic, TRUE);
9632   freeAsmop (right, NULL, ic, TRUE);
9633
9634
9635 }
9636
9637 /*-----------------------------------------------------------------*/
9638 /* genPagedPointerSet - emitcode for Paged pointer put             */
9639 /*-----------------------------------------------------------------*/
9640 static void
9641 genPagedPointerSet (operand * right,
9642                     operand * result,
9643                     iCode * ic,
9644                     iCode *pi)
9645 {
9646   asmop *aop = NULL;
9647   regs *preg = NULL;
9648   char *rname, *l;
9649   sym_link *retype, *letype;
9650
9651   retype = getSpec (operandType (right));
9652   letype = getSpec (operandType (result));
9653
9654   aopOp (result, ic, FALSE, FALSE);
9655
9656   /* if the value is already in a pointer register
9657      then don't need anything more */
9658   if (!AOP_INPREG (AOP (result)))
9659     {
9660       /* otherwise get a free pointer register */
9661       aop = newAsmop (0);
9662       preg = getFreePtr (ic, &aop, FALSE);
9663       emitcode ("mov", "%s,%s",
9664                 preg->name,
9665                 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9666       rname = preg->name;
9667     }
9668   else
9669     rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9670
9671   aopOp (right, ic, FALSE, FALSE);
9672
9673   /* if bitfield then unpack the bits */
9674   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9675     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
9676   else
9677     {
9678       /* we have can just get the values */
9679       int size = AOP_SIZE (right);
9680       int offset = 0;
9681
9682       while (size--)
9683         {
9684           l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
9685
9686           MOVA (l);
9687           emitcode ("movx", "@%s,a", rname);
9688
9689           if (size || pi)
9690             emitcode ("inc", "%s", rname);
9691
9692           offset++;
9693         }
9694     }
9695
9696   /* now some housekeeping stuff */
9697   if (aop)
9698     {
9699       if (pi) aopPut (AOP (result),rname,0);
9700       /* we had to allocate for this iCode */
9701       freeAsmop (NULL, aop, ic, TRUE);
9702     }
9703   else
9704     {
9705       /* we did not allocate which means left
9706          already in a pointer register, then
9707          if size > 0 && this could be used again
9708          we have to point it back to where it
9709          belongs */
9710       if (AOP_SIZE (right) > 1 &&
9711           !OP_SYMBOL (result)->remat &&
9712           (OP_SYMBOL (result)->liveTo > ic->seq ||
9713            ic->depth) &&
9714           !pi)
9715         {
9716           int size = AOP_SIZE (right) - 1;
9717           while (size--)
9718             emitcode ("dec", "%s", rname);
9719         }
9720     }
9721
9722   /* done */
9723   if (pi) pi->generated = 1;
9724   freeAsmop (result, NULL, ic, TRUE);
9725   freeAsmop (right, NULL, ic, TRUE);
9726
9727
9728 }
9729
9730 /*-----------------------------------------------------------------*/
9731 /* genFarPointerSet - set value from far space                     */
9732 /*-----------------------------------------------------------------*/
9733 static void
9734 genFarPointerSet (operand * right,
9735                   operand * result, iCode * ic, iCode *pi)
9736 {
9737   int size, offset, dopi=1;
9738   sym_link *retype = getSpec (operandType (right));
9739   sym_link *letype = getSpec (operandType (result));
9740
9741   aopOp (result, ic, FALSE, FALSE);
9742
9743   /* if the operand is already in dptr
9744      then we do nothing else we move the value to dptr */
9745   if (AOP_TYPE (result) != AOP_STR)
9746     {
9747       /* if this is remateriazable */
9748       if (AOP_TYPE (result) == AOP_IMMD)
9749         emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9750       else
9751         {
9752           /* we need to get it byte by byte */
9753           _startLazyDPSEvaluation ();
9754           if (AOP_TYPE (result) != AOP_DPTR)
9755             {
9756               emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9757               emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9758               if (options.model == MODEL_FLAT24)
9759                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9760             }
9761           else
9762             {
9763               /* We need to generate a load to DPTR indirect through DPTR. */
9764               D (emitcode (";", "genFarPointerSet -- indirection special case.");
9765                 );
9766               emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
9767               emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
9768               if (options.model == MODEL_FLAT24)
9769                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9770               emitcode ("pop", "dph");
9771               emitcode ("pop", "dpl");
9772               dopi=0;
9773             }
9774           _endLazyDPSEvaluation ();
9775         }
9776     }
9777   /* so dptr know contains the address */
9778   aopOp (right, ic, FALSE, TRUE);
9779
9780   /* if bit then unpack */
9781   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9782     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
9783   else
9784     {
9785       size = AOP_SIZE (right);
9786       offset = 0;
9787
9788       _startLazyDPSEvaluation ();
9789       while (size--)
9790         {
9791           char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9792           MOVA (l);
9793
9794           genSetDPTR (0);
9795           _flushLazyDPS ();
9796
9797           emitcode ("movx", "@dptr,a");
9798           if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
9799             emitcode ("inc", "dptr");
9800         }
9801       _endLazyDPSEvaluation ();
9802     }
9803
9804   if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
9805       aopPut (AOP(result),"dpl",0);
9806       aopPut (AOP(result),"dph",1);
9807       if (options.model == MODEL_FLAT24)
9808           aopPut (AOP(result),"dpx",2);
9809       pi->generated=1;
9810   } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
9811              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
9812       
9813       size = AOP_SIZE (right) - 1;
9814       while (size--) emitcode ("lcall","__decdptr");
9815   }
9816   freeAsmop (result, NULL, ic, TRUE);
9817   freeAsmop (right, NULL, ic, TRUE);
9818 }
9819
9820 /*-----------------------------------------------------------------*/
9821 /* genGenPointerSet - set value from generic pointer space         */
9822 /*-----------------------------------------------------------------*/
9823 static void
9824 genGenPointerSet (operand * right,
9825                   operand * result, iCode * ic, iCode *pi)
9826 {
9827   int size, offset;
9828   sym_link *retype = getSpec (operandType (right));
9829   sym_link *letype = getSpec (operandType (result));
9830
9831   aopOp (result, ic, FALSE, OP_SYMBOL(result)->ruonly ? FALSE : TRUE);
9832
9833   /* if the operand is already in dptr
9834      then we do nothing else we move the value to dptr */
9835   if (AOP_TYPE (result) != AOP_STR)
9836     {
9837       _startLazyDPSEvaluation ();
9838       /* if this is remateriazable */
9839       if (AOP_TYPE (result) == AOP_IMMD)
9840         {
9841           emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9842           if (AOP(result)->aopu.aop_immd.from_cast_remat) 
9843                   emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, FALSE));
9844           else
9845                   emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9846         }
9847       else
9848         {                       /* we need to get it byte by byte */
9849           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9850           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9851           if (options.model == MODEL_FLAT24) {
9852             emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9853             emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
9854           } else {
9855             emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9856           }
9857         }
9858       _endLazyDPSEvaluation ();
9859     }
9860   /* so dptr know contains the address */
9861   aopOp (right, ic, FALSE, TRUE);
9862
9863   /* if bit then unpack */
9864   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9865     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
9866   else
9867     {
9868       size = AOP_SIZE (right);
9869       offset = 0;
9870
9871       _startLazyDPSEvaluation ();
9872       while (size--)
9873         {
9874           char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9875           MOVA (l);
9876
9877           genSetDPTR (0);
9878           _flushLazyDPS ();
9879
9880           emitcode ("lcall", "__gptrput");
9881           if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
9882             emitcode ("inc", "dptr");
9883         }
9884       _endLazyDPSEvaluation ();
9885     }
9886
9887   if (pi && AOP_TYPE (result) != AOP_IMMD) {
9888       aopPut (AOP(result),"dpl",0);
9889       aopPut (AOP(result),"dph",1);
9890       if (options.model == MODEL_FLAT24) {
9891           aopPut (AOP(result),"dpx",2);
9892           aopPut (AOP(result),"b",3);
9893       } else {
9894           aopPut (AOP(result),"b",2);
9895       }
9896       pi->generated=1;
9897   } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
9898              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
9899       
9900       size = AOP_SIZE (right) - 1;
9901       while (size--) emitcode ("lcall","__decdptr");
9902   }
9903   freeAsmop (result, NULL, ic, TRUE);
9904   freeAsmop (right, NULL, ic, TRUE);
9905 }
9906
9907 /*-----------------------------------------------------------------*/
9908 /* genPointerSet - stores the value into a pointer location        */
9909 /*-----------------------------------------------------------------*/
9910 static void
9911 genPointerSet (iCode * ic, iCode *pi)
9912 {
9913   operand *right, *result;
9914   sym_link *type, *etype;
9915   int p_type;
9916
9917   D (emitcode (";", "genPointerSet ");
9918     );
9919
9920   right = IC_RIGHT (ic);
9921   result = IC_RESULT (ic);
9922
9923   /* depending on the type of pointer we need to
9924      move it to the correct pointer register */
9925   type = operandType (result);
9926   etype = getSpec (type);
9927   /* if left is of type of pointer then it is simple */
9928   if (IS_PTR (type) && !IS_FUNC (type->next))
9929     {
9930       p_type = DCL_TYPE (type);
9931     }
9932   else
9933     {
9934       /* we have to go by the storage class */
9935       p_type = PTR_TYPE (SPEC_OCLS (etype));
9936     }
9937   /* special case when cast remat */
9938   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
9939       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
9940           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
9941           type =   type = operandType (result);
9942           p_type = DCL_TYPE (type);
9943   }
9944
9945   /* now that we have the pointer type we assign
9946      the pointer values */
9947   switch (p_type)
9948     {
9949
9950     case POINTER:
9951     case IPOINTER:
9952       genNearPointerSet (right, result, ic, pi);
9953       break;
9954
9955     case PPOINTER:
9956       genPagedPointerSet (right, result, ic, pi);
9957       break;
9958
9959     case FPOINTER:
9960       genFarPointerSet (right, result, ic, pi);
9961       break;
9962
9963     case GPOINTER:
9964       genGenPointerSet (right, result, ic, pi);
9965       break;
9966     }
9967
9968 }
9969
9970 /*-----------------------------------------------------------------*/
9971 /* genIfx - generate code for Ifx statement                        */
9972 /*-----------------------------------------------------------------*/
9973 static void
9974 genIfx (iCode * ic, iCode * popIc)
9975 {
9976   operand *cond = IC_COND (ic);
9977   int isbit = 0;
9978
9979   D (emitcode (";", "genIfx "););
9980
9981   aopOp (cond, ic, FALSE, FALSE);
9982
9983   /* get the value into acc */
9984   if (AOP_TYPE (cond) != AOP_CRY)
9985     toBoolean (cond);
9986   else
9987     isbit = 1;
9988   /* the result is now in the accumulator */
9989   freeAsmop (cond, NULL, ic, TRUE);
9990
9991   /* if there was something to be popped then do it */
9992   if (popIc)
9993     genIpop (popIc);
9994
9995   /* if the condition is  a bit variable */
9996   if (isbit && IS_ITEMP (cond) &&
9997       SPIL_LOC (cond))
9998     genIfxJump (ic, SPIL_LOC (cond)->rname);
9999   else if (isbit && !IS_ITEMP (cond))
10000     genIfxJump (ic, OP_SYMBOL (cond)->rname);
10001   else
10002     genIfxJump (ic, "a");
10003
10004   ic->generated = 1;
10005 }
10006
10007 /*-----------------------------------------------------------------*/
10008 /* genAddrOf - generates code for address of                       */
10009 /*-----------------------------------------------------------------*/
10010 static void
10011 genAddrOf (iCode * ic)
10012 {
10013   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10014   int size, offset;
10015
10016   D (emitcode (";", "genAddrOf ");
10017     );
10018
10019   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10020
10021   /* if the operand is on the stack then we
10022      need to get the stack offset of this
10023      variable */
10024   if (sym->onStack) {
10025       
10026       /* if 10 bit stack */
10027       if (options.stack10bit) {
10028           char buff[10];
10029           tsprintf(buff,"#!constbyte",(options.stack_loc >> 16) & 0xff);
10030           /* if it has an offset then we need to compute it */
10031           emitcode ("subb", "a,#!constbyte",
10032                     -((sym->stack < 0) ?
10033                       ((short) (sym->stack - _G.nRegsSaved)) :
10034                       ((short) sym->stack)) & 0xff);
10035           emitcode ("mov","b,a");
10036           emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ?
10037                                          ((short) (sym->stack - _G.nRegsSaved)) :
10038                                          ((short) sym->stack)) >> 8) & 0xff);
10039           if (sym->stack) {
10040               emitcode ("mov", "a,_bpx");
10041               emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ? 
10042                                              ((char) (sym->stack - _G.nRegsSaved)) :
10043                                              ((char) sym->stack )) & 0xff);
10044               emitcode ("mov", "b,a");
10045               emitcode ("mov", "a,_bpx+1");
10046               emitcode ("addc","a,#!constbyte", (((sym->stack < 0) ? 
10047                                               ((short) (sym->stack - _G.nRegsSaved)) :
10048                                               ((short) sym->stack )) >> 8) & 0xff);
10049               aopPut (AOP (IC_RESULT (ic)), "b", 0);
10050               aopPut (AOP (IC_RESULT (ic)), "a", 1);
10051               aopPut (AOP (IC_RESULT (ic)), buff, 2);
10052           } else {
10053               /* we can just move _bp */
10054               aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
10055               aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
10056               aopPut (AOP (IC_RESULT (ic)), buff, 2);
10057           }       
10058       } else {
10059           /* if it has an offset then we need to compute it */
10060           if (sym->stack) {
10061               emitcode ("mov", "a,_bp");
10062               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
10063               aopPut (AOP (IC_RESULT (ic)), "a", 0);
10064           } else {
10065               /* we can just move _bp */
10066               aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
10067           }
10068           /* fill the result with zero */
10069           size = AOP_SIZE (IC_RESULT (ic)) - 1;
10070           
10071           
10072           if (options.stack10bit && size < (FPTRSIZE - 1)) {
10073               fprintf (stderr,
10074                        "*** warning: pointer to stack var truncated.\n");
10075           }
10076
10077           offset = 1;
10078           while (size--) {
10079               aopPut (AOP (IC_RESULT (ic)), zero, offset++);
10080           }      
10081       }
10082       goto release;
10083   }
10084
10085   /* object not on stack then we need the name */
10086   size = AOP_SIZE (IC_RESULT (ic));
10087   offset = 0;
10088
10089   while (size--)
10090     {
10091       char s[SDCC_NAME_MAX];
10092       if (offset) {
10093           switch (offset) {
10094           case 1:
10095               tsprintf(s,"!his",sym->rname);
10096               break;
10097           case 2:
10098               tsprintf(s,"!hihis",sym->rname);
10099               break;
10100           case 3:
10101               tsprintf(s,"!hihihis",sym->rname);
10102               break;
10103           default: /* should not need this (just in case) */
10104               sprintf (s, "#(%s >> %d)",
10105                        sym->rname,
10106                        offset * 8);
10107           }
10108       } else
10109           sprintf (s, "#%s", sym->rname);
10110       aopPut (AOP (IC_RESULT (ic)), s, offset++);
10111     }
10112
10113 release:
10114   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10115
10116 }
10117
10118 /*-----------------------------------------------------------------*/
10119 /* genArrayInit - generates code for address of                       */
10120 /*-----------------------------------------------------------------*/
10121 static void
10122 genArrayInit (iCode * ic)
10123 {
10124     literalList *iLoop;
10125     int         ix, count;
10126     int         elementSize = 0, eIndex;
10127     unsigned    val, lastVal;
10128     sym_link    *type;
10129     operand     *left=IC_LEFT(ic);
10130     
10131     D (emitcode (";", "genArrayInit "););
10132
10133     aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10134     
10135     if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10136     {
10137         // Load immediate value into DPTR.
10138         emitcode("mov", "dptr, %s",
10139              aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, TRUE));
10140     }
10141     else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10142     {
10143 #if 0
10144       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10145               "Unexpected operand to genArrayInit.\n");
10146       exit(1);
10147 #else
10148       // a regression because of SDCCcse.c:1.52
10149       emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
10150       emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
10151       if (options.model == MODEL_FLAT24)
10152         emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
10153 #endif
10154     }
10155     
10156     type = operandType(IC_LEFT(ic));
10157     
10158     if (type && type->next)
10159     {
10160         elementSize = getSize(type->next);
10161     }
10162     else
10163     {
10164         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10165                                 "can't determine element size in genArrayInit.\n");
10166         exit(1);
10167     }
10168     
10169     iLoop = IC_ARRAYILIST(ic);
10170     lastVal = 0xffff;
10171     
10172     while (iLoop)
10173     {
10174         bool firstpass = TRUE;
10175         
10176         emitcode(";", "store %d x 0x%x to DPTR (element size %d)", 
10177                  iLoop->count, (int)iLoop->literalValue, elementSize);
10178         
10179         ix = iLoop->count;
10180         
10181         while (ix)
10182         {
10183             symbol *tlbl = NULL;
10184             
10185             count = ix > 256 ? 256 : ix;
10186             
10187             if (count > 1)
10188             {
10189                 tlbl = newiTempLabel (NULL);
10190                 if (firstpass || (count & 0xff))
10191                 {
10192                     emitcode("mov", "b, #!constbyte", count & 0xff);
10193                 }
10194                 
10195                 emitcode ("", "!tlabeldef", tlbl->key + 100);
10196             }
10197             
10198             firstpass = FALSE;
10199                 
10200             for (eIndex = 0; eIndex < elementSize; eIndex++)
10201             {
10202                 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10203                 if (val != lastVal)
10204                 {
10205                     emitcode("mov", "a, #!constbyte", val);
10206                     lastVal = val;
10207                 }
10208                 
10209                 emitcode("movx", "@dptr, a");
10210                 emitcode("inc", "dptr");
10211             }
10212             
10213             if (count > 1)
10214             {
10215                 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
10216             }
10217             
10218             ix -= count;
10219         }
10220         
10221         iLoop = iLoop->next;
10222     }
10223     
10224     freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10225 }
10226
10227 /*-----------------------------------------------------------------*/
10228 /* genFarFarAssign - assignment when both are in far space         */
10229 /*-----------------------------------------------------------------*/
10230 static void
10231 genFarFarAssign (operand * result, operand * right, iCode * ic)
10232 {
10233   int size = AOP_SIZE (right);
10234   int offset = 0;
10235   symbol *rSym = NULL;
10236
10237   if (size == 1)
10238   {
10239       /* quick & easy case. */
10240       D(emitcode(";","genFarFarAssign (1 byte case)"););      
10241       MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
10242       freeAsmop (right, NULL, ic, FALSE);
10243       /* now assign DPTR to result */
10244       _G.accInUse++;
10245       aopOp(result, ic, FALSE, FALSE);
10246       _G.accInUse--;
10247       aopPut(AOP(result), "a", 0);
10248       freeAsmop(result, NULL, ic, FALSE);
10249       return;
10250   }
10251   
10252   /* See if we've got an underlying symbol to abuse. */
10253   if (IS_SYMOP(result) && OP_SYMBOL(result))
10254   {
10255       if (IS_TRUE_SYMOP(result))
10256       {
10257           rSym = OP_SYMBOL(result);
10258       }
10259       else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10260       {
10261           rSym = OP_SYMBOL(result)->usl.spillLoc;
10262       }
10263   }
10264              
10265   if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10266   {
10267       /* We can use the '390 auto-toggle feature to good effect here. */
10268       
10269       D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10270       emitcode("mov", "dps,#!constbyte",0x21);  /* Select DPTR2 & auto-toggle. */
10271       emitcode ("mov", "dptr,#%s", rSym->rname); 
10272       /* DP2 = result, DP1 = right, DP1 is current. */
10273       while (size)
10274       {
10275           emitcode("movx", "a,@dptr");
10276           emitcode("movx", "@dptr,a");
10277           if (--size)
10278           {
10279                emitcode("inc", "dptr");
10280                emitcode("inc", "dptr");
10281           }
10282       }
10283       emitcode("mov", "dps,#0");
10284       freeAsmop (right, NULL, ic, FALSE);
10285 #if 0
10286 some alternative code for processors without auto-toggle
10287 no time to test now, so later well put in...kpb
10288         D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10289         emitcode("mov", "dps,#1");      /* Select DPTR2. */
10290         emitcode ("mov", "dptr,#%s", rSym->rname); 
10291         /* DP2 = result, DP1 = right, DP1 is current. */
10292         while (size)
10293         {
10294           --size;
10295           emitcode("movx", "a,@dptr");
10296           if (size)
10297             emitcode("inc", "dptr");
10298           emitcode("inc", "dps");
10299           emitcode("movx", "@dptr,a");
10300           if (size)
10301             emitcode("inc", "dptr");
10302           emitcode("inc", "dps");
10303         }
10304         emitcode("mov", "dps,#0");
10305         freeAsmop (right, NULL, ic, FALSE);
10306 #endif
10307   }
10308   else
10309   {
10310       D (emitcode (";", "genFarFarAssign"););
10311       aopOp (result, ic, TRUE, TRUE);
10312
10313       _startLazyDPSEvaluation ();
10314       
10315       while (size--)
10316         {
10317           aopPut (AOP (result),
10318                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
10319           offset++;
10320         }
10321       _endLazyDPSEvaluation ();
10322       freeAsmop (result, NULL, ic, FALSE);
10323       freeAsmop (right, NULL, ic, FALSE);
10324   }
10325 }
10326
10327 /*-----------------------------------------------------------------*/
10328 /* genAssign - generate code for assignment                        */
10329 /*-----------------------------------------------------------------*/
10330 static void
10331 genAssign (iCode * ic)
10332 {
10333   operand *result, *right;
10334   int size, offset;
10335   unsigned long lit = 0L;
10336
10337   D (emitcode (";", "genAssign ");
10338     );
10339
10340   result = IC_RESULT (ic);
10341   right = IC_RIGHT (ic);
10342
10343   /* if they are the same */
10344   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10345     return;
10346
10347   aopOp (right, ic, FALSE, FALSE);
10348
10349   emitcode (";", "genAssign: resultIsFar = %s",
10350             isOperandInFarSpace (result) ?
10351             "TRUE" : "FALSE");
10352
10353   /* special case both in far space */
10354   if ((AOP_TYPE (right) == AOP_DPTR ||
10355        AOP_TYPE (right) == AOP_DPTR2) &&
10356   /* IS_TRUE_SYMOP(result)       && */
10357       isOperandInFarSpace (result))
10358     {
10359       genFarFarAssign (result, right, ic);
10360       return;
10361     }
10362
10363   aopOp (result, ic, TRUE, FALSE);
10364
10365   /* if they are the same registers */
10366   if (sameRegs (AOP (right), AOP (result)))
10367     goto release;
10368
10369   /* if the result is a bit */
10370   if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10371     {
10372       /* if the right size is a literal then
10373          we know what the value is */
10374       if (AOP_TYPE (right) == AOP_LIT)
10375         {
10376           if (((int) operandLitValue (right)))
10377             aopPut (AOP (result), one, 0);
10378           else
10379             aopPut (AOP (result), zero, 0);
10380           goto release;
10381         }
10382
10383       /* the right is also a bit variable */
10384       if (AOP_TYPE (right) == AOP_CRY)
10385         {
10386           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10387           aopPut (AOP (result), "c", 0);
10388           goto release;
10389         }
10390
10391       /* we need to or */
10392       toBoolean (right);
10393       aopPut (AOP (result), "a", 0);
10394       goto release;
10395     }
10396
10397   /* bit variables done */
10398   /* general case */
10399   size = AOP_SIZE (result);
10400   offset = 0;
10401   if (AOP_TYPE (right) == AOP_LIT)
10402     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10403
10404   if ((size > 1) &&
10405       (AOP_TYPE (result) != AOP_REG) &&
10406       (AOP_TYPE (right) == AOP_LIT) &&
10407       !IS_FLOAT (operandType (right)))
10408     {
10409       _startLazyDPSEvaluation ();
10410       while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10411         {
10412           aopPut (AOP (result),
10413                   aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
10414                   offset);
10415           offset++;
10416           size--;
10417         }
10418       /* And now fill the rest with zeros. */
10419       if (size)
10420         {
10421           emitcode ("clr", "a");
10422         }
10423       while (size--)
10424         {
10425           aopPut (AOP (result), "a", offset++);
10426         }
10427       _endLazyDPSEvaluation ();
10428     }
10429   else
10430     {
10431       _startLazyDPSEvaluation ();
10432       while (size--)
10433         {
10434           aopPut (AOP (result),
10435                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10436                   offset);
10437           offset++;
10438         }
10439       _endLazyDPSEvaluation ();
10440     }
10441
10442 release:
10443   freeAsmop (right, NULL, ic, FALSE);
10444   freeAsmop (result, NULL, ic, TRUE);
10445 }
10446
10447 /*-----------------------------------------------------------------*/
10448 /* genJumpTab - generates code for jump table                      */
10449 /*-----------------------------------------------------------------*/
10450 static void
10451 genJumpTab (iCode * ic)
10452 {
10453   symbol *jtab;
10454   char *l;
10455
10456   D (emitcode (";", "genJumpTab ");
10457     );
10458
10459   aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10460   /* get the condition into accumulator */
10461   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
10462   MOVA (l);
10463   /* multiply by four! */
10464   emitcode ("add", "a,acc");
10465   emitcode ("add", "a,acc");
10466   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10467
10468   jtab = newiTempLabel (NULL);
10469   emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
10470   emitcode ("jmp", "@a+dptr");
10471   emitcode ("", "!tlabeldef", jtab->key + 100);
10472   /* now generate the jump labels */
10473   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10474        jtab = setNextItem (IC_JTLABELS (ic)))
10475     emitcode ("ljmp", "!tlabel", jtab->key + 100);
10476
10477 }
10478
10479 /*-----------------------------------------------------------------*/
10480 /* genCast - gen code for casting                                  */
10481 /*-----------------------------------------------------------------*/
10482 static void
10483 genCast (iCode * ic)
10484 {
10485   operand *result = IC_RESULT (ic);
10486   sym_link *ctype = operandType (IC_LEFT (ic));
10487   sym_link *rtype = operandType (IC_RIGHT (ic));
10488   operand *right = IC_RIGHT (ic);
10489   int size, offset;
10490
10491   D (emitcode (";", "genCast ");
10492     );
10493
10494   /* if they are equivalent then do nothing */
10495   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10496     return;
10497
10498   aopOp (right, ic, FALSE, FALSE);
10499   aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
10500
10501   /* if the result is a bit */
10502   // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10503   if (IS_BITVAR(OP_SYMBOL(result)->type))
10504     {
10505       /* if the right size is a literal then
10506          we know what the value is */
10507       if (AOP_TYPE (right) == AOP_LIT)
10508         {
10509           if (((int) operandLitValue (right)))
10510             aopPut (AOP (result), one, 0);
10511           else
10512             aopPut (AOP (result), zero, 0);
10513
10514           goto release;
10515         }
10516
10517       /* the right is also a bit variable */
10518       if (AOP_TYPE (right) == AOP_CRY)
10519         {
10520           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10521           aopPut (AOP (result), "c", 0);
10522           goto release;
10523         }
10524
10525       /* we need to or */
10526       toBoolean (right);
10527       aopPut (AOP (result), "a", 0);
10528       goto release;
10529     }
10530
10531   /* if they are the same size : or less */
10532   if (AOP_SIZE (result) <= AOP_SIZE (right))
10533     {
10534
10535       /* if they are in the same place */
10536       if (sameRegs (AOP (right), AOP (result)))
10537         goto release;
10538
10539       /* if they in different places then copy */
10540       size = AOP_SIZE (result);
10541       offset = 0;
10542       _startLazyDPSEvaluation ();
10543       while (size--)
10544         {
10545           aopPut (AOP (result),
10546                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10547                   offset);
10548           offset++;
10549         }
10550       _endLazyDPSEvaluation ();
10551       goto release;
10552     }
10553
10554
10555   /* if the result is of type pointer */
10556   if (IS_PTR (ctype))
10557     {
10558
10559       int p_type;
10560       sym_link *type = operandType (right);
10561
10562       /* pointer to generic pointer */
10563       if (IS_GENPTR (ctype))
10564         {
10565           char *l = zero;
10566
10567           if (IS_PTR (type))
10568             {
10569               p_type = DCL_TYPE (type);
10570             }
10571           else
10572             {
10573 #if OLD_CAST_BEHAVIOR
10574               /* KV: we are converting a non-pointer type to
10575                * a generic pointer. This (ifdef'd out) code
10576                * says that the resulting generic pointer
10577                * should have the same class as the storage
10578                * location of the non-pointer variable.
10579                *
10580                * For example, converting an int (which happens
10581                * to be stored in DATA space) to a pointer results
10582                * in a DATA generic pointer; if the original int
10583                * in XDATA space, so will be the resulting pointer.
10584                *
10585                * I don't like that behavior, and thus this change:
10586                * all such conversions will be forced to XDATA and
10587                * throw a warning. If you want some non-XDATA
10588                * type, or you want to suppress the warning, you
10589                * must go through an intermediate cast, like so:
10590                *
10591                * char _generic *gp = (char _xdata *)(intVar);
10592                */
10593               sym_link *etype = getSpec (type);
10594
10595               /* we have to go by the storage class */
10596               if (SPEC_OCLS (etype) != generic)
10597                 {
10598                   p_type = PTR_TYPE (SPEC_OCLS (etype));
10599                 }
10600               else
10601 #endif
10602                 {
10603                   /* Converting unknown class (i.e. register variable)
10604                    * to generic pointer. This is not good, but
10605                    * we'll make a guess (and throw a warning).
10606                    */
10607                   p_type = FPOINTER;
10608                   werror (W_INT_TO_GEN_PTR_CAST);
10609                 }
10610             }
10611
10612           /* the first two bytes are known */
10613           size = GPTRSIZE - 1;
10614           offset = 0;
10615           _startLazyDPSEvaluation ();
10616           while (size--)
10617             {
10618               aopPut (AOP (result),
10619                       aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10620                       offset);
10621               offset++;
10622             }
10623           _endLazyDPSEvaluation ();
10624
10625           /* the last byte depending on type */
10626           switch (p_type)
10627             {
10628             case IPOINTER:
10629             case POINTER:
10630               l = zero;
10631               break;
10632             case FPOINTER:
10633               l = one;
10634               break;
10635             case CPOINTER:
10636               l = "#0x02";
10637               break;
10638             case PPOINTER:
10639               l = "#0x03";
10640               break;
10641
10642             default:
10643               /* this should never happen */
10644               werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10645                       "got unknown pointer type");
10646               exit (1);
10647             }
10648           aopPut (AOP (result), l, GPTRSIZE - 1);
10649           goto release;
10650         }
10651
10652       /* just copy the pointers */
10653       size = AOP_SIZE (result);
10654       offset = 0;
10655       _startLazyDPSEvaluation ();
10656       while (size--)
10657         {
10658           aopPut (AOP (result),
10659                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10660                   offset);
10661           offset++;
10662         }
10663       _endLazyDPSEvaluation ();
10664       goto release;
10665     }
10666
10667   /* so we now know that the size of destination is greater
10668      than the size of the source */
10669   /* we move to result for the size of source */
10670   size = AOP_SIZE (right);
10671   offset = 0;
10672   _startLazyDPSEvaluation ();
10673   while (size--)
10674     {
10675       aopPut (AOP (result),
10676               aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10677               offset);
10678       offset++;
10679     }
10680   _endLazyDPSEvaluation ();
10681
10682   /* now depending on the sign of the source && destination */
10683   size = AOP_SIZE (result) - AOP_SIZE (right);
10684   /* if unsigned or not an integral type */
10685   /* also, if the source is a bit, we don't need to sign extend, because
10686    * it can't possibly have set the sign bit.
10687    */
10688   if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
10689     {
10690       while (size--)
10691         {
10692           aopPut (AOP (result), zero, offset++);
10693         }
10694     }
10695   else
10696     {
10697       /* we need to extend the sign :{ */
10698       char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
10699                         FALSE, FALSE, TRUE);
10700       MOVA (l);
10701       emitcode ("rlc", "a");
10702       emitcode ("subb", "a,acc");
10703       while (size--)
10704         aopPut (AOP (result), "a", offset++);
10705     }
10706
10707   /* we are done hurray !!!! */
10708
10709 release:
10710   freeAsmop (right, NULL, ic, TRUE);
10711   freeAsmop (result, NULL, ic, TRUE);
10712
10713 }
10714
10715 /*-----------------------------------------------------------------*/
10716 /* genDjnz - generate decrement & jump if not zero instrucion      */
10717 /*-----------------------------------------------------------------*/
10718 static int
10719 genDjnz (iCode * ic, iCode * ifx)
10720 {
10721   symbol *lbl, *lbl1;
10722   if (!ifx)
10723     return 0;
10724
10725   /* if the if condition has a false label
10726      then we cannot save */
10727   if (IC_FALSE (ifx))
10728     return 0;
10729
10730   /* if the minus is not of the form
10731      a = a - 1 */
10732   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
10733       !IS_OP_LITERAL (IC_RIGHT (ic)))
10734     return 0;
10735
10736   if (operandLitValue (IC_RIGHT (ic)) != 1)
10737     return 0;
10738
10739   /* if the size of this greater than one then no
10740      saving */
10741   if (getSize (operandType (IC_RESULT (ic))) > 1)
10742     return 0;
10743
10744   /* otherwise we can save BIG */
10745   D(emitcode(";", "genDjnz"););
10746
10747   lbl = newiTempLabel (NULL);
10748   lbl1 = newiTempLabel (NULL);
10749
10750   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10751
10752   if (AOP_NEEDSACC(IC_RESULT(ic)))
10753   {
10754       /* If the result is accessed indirectly via
10755        * the accumulator, we must explicitly write
10756        * it back after the decrement.
10757        */
10758       char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
10759       
10760       if (strcmp(rByte, "a"))
10761       {
10762            /* Something is hopelessly wrong */
10763            fprintf(stderr, "*** warning: internal error at %s:%d\n",
10764                    __FILE__, __LINE__);
10765            /* We can just give up; the generated code will be inefficient,
10766             * but what the hey.
10767             */
10768            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10769            return 0;
10770       }
10771       emitcode ("dec", "%s", rByte);
10772       aopPut(AOP(IC_RESULT(ic)), rByte, 0);
10773       emitcode ("jnz", "!tlabel", lbl->key + 100);
10774   }
10775   else if (IS_AOP_PREG (IC_RESULT (ic)))
10776     {
10777       emitcode ("dec", "%s",
10778                 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10779       emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10780       emitcode ("jnz", "!tlabel", lbl->key + 100);
10781     }
10782   else
10783     {
10784       emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
10785                 lbl->key + 100);
10786     }
10787   emitcode ("sjmp", "!tlabel", lbl1->key + 100);
10788   emitcode ("", "!tlabeldef", lbl->key + 100);
10789   emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
10790   emitcode ("", "!tlabeldef", lbl1->key + 100);
10791
10792   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10793   ifx->generated = 1;
10794   return 1;
10795 }
10796
10797 /*-----------------------------------------------------------------*/
10798 /* genReceive - generate code for a receive iCode                  */
10799 /*-----------------------------------------------------------------*/
10800 static void
10801 genReceive (iCode * ic)
10802 {
10803
10804   D (emitcode (";", "genReceive ");
10805     );
10806
10807   if (isOperandInFarSpace (IC_RESULT (ic)) &&
10808       (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
10809        IS_TRUE_SYMOP (IC_RESULT (ic))))
10810     {
10811       int size = getSize (operandType (IC_RESULT (ic)));
10812       int offset = fReturnSizeDS390 - size;
10813       while (size--)
10814         {
10815           emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
10816                             fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
10817           offset++;
10818         }
10819       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10820       size = AOP_SIZE (IC_RESULT (ic));
10821       offset = 0;
10822       while (size--)
10823         {
10824           emitcode ("pop", "acc");
10825           aopPut (AOP (IC_RESULT (ic)), "a", offset++);
10826         }
10827
10828     }
10829   else
10830     {
10831       _G.accInUse++;
10832       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10833       _G.accInUse--;
10834       assignResultValue (IC_RESULT (ic));
10835     }
10836
10837   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10838 }
10839
10840 /*-----------------------------------------------------------------*/
10841 /* genMemcpyX2X - gen code for memcpy xdata to xdata               */
10842 /*-----------------------------------------------------------------*/
10843 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
10844 {
10845     operand *from , *to , *count;
10846     symbol *lbl;
10847     bitVect *rsave;
10848     int i;
10849
10850     /* we know it has to be 3 parameters */
10851     assert (nparms == 3);
10852     
10853     rsave = newBitVect(16);
10854     /* save DPTR if it needs to be saved */
10855     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
10856             if (bitVectBitValue(ic->rMask,i))
10857                     rsave = bitVectSetBit(rsave,i);
10858     }
10859     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
10860                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
10861     savermask(rsave);
10862     
10863     to = parms[0];
10864     from = parms[1];
10865     count = parms[2];
10866
10867     aopOp (from, ic->next, FALSE, FALSE);
10868
10869     /* get from into DPTR1 */
10870     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, TRUE));
10871     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, TRUE));
10872     if (options.model == MODEL_FLAT24) {
10873         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, TRUE));
10874     }
10875
10876     freeAsmop (from, NULL, ic, FALSE);
10877     aopOp (to, ic, FALSE, FALSE);
10878     /* get "to" into DPTR */
10879     /* if the operand is already in dptr
10880        then we do nothing else we move the value to dptr */
10881     if (AOP_TYPE (to) != AOP_STR) {
10882         /* if already in DPTR then we need to push */
10883         if (AOP_TYPE(to) == AOP_DPTR) {
10884             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
10885             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
10886             if (options.model == MODEL_FLAT24)
10887                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
10888             emitcode ("pop", "dph");
10889             emitcode ("pop", "dpl");        
10890         } else {
10891             _startLazyDPSEvaluation ();
10892             /* if this is remateriazable */
10893             if (AOP_TYPE (to) == AOP_IMMD) {
10894                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
10895             } else {                    /* we need to get it byte by byte */
10896                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
10897                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
10898                 if (options.model == MODEL_FLAT24) {
10899                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
10900                 }
10901             }
10902             _endLazyDPSEvaluation ();
10903         }
10904     }
10905     freeAsmop (to, NULL, ic, FALSE);
10906
10907     aopOp (count, ic->next->next, FALSE,FALSE);
10908     lbl =newiTempLabel(NULL);
10909
10910     /* now for the actual copy */
10911     if (AOP_TYPE(count) == AOP_LIT && 
10912         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
10913         emitcode (";","OH  JOY auto increment with djnz (very fast)");
10914         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
10915         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
10916         emitcode ("","!tlabeldef",lbl->key+100);
10917         if (fromc) {
10918             emitcode ("clr","a");
10919             emitcode ("movc", "a,@a+dptr");
10920         } else 
10921             emitcode ("movx", "a,@dptr");
10922         emitcode ("movx", "@dptr,a");
10923         emitcode ("inc", "dptr");
10924         emitcode ("inc", "dptr");
10925         emitcode ("djnz","b,!tlabel",lbl->key+100);
10926     } else {
10927         symbol *lbl1 = newiTempLabel(NULL);
10928         
10929         emitcode (";"," Auto increment but no djnz");
10930         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
10931         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
10932         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
10933         emitcode ("","!tlabeldef",lbl->key+100);
10934         if (fromc) {
10935             emitcode ("clr","a");
10936             emitcode ("movc", "a,@a+dptr");
10937         } else 
10938             emitcode ("movx", "a,@dptr");
10939         emitcode ("movx", "@dptr,a");
10940         emitcode ("inc", "dptr");
10941         emitcode ("inc", "dptr");
10942         emitcode ("mov","a,b");
10943         emitcode ("orl","a,_ap");
10944         emitcode ("jz","!tlabel",lbl1->key+100);
10945         emitcode ("mov","a,_ap");
10946         emitcode ("add","a,#!constbyte",0xFF);
10947         emitcode ("mov","_ap,a");
10948         emitcode ("mov","a,b");
10949         emitcode ("addc","a,#!constbyte",0xFF);
10950         emitcode ("mov","b,a");
10951         emitcode ("sjmp","!tlabel",lbl->key+100);
10952         emitcode ("","!tlabeldef",lbl1->key+100);
10953     }
10954     emitcode ("mov", "dps,#0"); 
10955     freeAsmop (count, NULL, ic, FALSE);
10956     unsavermask(rsave);
10957
10958 }
10959
10960 /*-----------------------------------------------------------------*/
10961 /* genMemsetX - gencode for memSetX data                           */
10962 /*-----------------------------------------------------------------*/
10963 static void genMemsetX(iCode *ic, int nparms, operand **parms)
10964 {
10965     operand *to , *val , *count;
10966     symbol *lbl;
10967     char *l;
10968     int i;
10969     bitVect *rsave = NULL;
10970
10971     /* we know it has to be 3 parameters */
10972     assert (nparms == 3);
10973     
10974     to = parms[0];
10975     val = parms[1];
10976     count = parms[2];
10977         
10978     /* save DPTR if it needs to be saved */
10979     rsave = newBitVect(16);
10980     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
10981             if (bitVectBitValue(ic->rMask,i))
10982                     rsave = bitVectSetBit(rsave,i);
10983     }
10984     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
10985                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
10986     savermask(rsave);
10987
10988     aopOp (to, ic, FALSE, FALSE);
10989     /* get "to" into DPTR */
10990     /* if the operand is already in dptr
10991        then we do nothing else we move the value to dptr */
10992     if (AOP_TYPE (to) != AOP_STR) {
10993         /* if already in DPTR then we need to push */
10994         if (AOP_TYPE(to) == AOP_DPTR) {
10995             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
10996             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
10997             if (options.model == MODEL_FLAT24)
10998                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
10999             emitcode ("pop", "dph");
11000             emitcode ("pop", "dpl");        
11001         } else {
11002             _startLazyDPSEvaluation ();
11003             /* if this is remateriazable */
11004             if (AOP_TYPE (to) == AOP_IMMD) {
11005                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
11006             } else {                    /* we need to get it byte by byte */
11007                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
11008                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
11009                 if (options.model == MODEL_FLAT24) {
11010                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11011                 }
11012             }
11013             _endLazyDPSEvaluation ();
11014         }
11015     }
11016     freeAsmop (to, NULL, ic, FALSE);
11017
11018     aopOp (val, ic->next->next, FALSE,FALSE);
11019     aopOp (count, ic->next->next, FALSE,FALSE);    
11020     lbl =newiTempLabel(NULL);
11021     /* now for the actual copy */
11022     if (AOP_TYPE(count) == AOP_LIT && 
11023         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11024         l = aopGet(AOP (val), 0, FALSE, FALSE, TRUE);
11025         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
11026         MOVA(l);
11027         emitcode ("","!tlabeldef",lbl->key+100);
11028         emitcode ("movx", "@dptr,a");
11029         emitcode ("inc", "dptr");
11030         emitcode ("djnz","b,!tlabel",lbl->key+100);
11031     } else {
11032         symbol *lbl1 = newiTempLabel(NULL);
11033         
11034         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
11035         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
11036         emitcode ("","!tlabeldef",lbl->key+100);
11037         l = aopGet(AOP (val), 0, FALSE, FALSE, TRUE);
11038         MOVA(l);
11039         emitcode ("movx", "a,@dptr");
11040         emitcode ("inc", "dptr");
11041         emitcode ("mov","a,b");
11042         emitcode ("orl","a,_ap");
11043         emitcode ("jz","!tlabel",lbl1->key+100);
11044         emitcode ("mov","a,_ap");
11045         emitcode ("add","a,#!constbyte",0xFF);
11046         emitcode ("mov","_ap,a");
11047         emitcode ("mov","a,b");
11048         emitcode ("addc","a,#!constbyte",0xFF);
11049         emitcode ("mov","b,a");
11050         emitcode ("sjmp","!tlabel",lbl->key+100);
11051         emitcode ("","!tlabeldef",lbl1->key+100);
11052     }
11053     freeAsmop (count, NULL, ic, FALSE);
11054     unsavermask(rsave);
11055 }
11056
11057 /*-----------------------------------------------------------------*/
11058 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
11059 /*-----------------------------------------------------------------*/
11060 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
11061 {
11062         bitVect *rsave ;
11063         operand *pnum, *result;
11064         int i;
11065     
11066         assert (nparms==1);
11067         /* save registers that need to be saved */
11068         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11069                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11070     
11071         pnum = parms[0]; 
11072         aopOp (pnum, ic, FALSE, FALSE);
11073         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,FALSE));
11074         freeAsmop (pnum, NULL, ic, FALSE);
11075         emitcode ("lcall","NatLib_LoadPrimitive");
11076         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11077         if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) || 
11078             aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
11079                 for (i = (size-1) ; i >= 0 ; i-- ) {
11080                         emitcode ("push","a%s",javaRet[i]);
11081                 }
11082                 for (i=0; i < size ; i++ ) {
11083                         emitcode ("pop","a%s",aopGet(AOP(result),i,FALSE,FALSE,FALSE));
11084                 }
11085         } else {
11086                 for (i = 0 ; i < size ; i++ ) {
11087                         aopPut(AOP(result),javaRet[i],i);
11088                 }
11089         }    
11090         freeAsmop (result, NULL, ic, FALSE);
11091         unsavermask(rsave);
11092 }
11093
11094 /*-----------------------------------------------------------------*/
11095 /* genNatLibLoadPointer - calls TINI api function to load pointer  */
11096 /*-----------------------------------------------------------------*/
11097 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
11098 {
11099         bitVect *rsave ;
11100         operand *pnum, *result;
11101         int size = 3;
11102         int i;
11103     
11104         assert (nparms==1);
11105         /* save registers that need to be saved */
11106         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11107                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11108     
11109         pnum = parms[0]; 
11110         aopOp (pnum, ic, FALSE, FALSE);
11111         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,FALSE));
11112         freeAsmop (pnum, NULL, ic, FALSE);
11113         emitcode ("lcall","NatLib_LoadPointer");
11114         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11115         if (AOP_TYPE(result)!=AOP_STR) {
11116                 for (i = 0 ; i < size ; i++ ) {
11117                         aopPut(AOP(result),fReturn[i],i);
11118                 }
11119         }    
11120         freeAsmop (result, NULL, ic, FALSE);
11121         unsavermask(rsave);
11122 }
11123
11124 /*-----------------------------------------------------------------*/
11125 /* genNatLibInstallStateBlock -                                    */
11126 /*-----------------------------------------------------------------*/
11127 static void genNatLibInstallStateBlock(iCode *ic, int nparms, 
11128                                        operand **parms, const char *name)
11129 {
11130         bitVect *rsave ;
11131         operand *psb, *handle;
11132         assert (nparms==2);
11133
11134         /* save registers that need to be saved */
11135         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11136                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11137         psb = parms[0];
11138         handle = parms[1];
11139
11140         /* put pointer to state block into DPTR1 */
11141         aopOp (psb, ic, FALSE, FALSE);
11142         if (AOP_TYPE (psb) == AOP_IMMD) {
11143                 emitcode ("mov","dps,#1");
11144                 emitcode ("mov", "dptr,%s", aopGet (AOP (psb), 0, TRUE, FALSE, FALSE));
11145                 emitcode ("mov","dps,#0");
11146         } else {
11147                 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,FALSE));
11148                 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,FALSE));
11149                 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,FALSE));
11150         }
11151         freeAsmop (psb, NULL, ic, FALSE);
11152
11153         /* put libraryID into DPTR */
11154         emitcode ("mov","dptr,#LibraryID");
11155
11156         /* put handle into r3:r2 */
11157         aopOp (handle, ic, FALSE, FALSE);
11158         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11159                 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));  
11160                 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11161                 emitcode ("pop","ar3");
11162                 emitcode ("pop","ar2");
11163         } else {        
11164                 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));        
11165                 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11166         }
11167         freeAsmop (psb, NULL, ic, FALSE);
11168
11169         /* make the call */
11170         emitcode ("lcall","NatLib_Install%sStateBlock",name);
11171
11172         /* put return value into place*/
11173         _G.accInUse++;
11174         aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
11175         _G.accInUse--;
11176         aopPut(AOP(IC_RESULT(ic)),"a",0);
11177         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11178         unsavermask(rsave);
11179 }
11180
11181 /*-----------------------------------------------------------------*/
11182 /* genNatLibRemoveStateBlock -                                     */
11183 /*-----------------------------------------------------------------*/
11184 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
11185 {
11186         bitVect *rsave ;
11187
11188         assert(nparms==0);
11189
11190         /* save registers that need to be saved */
11191         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11192                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11193
11194         /* put libraryID into DPTR */
11195         emitcode ("mov","dptr,#LibraryID");
11196         /* make the call */
11197         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
11198         unsavermask(rsave);
11199 }
11200
11201 /*-----------------------------------------------------------------*/
11202 /* genNatLibGetStateBlock -                                        */
11203 /*-----------------------------------------------------------------*/
11204 static void genNatLibGetStateBlock(iCode *ic,int nparms,
11205                                    operand **parms,const char *name)
11206 {
11207         bitVect *rsave ;
11208         symbol *lbl = newiTempLabel(NULL);
11209         
11210         assert(nparms==0);
11211         /* save registers that need to be saved */
11212         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11213                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11214
11215         /* put libraryID into DPTR */
11216         emitcode ("mov","dptr,#LibraryID");
11217         /* make the call */
11218         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
11219         emitcode ("jnz","!tlabel",lbl->key+100);
11220
11221         /* put return value into place */
11222         aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
11223         if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
11224                 emitcode ("push","ar3");
11225                 emitcode ("push","ar2");
11226                 emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,FALSE));
11227                 emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,FALSE));
11228         } else {
11229                 aopPut(AOP(IC_RESULT(ic)),"r2",0);
11230                 aopPut(AOP(IC_RESULT(ic)),"r3",1);
11231         }
11232         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11233         emitcode ("","!tlabeldef",lbl->key+100);
11234         unsavermask(rsave);
11235 }
11236
11237 /*-----------------------------------------------------------------*/
11238 /* genMMMalloc -                                                   */
11239 /*-----------------------------------------------------------------*/
11240 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
11241                          int size, const char *name)
11242 {
11243         bitVect *rsave ;
11244         operand *bsize;
11245         symbol *rsym;
11246         symbol *lbl = newiTempLabel(NULL);
11247
11248         assert (nparms == 1);
11249         /* save registers that need to be saved */
11250         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11251                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
11252         
11253         bsize=parms[0];
11254         aopOp (bsize,ic,FALSE,FALSE);
11255
11256         /* put the size in R4-R2 */
11257         if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
11258                 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,FALSE));
11259                 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,FALSE));
11260                 if (size==3) {
11261                         emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,FALSE));
11262                         emitcode("pop","ar4");
11263                 }
11264                 emitcode("pop","ar3");
11265                 emitcode("pop","ar2");          
11266         } else {
11267                 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,FALSE));
11268                 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,FALSE));
11269                 if (size==3) {
11270                         emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,FALSE));
11271                 }
11272         }
11273         freeAsmop (bsize, NULL, ic, FALSE);
11274
11275         /* make the call */
11276         emitcode ("lcall","MM_%s",name);
11277         emitcode ("jz","!tlabel",lbl->key+100);
11278         emitcode ("mov","r2,#!constbyte",0xff);
11279         emitcode ("mov","r3,#!constbyte",0xff);
11280         emitcode ("","!tlabeldef",lbl->key+100);
11281         /* we don't care about the pointer : we just save the handle */
11282         rsym = OP_SYMBOL(IC_RESULT(ic));
11283         if (rsym->liveFrom != rsym->liveTo) {
11284                 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
11285                 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
11286                         emitcode ("push","ar3");
11287                         emitcode ("push","ar2");
11288                         emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,FALSE));
11289                         emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,FALSE));
11290                 } else {
11291                         aopPut(AOP(IC_RESULT(ic)),"r2",0);
11292                         aopPut(AOP(IC_RESULT(ic)),"r3",1);
11293                 }
11294                 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11295         }
11296         unsavermask(rsave);
11297 }
11298
11299 /*-----------------------------------------------------------------*/
11300 /* genMMDeref -                                                    */
11301 /*-----------------------------------------------------------------*/
11302 static void genMMDeref (iCode *ic,int nparms, operand **parms)
11303 {
11304         bitVect *rsave ;
11305         operand *handle;
11306
11307         assert (nparms == 1);
11308         /* save registers that need to be saved */
11309         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11310                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
11311         
11312         handle=parms[0];
11313         aopOp (handle,ic,FALSE,FALSE);
11314
11315         /* put the size in R4-R2 */
11316         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11317                 emitcode("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11318                 emitcode("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11319                 emitcode("pop","ar3");
11320                 emitcode("pop","ar2");          
11321         } else {
11322                 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11323                 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11324         }
11325         freeAsmop (handle, NULL, ic, FALSE);
11326
11327         /* make the call */
11328         emitcode ("lcall","MM_Deref");
11329         
11330         {
11331                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11332                 if (rsym->liveFrom != rsym->liveTo) {                   
11333                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11334                         if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
11335                                 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
11336                                 aopPut(AOP(IC_RESULT(ic)),"dph",1);
11337                                 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
11338                         }
11339                 }
11340         }
11341         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11342         unsavermask(rsave);
11343 }
11344
11345 /*-----------------------------------------------------------------*/
11346 /* genMMUnrestrictedPersist -                                      */
11347 /*-----------------------------------------------------------------*/
11348 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
11349 {
11350         bitVect *rsave ;
11351         operand *handle;
11352
11353         assert (nparms == 1);
11354         /* save registers that need to be saved */
11355         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11356                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
11357         
11358         handle=parms[0];
11359         aopOp (handle,ic,FALSE,FALSE);
11360
11361         /* put the size in R3-R2 */
11362         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11363                 emitcode("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11364                 emitcode("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11365                 emitcode("pop","ar3");
11366                 emitcode("pop","ar2");          
11367         } else {
11368                 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11369                 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11370         }
11371         freeAsmop (handle, NULL, ic, FALSE);
11372
11373         /* make the call */
11374         emitcode ("lcall","MM_UnrestrictedPersist");
11375
11376         {
11377                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11378                 if (rsym->liveFrom != rsym->liveTo) {   
11379                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11380                         aopPut(AOP(IC_RESULT(ic)),"a",0);
11381                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11382                 }
11383         }
11384         unsavermask(rsave);
11385 }
11386
11387 /*-----------------------------------------------------------------*/
11388 /* genSystemExecJavaProcess -                                      */
11389 /*-----------------------------------------------------------------*/
11390 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
11391 {
11392         bitVect *rsave ;
11393         operand *handle, *pp;
11394
11395         assert (nparms==2);
11396         /* save registers that need to be saved */
11397         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11398                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
11399         
11400         pp = parms[0];
11401         handle = parms[1];
11402         
11403         /* put the handle in R3-R2 */
11404         aopOp (handle,ic,FALSE,FALSE);
11405         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11406                 emitcode("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11407                 emitcode("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11408                 emitcode("pop","ar3");
11409                 emitcode("pop","ar2");          
11410         } else {
11411                 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11412                 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11413         }
11414         freeAsmop (handle, NULL, ic, FALSE);
11415         
11416         /* put pointer in DPTR */
11417         aopOp (pp,ic,FALSE,FALSE);
11418         if (AOP_TYPE(pp) == AOP_IMMD) {
11419                 emitcode ("mov", "dptr,%s", aopGet (AOP (pp), 0, TRUE, FALSE, FALSE));          
11420         } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
11421                 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,FALSE));
11422                 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,FALSE));
11423                 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,FALSE));
11424         }
11425         freeAsmop (handle, NULL, ic, FALSE);
11426
11427         /* make the call */
11428         emitcode ("lcall","System_ExecJavaProcess");
11429         
11430         /* put result in place */
11431         {
11432                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11433                 if (rsym->liveFrom != rsym->liveTo) {   
11434                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11435                         aopPut(AOP(IC_RESULT(ic)),"a",0);
11436                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11437                 }
11438         }
11439         
11440         unsavermask(rsave);
11441 }
11442
11443 /*-----------------------------------------------------------------*/
11444 /* genSystemRTCRegisters -                                         */
11445 /*-----------------------------------------------------------------*/
11446 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
11447                                   char *name)
11448 {
11449         bitVect *rsave ;
11450         operand *pp;
11451
11452         assert (nparms==1);
11453         /* save registers that need to be saved */
11454         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11455                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
11456         
11457         pp=parms[0];
11458         /* put pointer in DPTR */
11459         aopOp (pp,ic,FALSE,FALSE);
11460         if (AOP_TYPE (pp) == AOP_IMMD) {
11461                 emitcode ("mov","dps,#1");
11462                 emitcode ("mov", "dptr,%s", aopGet (AOP (pp), 0, TRUE, FALSE, FALSE));
11463                 emitcode ("mov","dps,#0");
11464         } else {
11465                 emitcode ("mov","dpl1,%s",aopGet(AOP(pp),0,FALSE,FALSE,FALSE));
11466                 emitcode ("mov","dph1,%s",aopGet(AOP(pp),1,FALSE,FALSE,FALSE));
11467                 emitcode ("mov","dpx1,%s",aopGet(AOP(pp),2,FALSE,FALSE,FALSE));
11468         }
11469         freeAsmop (pp, NULL, ic, FALSE);
11470
11471         /* make the call */
11472         emitcode ("lcall","System_%sRTCRegisters",name);
11473
11474         unsavermask(rsave);
11475 }
11476
11477 /*-----------------------------------------------------------------*/
11478 /* genSystemThreadSleep -                                          */
11479 /*-----------------------------------------------------------------*/
11480 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
11481 {
11482         bitVect *rsave ;
11483         operand *to, *s;
11484
11485         assert (nparms==1);
11486         /* save registers that need to be saved */
11487         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11488                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
11489
11490         to = parms[0];
11491         aopOp(to,ic,FALSE,FALSE);
11492         if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
11493             aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
11494                 emitcode ("push","%s",aopGet(AOP(to),0,FALSE,TRUE,FALSE));
11495                 emitcode ("push","%s",aopGet(AOP(to),1,FALSE,TRUE,FALSE));
11496                 emitcode ("push","%s",aopGet(AOP(to),2,FALSE,TRUE,FALSE));
11497                 emitcode ("push","%s",aopGet(AOP(to),3,FALSE,TRUE,FALSE));
11498                 emitcode ("pop","ar3");
11499                 emitcode ("pop","ar2");
11500                 emitcode ("pop","ar1");
11501                 emitcode ("pop","ar0");
11502         } else {
11503                 emitcode ("mov","r0,%s",aopGet(AOP(to),0,FALSE,TRUE,FALSE));
11504                 emitcode ("mov","r1,%s",aopGet(AOP(to),1,FALSE,TRUE,FALSE));
11505                 emitcode ("mov","r2,%s",aopGet(AOP(to),2,FALSE,TRUE,FALSE));
11506                 emitcode ("mov","r3,%s",aopGet(AOP(to),3,FALSE,TRUE,FALSE));
11507         }
11508         freeAsmop (to, NULL, ic, FALSE);
11509
11510         /* suspend in acc */
11511         s = parms[1];
11512         aopOp(s,ic,FALSE,FALSE);
11513         emitcode ("mov","a,%s",aopGet(AOP(s),0,FALSE,TRUE,FALSE));
11514         freeAsmop (s, NULL, ic, FALSE);
11515
11516         /* make the call */
11517         emitcode ("lcall","System_%s",name);
11518
11519         unsavermask(rsave);
11520 }
11521
11522 /*-----------------------------------------------------------------*/
11523 /* genSystemThreadResume -                                         */
11524 /*-----------------------------------------------------------------*/
11525 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
11526 {
11527         bitVect *rsave ;
11528         operand *tid,*pid;
11529
11530         assert (nparms==2);
11531         /* save registers that need to be saved */
11532         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11533                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11534         
11535         tid = parms[0];
11536         pid = parms[1];
11537         
11538         /* PID in R0 */
11539         aopOp(pid,ic,FALSE,FALSE);
11540         emitcode ("mov","r0,%s",aopGet(AOP(pid),0,FALSE,TRUE,FALSE));
11541         freeAsmop (pid, NULL, ic, FALSE);
11542         
11543         /* tid into ACC */
11544         aopOp(tid,ic,FALSE,FALSE);
11545         emitcode ("mov","a,%s",aopGet(AOP(tid),0,FALSE,TRUE,FALSE));
11546         freeAsmop (tid, NULL, ic, FALSE);
11547         
11548         emitcode ("lcall","System_ThreadResume");
11549
11550         /* put result into place */
11551         {
11552                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11553                 if (rsym->liveFrom != rsym->liveTo) {   
11554                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11555                         aopPut(AOP(IC_RESULT(ic)),"a",0);
11556                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11557                 }
11558         }
11559         unsavermask(rsave);
11560 }
11561
11562 /*-----------------------------------------------------------------*/
11563 /* genSystemProcessResume -                                        */
11564 /*-----------------------------------------------------------------*/
11565 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
11566 {
11567         bitVect *rsave ;
11568         operand *pid;
11569
11570         assert (nparms==1);
11571         /* save registers that need to be saved */
11572         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11573                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11574         
11575         pid = parms[0];
11576         
11577         /* pid into ACC */
11578         aopOp(pid,ic,FALSE,FALSE);
11579         emitcode ("mov","a,%s",aopGet(AOP(pid),0,FALSE,TRUE,FALSE));
11580         freeAsmop (pid, NULL, ic, FALSE);
11581         
11582         emitcode ("lcall","System_ProcessResume");
11583
11584         unsavermask(rsave);
11585 }
11586
11587 /*-----------------------------------------------------------------*/
11588 /* genSystem -                                                     */
11589 /*-----------------------------------------------------------------*/
11590 static void genSystem (iCode *ic,int nparms,char *name)
11591 {
11592         assert(nparms == 0);
11593
11594         emitcode ("lcall","System_%s",name);
11595 }
11596
11597 /*-----------------------------------------------------------------*/
11598 /* genSystemPoll -                                                  */
11599 /*-----------------------------------------------------------------*/
11600 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
11601 {
11602         bitVect *rsave ;
11603         operand *fp;
11604
11605         assert (nparms==1);
11606         /* save registers that need to be saved */
11607         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11608                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11609
11610         fp = parms[0];
11611         aopOp (fp,ic,FALSE,FALSE);
11612         if (AOP_TYPE (fp) == AOP_IMMD) {
11613                 emitcode ("mov", "dptr,%s", aopGet (AOP (fp), 0, TRUE, FALSE, FALSE));
11614         } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
11615                 emitcode ("mov","dpl,%s",aopGet(AOP(fp),0,FALSE,FALSE,FALSE));
11616                 emitcode ("mov","dph,%s",aopGet(AOP(fp),1,FALSE,FALSE,FALSE));
11617                 emitcode ("mov","dpx,%s",aopGet(AOP(fp),2,FALSE,FALSE,FALSE));
11618         }
11619         freeAsmop (fp, NULL, ic, FALSE);
11620
11621         emitcode ("lcall","System_%sPoll",name);
11622
11623         /* put result into place */
11624         {
11625                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11626                 if (rsym->liveFrom != rsym->liveTo) {   
11627                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11628                         aopPut(AOP(IC_RESULT(ic)),"a",0);
11629                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11630                 }
11631         }
11632         unsavermask(rsave);
11633 }
11634
11635 /*-----------------------------------------------------------------*/
11636 /* genSystemGetCurrentID -                                         */
11637 /*-----------------------------------------------------------------*/
11638 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
11639 {
11640         assert (nparms==0);
11641
11642         emitcode ("lcall","System_GetCurrent%sId",name);
11643         /* put result into place */
11644         {
11645                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11646                 if (rsym->liveFrom != rsym->liveTo) {   
11647                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11648                         aopPut(AOP(IC_RESULT(ic)),"a",0);
11649                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11650                 }
11651         }
11652 }
11653
11654 /*-----------------------------------------------------------------*/
11655 /* genBuiltIn - calls the appropriate function to  generating code */
11656 /* for a built in function                                         */
11657 /*-----------------------------------------------------------------*/
11658 static void genBuiltIn (iCode *ic)
11659 {
11660         operand *bi_parms[MAX_BUILTIN_ARGS];
11661         int nbi_parms;
11662         iCode *bi_iCode;
11663         symbol *bif;
11664
11665         /* get all the arguments for a built in function */
11666         bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
11667
11668         /* which function is it */
11669         bif = OP_SYMBOL(IC_LEFT(bi_iCode));
11670         if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
11671                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
11672         } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
11673                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
11674         } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
11675                 genMemsetX(bi_iCode,nbi_parms,bi_parms);
11676         } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
11677                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
11678         } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
11679                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
11680         } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
11681                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
11682         } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
11683                 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
11684         } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
11685                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
11686         } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
11687                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
11688         } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
11689                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
11690         } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
11691                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
11692         } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
11693                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
11694         } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
11695                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
11696         } else if (strcmp(bif->name,"MM_XMalloc")==0) {
11697                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
11698         } else if (strcmp(bif->name,"MM_Malloc")==0) {
11699                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
11700         } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
11701                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
11702         } else if (strcmp(bif->name,"MM_Free")==0) {
11703                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
11704         } else if (strcmp(bif->name,"MM_Deref")==0) {
11705                 genMMDeref(bi_iCode,nbi_parms,bi_parms);
11706         } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
11707                 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
11708         } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
11709                 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
11710         } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
11711                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
11712         } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
11713                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
11714         } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
11715                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
11716         } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
11717                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
11718         } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
11719                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
11720         } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
11721                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
11722         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
11723                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
11724         } else if (strcmp(bif->name,"System_SaveThread")==0) {
11725                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
11726         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
11727                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
11728         } else if (strcmp(bif->name,"System_ProcessResume")==0) {
11729                 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
11730         } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
11731                 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
11732         } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
11733                 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
11734         } else if (strcmp(bif->name,"System_ProcessYield")==0) {
11735                 genSystem(bi_iCode,nbi_parms,"ProcessYield");
11736         } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
11737                 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
11738         } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
11739                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
11740         } else if (strcmp(bif->name,"System_RemovePoll")==0) {
11741                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
11742         } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
11743                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
11744         } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
11745                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
11746         } else {
11747                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
11748                 return ;
11749         }
11750         return ;    
11751 }
11752
11753 /*-----------------------------------------------------------------*/
11754 /* gen390Code - generate code for Dallas 390 based controllers     */
11755 /*-----------------------------------------------------------------*/
11756 void
11757 gen390Code (iCode * lic)
11758 {
11759   iCode *ic;
11760   int cln = 0;
11761
11762   lineHead = lineCurr = NULL;
11763
11764   if (options.model == MODEL_FLAT24) {
11765     fReturnSizeDS390 = 5;
11766     fReturn = fReturn24;
11767   } else {
11768     fReturnSizeDS390 = 4;
11769     fReturn = fReturn16;
11770     options.stack10bit=0;
11771   }
11772 #if 0
11773   //REMOVE ME!!!
11774   /* print the allocation information */
11775   if (allocInfo)
11776     printAllocInfo (currFunc, codeOutFile);
11777 #endif
11778   /* if debug information required */
11779   if (options.debug && currFunc)
11780     {
11781       cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
11782       _G.debugLine = 1;
11783       if (IS_STATIC (currFunc->etype))
11784         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
11785       else
11786         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
11787       _G.debugLine = 0;
11788     }
11789   /* stack pointer name */
11790   if (options.useXstack)
11791     spname = "_spx";
11792   else
11793     spname = "sp";
11794
11795
11796   for (ic = lic; ic; ic = ic->next)
11797     {
11798
11799       if (cln != ic->lineno)
11800         {
11801           if (options.debug)
11802             {
11803               _G.debugLine = 1;
11804               emitcode ("", "C$%s$%d$%d$%d ==.",
11805                         FileBaseName (ic->filename), ic->lineno,
11806                         ic->level, ic->block);
11807               _G.debugLine = 0;
11808             }
11809           emitcode (";", "%s %d", ic->filename, ic->lineno);
11810           cln = ic->lineno;
11811         }
11812       /* if the result is marked as
11813          spilt and rematerializable or code for
11814          this has already been generated then
11815          do nothing */
11816       if (resultRemat (ic) || ic->generated)
11817         continue;
11818
11819       /* depending on the operation */
11820       switch (ic->op)
11821         {
11822         case '!':
11823           genNot (ic);
11824           break;
11825
11826         case '~':
11827           genCpl (ic);
11828           break;
11829
11830         case UNARYMINUS:
11831           genUminus (ic);
11832           break;
11833
11834         case IPUSH:
11835           genIpush (ic);
11836           break;
11837
11838         case IPOP:
11839           /* IPOP happens only when trying to restore a
11840              spilt live range, if there is an ifx statement
11841              following this pop then the if statement might
11842              be using some of the registers being popped which
11843              would destory the contents of the register so
11844              we need to check for this condition and handle it */
11845           if (ic->next &&
11846               ic->next->op == IFX &&
11847               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11848             genIfx (ic->next, ic);
11849           else
11850             genIpop (ic);
11851           break;
11852
11853         case CALL:
11854           genCall (ic);
11855           break;
11856
11857         case PCALL:
11858           genPcall (ic);
11859           break;
11860
11861         case FUNCTION:
11862           genFunction (ic);
11863           break;
11864
11865         case ENDFUNCTION:
11866           genEndFunction (ic);
11867           break;
11868
11869         case RETURN:
11870           genRet (ic);
11871           break;
11872
11873         case LABEL:
11874           genLabel (ic);
11875           break;
11876
11877         case GOTO:
11878           genGoto (ic);
11879           break;
11880
11881         case '+':
11882           genPlus (ic);
11883           break;
11884
11885         case '-':
11886           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11887             genMinus (ic);
11888           break;
11889
11890         case '*':
11891           genMult (ic);
11892           break;
11893
11894         case '/':
11895           genDiv (ic);
11896           break;
11897
11898         case '%':
11899           genMod (ic);
11900           break;
11901
11902         case '>':
11903           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11904           break;
11905
11906         case '<':
11907           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11908           break;
11909
11910         case LE_OP:
11911         case GE_OP:
11912         case NE_OP:
11913
11914           /* note these two are xlated by algebraic equivalence
11915              during parsing SDCC.y */
11916           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11917                   "got '>=' or '<=' shouldn't have come here");
11918           break;
11919
11920         case EQ_OP:
11921           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11922           break;
11923
11924         case AND_OP:
11925           genAndOp (ic);
11926           break;
11927
11928         case OR_OP:
11929           genOrOp (ic);
11930           break;
11931
11932         case '^':
11933           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11934           break;
11935
11936         case '|':
11937           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11938           break;
11939
11940         case BITWISEAND:
11941           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
11942           break;
11943
11944         case INLINEASM:
11945           genInline (ic);
11946           break;
11947
11948         case RRC:
11949           genRRC (ic);
11950           break;
11951
11952         case RLC:
11953           genRLC (ic);
11954           break;
11955
11956         case GETHBIT:
11957           genGetHbit (ic);
11958           break;
11959
11960         case LEFT_OP:
11961           genLeftShift (ic);
11962           break;
11963
11964         case RIGHT_OP:
11965           genRightShift (ic);
11966           break;
11967
11968         case GET_VALUE_AT_ADDRESS:
11969           genPointerGet (ic,hasInc(IC_LEFT(ic),ic));
11970           break;
11971
11972         case '=':
11973           if (POINTER_SET (ic))
11974             genPointerSet (ic,hasInc(IC_RESULT(ic),ic));
11975           else
11976             genAssign (ic);
11977           break;
11978
11979         case IFX:
11980           genIfx (ic, NULL);
11981           break;
11982
11983         case ADDRESS_OF:
11984           genAddrOf (ic);
11985           break;
11986
11987         case JUMPTABLE:
11988           genJumpTab (ic);
11989           break;
11990
11991         case CAST:
11992           genCast (ic);
11993           break;
11994
11995         case RECEIVE:
11996           genReceive (ic);
11997           break;
11998
11999         case SEND:
12000           if (ic->builtinSEND) genBuiltIn(ic);
12001           else addSet (&_G.sendSet, ic);
12002           break;
12003
12004         case ARRAYINIT:
12005             genArrayInit(ic);
12006             break;
12007             
12008         default:
12009           ic = ic;
12010         }
12011     }
12012
12013
12014   /* now we are ready to call the
12015      peep hole optimizer */
12016   if (!options.nopeep)
12017     peepHole (&lineHead);
12018
12019   /* now do the actual printing */
12020   printLine (lineHead, codeOutFile);
12021   return;
12022 }