875b591389b8869ee9958b3323805402eedd6951
[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 = "#0";
66 static char *one = "#1";
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         short stack_val = -((sym->stack < 0) ?
464                             ((short) (sym->stack - _G.nRegsSaved)) :
465                             ((short) sym->stack)) ;
466       /* It's on the 10 bit stack, which is located in
467        * far data space.
468        */
469         if (stack_val < 0 && stack_val > -3) { /* between -3 & -1 */
470             if (useDP2) {
471                 if (options.model == MODEL_FLAT24)
472                     emitcode ("mov", "dpx1,#!constbyte", (options.stack_loc >> 16) & 0xff);
473                 TR_DPTR("#2");
474                 emitcode ("mov", "dph1,_bpx+1");
475                 emitcode ("mov", "dpl1,_bpx");
476                 emitcode ("mov","dps,#1");
477             } else {
478                 if (options.model == MODEL_FLAT24)
479                     emitcode ("mov", "dpx,#!constbyte", (options.stack_loc >> 16) & 0xff);
480                 emitcode ("mov", "dph,_bpx+1");
481                 emitcode ("mov", "dpl,_bpx");
482             }
483             stack_val = -stack_val;
484             while (stack_val--) {
485                 emitcode ("inc","dptr");
486             }
487             if (useDP2) {
488                 emitcode("mov","dps,#0");
489             }
490         }  else {
491             if (_G.accInUse)
492                 emitcode ("push", "acc");
493             
494             if (_G.bInUse)
495                 emitcode ("push", "b");
496         
497             emitcode ("mov", "a,_bpx");
498             emitcode ("clr","c");
499             emitcode ("subb", "a,#!constbyte", stack_val & 0xff);
500             emitcode ("mov","b,a");
501             emitcode ("mov","a,_bpx+1");
502             emitcode ("subb","a,#!constbyte",(stack_val >> 8) & 0xff);
503             if (useDP2) {
504                 if (options.model == MODEL_FLAT24)
505                     emitcode ("mov", "dpx1,#!constbyte", (options.stack_loc >> 16) & 0xff);
506                 TR_DPTR("#2");
507                 emitcode ("mov", "dph1,a");
508                 emitcode ("mov", "dpl1,b");
509             } else {
510                 if (options.model == MODEL_FLAT24)
511                     emitcode ("mov", "dpx,#!constbyte", (options.stack_loc >> 16) & 0xff);
512                 emitcode ("mov", "dph,a");
513                 emitcode ("mov", "dpl,b");
514             }
515             
516             if (_G.bInUse)
517                 emitcode ("pop", "b");
518             
519             if (_G.accInUse)
520                 emitcode ("pop", "acc");
521         }
522         sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
523         aop->size = getSize (sym->type);
524         return aop;
525     }
526
527   /* if in bit space */
528   if (IN_BITSPACE (space))
529     {
530       sym->aop = aop = newAsmop (AOP_CRY);
531       aop->aopu.aop_dir = sym->rname;
532       aop->size = getSize (sym->type);
533       return aop;
534     }
535   /* if it is in direct space */
536   if (IN_DIRSPACE (space))
537     {
538       sym->aop = aop = newAsmop (AOP_DIR);
539       aop->aopu.aop_dir = sym->rname;
540       aop->size = getSize (sym->type);
541       return aop;
542     }
543
544   /* special case for a function */
545   if (IS_FUNC (sym->type))
546     {
547       sym->aop = aop = newAsmop (AOP_IMMD);
548       aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
549       strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
550       aop->size = FPTRSIZE;
551       return aop;
552     }
553
554   /* only remaining is far space */
555   /* in which case DPTR gets the address */
556   sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
557   if (useDP2)
558     {
559       genSetDPTR (1);
560       _flushLazyDPS ();
561       emitcode ("mov", "dptr,#%s", sym->rname);
562       genSetDPTR (0);
563     }
564   else
565     {
566       emitcode ("mov", "dptr,#%s", sym->rname);
567     }
568   aop->size = getSize (sym->type);
569
570   /* if it is in code space */
571   if (IN_CODESPACE (space))
572     aop->code = 1;
573
574   return aop;
575 }
576
577 /*-----------------------------------------------------------------*/
578 /* aopForRemat - rematerialzes an object                           */
579 /*-----------------------------------------------------------------*/
580 static asmop *
581 aopForRemat (symbol * sym)
582 {
583   iCode *ic = sym->rematiCode;
584   asmop *aop = newAsmop (AOP_IMMD);
585   int ptr_type =0;
586   int val = 0;
587
588   for (;;)
589     {
590       if (ic->op == '+')
591         val += (int) operandLitValue (IC_RIGHT (ic));
592       else if (ic->op == '-')
593         val -= (int) operandLitValue (IC_RIGHT (ic));
594       else if (IS_CAST_ICODE(ic)) {
595               sym_link *from_type = operandType(IC_RIGHT(ic));
596               aop->aopu.aop_immd.from_cast_remat = 1;
597               ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
598               ptr_type = DCL_TYPE(from_type);
599               if (ptr_type == IPOINTER) {
600                 // bug #481053
601                 ptr_type = POINTER;
602               }
603               continue ;
604       } else break;
605       
606       ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
607     }
608
609   if (val)
610     sprintf (buffer, "(%s %c 0x%04x)",
611              OP_SYMBOL (IC_LEFT (ic))->rname,
612              val >= 0 ? '+' : '-',
613              abs (val) & 0xffff);
614   else
615     strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
616
617   aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
618   strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
619   /* set immd2 field if required */
620   if (aop->aopu.aop_immd.from_cast_remat) {
621           tsprintf(buffer,"#!constbyte",ptr_type);
622           aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
623           strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
624   }
625
626   return aop;
627 }
628
629 /*-----------------------------------------------------------------*/
630 /* aopHasRegs - returns true if aop has regs between from-to       */
631 /*-----------------------------------------------------------------*/
632 static int aopHasRegs(asmop *aop, int from, int to)
633 {
634     int size =0;
635
636     if (aop->type != AOP_REG) return 0; /* if not assigned to regs */
637
638     for (; size < aop->size ; size++) {
639         int reg;
640         for (reg = from ; reg <= to ; reg++)
641             if (aop->aopu.aop_reg[size] == ds390_regWithIdx(reg)) return 1;
642     }
643     return 0;
644 }
645
646 /*-----------------------------------------------------------------*/
647 /* regsInCommon - two operands have some registers in common       */
648 /*-----------------------------------------------------------------*/
649 static bool
650 regsInCommon (operand * op1, operand * op2)
651 {
652   symbol *sym1, *sym2;
653   int i;
654
655   /* if they have registers in common */
656   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
657     return FALSE;
658
659   sym1 = OP_SYMBOL (op1);
660   sym2 = OP_SYMBOL (op2);
661
662   if (sym1->nRegs == 0 || sym2->nRegs == 0)
663     return FALSE;
664
665   for (i = 0; i < sym1->nRegs; i++)
666     {
667       int j;
668       if (!sym1->regs[i])
669         continue;
670
671       for (j = 0; j < sym2->nRegs; j++)
672         {
673           if (!sym2->regs[j])
674             continue;
675
676           if (sym2->regs[j] == sym1->regs[i])
677             return TRUE;
678         }
679     }
680
681   return FALSE;
682 }
683
684 /*-----------------------------------------------------------------*/
685 /* operandsEqu - equivalent                                        */
686 /*-----------------------------------------------------------------*/
687 static bool
688 operandsEqu (operand * op1, operand * op2)
689 {
690   symbol *sym1, *sym2;
691
692   /* if they not symbols */
693   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
694     return FALSE;
695
696   sym1 = OP_SYMBOL (op1);
697   sym2 = OP_SYMBOL (op2);
698
699   /* if both are itemps & one is spilt
700      and the other is not then false */
701   if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
702       sym1->isspilt != sym2->isspilt)
703     return FALSE;
704
705   /* if they are the same */
706   if (sym1 == sym2)
707     return TRUE;
708
709   if (strcmp (sym1->rname, sym2->rname) == 0)
710     return TRUE;
711
712
713   /* if left is a tmp & right is not */
714   if (IS_ITEMP (op1) &&
715       !IS_ITEMP (op2) &&
716       sym1->isspilt &&
717       (sym1->usl.spillLoc == sym2))
718     return TRUE;
719
720   if (IS_ITEMP (op2) &&
721       !IS_ITEMP (op1) &&
722       sym2->isspilt &&
723       sym1->level > 0 &&
724       (sym2->usl.spillLoc == sym1))
725     return TRUE;
726
727   return FALSE;
728 }
729
730 /*-----------------------------------------------------------------*/
731 /* sameRegs - two asmops have the same registers                   */
732 /*-----------------------------------------------------------------*/
733 static bool
734 sameRegs (asmop * aop1, asmop * aop2)
735 {
736   int i;
737
738   if (aop1 == aop2)
739     {
740       if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
741         {
742           return FALSE;
743         }
744       return TRUE;
745     }
746
747   if (aop1->type != AOP_REG ||
748       aop2->type != AOP_REG)
749     return FALSE;
750
751   if (aop1->size != aop2->size)
752     return FALSE;
753
754   for (i = 0; i < aop1->size; i++)
755     if (aop1->aopu.aop_reg[i] !=
756         aop2->aopu.aop_reg[i])
757       return FALSE;
758
759   return TRUE;
760 }
761
762 /*-----------------------------------------------------------------*/
763 /* aopOp - allocates an asmop for an operand  :                    */
764 /*-----------------------------------------------------------------*/
765 static void
766 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
767 {
768   asmop *aop;
769   symbol *sym;
770   int i;
771
772   if (!op)
773     return;
774
775   /* if this a literal */
776   if (IS_OP_LITERAL (op))
777     {
778       op->aop = aop = newAsmop (AOP_LIT);
779       aop->aopu.aop_lit = op->operand.valOperand;
780       aop->size = getSize (operandType (op));
781       return;
782     }
783
784   /* if already has a asmop then continue */
785   if (op->aop)
786     return;
787
788   /* if the underlying symbol has a aop */
789   if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
790     {
791       op->aop = OP_SYMBOL (op)->aop;
792       return;
793     }
794
795   /* if this is a true symbol */
796   if (IS_TRUE_SYMOP (op))
797     {
798       op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
799       return;
800     }
801
802   /* this is a temporary : this has
803      only four choices :
804      a) register
805      b) spillocation
806      c) rematerialize
807      d) conditional
808      e) can be a return use only */
809
810   sym = OP_SYMBOL (op);
811
812
813   /* if the type is a conditional */
814   if (sym->regType == REG_CND)
815     {
816       aop = op->aop = sym->aop = newAsmop (AOP_CRY);
817       aop->size = 0;
818       return;
819     }
820
821   /* if it is spilt then two situations
822      a) is rematerialize
823      b) has a spill location */
824   if (sym->isspilt || sym->nRegs == 0)
825     {
826
827       /* rematerialize it NOW */
828       if (sym->remat)
829         {
830           sym->aop = op->aop = aop =
831             aopForRemat (sym);
832           aop->size = getSize (sym->type);
833           return;
834         }
835
836       if (sym->accuse)
837         {
838           int i;
839           aop = op->aop = sym->aop = newAsmop (AOP_ACC);
840           aop->size = getSize (sym->type);
841           for (i = 0; i < 2; i++)
842             aop->aopu.aop_str[i] = accUse[i];
843           return;
844         }
845
846       if (sym->ruonly)
847         {
848           int i;
849
850           if (useDP2)
851             {
852               /* a AOP_STR uses DPTR, but DPTR is already in use;
853                * we're just hosed.
854                */
855               fprintf (stderr, "*** Internal error: AOP_STR with DPTR in use! for operand %s\n",sym->name);
856             }
857
858           aop = op->aop = sym->aop = newAsmop (AOP_STR);
859           aop->size = getSize (sym->type);
860           for (i = 0; i < (int) fReturnSizeDS390; i++)
861             aop->aopu.aop_str[i] = fReturn[i];
862           return;
863         }
864
865       /* else spill location  */
866       if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
867           /* force a new aop if sizes differ */
868           sym->usl.spillLoc->aop = NULL;
869       }
870       sym->aop = op->aop = aop =
871         aopForSym (ic, sym->usl.spillLoc, result, useDP2);
872       aop->size = getSize (sym->type);
873       return;
874     }
875
876   /* must be in a register */
877   sym->aop = op->aop = aop = newAsmop (AOP_REG);
878   aop->size = sym->nRegs;
879   for (i = 0; i < sym->nRegs; i++)
880     aop->aopu.aop_reg[i] = sym->regs[i];
881 }
882
883 /*-----------------------------------------------------------------*/
884 /* freeAsmop - free up the asmop given to an operand               */
885 /*----------------------------------------------------------------*/
886 static void
887 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
888 {
889   asmop *aop;
890
891   if (!op)
892     aop = aaop;
893   else
894     aop = op->aop;
895
896   if (!aop)
897     return;
898
899   if (aop->freed)
900     goto dealloc;
901
902   aop->freed = 1;
903
904   /* depending on the asmop type only three cases need work AOP_RO
905      , AOP_R1 && AOP_STK */
906   switch (aop->type)
907     {
908     case AOP_R0:
909       if (_G.r0Pushed)
910         {
911           if (pop)
912             {
913               emitcode ("pop", "ar0");
914               _G.r0Pushed--;
915             }
916         }
917       bitVectUnSetBit (ic->rUsed, R0_IDX);
918       break;
919
920     case AOP_R1:
921       if (_G.r1Pushed)
922         {
923           if (pop)
924             {
925               emitcode ("pop", "ar1");
926               _G.r1Pushed--;
927             }
928         }
929       bitVectUnSetBit (ic->rUsed, R1_IDX);
930       break;
931
932     case AOP_STK:
933       {
934         int sz = aop->size;
935         int stk = aop->aopu.aop_stk + aop->size;
936         bitVectUnSetBit (ic->rUsed, R0_IDX);
937         bitVectUnSetBit (ic->rUsed, R1_IDX);
938
939         getFreePtr (ic, &aop, FALSE);
940
941         if (options.stack10bit)
942           {
943             /* I'm not sure what to do here yet... */
944             /* #STUB */
945             fprintf (stderr,
946                      "*** Warning: probably generating bad code for "
947                      "10 bit stack mode.\n");
948           }
949
950         if (stk)
951           {
952             emitcode ("mov", "a,_bp");
953             emitcode ("add", "a,#!constbyte", ((char) stk) & 0xff);
954             emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
955           }
956         else
957           {
958             emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
959           }
960
961         while (sz--)
962           {
963             emitcode ("pop", "acc");
964             emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
965             if (!sz)
966               break;
967             emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
968           }
969         op->aop = aop;
970         freeAsmop (op, NULL, ic, TRUE);
971         if (_G.r0Pushed)
972           {
973             emitcode ("pop", "ar0");
974             _G.r0Pushed--;
975           }
976
977         if (_G.r1Pushed)
978           {
979             emitcode ("pop", "ar1");
980             _G.r1Pushed--;
981           }
982       }
983     }
984
985 dealloc:
986   /* all other cases just dealloc */
987   if (op)
988     {
989       op->aop = NULL;
990       if (IS_SYMOP (op))
991         {
992           OP_SYMBOL (op)->aop = NULL;
993           /* if the symbol has a spill */
994           if (SPIL_LOC (op))
995             SPIL_LOC (op)->aop = NULL;
996         }
997     }
998 }
999
1000 /*------------------------------------------------------------------*/
1001 /* aopGet - for fetching value of the aop                           */
1002 /*                    */
1003 /* Set canClobberACC if you are sure it is OK to clobber the value  */
1004 /* in the accumulator. Set it FALSE otherwise; FALSE is always safe, */
1005 /* just less efficient.               */
1006 /*------------------------------------------------------------------*/
1007
1008 static char *
1009 aopGet (asmop * aop,
1010         int offset,
1011         bool bit16,
1012         bool dname,
1013         bool canClobberACC)
1014 {
1015   char *s = buffer;
1016   char *rs;
1017
1018   /* offset is greater than
1019      size then zero */
1020   if (offset > (aop->size - 1) &&
1021       aop->type != AOP_LIT)
1022     return zero;
1023
1024   /* depending on type */
1025   switch (aop->type)
1026     {
1027
1028     case AOP_R0:
1029     case AOP_R1:
1030       /* if we need to increment it */
1031       while (offset > aop->coff)
1032         {
1033           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1034           aop->coff++;
1035         }
1036
1037       while (offset < aop->coff)
1038         {
1039           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1040           aop->coff--;
1041         }
1042
1043       aop->coff = offset;
1044       if (aop->paged)
1045         {
1046           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1047           return (dname ? "acc" : "a");
1048         }
1049       sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1050       rs = Safe_calloc (1, strlen (s) + 1);
1051       strcpy (rs, s);
1052       return rs;
1053
1054     case AOP_DPTR:
1055     case AOP_DPTR2:
1056
1057       if (aop->type == AOP_DPTR2)
1058         {
1059           genSetDPTR (1);
1060           if (!canClobberACC)
1061             {
1062                     TR_AP("#1");
1063                     emitcode ("xch", "a, %s", DP2_RESULT_REG);
1064             }
1065         }
1066
1067       _flushLazyDPS ();
1068
1069       while (offset > aop->coff)
1070         {
1071           emitcode ("inc", "dptr");
1072           aop->coff++;
1073         }
1074
1075       while (offset < aop->coff)
1076         {
1077           emitcode ("lcall", "__decdptr");
1078           aop->coff--;
1079         }
1080
1081       aop->coff = offset;
1082       if (aop->code)
1083         {
1084           emitcode ("clr", "a");
1085           emitcode ("movc", "a,@a+dptr");
1086         }
1087       else
1088         {
1089           emitcode ("movx", "a,@dptr");
1090         }
1091
1092       if (aop->type == AOP_DPTR2)
1093         {
1094           genSetDPTR (0);
1095           if (!canClobberACC)
1096             {
1097        TR_AP("#2");
1098               emitcode ("xch", "a, %s", DP2_RESULT_REG);
1099               return DP2_RESULT_REG;
1100             }
1101         }
1102       return (dname ? "acc" : "a");
1103
1104     case AOP_IMMD:
1105       if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
1106               sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
1107       } else if (bit16)
1108         sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
1109       else if (offset) {
1110           switch (offset) {
1111           case 1:
1112               tsprintf(s,"#!his",aop->aopu.aop_immd.aop_immd1);
1113               break;
1114           case 2:
1115               tsprintf(s,"#!hihis",aop->aopu.aop_immd.aop_immd1);
1116               break;
1117           case 3:
1118               tsprintf(s,"#!hihihis",aop->aopu.aop_immd.aop_immd1);
1119               break;
1120           default: /* should not need this (just in case) */
1121               sprintf (s, "#(%s >> %d)",
1122                        aop->aopu.aop_immd.aop_immd1,
1123                        offset * 8);
1124           }
1125       }
1126       else
1127         sprintf (s, "#%s",
1128                  aop->aopu.aop_immd.aop_immd1);
1129       rs = Safe_calloc (1, strlen (s) + 1);
1130       strcpy (rs, s);
1131       return rs;
1132
1133     case AOP_DIR:
1134       if (offset)
1135         sprintf (s, "(%s + %d)",
1136                  aop->aopu.aop_dir,
1137                  offset);
1138       else
1139         sprintf (s, "%s", aop->aopu.aop_dir);
1140       rs = Safe_calloc (1, strlen (s) + 1);
1141       strcpy (rs, s);
1142       return rs;
1143
1144     case AOP_REG:
1145       if (dname)
1146         return aop->aopu.aop_reg[offset]->dname;
1147       else
1148         return aop->aopu.aop_reg[offset]->name;
1149
1150     case AOP_CRY:
1151       emitcode ("clr", "a");
1152       emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1153       emitcode ("rlc", "a");
1154       return (dname ? "acc" : "a");
1155
1156     case AOP_ACC:
1157       if (!offset && dname)
1158         return "acc";
1159       return aop->aopu.aop_str[offset];
1160
1161     case AOP_LIT:
1162       return aopLiteral (aop->aopu.aop_lit, offset);
1163
1164     case AOP_STR:
1165       aop->coff = offset;
1166       if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1167           dname)
1168         return "acc";
1169
1170       return aop->aopu.aop_str[offset];
1171
1172     }
1173
1174   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1175           "aopget got unsupported aop->type");
1176   exit (1);
1177 }
1178 /*-----------------------------------------------------------------*/
1179 /* aopPut - puts a string for a aop                                */
1180 /*-----------------------------------------------------------------*/
1181 static void
1182 aopPut (asmop * aop, char *s, int offset)
1183 {
1184   char *d = buffer;
1185
1186   if (aop->size && offset > (aop->size - 1))
1187     {
1188       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1189               "aopPut got offset > aop->size");
1190       exit (1);
1191     }
1192
1193   /* will assign value to value */
1194   /* depending on where it is ofcourse */
1195   switch (aop->type)
1196     {
1197     case AOP_DIR:
1198       if (offset)
1199         sprintf (d, "(%s + %d)",
1200                  aop->aopu.aop_dir, offset);
1201       else
1202         sprintf (d, "%s", aop->aopu.aop_dir);
1203
1204       if (strcmp (d, s))
1205         emitcode ("mov", "%s,%s", d, s);
1206
1207       break;
1208
1209     case AOP_REG:
1210       if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1211           strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1212         {
1213           if (*s == '@' ||
1214               strcmp (s, "r0") == 0 ||
1215               strcmp (s, "r1") == 0 ||
1216               strcmp (s, "r2") == 0 ||
1217               strcmp (s, "r3") == 0 ||
1218               strcmp (s, "r4") == 0 ||
1219               strcmp (s, "r5") == 0 ||
1220               strcmp (s, "r6") == 0 ||
1221               strcmp (s, "r7") == 0)
1222             emitcode ("mov", "%s,%s",
1223                       aop->aopu.aop_reg[offset]->dname, s);
1224           else
1225             emitcode ("mov", "%s,%s",
1226                       aop->aopu.aop_reg[offset]->name, s);
1227         }
1228       break;
1229
1230     case AOP_DPTR:
1231     case AOP_DPTR2:
1232
1233       if (aop->type == AOP_DPTR2)
1234         {
1235           genSetDPTR (1);
1236         }
1237       _flushLazyDPS ();
1238
1239       if (aop->code)
1240         {
1241           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1242                   "aopPut writting to code space");
1243           exit (1);
1244         }
1245
1246       while (offset > aop->coff)
1247         {
1248           aop->coff++;
1249           emitcode ("inc", "dptr");
1250         }
1251
1252       while (offset < aop->coff)
1253         {
1254           aop->coff--;
1255           emitcode ("lcall", "__decdptr");
1256         }
1257
1258       aop->coff = offset;
1259
1260       /* if not in accumulater */
1261       MOVA (s);
1262
1263       emitcode ("movx", "@dptr,a");
1264
1265       if (aop->type == AOP_DPTR2)
1266         {
1267           genSetDPTR (0);
1268         }
1269       break;
1270
1271     case AOP_R0:
1272     case AOP_R1:
1273       while (offset > aop->coff)
1274         {
1275           aop->coff++;
1276           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1277         }
1278       while (offset < aop->coff)
1279         {
1280           aop->coff--;
1281           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1282         }
1283       aop->coff = offset;
1284
1285       if (aop->paged)
1286         {
1287           MOVA (s);
1288           emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1289
1290         }
1291       else if (*s == '@')
1292         {
1293           MOVA (s);
1294           emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1295         }
1296       else if (strcmp (s, "r0") == 0 ||
1297                strcmp (s, "r1") == 0 ||
1298                strcmp (s, "r2") == 0 ||
1299                strcmp (s, "r3") == 0 ||
1300                strcmp (s, "r4") == 0 ||
1301                strcmp (s, "r5") == 0 ||
1302                strcmp (s, "r6") == 0 ||
1303                strcmp (s, "r7") == 0)
1304         {
1305           char buffer[10];
1306           sprintf (buffer, "a%s", s);
1307           emitcode ("mov", "@%s,%s",
1308                     aop->aopu.aop_ptr->name, buffer);
1309         }
1310       else
1311         emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1312
1313       break;
1314
1315     case AOP_STK:
1316       if (strcmp (s, "a") == 0)
1317         emitcode ("push", "acc");
1318       else
1319         if (*s=='@') {
1320           MOVA(s);
1321           emitcode ("push", "acc");
1322         } else {
1323           emitcode ("push", s);
1324         }
1325
1326       break;
1327
1328     case AOP_CRY:
1329       /* if bit variable */
1330       if (!aop->aopu.aop_dir)
1331         {
1332           emitcode ("clr", "a");
1333           emitcode ("rlc", "a");
1334         }
1335       else
1336         {
1337           if (s == zero)
1338             emitcode ("clr", "%s", aop->aopu.aop_dir);
1339           else if (s == one)
1340             emitcode ("setb", "%s", aop->aopu.aop_dir);
1341           else if (!strcmp (s, "c"))
1342             emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1343           else
1344             {
1345               if (strcmp (s, "a"))
1346                 {
1347                   MOVA (s);
1348                 }
1349               {
1350                 symbol *lbl = newiTempLabel (NULL);
1351                 emitcode ("clr", "c");
1352                 emitcode ("jz", "!tlabel", lbl->key + 100);
1353                 emitcode ("cpl", "c");
1354                 emitcode ("", "!tlabeldef", lbl->key + 100);
1355                 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1356               }
1357             }
1358         }
1359       break;
1360
1361     case AOP_STR:
1362       aop->coff = offset;
1363       if (strcmp (aop->aopu.aop_str[offset], s))
1364         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1365       break;
1366
1367     case AOP_ACC:
1368       aop->coff = offset;
1369       if (!offset && (strcmp (s, "acc") == 0))
1370         break;
1371
1372       if (strcmp (aop->aopu.aop_str[offset], s))
1373         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1374       break;
1375
1376     default:
1377       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1378               "aopPut got unsupported aop->type");
1379       exit (1);
1380     }
1381
1382 }
1383
1384
1385 /*--------------------------------------------------------------------*/
1386 /* reAdjustPreg - points a register back to where it should (coff==0) */
1387 /*--------------------------------------------------------------------*/
1388 static void
1389 reAdjustPreg (asmop * aop)
1390 {
1391   if ((aop->coff==0) || (aop->size <= 1)) {
1392     return;
1393   }
1394
1395   switch (aop->type)
1396     {
1397     case AOP_R0:
1398     case AOP_R1:
1399       while (aop->coff--)
1400         emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1401       break;
1402     case AOP_DPTR:
1403     case AOP_DPTR2:
1404       if (aop->type == AOP_DPTR2)
1405         {
1406           genSetDPTR (1);
1407           _flushLazyDPS ();
1408         }
1409       while (aop->coff--)
1410         {
1411           emitcode ("lcall", "__decdptr");
1412         }
1413
1414       if (aop->type == AOP_DPTR2)
1415         {
1416           genSetDPTR (0);
1417         }
1418       break;
1419
1420     }
1421   aop->coff=0;
1422 }
1423
1424 #define AOP(op) op->aop
1425 #define AOP_TYPE(op) AOP(op)->type
1426 #define AOP_SIZE(op) AOP(op)->size
1427 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1428                        AOP_TYPE(x) == AOP_R0))
1429
1430 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
1431                         AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1432                          AOP(x)->paged))
1433
1434 #define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
1435                       (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1436                       x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1437
1438 /* Workaround for DS80C390 bug: div ab may return bogus results
1439  * if A is accessed in instruction immediately before the div.
1440  *
1441  * Will be fixed in B4 rev of processor, Dallas claims.
1442  */
1443
1444 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L)       \
1445     if (!AOP_NEEDSACC(RIGHT))         \
1446     {               \
1447       /* We can load A first, then B, since     \
1448        * B (the RIGHT operand) won't clobber A,   \
1449        * thus avoiding touching A right before the div. \
1450        */             \
1451       D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1452       L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE);     \
1453       MOVA(L);            \
1454       emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1455     }               \
1456     else              \
1457     {               \
1458       /* Just stuff in a nop after loading A. */    \
1459       emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1460       L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE);   \
1461       MOVA(L);            \
1462       emitcode("nop", "; workaround for DS80C390 div bug.");  \
1463     }
1464
1465 /*-----------------------------------------------------------------*/
1466 /* genNotFloat - generates not for float operations              */
1467 /*-----------------------------------------------------------------*/
1468 static void
1469 genNotFloat (operand * op, operand * res)
1470 {
1471   int size, offset;
1472   char *l;
1473   symbol *tlbl;
1474
1475   D (emitcode (";", "genNotFloat ");
1476     );
1477
1478   /* we will put 127 in the first byte of
1479      the result */
1480   aopPut (AOP (res), "#127", 0);
1481   size = AOP_SIZE (op) - 1;
1482   offset = 1;
1483
1484   _startLazyDPSEvaluation ();
1485   l = aopGet (op->aop, offset++, FALSE, FALSE, TRUE);
1486   MOVA (l);
1487
1488   while (size--)
1489     {
1490       emitcode ("orl", "a,%s",
1491                 aopGet (op->aop,
1492                         offset++, FALSE, FALSE, FALSE));
1493     }
1494   _endLazyDPSEvaluation ();
1495
1496   tlbl = newiTempLabel (NULL);
1497   aopPut (res->aop, one, 1);
1498   emitcode ("jz", "!tlabel", (tlbl->key + 100));
1499   aopPut (res->aop, zero, 1);
1500   emitcode ("", "!tlabeldef", (tlbl->key + 100));
1501
1502   size = res->aop->size - 2;
1503   offset = 2;
1504   /* put zeros in the rest */
1505   while (size--)
1506     aopPut (res->aop, zero, offset++);
1507 }
1508
1509 /*-----------------------------------------------------------------*/
1510 /* opIsGptr: returns non-zero if the passed operand is       */
1511 /* a generic pointer type.             */
1512 /*-----------------------------------------------------------------*/
1513 static int
1514 opIsGptr (operand * op)
1515 {
1516   sym_link *type = operandType (op);
1517
1518   if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1519     {
1520       return 1;
1521     }
1522   return 0;
1523 }
1524
1525 /*-----------------------------------------------------------------*/
1526 /* getDataSize - get the operand data size                         */
1527 /*-----------------------------------------------------------------*/
1528 static int
1529 getDataSize (operand * op)
1530 {
1531   int size;
1532   size = AOP_SIZE (op);
1533   if (size == GPTRSIZE)
1534     {
1535       sym_link *type = operandType (op);
1536       if (IS_GENPTR (type))
1537         {
1538           /* generic pointer; arithmetic operations
1539            * should ignore the high byte (pointer type).
1540            */
1541           size--;
1542         }
1543     }
1544   return size;
1545 }
1546
1547 /*-----------------------------------------------------------------*/
1548 /* outAcc - output Acc                                             */
1549 /*-----------------------------------------------------------------*/
1550 static void
1551 outAcc (operand * result)
1552 {
1553   int size, offset;
1554   size = getDataSize (result);
1555   if (size)
1556     {
1557       aopPut (AOP (result), "a", 0);
1558       size--;
1559       offset = 1;
1560       /* unsigned or positive */
1561       while (size--)
1562         {
1563           aopPut (AOP (result), zero, offset++);
1564         }
1565     }
1566 }
1567
1568 /*-----------------------------------------------------------------*/
1569 /* outBitC - output a bit C                                        */
1570 /*-----------------------------------------------------------------*/
1571 static void
1572 outBitC (operand * result)
1573 {
1574   /* if the result is bit */
1575   if (AOP_TYPE (result) == AOP_CRY)
1576     {
1577       aopPut (AOP (result), "c", 0);
1578     }
1579   else
1580     {
1581       emitcode ("clr", "a");
1582       emitcode ("rlc", "a");
1583       outAcc (result);
1584     }
1585 }
1586
1587 /*-----------------------------------------------------------------*/
1588 /* toBoolean - emit code for orl a,operator(sizeop)                */
1589 /*-----------------------------------------------------------------*/
1590 static void
1591 toBoolean (operand * oper)
1592 {
1593   int   size = AOP_SIZE (oper) - 1;
1594   int   offset = 1;
1595   bool usedB = FALSE;
1596
1597   /* The generic part of a generic pointer should
1598    * not participate in it's truth value.
1599    *
1600    * i.e. 0x10000000 is zero.
1601    */
1602   if (opIsGptr (oper))
1603     {
1604       D (emitcode (";", "toBoolean: generic ptr special case.");
1605         );
1606       size--;
1607     }
1608
1609   _startLazyDPSEvaluation ();
1610   if (AOP_NEEDSACC (oper) && size)
1611     {
1612       usedB = TRUE;
1613       emitcode ("push", "b");
1614       emitcode ("mov", "b, %s", aopGet (AOP (oper), 0, FALSE, FALSE, FALSE));
1615     }
1616   else
1617     {
1618       MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, TRUE));
1619     }
1620   while (size--)
1621     {
1622       if (usedB)
1623         {
1624           emitcode ("orl", "b,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1625         }
1626       else
1627         {
1628           emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1629         }
1630     }
1631   _endLazyDPSEvaluation ();
1632
1633   if (usedB)
1634     {
1635       emitcode ("mov", "a,b");
1636       emitcode ("pop", "b");
1637     }
1638 }
1639
1640
1641 /*-----------------------------------------------------------------*/
1642 /* genNot - generate code for ! operation                          */
1643 /*-----------------------------------------------------------------*/
1644 static void
1645 genNot (iCode * ic)
1646 {
1647   symbol *tlbl;
1648   sym_link *optype = operandType (IC_LEFT (ic));
1649
1650   D (emitcode (";", "genNot ");
1651     );
1652
1653   /* assign asmOps to operand & result */
1654   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1655   aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1656
1657   /* if in bit space then a special case */
1658   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1659     {
1660       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1661       emitcode ("cpl", "c");
1662       outBitC (IC_RESULT (ic));
1663       goto release;
1664     }
1665
1666   /* if type float then do float */
1667   if (IS_FLOAT (optype))
1668     {
1669       genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1670       goto release;
1671     }
1672
1673   toBoolean (IC_LEFT (ic));
1674
1675   tlbl = newiTempLabel (NULL);
1676   emitcode ("cjne", "a,#1,!tlabel", tlbl->key + 100);
1677   emitcode ("", "!tlabeldef", tlbl->key + 100);
1678   outBitC (IC_RESULT (ic));
1679
1680 release:
1681   /* release the aops */
1682   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1683   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1684 }
1685
1686
1687 /*-----------------------------------------------------------------*/
1688 /* genCpl - generate code for complement                           */
1689 /*-----------------------------------------------------------------*/
1690 static void
1691 genCpl (iCode * ic)
1692 {
1693   int offset = 0;
1694   int size;
1695
1696   D (emitcode (";", "genCpl ");
1697     );
1698
1699
1700   /* assign asmOps to operand & result */
1701   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1702   aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1703
1704   /* if both are in bit space then
1705      a special case */
1706   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1707       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1708     {
1709
1710       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1711       emitcode ("cpl", "c");
1712       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1713       goto release;
1714     }
1715
1716   size = AOP_SIZE (IC_RESULT (ic));
1717   _startLazyDPSEvaluation ();
1718   while (size--)
1719     {
1720       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1721       MOVA (l);
1722       emitcode ("cpl", "a");
1723       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1724     }
1725   _endLazyDPSEvaluation ();
1726
1727
1728 release:
1729   /* release the aops */
1730   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1731   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1732 }
1733
1734 /*-----------------------------------------------------------------*/
1735 /* genUminusFloat - unary minus for floating points                */
1736 /*-----------------------------------------------------------------*/
1737 static void
1738 genUminusFloat (operand * op, operand * result)
1739 {
1740   int size, offset = 0;
1741   char *l;
1742   /* for this we just need to flip the
1743      first it then copy the rest in place */
1744   D (emitcode (";", "genUminusFloat");
1745     );
1746
1747   _startLazyDPSEvaluation ();
1748   size = AOP_SIZE (op) - 1;
1749   l = aopGet (AOP (op), 3, FALSE, FALSE, TRUE);
1750   MOVA (l);
1751
1752   emitcode ("cpl", "acc.7");
1753   aopPut (AOP (result), "a", 3);
1754
1755   while (size--)
1756     {
1757       aopPut (AOP (result),
1758               aopGet (AOP (op), offset, FALSE, FALSE, FALSE),
1759               offset);
1760       offset++;
1761     }
1762   _endLazyDPSEvaluation ();
1763 }
1764
1765 /*-----------------------------------------------------------------*/
1766 /* genUminus - unary minus code generation                         */
1767 /*-----------------------------------------------------------------*/
1768 static void
1769 genUminus (iCode * ic)
1770 {
1771   int offset, size;
1772   sym_link *optype, *rtype;
1773
1774   D (emitcode (";", "genUminus ");
1775     );
1776
1777
1778   /* assign asmops */
1779   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1780   aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1781
1782   /* if both in bit space then special
1783      case */
1784   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1785       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1786     {
1787
1788       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1789       emitcode ("cpl", "c");
1790       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1791       goto release;
1792     }
1793
1794   optype = operandType (IC_LEFT (ic));
1795   rtype = operandType (IC_RESULT (ic));
1796
1797   /* if float then do float stuff */
1798   if (IS_FLOAT (optype))
1799     {
1800       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1801       goto release;
1802     }
1803
1804   /* otherwise subtract from zero */
1805   size = AOP_SIZE (IC_LEFT (ic));
1806   offset = 0;
1807   _startLazyDPSEvaluation ();
1808   while (size--)
1809     {
1810       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1811       if (!strcmp (l, "a"))
1812         {
1813           if (offset == 0)
1814             SETC;
1815           emitcode ("cpl", "a");
1816           emitcode ("addc", "a,#0");
1817         }
1818       else
1819         {
1820           if (offset == 0)
1821             CLRC;
1822           emitcode ("clr", "a");
1823           emitcode ("subb", "a,%s", l);
1824         }
1825       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1826     }
1827   _endLazyDPSEvaluation ();
1828
1829   /* if any remaining bytes in the result */
1830   /* we just need to propagate the sign   */
1831   if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1832     {
1833       emitcode ("rlc", "a");
1834       emitcode ("subb", "a,acc");
1835       while (size--)
1836         aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1837     }
1838
1839 release:
1840   /* release the aops */
1841   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1842   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1843 }
1844
1845 /*-----------------------------------------------------------------*/
1846 /* savermask - saves registers in the mask                         */
1847 /*-----------------------------------------------------------------*/
1848 static void savermask(bitVect *rs_mask)
1849 {
1850     int i;
1851     if (options.useXstack) {
1852         if (bitVectBitValue (rs_mask, R0_IDX))
1853             emitcode ("mov", "b,r0");
1854         emitcode ("mov", "r0,%s", spname);
1855         for (i = 0; i < ds390_nRegs; i++) {
1856             if (bitVectBitValue (rs_mask, i)) {
1857                 if (i == R0_IDX)
1858                     emitcode ("mov", "a,b");
1859                 else
1860                     emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
1861                 emitcode ("movx", "@r0,a");
1862                 emitcode ("inc", "r0");
1863             }
1864         }
1865         emitcode ("mov", "%s,r0", spname);
1866         if (bitVectBitValue (rs_mask, R0_IDX))
1867             emitcode ("mov", "r0,b");
1868     } else {
1869         for (i = 0; i < ds390_nRegs; i++) {
1870             if (bitVectBitValue (rs_mask, i))
1871                 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
1872         }
1873     }
1874 }
1875
1876 /*-----------------------------------------------------------------*/
1877 /* saveRegisters - will look for a call and save the registers     */
1878 /*-----------------------------------------------------------------*/
1879 static void
1880 saveRegisters (iCode * lic)
1881 {
1882   iCode *ic;
1883   bitVect *rsave;
1884
1885   /* look for call */
1886   for (ic = lic; ic; ic = ic->next)
1887     if (ic->op == CALL || ic->op == PCALL)
1888       break;
1889
1890   if (!ic)
1891     {
1892       fprintf (stderr, "found parameter push with no function call\n");
1893       return;
1894     }
1895
1896   /* if the registers have been saved already then
1897      do nothing */
1898   if (ic->regsSaved || IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic)))) return ;
1899
1900   /* special case if DPTR alive across a function call then must save it 
1901      even though callee saves */
1902   if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
1903       int i =0;
1904       rsave = newBitVect(ic->rMask->size);
1905       for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
1906           if (bitVectBitValue(ic->rMask,i))
1907               rsave = bitVectSetBit(rsave,i);
1908       }
1909       rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
1910   } else {
1911     /* safe the registers in use at this time but skip the
1912        ones for the result */
1913     rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1914                            ds390_rUmaskForOp (IC_RESULT(ic)));
1915   }
1916   ic->regsSaved = 1;
1917   savermask(rsave);
1918 }
1919
1920 /*-----------------------------------------------------------------*/
1921 /* usavermask - restore registers with mask                        */
1922 /*-----------------------------------------------------------------*/
1923 static void unsavermask(bitVect *rs_mask)
1924 {
1925     int i;
1926     if (options.useXstack) {
1927         emitcode ("mov", "r0,%s", spname);
1928         for (i = ds390_nRegs; i >= 0; i--) {
1929             if (bitVectBitValue (rs_mask, i)) {
1930                 emitcode ("dec", "r0");
1931                 emitcode ("movx", "a,@r0");
1932                 if (i == R0_IDX)
1933                     emitcode ("mov", "b,a");
1934                 else
1935                     emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
1936             }       
1937         }
1938         emitcode ("mov", "%s,r0", spname);
1939         if (bitVectBitValue (rs_mask, R0_IDX))
1940             emitcode ("mov", "r0,b");
1941     } else {
1942         for (i = ds390_nRegs; i >= 0; i--) {
1943             if (bitVectBitValue (rs_mask, i))
1944                 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
1945         }
1946     }
1947 }
1948
1949 /*-----------------------------------------------------------------*/
1950 /* unsaveRegisters - pop the pushed registers                      */
1951 /*-----------------------------------------------------------------*/
1952 static void
1953 unsaveRegisters (iCode * ic)
1954 {
1955   bitVect *rsave;
1956
1957   if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
1958       int i =0;
1959       rsave = newBitVect(ic->rMask->size);
1960       for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
1961           if (bitVectBitValue(ic->rMask,i))
1962               rsave = bitVectSetBit(rsave,i);
1963       }
1964       rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
1965   } else {
1966     /* restore the registers in use at this time but skip the
1967        ones for the result */
1968     rsave = bitVectCplAnd (bitVectCopy (ic->rMask), 
1969                            ds390_rUmaskForOp (IC_RESULT(ic)));
1970   }
1971   unsavermask(rsave);
1972 }
1973
1974
1975 /*-----------------------------------------------------------------*/
1976 /* pushSide -                */
1977 /*-----------------------------------------------------------------*/
1978 static void
1979 pushSide (operand * oper, int size)
1980 {
1981   int offset = 0;
1982   _startLazyDPSEvaluation ();
1983   while (size--)
1984     {
1985       char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, FALSE);
1986       if (AOP_TYPE (oper) != AOP_REG &&
1987           AOP_TYPE (oper) != AOP_DIR &&
1988           strcmp (l, "a"))
1989         {
1990           emitcode ("mov", "a,%s", l);
1991           emitcode ("push", "acc");
1992         }
1993       else
1994         emitcode ("push", "%s", l);
1995     }
1996   _endLazyDPSEvaluation ();
1997 }
1998
1999 /*-----------------------------------------------------------------*/
2000 /* assignResultValue -               */
2001 /*-----------------------------------------------------------------*/
2002 static void
2003 assignResultValue (operand * oper)
2004 {
2005   int offset = 0;
2006   int size = AOP_SIZE (oper);
2007
2008   _startLazyDPSEvaluation ();
2009   while (size--)
2010     {
2011       aopPut (AOP (oper), fReturn[offset], offset);
2012       offset++;
2013     }
2014   _endLazyDPSEvaluation ();
2015 }
2016
2017
2018 /*-----------------------------------------------------------------*/
2019 /* genXpush - pushes onto the external stack                       */
2020 /*-----------------------------------------------------------------*/
2021 static void
2022 genXpush (iCode * ic)
2023 {
2024   asmop *aop = newAsmop (0);
2025   regs *r;
2026   int size, offset = 0;
2027
2028   D (emitcode (";", "genXpush ");
2029     );
2030
2031   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2032   r = getFreePtr (ic, &aop, FALSE);
2033
2034
2035   emitcode ("mov", "%s,_spx", r->name);
2036
2037   size = AOP_SIZE (IC_LEFT (ic));
2038   _startLazyDPSEvaluation ();
2039   while (size--)
2040     {
2041
2042       char *l = aopGet (AOP (IC_LEFT (ic)),
2043                         offset++, FALSE, FALSE, TRUE);
2044       MOVA (l);
2045       emitcode ("movx", "@%s,a", r->name);
2046       emitcode ("inc", "%s", r->name);
2047
2048     }
2049   _endLazyDPSEvaluation ();
2050
2051
2052   emitcode ("mov", "_spx,%s", r->name);
2053
2054   freeAsmop (NULL, aop, ic, TRUE);
2055   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2056 }
2057
2058 /*-----------------------------------------------------------------*/
2059 /* genIpush - genrate code for pushing this gets a little complex  */
2060 /*-----------------------------------------------------------------*/
2061 static void
2062 genIpush (iCode * ic)
2063 {
2064   int size, offset = 0;
2065   char *l;
2066
2067   D (emitcode (";", "genIpush ");
2068     );
2069
2070   /* if this is not a parm push : ie. it is spill push
2071      and spill push is always done on the local stack */
2072   if (!ic->parmPush)
2073     {
2074
2075       /* and the item is spilt then do nothing */
2076       if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2077         return;
2078
2079       aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2080       size = AOP_SIZE (IC_LEFT (ic));
2081       /* push it on the stack */
2082       _startLazyDPSEvaluation ();
2083       while (size--)
2084         {
2085           l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, TRUE);
2086           if (*l == '#')
2087             {
2088               MOVA (l);
2089               l = "acc";
2090             }
2091           emitcode ("push", "%s", l);
2092         }
2093       _endLazyDPSEvaluation ();
2094       return;
2095     }
2096
2097   /* this is a paramter push: in this case we call
2098      the routine to find the call and save those
2099      registers that need to be saved */
2100   saveRegisters (ic);
2101
2102   /* if use external stack then call the external
2103      stack pushing routine */
2104   if (options.useXstack)
2105     {
2106       genXpush (ic);
2107       return;
2108     }
2109
2110   /* then do the push */
2111   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2112
2113   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2114   size = AOP_SIZE (IC_LEFT (ic));
2115
2116   _startLazyDPSEvaluation ();
2117   while (size--)
2118     {
2119       l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, FALSE);
2120       if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2121           AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2122           strcmp (l, "a"))
2123         {
2124           emitcode ("mov", "a,%s", l);
2125           emitcode ("push", "acc");
2126         }
2127       else
2128         emitcode ("push", "%s", l);
2129     }
2130   _endLazyDPSEvaluation ();
2131
2132   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2133 }
2134
2135 /*-----------------------------------------------------------------*/
2136 /* genIpop - recover the registers: can happen only for spilling   */
2137 /*-----------------------------------------------------------------*/
2138 static void
2139 genIpop (iCode * ic)
2140 {
2141   int size, offset;
2142
2143   D (emitcode (";", "genIpop ");
2144     );
2145
2146
2147   /* if the temp was not pushed then */
2148   if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2149     return;
2150
2151   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2152   size = AOP_SIZE (IC_LEFT (ic));
2153   offset = (size - 1);
2154   _startLazyDPSEvaluation ();
2155   while (size--)
2156     {
2157       emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2158                                      FALSE, TRUE, TRUE));
2159     }
2160   _endLazyDPSEvaluation ();
2161
2162   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2163 }
2164
2165 /*-----------------------------------------------------------------*/
2166 /* unsaveRBank - restores the resgister bank from stack            */
2167 /*-----------------------------------------------------------------*/
2168 static void
2169 unsaveRBank (int bank, iCode * ic, bool popPsw)
2170 {
2171   int i;
2172   asmop *aop = NULL;
2173   regs *r = NULL;
2174
2175   if (options.useXstack)
2176   {
2177       if (!ic)
2178       {
2179           /* Assume r0 is available for use. */
2180           r = ds390_regWithIdx (R0_IDX);;          
2181       } 
2182       else
2183       {
2184           aop = newAsmop (0);
2185           r = getFreePtr (ic, &aop, FALSE);
2186       }
2187       emitcode ("mov", "%s,_spx", r->name);      
2188   }
2189   
2190   if (popPsw)
2191     {
2192       if (options.useXstack)
2193       {
2194           emitcode ("movx", "a,@%s", r->name);
2195           emitcode ("mov", "psw,a");
2196           emitcode ("dec", "%s", r->name);
2197         }
2198       else
2199       {
2200         emitcode ("pop", "psw");
2201       }
2202     }
2203
2204   for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2205     {
2206       if (options.useXstack)
2207         {
2208           emitcode ("movx", "a,@%s", r->name);
2209           emitcode ("mov", "(%s+%d),a",
2210                     regs390[i].base, 8 * bank + regs390[i].offset);
2211           emitcode ("dec", "%s", r->name);
2212
2213         }
2214       else
2215         emitcode ("pop", "(%s+%d)",
2216                   regs390[i].base, 8 * bank + regs390[i].offset);
2217     }
2218
2219   if (options.useXstack)
2220     {
2221       emitcode ("mov", "_spx,%s", r->name);
2222     }
2223     
2224   if (aop)
2225   {
2226       freeAsmop (NULL, aop, ic, TRUE);  
2227   }    
2228 }
2229
2230 /*-----------------------------------------------------------------*/
2231 /* saveRBank - saves an entire register bank on the stack          */
2232 /*-----------------------------------------------------------------*/
2233 static void
2234 saveRBank (int bank, iCode * ic, bool pushPsw)
2235 {
2236   int i;
2237   asmop *aop = NULL;
2238   regs *r = NULL;
2239
2240   if (options.useXstack)
2241     {
2242         if (!ic)
2243         {
2244           /* Assume r0 is available for use. */
2245                   r = ds390_regWithIdx (R0_IDX);;
2246         }
2247         else
2248         {
2249           aop = newAsmop (0);
2250           r = getFreePtr (ic, &aop, FALSE);
2251         }
2252         emitcode ("mov", "%s,_spx", r->name);    
2253     }
2254
2255   for (i = 0; i < 8 ; i++) /* only R0-R7 needs saving */
2256     {
2257       if (options.useXstack)
2258         {
2259           emitcode ("inc", "%s", r->name);
2260           emitcode ("mov", "a,(%s+%d)",
2261                     regs390[i].base, 8 * bank + regs390[i].offset);
2262           emitcode ("movx", "@%s,a", r->name);
2263         }
2264       else
2265         emitcode ("push", "(%s+%d)",
2266                   regs390[i].base, 8 * bank + regs390[i].offset);
2267     }
2268
2269   if (pushPsw)
2270     {
2271       if (options.useXstack)
2272         {
2273           emitcode ("mov", "a,psw");
2274           emitcode ("movx", "@%s,a", r->name);
2275           emitcode ("inc", "%s", r->name);
2276           emitcode ("mov", "_spx,%s", r->name);
2277         }
2278       else
2279       {
2280         emitcode ("push", "psw");
2281       }
2282
2283       emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2284     }
2285   
2286   if (aop)
2287   {
2288        freeAsmop (NULL, aop, ic, TRUE);
2289   }    
2290     
2291   if (ic)
2292   {  
2293       ic->bankSaved = 1;
2294   }
2295 }
2296
2297 /*-----------------------------------------------------------------*/
2298 /* genCall - generates a call statement                            */
2299 /*-----------------------------------------------------------------*/
2300 static void
2301 genCall (iCode * ic)
2302 {
2303   sym_link *dtype;
2304   bool restoreBank = FALSE;
2305   bool swapBanks = FALSE;
2306
2307   D (emitcode (";", "genCall "););
2308
2309   /* if we are calling a not _naked function that is not using
2310      the same register bank then we need to save the
2311      destination registers on the stack */
2312   dtype = operandType (IC_LEFT (ic));
2313   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2314       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2315       IFFUNC_ISISR (currFunc->type))
2316   {
2317       if (!ic->bankSaved) 
2318       {
2319            /* This is unexpected; the bank should have been saved in
2320             * genFunction.
2321             */
2322            saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2323            restoreBank = TRUE;
2324       }
2325       swapBanks = TRUE;
2326   }
2327   
2328     /* if caller saves & we have not saved then */
2329     if (!ic->regsSaved)
2330       saveRegisters (ic);
2331   
2332   /* if send set is not empty the assign */
2333   /* We've saved all the registers we care about;
2334   * therefore, we may clobber any register not used
2335   * in the calling convention (i.e. anything not in
2336   * fReturn.
2337   */
2338   if (_G.sendSet)
2339     {
2340       iCode *sic;
2341
2342       for (sic = setFirstItem (_G.sendSet); sic;
2343            sic = setNextItem (_G.sendSet))
2344         {
2345           int size, offset = 0;
2346
2347           // we know that dpl(hxb) is the result, so
2348           _startLazyDPSEvaluation ();
2349           size=getSize(operandType(IC_LEFT(sic)));
2350           if (size>1) {
2351             aopOp (IC_LEFT (sic), sic, FALSE, 
2352                    (IS_SYMOP(IC_LEFT(sic)) && OP_SYMBOL(IC_LEFT(sic))->ruonly ? FALSE : TRUE));
2353           } else {
2354             aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2355           }
2356           while (size--)
2357             {
2358               char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2359                                 FALSE, FALSE, TRUE);
2360               if (strcmp (l, fReturn[offset]))
2361                 {
2362                   emitcode ("mov", "%s,%s",
2363                             fReturn[offset],
2364                             l);
2365                 }
2366               offset++;
2367             }
2368           _endLazyDPSEvaluation ();
2369           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2370         }
2371       _G.sendSet = NULL;
2372     }  
2373     
2374   if (swapBanks)
2375   {
2376         emitcode ("mov", "psw,#!constbyte", 
2377            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2378   }
2379
2380   /* make the call */
2381   emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2382                             OP_SYMBOL (IC_LEFT (ic))->rname :
2383                             OP_SYMBOL (IC_LEFT (ic))->name));
2384
2385   if (swapBanks)
2386   {
2387        emitcode ("mov", "psw,#!constbyte", 
2388           ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2389   }
2390
2391   /* if we need assign a result value */
2392   if ((IS_ITEMP (IC_RESULT (ic)) &&
2393        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2394         OP_SYMBOL (IC_RESULT (ic))->accuse ||
2395         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2396       IS_TRUE_SYMOP (IC_RESULT (ic)))
2397     {
2398       if (isOperandInFarSpace (IC_RESULT (ic))
2399           && getSize (operandType (IC_RESULT (ic))) <= 2)
2400         {
2401           int size = getSize (operandType (IC_RESULT (ic)));
2402
2403           /* Special case for 1 or 2 byte return in far space. */
2404           MOVA (fReturn[0]);
2405           if (size > 1)
2406             {
2407               emitcode ("mov", "b,%s", fReturn[1]);
2408             }
2409
2410           aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2411           aopPut (AOP (IC_RESULT (ic)), "a", 0);
2412
2413           if (size > 1)
2414             {
2415               aopPut (AOP (IC_RESULT (ic)), "b", 1);
2416             }
2417           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2418         }
2419       else
2420         {
2421           _G.accInUse++;
2422           aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2423           _G.accInUse--;
2424
2425           assignResultValue (IC_RESULT (ic));
2426
2427           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2428         }
2429     }
2430
2431   /* adjust the stack for parameters if
2432      required */
2433   if (ic->parmBytes) {
2434       int i;
2435       if (options.stack10bit) {
2436           if (ic->parmBytes <= 4) {
2437               emitcode(";","stack adjustment for parms");
2438               for (i=0; i < ic->parmBytes ; i++) {
2439                   emitcode("pop","acc");
2440               }
2441           } else {
2442               emitcode ("clr","c");
2443               emitcode ("mov","a,sp");
2444               emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2445               emitcode ("mov","sp,a");
2446               emitcode ("mov","a,esp");
2447               emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2448               emitcode ("mov","esp,a");   
2449           }
2450       } else {
2451           if (ic->parmBytes > 3) {
2452               emitcode ("mov", "a,%s", spname);
2453               emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2454               emitcode ("mov", "%s,a", spname);
2455           } else
2456               for (i = 0; i < ic->parmBytes; i++)
2457                   emitcode ("dec", "%s", spname);
2458       }
2459   }
2460
2461   /* if we hade saved some registers then unsave them */
2462   if (ic->regsSaved)
2463     unsaveRegisters (ic);
2464
2465   /* if register bank was saved then pop them */
2466   if (restoreBank)
2467     unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2468 }
2469
2470 /*-----------------------------------------------------------------*/
2471 /* genPcall - generates a call by pointer statement                */
2472 /*-----------------------------------------------------------------*/
2473 static void
2474 genPcall (iCode * ic)
2475 {
2476   sym_link *dtype;
2477   symbol *rlbl = newiTempLabel (NULL);
2478   bool restoreBank=FALSE;
2479
2480   D (emitcode (";", "genPcall ");
2481     );
2482
2483
2484   /* if caller saves & we have not saved then */
2485   if (!ic->regsSaved)
2486     saveRegisters (ic);
2487
2488   /* if we are calling a function that is not using
2489      the same register bank then we need to save the
2490      destination registers on the stack */
2491   dtype = operandType (IC_LEFT (ic));
2492   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2493       IFFUNC_ISISR (currFunc->type) &&
2494       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2495     saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2496     restoreBank=TRUE;
2497   }
2498
2499   /* push the return address on to the stack */
2500   emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
2501   emitcode ("push", "acc");
2502   emitcode ("mov", "a,#!hil", (rlbl->key + 100));
2503   emitcode ("push", "acc");
2504
2505   if (options.model == MODEL_FLAT24)
2506     {
2507       emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
2508       emitcode ("push", "acc");
2509     }
2510
2511   /* now push the calling address */
2512   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2513
2514   pushSide (IC_LEFT (ic), FPTRSIZE);
2515
2516   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2517
2518   /* if send set is not empty the assign */
2519   if (_G.sendSet)
2520     {
2521       iCode *sic;
2522
2523       for (sic = setFirstItem (_G.sendSet); sic;
2524            sic = setNextItem (_G.sendSet))
2525         {
2526           int size, offset = 0;
2527
2528           // we know that dpl(hxb) is the result, so
2529           _startLazyDPSEvaluation ();
2530           size=getSize(operandType(IC_LEFT(sic)));
2531           if (size>1) {
2532             aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2533           } else {
2534             aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2535           }
2536           while (size--)
2537             {
2538               char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2539                                 FALSE, FALSE, TRUE);
2540               if (strcmp (l, fReturn[offset]))
2541                 {
2542                   emitcode ("mov", "%s,%s",
2543                             fReturn[offset],
2544                             l);
2545                 }
2546               offset++;
2547             }
2548           _endLazyDPSEvaluation ();
2549           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2550         }
2551       _G.sendSet = NULL;
2552     }
2553
2554   emitcode ("ret", "");
2555   emitcode ("", "!tlabeldef", (rlbl->key + 100));
2556
2557
2558   /* if we need assign a result value */
2559   if ((IS_ITEMP (IC_RESULT (ic)) &&
2560        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2561         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2562       IS_TRUE_SYMOP (IC_RESULT (ic)))
2563     {
2564
2565       _G.accInUse++;
2566       aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2567       _G.accInUse--;
2568
2569       assignResultValue (IC_RESULT (ic));
2570
2571       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2572     }
2573
2574   /* adjust the stack for parameters if
2575      required */
2576   if (ic->parmBytes)
2577     {
2578       int i;
2579       if (ic->parmBytes > 3)
2580         {
2581           emitcode ("mov", "a,%s", spname);
2582           emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2583           emitcode ("mov", "%s,a", spname);
2584         }
2585       else
2586         for (i = 0; i < ic->parmBytes; i++)
2587           emitcode ("dec", "%s", spname);
2588
2589     }
2590
2591   /* if register bank was saved then unsave them */
2592   if (restoreBank)
2593     unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2594   
2595   /* if we hade saved some registers then
2596      unsave them */
2597   if (ic->regsSaved)
2598     unsaveRegisters (ic);
2599
2600 }
2601
2602 /*-----------------------------------------------------------------*/
2603 /* resultRemat - result  is rematerializable                       */
2604 /*-----------------------------------------------------------------*/
2605 static int
2606 resultRemat (iCode * ic)
2607 {
2608   if (SKIP_IC (ic) || ic->op == IFX)
2609     return 0;
2610
2611   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2612     {
2613       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2614       if (sym->remat && !POINTER_SET (ic))
2615         return 1;
2616     }
2617
2618   return 0;
2619 }
2620
2621 #if defined(__BORLANDC__) || defined(_MSC_VER)
2622 #define STRCASECMP stricmp
2623 #else
2624 #define STRCASECMP strcasecmp
2625 #endif
2626
2627 /*-----------------------------------------------------------------*/
2628 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2629 /*-----------------------------------------------------------------*/
2630 static bool
2631 inExcludeList (char *s)
2632 {
2633   int i = 0;
2634
2635   if (options.excludeRegs[i] &&
2636       STRCASECMP (options.excludeRegs[i], "none") == 0)
2637     return FALSE;
2638
2639   for (i = 0; options.excludeRegs[i]; i++)
2640     {
2641       if (options.excludeRegs[i] &&
2642           STRCASECMP (s, options.excludeRegs[i]) == 0)
2643         return TRUE;
2644     }
2645   return FALSE;
2646 }
2647
2648 /*-----------------------------------------------------------------*/
2649 /* genFunction - generated code for function entry                 */
2650 /*-----------------------------------------------------------------*/
2651 static void
2652 genFunction (iCode * ic)
2653 {
2654   symbol *sym;
2655   sym_link *ftype;
2656   bool   switchedPSW = FALSE;
2657
2658   D (emitcode (";", "genFunction "););
2659
2660   _G.nRegsSaved = 0;
2661   /* create the function header */
2662   emitcode (";", "-----------------------------------------");
2663   emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2664   emitcode (";", "-----------------------------------------");
2665
2666   emitcode ("", "%s:", sym->rname);
2667   ftype = operandType (IC_LEFT (ic));
2668
2669   if (IFFUNC_ISNAKED(ftype))
2670   {
2671       emitcode(";", "naked function: no prologue.");
2672       return;
2673   }
2674   
2675   if (options.stack_probe) 
2676       emitcode ("lcall","__stack_probe");
2677   /* if critical function then turn interrupts off */
2678   if (IFFUNC_ISCRITICAL (ftype))
2679     emitcode ("clr", "ea");
2680
2681   /* here we need to generate the equates for the
2682      register bank if required */
2683   if (FUNC_REGBANK (ftype) != rbank)
2684     {
2685       int i;
2686
2687       rbank = FUNC_REGBANK (ftype);
2688       for (i = 0; i < ds390_nRegs; i++)
2689         {
2690           if (regs390[i].print) {
2691               if (strcmp (regs390[i].base, "0") == 0)
2692                   emitcode ("", "%s !equ !constbyte",
2693                             regs390[i].dname,
2694                             8 * rbank + regs390[i].offset);
2695               else
2696                   emitcode ("", "%s !equ %s + !constbyte",
2697                             regs390[i].dname,
2698                             regs390[i].base,
2699                             8 * rbank + regs390[i].offset);
2700           }
2701         }
2702     }
2703
2704   /* if this is an interrupt service routine then
2705      save acc, b, dpl, dph  */
2706   if (IFFUNC_ISISR (sym->type))
2707     {
2708
2709       if (!inExcludeList ("acc"))
2710         emitcode ("push", "acc");
2711       if (!inExcludeList ("b"))
2712         emitcode ("push", "b");
2713       if (!inExcludeList ("dpl"))
2714         emitcode ("push", "dpl");
2715       if (!inExcludeList ("dph"))
2716         emitcode ("push", "dph");
2717       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2718         {
2719           emitcode ("push", "dpx");
2720           /* Make sure we're using standard DPTR */
2721           emitcode ("push", "dps");
2722           emitcode ("mov", "dps,#0");
2723           if (options.stack10bit)
2724             {
2725               /* This ISR could conceivably use DPTR2. Better save it. */
2726               emitcode ("push", "dpl1");
2727               emitcode ("push", "dph1");
2728               emitcode ("push", "dpx1");
2729               emitcode ("push",  DP2_RESULT_REG);
2730             }
2731         }
2732       /* if this isr has no bank i.e. is going to
2733          run with bank 0 , then we need to save more
2734          registers :-) */
2735       if (!FUNC_REGBANK (sym->type))
2736         {
2737
2738           /* if this function does not call any other
2739              function then we can be economical and
2740              save only those registers that are used */
2741           if (!IFFUNC_HASFCALL(sym->type))
2742             {
2743               int i;
2744
2745               /* if any registers used */
2746               if (sym->regsUsed)
2747                 {
2748                   /* save the registers used */
2749                   for (i = 0; i < sym->regsUsed->size; i++)
2750                     {
2751                       if (bitVectBitValue (sym->regsUsed, i) ||
2752                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2753                         emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2754                     }
2755                 }
2756
2757             }
2758           else
2759             {
2760               /* this function has  a function call cannot
2761                  determines register usage so we will have to push the
2762                  entire bank */
2763               saveRBank (0, ic, FALSE);
2764             }
2765         }
2766         else
2767         {
2768             /* This ISR uses a non-zero bank.
2769              *
2770              * We assume that the bank is available for our
2771              * exclusive use.
2772              *
2773              * However, if this ISR calls a function which uses some
2774              * other bank, we must save that bank entirely.
2775              */
2776             unsigned long banksToSave = 0;
2777             
2778             if (IFFUNC_HASFCALL(sym->type))
2779             {
2780
2781 #define MAX_REGISTER_BANKS 4
2782
2783                 iCode *i;
2784                 int ix;
2785
2786                 for (i = ic; i; i = i->next)
2787                 {
2788                     if (i->op == ENDFUNCTION)
2789                     {
2790                         /* we got to the end OK. */
2791                         break;
2792                     }
2793                     
2794                     if (i->op == CALL)
2795                     {
2796                         sym_link *dtype;
2797                         
2798                         dtype = operandType (IC_LEFT(i));
2799                         if (dtype 
2800                          && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2801                         {
2802                              /* Mark this bank for saving. */
2803                              if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2804                              {
2805                                  werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2806                              }
2807                              else
2808                              {
2809                                  banksToSave |= (1 << FUNC_REGBANK(dtype));
2810                              }
2811                              
2812                              /* And note that we don't need to do it in 
2813                               * genCall.
2814                               */
2815                              i->bankSaved = 1;
2816                         }
2817                     }
2818                     if (i->op == PCALL)
2819                     {
2820                         /* This is a mess; we have no idea what
2821                          * register bank the called function might
2822                          * use.
2823                          *
2824                          * The only thing I can think of to do is
2825                          * throw a warning and hope.
2826                          */
2827                         werror(W_FUNCPTR_IN_USING_ISR);   
2828                     }
2829                 }
2830
2831                 if (banksToSave && options.useXstack)
2832                 {
2833                     /* Since we aren't passing it an ic, 
2834                      * saveRBank will assume r0 is available to abuse.
2835                      *
2836                      * So switch to our (trashable) bank now, so
2837                      * the caller's R0 isn't trashed.
2838                      */
2839                     emitcode ("push", "psw");
2840                     emitcode ("mov", "psw,#!constbyte", 
2841                               (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2842                     switchedPSW = TRUE;
2843                 }
2844                 
2845                 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2846                 {
2847                      if (banksToSave & (1 << ix))
2848                      {
2849                          saveRBank(ix, NULL, FALSE);
2850                      }
2851                 }
2852             }
2853             // jwk: this needs a closer look
2854             SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2855         }
2856     }
2857   else
2858     {
2859       /* if callee-save to be used for this function
2860          then save the registers being used in this function */
2861       if (IFFUNC_CALLEESAVES(sym->type))
2862         {
2863           int i;
2864
2865           /* if any registers used */
2866           if (sym->regsUsed)
2867             {
2868               /* save the registers used */
2869               for (i = 0; i < sym->regsUsed->size; i++)
2870                 {
2871                   if (bitVectBitValue (sym->regsUsed, i) ||
2872                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2873                     {
2874                       emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2875                       _G.nRegsSaved++;
2876                     }
2877                 }
2878             }
2879         }
2880     }
2881
2882   /* set the register bank to the desired value */
2883   if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
2884    && !switchedPSW)
2885     {
2886       emitcode ("push", "psw");
2887       emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2888     }
2889
2890   if ( (IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
2891        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
2892       if (options.stack10bit) {
2893           emitcode ("push","_bpx");
2894           emitcode ("push","_bpx+1");
2895           emitcode ("mov","_bpx,%s",spname);
2896           emitcode ("mov","_bpx+1,esp");
2897           emitcode ("anl","_bpx+1,#3");
2898       } else {
2899           if (options.useXstack) {
2900               emitcode ("mov", "r0,%s", spname);
2901               emitcode ("mov", "a,_bp");
2902               emitcode ("movx", "@r0,a");
2903               emitcode ("inc", "%s", spname);
2904           } else {
2905               /* set up the stack */
2906               emitcode ("push", "_bp"); /* save the callers stack  */
2907           }
2908           emitcode ("mov", "_bp,%s", spname);
2909       }
2910   }
2911
2912   /* adjust the stack for the function */
2913   if (sym->stack) {
2914       int i = sym->stack;
2915       if (options.stack10bit) {
2916           if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);
2917           assert (sym->recvSize <= 4);
2918           emitcode ("mov","a,sp");
2919           emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
2920           emitcode ("mov","sp,a");
2921           emitcode ("mov","a,esp");
2922           emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
2923           emitcode ("mov","esp,a");
2924       } else {
2925           if (i > 256)
2926               werror (W_STACK_OVERFLOW, sym->name);
2927           
2928           if (i > 3 && sym->recvSize < 4) {
2929               
2930               emitcode ("mov", "a,sp");
2931               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
2932               emitcode ("mov", "sp,a");
2933               
2934           } else
2935               while (i--)
2936                   emitcode ("inc", "sp");
2937       }
2938   }
2939
2940   if (sym->xstack)
2941     {
2942
2943       emitcode ("mov", "a,_spx");
2944       emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
2945       emitcode ("mov", "_spx,a");
2946     }
2947
2948 }
2949
2950 /*-----------------------------------------------------------------*/
2951 /* genEndFunction - generates epilogue for functions               */
2952 /*-----------------------------------------------------------------*/
2953 static void
2954 genEndFunction (iCode * ic)
2955 {
2956   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2957
2958   D (emitcode (";", "genEndFunction "););
2959
2960   if (IFFUNC_ISNAKED(sym->type))
2961   {
2962       emitcode(";", "naked function: no epilogue.");
2963       return;
2964   }
2965
2966   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
2967        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
2968
2969       if (options.stack10bit) {
2970           emitcode ("mov", "sp,_bpx", spname);
2971           emitcode ("mov", "esp,_bpx+1", spname);
2972       } else {
2973           emitcode ("mov", "%s,_bp", spname);
2974       }
2975   }
2976
2977   /* if use external stack but some variables were
2978      added to the local stack then decrement the
2979      local stack */
2980   if (options.useXstack && sym->stack) {
2981       emitcode ("mov", "a,sp");
2982       emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
2983       emitcode ("mov", "sp,a");
2984   }
2985
2986
2987   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
2988        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
2989
2990       if (options.useXstack) {
2991           emitcode ("mov", "r0,%s", spname);
2992           emitcode ("movx", "a,@r0");
2993           emitcode ("mov", "_bp,a");
2994           emitcode ("dec", "%s", spname);
2995       } else {
2996           if (options.stack10bit) {
2997               emitcode ("pop", "_bpx+1");
2998               emitcode ("pop", "_bpx");
2999           } else {
3000               emitcode ("pop", "_bp");
3001           }
3002       }
3003   }
3004
3005   /* restore the register bank  */
3006   if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3007   {
3008     if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3009      || !options.useXstack)
3010     {
3011         /* Special case of ISR using non-zero bank with useXstack
3012          * is handled below.
3013          */
3014         emitcode ("pop", "psw");
3015     }
3016   }
3017
3018   if (IFFUNC_ISISR (sym->type))
3019     {
3020
3021       /* now we need to restore the registers */
3022       /* if this isr has no bank i.e. is going to
3023          run with bank 0 , then we need to save more
3024          registers :-) */
3025       if (!FUNC_REGBANK (sym->type))
3026         {
3027           /* if this function does not call any other
3028              function then we can be economical and
3029              save only those registers that are used */
3030           if (!IFFUNC_HASFCALL(sym->type))
3031             {
3032               int i;
3033
3034               /* if any registers used */
3035               if (sym->regsUsed)
3036                 {
3037                   /* save the registers used */
3038                   for (i = sym->regsUsed->size; i >= 0; i--)
3039                     {
3040                       if (bitVectBitValue (sym->regsUsed, i) ||
3041                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3042                         emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3043                     }
3044                 }
3045
3046             }
3047           else
3048             {
3049               /* this function has  a function call cannot
3050                  determines register usage so we will have to pop the
3051                  entire bank */
3052               unsaveRBank (0, ic, FALSE);
3053             }
3054         }
3055         else
3056         {
3057             /* This ISR uses a non-zero bank.
3058              *
3059              * Restore any register banks saved by genFunction
3060              * in reverse order.
3061              */
3062           // jwk: this needs a closer look
3063             unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3064             int ix;
3065           
3066             for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3067             {
3068                 if (savedBanks & (1 << ix))
3069                 {
3070                     unsaveRBank(ix, NULL, FALSE);
3071                 }
3072             }
3073             
3074             if (options.useXstack)
3075             {
3076                 /* Restore bank AFTER calling unsaveRBank,
3077                  * since it can trash r0.
3078                  */
3079                 emitcode ("pop", "psw");
3080             }
3081         }
3082
3083       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3084         {
3085           if (options.stack10bit)
3086             {
3087               emitcode ("pop", DP2_RESULT_REG);
3088               emitcode ("pop", "dpx1");
3089               emitcode ("pop", "dph1");
3090               emitcode ("pop", "dpl1");
3091             }
3092           emitcode ("pop", "dps");
3093           emitcode ("pop", "dpx");
3094         }
3095       if (!inExcludeList ("dph"))
3096         emitcode ("pop", "dph");
3097       if (!inExcludeList ("dpl"))
3098         emitcode ("pop", "dpl");
3099       if (!inExcludeList ("b"))
3100         emitcode ("pop", "b");
3101       if (!inExcludeList ("acc"))
3102         emitcode ("pop", "acc");
3103
3104       if (IFFUNC_ISCRITICAL (sym->type))
3105         emitcode ("setb", "ea");
3106
3107       /* if debug then send end of function */
3108       if (options.debug && currFunc) {
3109           _G.debugLine = 1;
3110           emitcode ("", "C$%s$%d$%d$%d ==.",
3111                     FileBaseName (ic->filename), currFunc->lastLine,
3112                     ic->level, ic->block);
3113           if (IS_STATIC (currFunc->etype))
3114             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3115           else
3116             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3117           _G.debugLine = 0;
3118         }
3119
3120       emitcode ("reti", "");
3121     }
3122   else
3123     {
3124       if (IFFUNC_ISCRITICAL (sym->type))
3125         emitcode ("setb", "ea");
3126
3127       if (IFFUNC_CALLEESAVES(sym->type))
3128         {
3129           int i;
3130
3131           /* if any registers used */
3132           if (sym->regsUsed)
3133             {
3134               /* save the registers used */
3135               for (i = sym->regsUsed->size; i >= 0; i--)
3136                 {
3137                   if (bitVectBitValue (sym->regsUsed, i) ||
3138                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3139                     emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3140                 }
3141             }
3142
3143         }
3144
3145       /* if debug then send end of function */
3146       if (options.debug && currFunc)
3147         {
3148           _G.debugLine = 1;
3149           emitcode ("", "C$%s$%d$%d$%d ==.",
3150                     FileBaseName (ic->filename), currFunc->lastLine,
3151                     ic->level, ic->block);
3152           if (IS_STATIC (currFunc->etype))
3153             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3154           else
3155             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3156           _G.debugLine = 0;
3157         }
3158
3159       emitcode ("ret", "");
3160     }
3161
3162 }
3163
3164 /*-----------------------------------------------------------------*/
3165 /* genJavaNativeRet - generate code for return JavaNative          */
3166 /*-----------------------------------------------------------------*/
3167 static void genJavaNativeRet(iCode *ic)
3168 {
3169     int i, size;
3170
3171     aopOp (IC_LEFT (ic), ic, FALSE, 
3172            (IS_SYMOP(IC_LEFT(ic)) && OP_SYMBOL(IC_LEFT(ic))->ruonly ? FALSE :TRUE));
3173     size = AOP_SIZE (IC_LEFT (ic));
3174
3175     assert (size <= 4);
3176
3177     /* it is assigned to GPR0-R3 then push them */
3178     if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3179         aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3180         for (i = 0 ; i < size ; i++ ) {
3181             emitcode ("push","%s",aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,FALSE));     
3182         }
3183         for (i = (size-1) ; i >= 0 ; i--) {
3184             emitcode ("pop","a%s",javaRet[i]);
3185         }
3186     } else {
3187         for (i = 0 ; i < size ; i++) 
3188             emitcode ("mov","%s,%s",javaRet[i],aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,FALSE));
3189     }
3190     for (i = size ; i < 4 ; i++ )
3191             emitcode ("mov","%s,#0",javaRet[i]);
3192     return;
3193 }
3194
3195 /*-----------------------------------------------------------------*/
3196 /* genRet - generate code for return statement                     */
3197 /*-----------------------------------------------------------------*/
3198 static void
3199 genRet (iCode * ic)
3200 {
3201   int size, offset = 0, pushed = 0;
3202
3203   D (emitcode (";", "genRet ");
3204     );
3205
3206   /* if we have no return value then
3207      just generate the "ret" */
3208   if (!IC_LEFT (ic))
3209     goto jumpret;
3210
3211   /* if this is a JavaNative function then return 
3212      value in different register */
3213   if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3214       genJavaNativeRet(ic);
3215       goto jumpret;
3216   }
3217   /* we have something to return then
3218      move the return value into place */
3219   aopOp (IC_LEFT (ic), ic, FALSE, 
3220          (IS_SYMOP(IC_LEFT(ic)) && OP_SYMBOL(IC_LEFT(ic))->ruonly ? FALSE :TRUE));
3221   size = AOP_SIZE (IC_LEFT (ic));
3222
3223   _startLazyDPSEvaluation ();
3224   while (size--)
3225     {
3226       char *l;
3227       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3228         {
3229           l = aopGet (AOP (IC_LEFT (ic)), offset++,
3230                       FALSE, TRUE, FALSE);
3231           emitcode ("push", "%s", l);
3232           pushed++;
3233         }
3234       else
3235         {
3236           /* Since A is the last element of fReturn,
3237            * is is OK to clobber it in the aopGet.
3238            */
3239           l = aopGet (AOP (IC_LEFT (ic)), offset,
3240                       FALSE, FALSE, TRUE);
3241           if (strcmp (fReturn[offset], l))
3242             emitcode ("mov", "%s,%s", fReturn[offset++], l);
3243         }
3244     }
3245   _endLazyDPSEvaluation ();
3246
3247   if (pushed)
3248     {
3249       while (pushed)
3250         {
3251           pushed--;
3252           if (strcmp (fReturn[pushed], "a"))
3253             emitcode ("pop", fReturn[pushed]);
3254           else
3255             emitcode ("pop", "acc");
3256         }
3257     }
3258   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3259
3260 jumpret:
3261   /* generate a jump to the return label
3262      if the next is not the return statement */
3263   if (!(ic->next && ic->next->op == LABEL &&
3264         IC_LABEL (ic->next) == returnLabel))
3265
3266     emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3267
3268 }
3269
3270 /*-----------------------------------------------------------------*/
3271 /* genLabel - generates a label                                    */
3272 /*-----------------------------------------------------------------*/
3273 static void
3274 genLabel (iCode * ic)
3275 {
3276   /* special case never generate */
3277   if (IC_LABEL (ic) == entryLabel)
3278     return;
3279
3280   D (emitcode (";", "genLabel ");
3281     );
3282
3283   emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3284 }
3285
3286 /*-----------------------------------------------------------------*/
3287 /* genGoto - generates a ljmp                                      */
3288 /*-----------------------------------------------------------------*/
3289 static void
3290 genGoto (iCode * ic)
3291 {
3292   D (emitcode (";", "genGoto ");
3293     );
3294   emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3295 }
3296
3297 /*-----------------------------------------------------------------*/
3298 /* findLabelBackwards: walks back through the iCode chain looking  */
3299 /* for the given label. Returns number of iCode instructions     */
3300 /* between that label and given ic.          */
3301 /* Returns zero if label not found.          */
3302 /*-----------------------------------------------------------------*/
3303 static int
3304 findLabelBackwards (iCode * ic, int key)
3305 {
3306   int count = 0;
3307
3308   while (ic->prev)
3309     {
3310       ic = ic->prev;
3311       count++;
3312
3313       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3314         {
3315           /* printf("findLabelBackwards = %d\n", count); */
3316           return count;
3317         }
3318     }
3319
3320   return 0;
3321 }
3322
3323 /*-----------------------------------------------------------------*/
3324 /* genPlusIncr :- does addition with increment if possible         */
3325 /*-----------------------------------------------------------------*/
3326 static bool
3327 genPlusIncr (iCode * ic)
3328 {
3329   unsigned int icount;
3330   unsigned int size = getDataSize (IC_RESULT (ic));
3331
3332   /* will try to generate an increment */
3333   /* if the right side is not a literal
3334      we cannot */
3335   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3336     return FALSE;
3337
3338   /* if the literal value of the right hand side
3339      is greater than 4 then it is not worth it */
3340   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3341     return FALSE;
3342
3343   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3344       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3345       while (icount--) {
3346           emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
3347       }
3348       return TRUE;
3349   }
3350   /* if increment 16 bits in register */
3351   if (
3352        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3353        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3354        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3355        (size > 1) &&
3356        (icount == 1))
3357     {
3358       symbol *tlbl;
3359       int emitTlbl;
3360       int labelRange;
3361
3362       /* If the next instruction is a goto and the goto target
3363        * is <= 5 instructions previous to this, we can generate
3364        * jumps straight to that target.
3365        */
3366       if (ic->next && ic->next->op == GOTO
3367           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3368           && labelRange <= 5)
3369         {
3370           emitcode (";", "tail increment optimized (range %d)", labelRange);
3371           tlbl = IC_LABEL (ic->next);
3372           emitTlbl = 0;
3373         }
3374       else
3375         {
3376           tlbl = newiTempLabel (NULL);
3377           emitTlbl = 1;
3378         }
3379       emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3380       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3381           IS_AOP_PREG (IC_RESULT (ic)))
3382         emitcode ("cjne", "%s,#0,!tlabel"
3383                   ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3384                   ,tlbl->key + 100);
3385       else
3386         {
3387           emitcode ("clr", "a");
3388           emitcode ("cjne", "a,%s,!tlabel"
3389                     ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3390                     ,tlbl->key + 100);
3391         }
3392
3393       emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3394       if (size > 2)
3395         {
3396           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3397               IS_AOP_PREG (IC_RESULT (ic)))
3398             emitcode ("cjne", "%s,#0,!tlabel"
3399                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3400                       ,tlbl->key + 100);
3401           else
3402             emitcode ("cjne", "a,%s,!tlabel"
3403                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3404                       ,tlbl->key + 100);
3405
3406           emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3407         }
3408       if (size > 3)
3409         {
3410           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3411               IS_AOP_PREG (IC_RESULT (ic)))
3412             emitcode ("cjne", "%s,#0,!tlabel"
3413                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3414                       ,tlbl->key + 100);
3415           else
3416             {
3417               emitcode ("cjne", "a,%s,!tlabel"
3418                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3419                         ,tlbl->key + 100);
3420             }
3421           emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3422         }
3423
3424       if (emitTlbl)
3425         {
3426           emitcode ("", "!tlabeldef", tlbl->key + 100);
3427         }
3428       return TRUE;
3429     }
3430
3431   /* if the sizes are greater than 1 then we cannot */
3432   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3433       AOP_SIZE (IC_LEFT (ic)) > 1)
3434     return FALSE;
3435
3436   /* we can if the aops of the left & result match or
3437      if they are in registers and the registers are the
3438      same */
3439   if (
3440        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3441        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3442        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3443     {
3444
3445       if (icount > 3)
3446         {
3447           MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3448           emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3449           aopPut (AOP (IC_RESULT (ic)), "a", 0);
3450         }
3451       else
3452         {
3453
3454           _startLazyDPSEvaluation ();
3455           while (icount--)
3456             {
3457               emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3458             }
3459           _endLazyDPSEvaluation ();
3460         }
3461
3462       return TRUE;
3463     }
3464
3465   return FALSE;
3466 }
3467
3468 /*-----------------------------------------------------------------*/
3469 /* outBitAcc - output a bit in acc                                 */
3470 /*-----------------------------------------------------------------*/
3471 static void
3472 outBitAcc (operand * result)
3473 {
3474   symbol *tlbl = newiTempLabel (NULL);
3475   /* if the result is a bit */
3476   if (AOP_TYPE (result) == AOP_CRY)
3477     {
3478       aopPut (AOP (result), "a", 0);
3479     }
3480   else
3481     {
3482       emitcode ("jz", "!tlabel", tlbl->key + 100);
3483       emitcode ("mov", "a,%s", one);
3484       emitcode ("", "!tlabeldef", tlbl->key + 100);
3485       outAcc (result);
3486     }
3487 }
3488
3489 /*-----------------------------------------------------------------*/
3490 /* genPlusBits - generates code for addition of two bits           */
3491 /*-----------------------------------------------------------------*/
3492 static void
3493 genPlusBits (iCode * ic)
3494 {
3495   D (emitcode (";", "genPlusBits ");
3496     );
3497   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3498     {
3499       symbol *lbl = newiTempLabel (NULL);
3500       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3501       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3502       emitcode ("cpl", "c");
3503       emitcode ("", "!tlabeldef", (lbl->key + 100));
3504       outBitC (IC_RESULT (ic));
3505     }
3506   else
3507     {
3508       emitcode ("clr", "a");
3509       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3510       emitcode ("rlc", "a");
3511       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3512       emitcode ("addc", "a,#0");
3513       outAcc (IC_RESULT (ic));
3514     }
3515 }
3516
3517 static void
3518 adjustArithmeticResult (iCode * ic)
3519 {
3520   if (opIsGptr (IC_RESULT (ic)) &&
3521       opIsGptr (IC_LEFT (ic)) &&
3522       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3523     {
3524       aopPut (AOP (IC_RESULT (ic)),
3525               aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3526               GPTRSIZE - 1);
3527     }
3528
3529   if (opIsGptr (IC_RESULT (ic)) &&
3530       opIsGptr (IC_RIGHT (ic)) &&
3531       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3532     {
3533       aopPut (AOP (IC_RESULT (ic)),
3534             aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3535               GPTRSIZE - 1);
3536     }
3537
3538   if (opIsGptr (IC_RESULT (ic)) &&
3539       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3540       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3541       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3542       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3543     {
3544       char buffer[5];
3545       sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3546       aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3547     }
3548 }
3549
3550 #if 0 // AOP_OP_3 is deprecated; nobody likes Ack errors.
3551       // Please don't bring it back without a really good reason.
3552 // Macro to aopOp all three operands of an ic. Will fatal if this cannot be done
3553 // (because all three operands are in far space).
3554 #define AOP_OP_3(ic) \
3555     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3556     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3557     aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3558               (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3559     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3560         AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3561     { \
3562         /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3563         fprintf(stderr,                                  \
3564                "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno);   \
3565     }
3566 #endif
3567
3568 // Macro to aopOp all three operands of an ic. If this cannot be done, 
3569 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3570 // will be set TRUE. The caller must then handle the case specially, noting
3571 // that the IC_RESULT operand is not aopOp'd.
3572 #define AOP_OP_3_NOFATAL(ic, rc) \
3573     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3574     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR) || \
3575                                   ((OP_SYMBOL(IC_RESULT(ic))->ruonly) && !isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)))); \
3576     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3577         (isOperandInFarSpace(IC_RESULT(ic)) || (OP_SYMBOL(IC_RESULT(ic))->ruonly && !isOperandEqual(IC_LEFT(ic),IC_RESULT(ic))))) \
3578     { \
3579        /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3580        rc = TRUE; \
3581     }  \
3582     else \
3583     { \
3584        aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3585                                      (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3586        rc = FALSE; \
3587        if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3588            AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3589        { \
3590             /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3591             fprintf(stderr,                                  \
3592                     "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno);   \
3593        } \
3594     }
3595
3596 // aopOp the left & right operands of an ic.
3597 #define AOP_OP_2(ic) \
3598     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3599     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3600
3601 // convienience macro.
3602 #define AOP_SET_LOCALS(ic) \
3603     left = IC_LEFT(ic); \
3604     right = IC_RIGHT(ic); \
3605     result = IC_RESULT(ic);
3606
3607
3608 // Given an integer value of pushedSize bytes on the stack,
3609 // adjust it to be resultSize bytes, either by discarding
3610 // the most significant bytes or by zero-padding.
3611 //
3612 // On exit from this macro, pushedSize will have been adjusted to
3613 // equal resultSize, and ACC may be trashed.
3614 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize)            \
3615       /* If the pushed data is bigger than the result,          \
3616        * simply discard unused bytes. Icky, but works.          \
3617        */                                                       \
3618       while (pushedSize > resultSize)                           \
3619       {                                                         \
3620           D (emitcode (";", "discarding unused result byte."););\
3621           emitcode ("pop", "acc");                              \
3622           pushedSize--;                                         \
3623       }                                                         \
3624       if (pushedSize < resultSize)                              \
3625       {                                                         \
3626           emitcode ("clr", "a");                                \
3627           /* Conversly, we haven't pushed enough here.          \
3628            * just zero-pad, and all is well.                    \
3629            */                                                   \
3630           while (pushedSize < resultSize)                       \
3631           {                                                     \
3632               emitcode("push", "acc");                          \
3633               pushedSize++;                                     \
3634           }                                                     \
3635       }                                                         \
3636       assert(pushedSize == resultSize);
3637
3638 /*-----------------------------------------------------------------*/
3639 /* genPlus - generates code for addition                           */
3640 /*-----------------------------------------------------------------*/
3641 static void
3642 genPlus (iCode * ic)
3643 {
3644   int size, offset = 0;
3645   bool pushResult = FALSE;
3646   int rSize;
3647
3648   D (emitcode (";", "genPlus "););
3649
3650   /* special cases :- */
3651   if ( IS_SYMOP(IC_LEFT(ic)) && OP_SYMBOL(IC_LEFT(ic))->ruonly &&
3652       isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
3653       aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
3654       size = floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
3655       if (size <= 9) {
3656           while (size--) emitcode ("inc","dptr");
3657       } else {
3658           emitcode ("mov","a,dpl");
3659           emitcode ("add","a,#!constbyte",size & 0xff);
3660           emitcode ("mov","dpl,a");
3661           emitcode ("mov","a,dph");
3662           emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
3663           emitcode ("mov","dph,a");
3664           emitcode ("mov","a,dpx");
3665           emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
3666           emitcode ("mov","dpx,a");
3667       }
3668       freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
3669       return ;
3670   }
3671   if ( IS_SYMOP(IC_LEFT(ic)) && 
3672        OP_SYMBOL(IC_LEFT(ic))->remat &&
3673        isOperandInFarSpace(IC_RIGHT(ic))) {
3674       operand *op = IC_RIGHT(ic);
3675       IC_RIGHT(ic) = IC_LEFT(ic);
3676       IC_LEFT(ic) = op;
3677   }
3678                 
3679   AOP_OP_3_NOFATAL (ic, pushResult);
3680   if (pushResult)
3681     {
3682       D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3683     }
3684
3685   if (!pushResult)
3686     {
3687       /* if literal, literal on the right or
3688          if left requires ACC or right is already
3689          in ACC */
3690       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3691        || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3692           || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3693         {
3694           operand *t = IC_RIGHT (ic);
3695           IC_RIGHT (ic) = IC_LEFT (ic);
3696           IC_LEFT (ic) = t;
3697           emitcode (";", "Swapped plus args.");
3698         }
3699
3700       /* if both left & right are in bit
3701          space */
3702       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3703           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3704         {
3705           genPlusBits (ic);
3706           goto release;
3707         }
3708
3709       /* if left in bit space & right literal */
3710       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3711           AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3712         {
3713           emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3714           /* if result in bit space */
3715           if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3716             {
3717               if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3718                 emitcode ("cpl", "c");
3719               outBitC (IC_RESULT (ic));
3720             }
3721           else
3722             {
3723               size = getDataSize (IC_RESULT (ic));
3724               _startLazyDPSEvaluation ();
3725               while (size--)
3726                 {
3727                   MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3728                   emitcode ("addc", "a,#0");
3729                   aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3730                 }
3731               _endLazyDPSEvaluation ();
3732             }
3733           goto release;
3734         }
3735
3736       /* if I can do an increment instead
3737          of add then GOOD for ME */
3738       if (genPlusIncr (ic) == TRUE)
3739         {
3740           emitcode (";", "did genPlusIncr");
3741           goto release;
3742         }
3743
3744     }
3745   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3746
3747   _startLazyDPSEvaluation ();
3748   while (size--)
3749     {
3750       if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
3751         {
3752           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3753           if (offset == 0)
3754             emitcode ("add", "a,%s",
3755                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3756           else
3757             emitcode ("addc", "a,%s",
3758                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3759         }
3760       else
3761         {
3762           if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
3763           {
3764               /* right is going to use ACC or we would have taken the
3765                * above branch.
3766                */
3767               assert(AOP_NEEDSACC(IC_RIGHT(ic)));
3768        TR_AP("#3");
3769               D(emitcode(";", "+ AOP_ACC special case."););
3770               emitcode("xch", "a, %s", DP2_RESULT_REG);
3771           }
3772           MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3773           if (offset == 0)
3774           {
3775             if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
3776             {
3777          TR_AP("#4");
3778                 emitcode("add", "a, %s", DP2_RESULT_REG); 
3779             }
3780             else
3781             {
3782                 emitcode ("add", "a,%s",
3783                         aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE, FALSE));
3784             }
3785           }
3786           else
3787           {
3788             emitcode ("addc", "a,%s",
3789                   aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3790           }
3791         }
3792       if (!pushResult)
3793         {
3794           aopPut (AOP (IC_RESULT (ic)), "a", offset);
3795         }
3796       else
3797         {
3798           emitcode ("push", "acc");
3799         }
3800       offset++;
3801     }
3802   _endLazyDPSEvaluation ();
3803
3804   if (pushResult)
3805     {
3806       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3807
3808       size = getDataSize (IC_LEFT (ic));
3809       rSize = getDataSize (IC_RESULT (ic));
3810
3811       ADJUST_PUSHED_RESULT(size, rSize);
3812
3813       _startLazyDPSEvaluation ();
3814       while (size--)
3815         {
3816           emitcode ("pop", "acc");
3817           aopPut (AOP (IC_RESULT (ic)), "a", size);
3818         }
3819       _endLazyDPSEvaluation ();
3820     }
3821
3822   adjustArithmeticResult (ic);
3823
3824 release:
3825   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3826   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3827   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3828 }
3829
3830 /*-----------------------------------------------------------------*/
3831 /* genMinusDec :- does subtraction with deccrement if possible     */
3832 /*-----------------------------------------------------------------*/
3833 static bool
3834 genMinusDec (iCode * ic)
3835 {
3836   unsigned int icount;
3837   unsigned int size = getDataSize (IC_RESULT (ic));
3838
3839   /* will try to generate an increment */
3840   /* if the right side is not a literal
3841      we cannot */
3842   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3843     return FALSE;
3844
3845   /* if the literal value of the right hand side
3846      is greater than 4 then it is not worth it */
3847   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3848     return FALSE;
3849
3850   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3851       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3852       while (icount--) {
3853           emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
3854       }
3855       return TRUE;
3856   }
3857   /* if decrement 16 bits in register */
3858   if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3859       AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3860       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3861       (size > 1) &&
3862       (icount == 1))
3863     {
3864       symbol *tlbl;
3865       int emitTlbl;
3866       int labelRange;
3867
3868       /* If the next instruction is a goto and the goto target
3869          * is <= 5 instructions previous to this, we can generate
3870          * jumps straight to that target.
3871        */
3872       if (ic->next && ic->next->op == GOTO
3873           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3874           && labelRange <= 5)
3875         {
3876           emitcode (";", "tail decrement optimized (range %d)", labelRange);
3877           tlbl = IC_LABEL (ic->next);
3878           emitTlbl = 0;
3879         }
3880       else
3881         {
3882           tlbl = newiTempLabel (NULL);
3883           emitTlbl = 1;
3884         }
3885
3886       emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3887       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3888           AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3889           IS_AOP_PREG (IC_RESULT (ic)))
3890         emitcode ("cjne", "%s,#!constbyte,!tlabel"
3891                   ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE), 0xff
3892                   ,tlbl->key + 100);
3893       else
3894         {
3895           emitcode ("mov", "a,#!constbyte",0xff);
3896           emitcode ("cjne", "a,%s,!tlabel"
3897                     ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3898                     ,tlbl->key + 100);
3899         }
3900       emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3901       if (size > 2)
3902         {
3903           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3904               AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3905               IS_AOP_PREG (IC_RESULT (ic)))
3906             emitcode ("cjne", "%s,#!constbyte,!tlabel"
3907                       ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE),0xff
3908                       ,tlbl->key + 100);
3909           else
3910             {
3911               emitcode ("cjne", "a,%s,!tlabel"
3912                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3913                         ,tlbl->key + 100);
3914             }
3915           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3916         }
3917       if (size > 3)
3918         {
3919           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3920               AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3921               IS_AOP_PREG (IC_RESULT (ic)))
3922             emitcode ("cjne", "%s,#!constbyte,!tlabel"
3923                       ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE),0xff
3924                       ,tlbl->key + 100);
3925           else
3926             {
3927               emitcode ("cjne", "a,%s,!tlabel"
3928                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3929                         ,tlbl->key + 100);
3930             }
3931           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3932         }
3933       if (emitTlbl)
3934         {
3935           emitcode ("", "!tlabeldef", tlbl->key + 100);
3936         }
3937       return TRUE;
3938     }
3939
3940   /* if the sizes are greater than 1 then we cannot */
3941   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3942       AOP_SIZE (IC_LEFT (ic)) > 1)
3943     return FALSE;
3944
3945   /* we can if the aops of the left & result match or
3946      if they are in registers and the registers are the
3947      same */
3948   if (
3949        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3950        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3951        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3952     {
3953
3954       _startLazyDPSEvaluation ();
3955       while (icount--)
3956         {
3957           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
3958         }
3959       _endLazyDPSEvaluation ();
3960
3961       return TRUE;
3962     }
3963
3964   return FALSE;
3965 }
3966
3967 /*-----------------------------------------------------------------*/
3968 /* addSign - complete with sign                                    */
3969 /*-----------------------------------------------------------------*/
3970 static void
3971 addSign (operand * result, int offset, int sign)
3972 {
3973   int size = (getDataSize (result) - offset);
3974   if (size > 0)
3975     {
3976       _startLazyDPSEvaluation();
3977       if (sign)
3978         {
3979           emitcode ("rlc", "a");
3980           emitcode ("subb", "a,acc");
3981           while (size--)
3982           {
3983             aopPut (AOP (result), "a", offset++);
3984           }
3985         }
3986       else
3987       {
3988         while (size--)
3989         {
3990           aopPut (AOP (result), zero, offset++);
3991         }
3992       }
3993       _endLazyDPSEvaluation();
3994     }
3995 }
3996
3997 /*-----------------------------------------------------------------*/
3998 /* genMinusBits - generates code for subtraction  of two bits      */
3999 /*-----------------------------------------------------------------*/
4000 static void
4001 genMinusBits (iCode * ic)
4002 {
4003   symbol *lbl = newiTempLabel (NULL);
4004
4005   D (emitcode (";", "genMinusBits "););
4006
4007   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4008     {
4009       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4010       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4011       emitcode ("cpl", "c");
4012       emitcode ("", "!tlabeldef", (lbl->key + 100));
4013       outBitC (IC_RESULT (ic));
4014     }
4015   else
4016     {
4017       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4018       emitcode ("subb", "a,acc");
4019       emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4020       emitcode ("inc", "a");
4021       emitcode ("", "!tlabeldef", (lbl->key + 100));
4022       aopPut (AOP (IC_RESULT (ic)), "a", 0);
4023       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4024     }
4025 }
4026
4027 /*-----------------------------------------------------------------*/
4028 /* genMinus - generates code for subtraction                       */
4029 /*-----------------------------------------------------------------*/
4030 static void
4031 genMinus (iCode * ic)
4032 {
4033   int size, offset = 0;
4034   int rSize;
4035   unsigned long lit = 0L;
4036   bool pushResult = FALSE;
4037
4038   D (emitcode (";", "genMinus "););
4039
4040   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
4041   aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
4042   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
4043       (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
4044     {
4045       pushResult = TRUE;
4046     }
4047   else
4048     {
4049       aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
4050
4051       /* special cases :- */
4052       /* if both left & right are in bit space */
4053       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4054           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4055         {
4056           genMinusBits (ic);
4057           goto release;
4058         }
4059
4060       /* if I can do an decrement instead
4061          of subtract then GOOD for ME */
4062       if (genMinusDec (ic) == TRUE)
4063         goto release;
4064
4065     }
4066
4067   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4068
4069   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4070     {
4071       CLRC;
4072     }
4073   else
4074     {
4075       lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4076       lit = -(long) lit;
4077     }
4078
4079
4080   /* if literal, add a,#-lit, else normal subb */
4081   _startLazyDPSEvaluation ();
4082   while (size--)
4083     {
4084       MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
4085       if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4086         emitcode ("subb", "a,%s",
4087                   aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
4088       else
4089         {
4090           /* first add without previous c */
4091           if (!offset) {
4092             if (!size && lit==-1) {
4093               emitcode ("dec", "a");
4094             } else {
4095               emitcode ("add", "a,#!constbyte",
4096                         (unsigned int) (lit & 0x0FFL));
4097             }
4098           } else {
4099             emitcode ("addc", "a,#!constbyte",
4100                       (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4101           }
4102         }
4103
4104       if (pushResult)
4105         {
4106           emitcode ("push", "acc");
4107         }
4108       else
4109         {
4110           aopPut (AOP (IC_RESULT (ic)), "a", offset);
4111         }
4112       offset++;
4113     }
4114   _endLazyDPSEvaluation ();
4115
4116   if (pushResult)
4117     {
4118       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4119
4120       size = getDataSize (IC_LEFT (ic));
4121       rSize = getDataSize (IC_RESULT (ic));
4122
4123       ADJUST_PUSHED_RESULT(size, rSize);
4124
4125       _startLazyDPSEvaluation ();
4126       while (size--)
4127         {
4128           emitcode ("pop", "acc");
4129           aopPut (AOP (IC_RESULT (ic)), "a", size);
4130         }
4131       _endLazyDPSEvaluation ();
4132     }
4133
4134   adjustArithmeticResult (ic);
4135
4136 release:
4137   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4138   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4139   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4140 }
4141
4142
4143 /*-----------------------------------------------------------------*/
4144 /* genMultbits :- multiplication of bits                           */
4145 /*-----------------------------------------------------------------*/
4146 static void
4147 genMultbits (operand * left,
4148              operand * right,
4149              operand * result,
4150              iCode   * ic)
4151 {
4152   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4153   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4154   aopOp(result, ic, TRUE, FALSE);
4155   outBitC (result);
4156 }
4157
4158
4159 /*-----------------------------------------------------------------*/
4160 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
4161 /*-----------------------------------------------------------------*/
4162 static void
4163 genMultOneByte (operand * left,
4164                 operand * right,
4165                 operand * result,
4166                 iCode   * ic)
4167 {
4168   sym_link *opetype = operandType (result);
4169   symbol *lbl;
4170
4171
4172   /* (if two literals: the value is computed before) */
4173   /* if one literal, literal on the right */
4174   if (AOP_TYPE (left) == AOP_LIT)
4175     {
4176       operand *t = right;
4177       right = left;
4178       left = t;
4179       emitcode (";", "swapped left and right");
4180     }
4181
4182   if (SPEC_USIGN(opetype)
4183       // ignore the sign of left and right, what else can we do?
4184       || (SPEC_USIGN(operandType(left)) && 
4185           SPEC_USIGN(operandType(right)))) {
4186     // just an unsigned 8*8=8/16 multiply
4187     //emitcode (";","unsigned");
4188     emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4189     MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4190     emitcode ("mul", "ab");
4191    
4192     _G.accInUse++; _G.bInUse++;
4193     aopOp(result, ic, TRUE, FALSE);
4194       
4195       if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4196       {
4197           // this should never happen
4198           fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4199                    AOP_SIZE(result), __FILE__, lineno);
4200           exit (1);
4201       }      
4202       
4203     aopPut (AOP (result), "a", 0);
4204     _G.accInUse--; _G.bInUse--;
4205     if (AOP_SIZE(result)==2) 
4206     {
4207       aopPut (AOP (result), "b", 1);
4208     }
4209     return;
4210   }
4211
4212   // we have to do a signed multiply
4213
4214   emitcode (";", "signed");
4215   emitcode ("clr", "F0"); // reset sign flag
4216   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4217
4218   lbl=newiTempLabel(NULL);
4219   emitcode ("jnb", "acc.7,!tlabel",  lbl->key+100);
4220   // left side is negative, 8-bit two's complement, this fails for -128
4221   emitcode ("setb", "F0"); // set sign flag
4222   emitcode ("cpl", "a");
4223   emitcode ("inc", "a");
4224
4225   emitcode ("", "!tlabeldef", lbl->key+100);
4226
4227   /* if literal */
4228   if (AOP_TYPE(right)==AOP_LIT) {
4229     signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
4230     /* AND literal negative */
4231     if ((int) val < 0) {
4232       emitcode ("cpl", "F0"); // complement sign flag
4233       emitcode ("mov", "b,#!constbyte", -val);
4234     } else {
4235       emitcode ("mov", "b,#!constbyte", val);
4236     }
4237   } else {
4238     lbl=newiTempLabel(NULL);
4239     emitcode ("mov", "b,a");
4240     emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4241     emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4242     // right side is negative, 8-bit two's complement
4243     emitcode ("cpl", "F0"); // complement sign flag
4244     emitcode ("cpl", "a");
4245     emitcode ("inc", "a");
4246     emitcode ("", "!tlabeldef", lbl->key+100);
4247   }
4248   emitcode ("mul", "ab");
4249     
4250   _G.accInUse++;_G.bInUse++;
4251   aopOp(result, ic, TRUE, FALSE);
4252     
4253   if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4254   {
4255     // this should never happen
4256       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4257                AOP_SIZE(result), __FILE__, lineno);
4258       exit (1);
4259   }    
4260     
4261   lbl=newiTempLabel(NULL);
4262   emitcode ("jnb", "F0,!tlabel", lbl->key+100);
4263   // only ONE op was negative, we have to do a 8/16-bit two's complement
4264   emitcode ("cpl", "a"); // lsb
4265   if (AOP_SIZE(result)==1) {
4266     emitcode ("inc", "a");
4267   } else {
4268     emitcode ("add", "a,#1");
4269     emitcode ("xch", "a,b");
4270     emitcode ("cpl", "a"); // msb
4271     emitcode ("addc", "a,#0");
4272     emitcode ("xch", "a,b");
4273   }
4274
4275   emitcode ("", "!tlabeldef", lbl->key+100);
4276   aopPut (AOP (result), "a", 0);
4277   _G.accInUse--;_G.bInUse--;
4278   if (AOP_SIZE(result)==2) {
4279     aopPut (AOP (result), "b", 1);
4280   }
4281 }
4282
4283 /*-----------------------------------------------------------------*/
4284 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply    */
4285 /*-----------------------------------------------------------------*/
4286 static void genMultTwoByte (operand *left, operand *right, 
4287                             operand *result, iCode *ic)
4288 {
4289         sym_link *retype = getSpec(operandType(right));
4290         sym_link *letype = getSpec(operandType(left));
4291         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4292         symbol *lbl;
4293
4294         if (AOP_TYPE (left) == AOP_LIT) {
4295                 operand *t = right;
4296                 right = left;
4297                 left = t;
4298         }
4299         /* save EA bit in F1 */
4300         lbl = newiTempLabel(NULL);
4301         emitcode ("setb","F1");
4302         emitcode ("jbc","EA,!tlabel",lbl->key+100);
4303         emitcode ("clr","F1");
4304         emitcode("","!tlabeldef",lbl->key+100);
4305
4306         /* load up MB with right */
4307         if (!umult) {
4308                 emitcode("clr","F0");
4309                 if (AOP_TYPE(right) == AOP_LIT) {
4310                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
4311                         if (val < 0) {
4312                                 emitcode("setb","F0");
4313                                 val = -val;
4314                         }
4315                         emitcode ("mov","mb,#!constbyte",val & 0xff);
4316                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
4317                 } else {
4318                         lbl = newiTempLabel(NULL);
4319                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4320                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4321                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
4322                         emitcode ("xch", "a,b");
4323                         emitcode ("cpl","a");
4324                         emitcode ("add", "a,#1");
4325                         emitcode ("xch", "a,b");
4326                         emitcode ("cpl", "a"); // msb
4327                         emitcode ("addc", "a,#0");
4328                         emitcode ("setb","F0");
4329                         emitcode ("","!tlabeldef",lbl->key+100);
4330                         emitcode ("mov","mb,b");
4331                         emitcode ("mov","mb,a");
4332                 }
4333         } else {
4334                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4335                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4336         }
4337         /* load up MA with left */
4338         if (!umult) {
4339                 lbl = newiTempLabel(NULL);
4340                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4341                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4342                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4343                 emitcode ("xch", "a,b");
4344                 emitcode ("cpl","a");
4345                 emitcode ("add", "a,#1");
4346                 emitcode ("xch", "a,b");
4347                 emitcode ("cpl", "a"); // msb
4348                 emitcode ("addc","a,#0");
4349                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4350                 emitcode ("setb","F0");
4351                 emitcode ("","!tlabeldef",lbl->key+100);
4352                 emitcode ("mov","ma,b");
4353                 emitcode ("mov","ma,a");
4354         } else {
4355                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4356                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4357         }
4358         /* wait for multiplication to finish */
4359         lbl = newiTempLabel(NULL);
4360         emitcode("","!tlabeldef", lbl->key+100);
4361         emitcode("mov","a,mcnt1");
4362         emitcode("anl","a,#!constbyte",0x80);
4363         emitcode("jnz","!tlabel",lbl->key+100);
4364         
4365         freeAsmop (left, NULL, ic, TRUE);
4366         freeAsmop (right, NULL, ic,TRUE);
4367         aopOp(result, ic, TRUE, FALSE);
4368
4369         /* if unsigned then simple */   
4370         if (umult) {
4371                 emitcode ("mov","a,ma");
4372                 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4373                 emitcode ("mov","a,ma");
4374                 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4375                 aopPut(AOP(result),"ma",1);
4376                 aopPut(AOP(result),"ma",0);
4377         } else {
4378                 emitcode("push","ma");
4379                 emitcode("push","ma");
4380                 emitcode("push","ma");
4381                 MOVA("ma");
4382                 /* negate result if needed */
4383                 lbl = newiTempLabel(NULL);      
4384                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4385                 emitcode("cpl","a");
4386                 emitcode("add","a,#1");
4387                 emitcode("","!tlabeldef", lbl->key+100);
4388                 if (AOP_TYPE(result) == AOP_ACC)
4389                 {
4390                     D(emitcode(";", "ACC special case."););
4391                     /* We know result is the only live aop, and 
4392                      * it's obviously not a DPTR2, so AP is available.
4393                      */
4394                     emitcode("mov", "%s,acc", DP2_RESULT_REG);
4395                 }
4396                 else
4397                 {
4398                     aopPut(AOP(result),"a",0);
4399                 }
4400             
4401                 emitcode("pop","acc");
4402                 lbl = newiTempLabel(NULL);      
4403                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4404                 emitcode("cpl","a");
4405                 emitcode("addc","a,#0");
4406                 emitcode("","!tlabeldef", lbl->key+100);
4407                 aopPut(AOP(result),"a",1);
4408                 emitcode("pop","acc");
4409                 if (AOP_SIZE(result) >= 3) {
4410                         lbl = newiTempLabel(NULL);      
4411                         emitcode("jnb","F0,!tlabel",lbl->key+100);
4412                         emitcode("cpl","a");
4413                         emitcode("addc","a,#0");                        
4414                         emitcode("","!tlabeldef", lbl->key+100);
4415                         aopPut(AOP(result),"a",2);
4416                 }
4417                 emitcode("pop","acc");
4418                 if (AOP_SIZE(result) >= 4) {
4419                         lbl = newiTempLabel(NULL);      
4420                         emitcode("jnb","F0,!tlabel",lbl->key+100);
4421                         emitcode("cpl","a");
4422                         emitcode("addc","a,#0");                        
4423                         emitcode("","!tlabeldef", lbl->key+100);
4424                         aopPut(AOP(result),"a",3);
4425                 }
4426                 if (AOP_TYPE(result) == AOP_ACC)
4427                 {
4428                     /* We stashed the result away above. */
4429                     emitcode("mov", "acc,%s", DP2_RESULT_REG);
4430                 }           
4431                 
4432         }
4433         freeAsmop (result, NULL, ic, TRUE);
4434
4435         /* restore EA bit in F1 */
4436         lbl = newiTempLabel(NULL);
4437         emitcode ("jnb","F1,!tlabel",lbl->key+100);
4438         emitcode ("setb","EA");
4439         emitcode("","!tlabeldef",lbl->key+100);
4440         return ;
4441 }
4442
4443 /*-----------------------------------------------------------------*/
4444 /* genMult - generates code for multiplication                     */
4445 /*-----------------------------------------------------------------*/
4446 static void
4447 genMult (iCode * ic)
4448 {
4449   operand *left = IC_LEFT (ic);
4450   operand *right = IC_RIGHT (ic);
4451   operand *result = IC_RESULT (ic);
4452
4453   D (emitcode (";", "genMult "););
4454
4455   /* assign the amsops */
4456   AOP_OP_2 (ic);
4457
4458   /* special cases first */
4459   /* both are bits */
4460   if (AOP_TYPE (left) == AOP_CRY &&
4461       AOP_TYPE (right) == AOP_CRY)
4462     {
4463       genMultbits (left, right, result, ic);
4464       goto release;
4465     }
4466
4467   /* if both are of size == 1 */
4468   if (AOP_SIZE (left) == 1 &&
4469       AOP_SIZE (right) == 1)
4470     {
4471       genMultOneByte (left, right, result, ic);
4472       goto release;
4473     }
4474
4475   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4476           /* use the ds390 ARITHMETIC accel UNIT */
4477           genMultTwoByte (left, right, result, ic);
4478           return ;
4479   }
4480   /* should have been converted to function call */
4481   assert (0);
4482
4483 release:
4484   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4485   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4486   freeAsmop (result, NULL, ic, TRUE);
4487 }
4488
4489 /*-----------------------------------------------------------------*/
4490 /* genDivbits :- division of bits                                  */
4491 /*-----------------------------------------------------------------*/
4492 static void
4493 genDivbits (operand * left,
4494             operand * right,
4495             operand * result,
4496             iCode   * ic)
4497 {
4498
4499   char *l;
4500
4501   /* the result must be bit */
4502   LOAD_AB_FOR_DIV (left, right, l);
4503   emitcode ("div", "ab");
4504   emitcode ("rrc", "a");
4505   aopOp(result, ic, TRUE, FALSE);
4506     
4507   aopPut (AOP (result), "c", 0);
4508 }
4509
4510 /*-----------------------------------------------------------------*/
4511 /* genDivOneByte : 8 bit division                                  */
4512 /*-----------------------------------------------------------------*/
4513 static void
4514 genDivOneByte (operand * left,
4515                operand * right,
4516                operand * result,
4517                iCode   * ic)
4518 {
4519   sym_link *opetype = operandType (result);
4520   char *l;
4521   symbol *lbl;
4522   int size, offset;
4523
4524   offset = 1;
4525   /* signed or unsigned */
4526   if (SPEC_USIGN (opetype))
4527     {
4528         /* unsigned is easy */
4529         LOAD_AB_FOR_DIV (left, right, l);
4530         emitcode ("div", "ab");
4531
4532         _G.accInUse++;
4533         aopOp(result, ic, TRUE, FALSE);
4534         aopPut (AOP (result), "a", 0);
4535         _G.accInUse--;
4536
4537         size = AOP_SIZE (result) - 1;
4538         
4539         while (size--)
4540         {
4541             aopPut (AOP (result), zero, offset++);
4542         }
4543       return;
4544     }
4545
4546   /* signed is a little bit more difficult */
4547
4548   /* save the signs of the operands */
4549   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4550   MOVA (l);
4551   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4552   emitcode ("push", "acc");     /* save it on the stack */
4553
4554   /* now sign adjust for both left & right */
4555   l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4556   MOVA (l);
4557   lbl = newiTempLabel (NULL);
4558   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4559   emitcode ("cpl", "a");
4560   emitcode ("inc", "a");
4561   emitcode ("", "!tlabeldef", (lbl->key + 100));
4562   emitcode ("mov", "b,a");
4563
4564   /* sign adjust left side */
4565   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4566   MOVA (l);
4567
4568   lbl = newiTempLabel (NULL);
4569   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4570   emitcode ("cpl", "a");
4571   emitcode ("inc", "a");
4572   emitcode ("", "!tlabeldef", (lbl->key + 100));
4573
4574   /* now the division */
4575   emitcode ("nop", "; workaround for DS80C390 div bug.");
4576   emitcode ("div", "ab");
4577   /* we are interested in the lower order
4578      only */
4579   emitcode ("mov", "b,a");
4580   lbl = newiTempLabel (NULL);
4581   emitcode ("pop", "acc");
4582   /* if there was an over flow we don't
4583      adjust the sign of the result */
4584   emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4585   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4586   CLRC;
4587   emitcode ("clr", "a");
4588   emitcode ("subb", "a,b");
4589   emitcode ("mov", "b,a");
4590   emitcode ("", "!tlabeldef", (lbl->key + 100));
4591
4592   /* now we are done */
4593   _G.accInUse++;     _G.bInUse++;
4594     aopOp(result, ic, TRUE, FALSE);
4595     
4596     aopPut (AOP (result), "b", 0);
4597     
4598     size = AOP_SIZE (result) - 1;
4599     
4600     if (size > 0)
4601     {
4602       emitcode ("mov", "c,b.7");
4603       emitcode ("subb", "a,acc");
4604     }
4605     while (size--)
4606     {
4607         aopPut (AOP (result), "a", offset++);
4608     }
4609     _G.accInUse--;     _G.bInUse--;
4610
4611 }
4612
4613 /*-----------------------------------------------------------------*/
4614 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide       */
4615 /*-----------------------------------------------------------------*/
4616 static void genDivTwoByte (operand *left, operand *right, 
4617                             operand *result, iCode *ic)
4618 {
4619         sym_link *retype = getSpec(operandType(right));
4620         sym_link *letype = getSpec(operandType(left));
4621         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4622         symbol *lbl;
4623
4624         /* save EA bit in F1 */
4625         lbl = newiTempLabel(NULL);
4626         emitcode ("setb","F1");
4627         emitcode ("jbc","EA,!tlabel",lbl->key+100);
4628         emitcode ("clr","F1");
4629         emitcode("","!tlabeldef",lbl->key+100);
4630
4631         /* load up MA with left */
4632         if (!umult) {
4633                 emitcode("clr","F0");
4634                 lbl = newiTempLabel(NULL);
4635                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4636                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4637                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4638                 emitcode ("xch", "a,b");
4639                 emitcode ("cpl","a");
4640                 emitcode ("add", "a,#1");
4641                 emitcode ("xch", "a,b");
4642                 emitcode ("cpl", "a"); // msb
4643                 emitcode ("addc","a,#0");
4644                 emitcode ("setb","F0");
4645                 emitcode ("","!tlabeldef",lbl->key+100);
4646                 emitcode ("mov","ma,b");
4647                 emitcode ("mov","ma,a");
4648         } else {
4649                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4650                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4651         }
4652
4653         /* load up MB with right */
4654         if (!umult) {
4655                 if (AOP_TYPE(right) == AOP_LIT) {
4656                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
4657                         if (val < 0) {
4658                                 lbl = newiTempLabel(NULL);
4659                                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4660                                 emitcode("setb","F0");
4661                                 emitcode ("","!tlabeldef",lbl->key+100);
4662                                 val = -val;
4663                         } 
4664                         emitcode ("mov","mb,#!constbyte",val & 0xff);               
4665                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4666                 } else {
4667                         lbl = newiTempLabel(NULL);
4668                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4669                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4670                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
4671                         emitcode ("xch", "a,b");
4672                         emitcode ("cpl","a");
4673                         emitcode ("add", "a,#1");
4674                         emitcode ("xch", "a,b");
4675                         emitcode ("cpl", "a"); // msb
4676                         emitcode ("addc", "a,#0");
4677                         emitcode ("jbc","F0,!tlabel",lbl->key+100);
4678                         emitcode ("setb","F0");
4679                         emitcode ("","!tlabeldef",lbl->key+100);
4680                         emitcode ("mov","mb,b");
4681                         emitcode ("mov","mb,a");
4682                 }
4683         } else {
4684                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4685                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4686         }
4687
4688         /* wait for multiplication to finish */
4689         lbl = newiTempLabel(NULL);
4690         emitcode("","!tlabeldef", lbl->key+100);
4691         emitcode("mov","a,mcnt1");
4692         emitcode("anl","a,#!constbyte",0x80);
4693         emitcode("jnz","!tlabel",lbl->key+100);
4694         
4695         freeAsmop (left, NULL, ic, TRUE);
4696         freeAsmop (right, NULL, ic,TRUE);
4697         aopOp(result, ic, TRUE, FALSE);
4698
4699         /* if unsigned then simple */   
4700         if (umult) {
4701                 aopPut(AOP(result),"ma",1);
4702                 aopPut(AOP(result),"ma",0);
4703         } else {
4704                 emitcode("push","ma");
4705                 MOVA("ma");
4706                 /* negate result if needed */
4707                 lbl = newiTempLabel(NULL);      
4708                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4709                 emitcode("cpl","a");
4710                 emitcode("add","a,#1");
4711                 emitcode("","!tlabeldef", lbl->key+100);
4712                 aopPut(AOP(result),"a",0);
4713                 emitcode("pop","acc");
4714                 lbl = newiTempLabel(NULL);      
4715                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4716                 emitcode("cpl","a");
4717                 emitcode("addc","a,#0");
4718                 emitcode("","!tlabeldef", lbl->key+100);
4719                 aopPut(AOP(result),"a",1);
4720         }
4721         freeAsmop (result, NULL, ic, TRUE);
4722         /* restore EA bit in F1 */
4723         lbl = newiTempLabel(NULL);
4724         emitcode ("jnb","F1,!tlabel",lbl->key+100);
4725         emitcode ("setb","EA");
4726         emitcode("","!tlabeldef",lbl->key+100);
4727         return ;
4728 }
4729
4730 /*-----------------------------------------------------------------*/
4731 /* genDiv - generates code for division                            */
4732 /*-----------------------------------------------------------------*/
4733 static void
4734 genDiv (iCode * ic)
4735 {
4736   operand *left = IC_LEFT (ic);
4737   operand *right = IC_RIGHT (ic);
4738   operand *result = IC_RESULT (ic);
4739
4740   D (emitcode (";", "genDiv "););
4741
4742   /* assign the amsops */
4743   AOP_OP_2 (ic);
4744
4745   /* special cases first */
4746   /* both are bits */
4747   if (AOP_TYPE (left) == AOP_CRY &&
4748       AOP_TYPE (right) == AOP_CRY)
4749     {
4750       genDivbits (left, right, result, ic);
4751       goto release;
4752     }
4753
4754   /* if both are of size == 1 */
4755   if (AOP_SIZE (left) == 1 &&
4756       AOP_SIZE (right) == 1)
4757     {
4758       genDivOneByte (left, right, result, ic);
4759       goto release;
4760     }
4761
4762   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4763           /* use the ds390 ARITHMETIC accel UNIT */
4764           genDivTwoByte (left, right, result, ic);
4765           return ;
4766   }
4767   /* should have been converted to function call */
4768   assert (0);
4769 release:
4770   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4771   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4772   freeAsmop (result, NULL, ic, TRUE);
4773 }
4774
4775 /*-----------------------------------------------------------------*/
4776 /* genModbits :- modulus of bits                                   */
4777 /*-----------------------------------------------------------------*/
4778 static void
4779 genModbits (operand * left,
4780             operand * right,
4781             operand * result,
4782             iCode   * ic)
4783 {
4784
4785   char *l;
4786
4787   /* the result must be bit */
4788   LOAD_AB_FOR_DIV (left, right, l);
4789   emitcode ("div", "ab");
4790   emitcode ("mov", "a,b");
4791   emitcode ("rrc", "a");
4792   aopOp(result, ic, TRUE, FALSE);
4793   aopPut (AOP (result), "c", 0);
4794 }
4795
4796 /*-----------------------------------------------------------------*/
4797 /* genModOneByte : 8 bit modulus                                   */
4798 /*-----------------------------------------------------------------*/
4799 static void
4800 genModOneByte (operand * left,
4801                operand * right,
4802                operand * result,
4803                iCode   * ic)
4804 {
4805   sym_link *opetype = operandType (result);
4806   char *l;
4807   symbol *lbl;
4808
4809   /* signed or unsigned */
4810   if (SPEC_USIGN (opetype))
4811     {
4812       /* unsigned is easy */
4813       LOAD_AB_FOR_DIV (left, right, l);
4814       emitcode ("div", "ab");
4815       aopOp(result, ic, TRUE, FALSE);   
4816       aopPut (AOP (result), "b", 0);
4817       return;
4818     }
4819
4820   /* signed is a little bit more difficult */
4821
4822   /* save the signs of the operands */
4823   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4824   MOVA (l);
4825
4826   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4827   emitcode ("push", "acc");     /* save it on the stack */
4828
4829   /* now sign adjust for both left & right */
4830   l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4831   MOVA (l);
4832
4833   lbl = newiTempLabel (NULL);
4834   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4835   emitcode ("cpl", "a");
4836   emitcode ("inc", "a");
4837   emitcode ("", "!tlabeldef", (lbl->key + 100));
4838   emitcode ("mov", "b,a");
4839
4840   /* sign adjust left side */
4841   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4842   MOVA (l);
4843
4844   lbl = newiTempLabel (NULL);
4845   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4846   emitcode ("cpl", "a");
4847   emitcode ("inc", "a");
4848   emitcode ("", "!tlabeldef", (lbl->key + 100));
4849
4850   /* now the multiplication */
4851   emitcode ("nop", "; workaround for DS80C390 div bug.");
4852   emitcode ("div", "ab");
4853   /* we are interested in the lower order
4854      only */
4855   lbl = newiTempLabel (NULL);
4856   emitcode ("pop", "acc");
4857   /* if there was an over flow we don't
4858      adjust the sign of the result */
4859   emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4860   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4861   CLRC;
4862   emitcode ("clr", "a");
4863   emitcode ("subb", "a,b");
4864   emitcode ("mov", "b,a");
4865   emitcode ("", "!tlabeldef", (lbl->key + 100));
4866   
4867   _G.bInUse++;
4868   /* now we are done */
4869   aopOp(result, ic, TRUE, FALSE);    
4870   aopPut (AOP (result), "b", 0);
4871   _G.bInUse--;
4872
4873 }
4874
4875 /*-----------------------------------------------------------------*/
4876 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus      */
4877 /*-----------------------------------------------------------------*/
4878 static void genModTwoByte (operand *left, operand *right, 
4879                             operand *result, iCode *ic)
4880 {
4881         sym_link *retype = getSpec(operandType(right));
4882         sym_link *letype = getSpec(operandType(left));
4883         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4884         symbol *lbl;
4885
4886         /* load up MA with left */
4887         /* save EA bit in F1 */
4888         lbl = newiTempLabel(NULL);
4889         emitcode ("setb","F1");
4890         emitcode ("jbc","EA,!tlabel",lbl->key+100);
4891         emitcode ("clr","F1");
4892         emitcode("","!tlabeldef",lbl->key+100);
4893
4894         if (!umult) {
4895                 lbl = newiTempLabel(NULL);
4896                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4897                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4898                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4899                 emitcode ("xch", "a,b");
4900                 emitcode ("cpl","a");
4901                 emitcode ("add", "a,#1");
4902                 emitcode ("xch", "a,b");
4903                 emitcode ("cpl", "a"); // msb
4904                 emitcode ("addc","a,#0");
4905                 emitcode ("","!tlabeldef",lbl->key+100);
4906                 emitcode ("mov","ma,b");
4907                 emitcode ("mov","ma,a");
4908         } else {
4909                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4910                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4911         }
4912
4913         /* load up MB with right */
4914         if (!umult) {
4915                 if (AOP_TYPE(right) == AOP_LIT) {
4916                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
4917                         if (val < 0) {
4918                                 val = -val;
4919                         } 
4920                         emitcode ("mov","mb,#!constbyte",val & 0xff);
4921                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
4922                 } else {
4923                         lbl = newiTempLabel(NULL);
4924                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4925                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4926                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
4927                         emitcode ("xch", "a,b");
4928                         emitcode ("cpl","a");
4929                         emitcode ("add", "a,#1");
4930                         emitcode ("xch", "a,b");
4931                         emitcode ("cpl", "a"); // msb
4932                         emitcode ("addc", "a,#0");
4933                         emitcode ("","!tlabeldef",lbl->key+100);
4934                         emitcode ("mov","mb,b");
4935                         emitcode ("mov","mb,a");
4936                 }
4937         } else {
4938                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4939                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4940         }
4941
4942         /* wait for multiplication to finish */
4943         lbl = newiTempLabel(NULL);
4944         emitcode("","!tlabeldef", lbl->key+100);
4945         emitcode("mov","a,mcnt1");
4946         emitcode("anl","a,#!constbyte",0x80);
4947         emitcode("jnz","!tlabel",lbl->key+100);
4948         
4949         freeAsmop (left, NULL, ic, TRUE);
4950         freeAsmop (right, NULL, ic,TRUE);
4951         aopOp(result, ic, TRUE, FALSE);
4952
4953         aopPut(AOP(result),"mb",1);
4954         aopPut(AOP(result),"mb",0);
4955         freeAsmop (result, NULL, ic, TRUE);
4956
4957         /* restore EA bit in F1 */
4958         lbl = newiTempLabel(NULL);
4959         emitcode ("jnb","F1,!tlabel",lbl->key+100);
4960         emitcode ("setb","EA");
4961         emitcode("","!tlabeldef",lbl->key+100);
4962         return ;
4963 }
4964
4965 /*-----------------------------------------------------------------*/
4966 /* genMod - generates code for division                            */
4967 /*-----------------------------------------------------------------*/
4968 static void
4969 genMod (iCode * ic)
4970 {
4971   operand *left = IC_LEFT (ic);
4972   operand *right = IC_RIGHT (ic);
4973   operand *result = IC_RESULT (ic);
4974
4975   D (emitcode (";", "genMod "); );
4976
4977   /* assign the amsops */
4978   AOP_OP_2 (ic);
4979
4980   /* special cases first */
4981   /* both are bits */
4982   if (AOP_TYPE (left) == AOP_CRY &&
4983       AOP_TYPE (right) == AOP_CRY)
4984     {
4985       genModbits (left, right, result, ic);
4986       goto release;
4987     }
4988
4989   /* if both are of size == 1 */
4990   if (AOP_SIZE (left) == 1 &&
4991       AOP_SIZE (right) == 1)
4992     {
4993       genModOneByte (left, right, result, ic);
4994       goto release;
4995     }
4996
4997   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4998           /* use the ds390 ARITHMETIC accel UNIT */
4999           genModTwoByte (left, right, result, ic);
5000           return ;
5001   }
5002
5003   /* should have been converted to function call */
5004   assert (0);
5005
5006 release:
5007   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5008   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5009   freeAsmop (result, NULL, ic, TRUE);
5010 }
5011
5012 /*-----------------------------------------------------------------*/
5013 /* genIfxJump :- will create a jump depending on the ifx           */
5014 /*-----------------------------------------------------------------*/
5015 static void
5016 genIfxJump (iCode * ic, char *jval)
5017 {
5018   symbol *jlbl;
5019   symbol *tlbl = newiTempLabel (NULL);
5020   char *inst;
5021
5022   D (emitcode (";", "genIfxJump ");
5023     );
5024
5025   /* if true label then we jump if condition
5026      supplied is true */
5027   if (IC_TRUE (ic))
5028     {
5029       jlbl = IC_TRUE (ic);
5030       inst = ((strcmp (jval, "a") == 0 ? "jz" :
5031                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5032     }
5033   else
5034     {
5035       /* false label is present */
5036       jlbl = IC_FALSE (ic);
5037       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5038                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5039     }
5040   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5041     emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5042   else
5043     emitcode (inst, "!tlabel", tlbl->key + 100);
5044   emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5045   emitcode ("", "!tlabeldef", tlbl->key + 100);
5046
5047   /* mark the icode as generated */
5048   ic->generated = 1;
5049 }
5050
5051 /*-----------------------------------------------------------------*/
5052 /* genCmp :- greater or less than comparison                       */
5053 /*-----------------------------------------------------------------*/
5054 static void
5055 genCmp (operand * left, operand * right,
5056         iCode * ic, iCode * ifx, int sign)
5057 {
5058   int size, offset = 0;
5059   unsigned long lit = 0L;
5060   operand *result;
5061
5062   D (emitcode (";", "genCmp");
5063     );
5064
5065   result = IC_RESULT (ic);
5066
5067   /* if left & right are bit variables */
5068   if (AOP_TYPE (left) == AOP_CRY &&
5069       AOP_TYPE (right) == AOP_CRY)
5070     {
5071       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5072       emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
5073     }
5074   else
5075     {
5076       /* subtract right from left if at the
5077          end the carry flag is set then we know that
5078          left is greater than right */
5079       size = max (AOP_SIZE (left), AOP_SIZE (right));
5080
5081       /* if unsigned char cmp with lit, do cjne left,#right,zz */
5082       if ((size == 1) && !sign &&
5083           (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5084         {
5085           symbol *lbl = newiTempLabel (NULL);
5086           emitcode ("cjne", "%s,%s,!tlabel",
5087                     aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5088                     aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
5089                     lbl->key + 100);
5090           emitcode ("", "!tlabeldef", lbl->key + 100);
5091         }
5092       else
5093         {
5094           if (AOP_TYPE (right) == AOP_LIT)
5095             {
5096               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5097               /* optimize if(x < 0) or if(x >= 0) */
5098               if (lit == 0L)
5099                 {
5100                   if (!sign)
5101                     {
5102                       CLRC;
5103                     }
5104                   else
5105                     {
5106                       MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
5107
5108                       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5109                       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5110
5111                       aopOp (result, ic, FALSE, FALSE);
5112
5113                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5114                         {
5115                           freeAsmop (result, NULL, ic, TRUE);
5116                           genIfxJump (ifx, "acc.7");
5117                           return;
5118                         }
5119                       else
5120                         {
5121                           emitcode ("rlc", "a");
5122                         }
5123                       goto release_freedLR;
5124                     }
5125                   goto release;
5126                 }
5127             }
5128           CLRC;
5129           while (size--)
5130             {
5131               //emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5132               MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5133               //emitcode (";", "genCmp #2");
5134               if (sign && (size == 0))
5135                 {
5136                     //emitcode (";", "genCmp #3");
5137                   emitcode ("xrl", "a,#!constbyte",0x80);
5138                   if (AOP_TYPE (right) == AOP_LIT)
5139                     {
5140                       unsigned long lit = (unsigned long)
5141                       floatFromVal (AOP (right)->aopu.aop_lit);
5142                       //emitcode (";", "genCmp #3.1");
5143                       emitcode ("subb", "a,#!constbyte",
5144                                 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5145                     }
5146                   else
5147                     {
5148                       //emitcode (";", "genCmp #3.2");
5149                       if (AOP_NEEDSACC (right))
5150                         {
5151                           emitcode ("push", "acc");
5152                         }
5153                       emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
5154                                                        FALSE, FALSE, FALSE));
5155                       emitcode ("xrl", "b,#!constbyte",0x80);
5156                       if (AOP_NEEDSACC (right))
5157                         {
5158                           emitcode ("pop", "acc");
5159                         }
5160                       emitcode ("subb", "a,b");
5161                     }
5162                 }
5163               else
5164                 {
5165                   const char *s;
5166
5167                   //emitcode (";", "genCmp #4");
5168                   if (AOP_NEEDSACC (right))
5169                     {
5170                       /* Yuck!! */
5171                       //emitcode (";", "genCmp #4.1");
5172                       emitcode ("xch", "a, b");
5173                       MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
5174                       emitcode ("xch", "a, b");
5175                       s = "b";
5176                     }
5177                   else
5178                     {
5179                       //emitcode (";", "genCmp #4.2");
5180                       s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
5181                     }
5182
5183                   emitcode ("subb", "a,%s", s);
5184                 }
5185             }
5186         }
5187     }
5188
5189 release:
5190 /* Don't need the left & right operands any more; do need the result. */
5191   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5192   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5193
5194   aopOp (result, ic, FALSE, FALSE);
5195
5196 release_freedLR:
5197
5198   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5199     {
5200       outBitC (result);
5201     }
5202   else
5203     {
5204       /* if the result is used in the next
5205          ifx conditional branch then generate
5206          code a little differently */
5207       if (ifx)
5208         {
5209           genIfxJump (ifx, "c");
5210         }
5211       else
5212         {
5213           outBitC (result);
5214         }
5215       /* leave the result in acc */
5216     }
5217   freeAsmop (result, NULL, ic, TRUE);
5218 }
5219
5220 /*-----------------------------------------------------------------*/
5221 /* genCmpGt :- greater than comparison                             */
5222 /*-----------------------------------------------------------------*/
5223 static void
5224 genCmpGt (iCode * ic, iCode * ifx)
5225 {
5226   operand *left, *right;
5227   sym_link *letype, *retype;
5228   int sign;
5229
5230   D (emitcode (";", "genCmpGt ");
5231     );
5232
5233   left = IC_LEFT (ic);
5234   right = IC_RIGHT (ic);
5235
5236   letype = getSpec (operandType (left));
5237   retype = getSpec (operandType (right));
5238   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5239
5240   /* assign the left & right amsops */
5241   AOP_OP_2 (ic);
5242
5243   genCmp (right, left, ic, ifx, sign);
5244 }
5245
5246 /*-----------------------------------------------------------------*/
5247 /* genCmpLt - less than comparisons                                */
5248 /*-----------------------------------------------------------------*/
5249 static void
5250 genCmpLt (iCode * ic, iCode * ifx)
5251 {
5252   operand *left, *right;
5253   sym_link *letype, *retype;
5254   int sign;
5255
5256   D (emitcode (";", "genCmpLt "););
5257
5258   left = IC_LEFT (ic);
5259   right = IC_RIGHT (ic);
5260
5261   letype = getSpec (operandType (left));
5262   retype = getSpec (operandType (right));
5263   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5264
5265   /* assign the left & right amsops */
5266   AOP_OP_2 (ic);
5267
5268   genCmp (left, right, ic, ifx, sign);
5269 }
5270
5271 /*-----------------------------------------------------------------*/
5272 /* gencjneshort - compare and jump if not equal                    */
5273 /*-----------------------------------------------------------------*/
5274 static void
5275 gencjneshort (operand * left, operand * right, symbol * lbl)
5276 {
5277   int size = max (AOP_SIZE (left), AOP_SIZE (right));
5278   int offset = 0;
5279   unsigned long lit = 0L;
5280
5281   D (emitcode (";", "gencjneshort");
5282     );
5283
5284   /* if the left side is a literal or
5285      if the right is in a pointer register and left
5286      is not */
5287   if ((AOP_TYPE (left) == AOP_LIT) ||
5288       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5289     {
5290       operand *t = right;
5291       right = left;
5292       left = t;
5293     }
5294
5295   if (AOP_TYPE (right) == AOP_LIT)
5296     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5297
5298   if (opIsGptr (left) || opIsGptr (right))
5299     {
5300       /* We are comparing a generic pointer to something.
5301        * Exclude the generic type byte from the comparison.
5302        */
5303       size--;
5304       D (emitcode (";", "cjneshort: generic ptr special case.");
5305         )
5306     }
5307
5308
5309   /* if the right side is a literal then anything goes */
5310   if (AOP_TYPE (right) == AOP_LIT &&
5311       AOP_TYPE (left) != AOP_DIR)
5312     {
5313       while (size--)
5314         {
5315           char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5316           MOVA (l);
5317           emitcode ("cjne", "a,%s,!tlabel",
5318                     aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
5319                     lbl->key + 100);
5320           offset++;
5321         }
5322     }
5323
5324   /* if the right side is in a register or in direct space or
5325      if the left is a pointer register & right is not */
5326   else if (AOP_TYPE (right) == AOP_REG ||
5327            AOP_TYPE (right) == AOP_DIR ||
5328            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5329            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5330     {
5331       while (size--)
5332         {
5333           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5334           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5335               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5336             emitcode ("jnz", "!tlabel", lbl->key + 100);
5337           else
5338             emitcode ("cjne", "a,%s,!tlabel",
5339                       aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
5340                       lbl->key + 100);
5341           offset++;
5342         }
5343     }
5344   else
5345     {
5346       /* right is a pointer reg need both a & b */
5347       while (size--)
5348         {
5349           char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5350           if (strcmp (l, "b"))
5351             emitcode ("mov", "b,%s", l);
5352           MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5353           emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
5354           offset++;
5355         }
5356     }
5357 }
5358
5359 /*-----------------------------------------------------------------*/
5360 /* gencjne - compare and jump if not equal                         */
5361 /*-----------------------------------------------------------------*/
5362 static void
5363 gencjne (operand * left, operand * right, symbol * lbl)
5364 {
5365   symbol *tlbl = newiTempLabel (NULL);
5366
5367   D (emitcode (";", "gencjne");
5368     );
5369
5370   gencjneshort (left, right, lbl);
5371
5372   emitcode ("mov", "a,%s", one);
5373   emitcode ("sjmp", "!tlabel", tlbl->key + 100);
5374   emitcode ("", "!tlabeldef", lbl->key + 100);
5375   emitcode ("clr", "a");
5376   emitcode ("", "!tlabeldef", tlbl->key + 100);
5377 }
5378
5379 /*-----------------------------------------------------------------*/
5380 /* genCmpEq - generates code for equal to                          */
5381 /*-----------------------------------------------------------------*/
5382 static void
5383 genCmpEq (iCode * ic, iCode * ifx)
5384 {
5385   operand *left, *right, *result;
5386
5387   D (emitcode (";", "genCmpEq ");
5388     );
5389
5390   AOP_OP_2 (ic);
5391   AOP_SET_LOCALS (ic);
5392
5393   /* if literal, literal on the right or
5394      if the right is in a pointer register and left
5395      is not */
5396   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5397       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5398     {
5399       operand *t = IC_RIGHT (ic);
5400       IC_RIGHT (ic) = IC_LEFT (ic);
5401       IC_LEFT (ic) = t;
5402     }
5403
5404   if (ifx &&                    /* !AOP_SIZE(result) */
5405       OP_SYMBOL (result) &&
5406       OP_SYMBOL (result)->regType == REG_CND)
5407     {
5408       symbol *tlbl;
5409       /* if they are both bit variables */
5410       if (AOP_TYPE (left) == AOP_CRY &&
5411           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5412         {
5413           if (AOP_TYPE (right) == AOP_LIT)
5414             {
5415               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5416               if (lit == 0L)
5417                 {
5418                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5419                   emitcode ("cpl", "c");
5420                 }
5421               else if (lit == 1L)
5422                 {
5423                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5424                 }
5425               else
5426                 {
5427                   emitcode ("clr", "c");
5428                 }
5429               /* AOP_TYPE(right) == AOP_CRY */
5430             }
5431           else
5432             {
5433               symbol *lbl = newiTempLabel (NULL);
5434               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5435               emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5436               emitcode ("cpl", "c");
5437               emitcode ("", "!tlabeldef", (lbl->key + 100));
5438             }
5439           /* if true label then we jump if condition
5440              supplied is true */
5441           tlbl = newiTempLabel (NULL);
5442           if (IC_TRUE (ifx))
5443             {
5444               emitcode ("jnc", "!tlabel", tlbl->key + 100);
5445               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5446             }
5447           else
5448             {
5449               emitcode ("jc", "!tlabel", tlbl->key + 100);
5450               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5451             }
5452           emitcode ("", "!tlabeldef", tlbl->key + 100);
5453         }
5454       else
5455         {
5456           tlbl = newiTempLabel (NULL);
5457           gencjneshort (left, right, tlbl);
5458           if (IC_TRUE (ifx))
5459             {
5460               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5461               emitcode ("", "!tlabeldef", tlbl->key + 100);
5462             }
5463           else
5464             {
5465               symbol *lbl = newiTempLabel (NULL);
5466               emitcode ("sjmp", "!tlabel", lbl->key + 100);
5467               emitcode ("", "!tlabeldef", tlbl->key + 100);
5468               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5469               emitcode ("", "!tlabeldef", lbl->key + 100);
5470             }
5471         }
5472       /* mark the icode as generated */
5473       ifx->generated = 1;
5474
5475       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5476       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5477       return;
5478     }
5479
5480   /* if they are both bit variables */
5481   if (AOP_TYPE (left) == AOP_CRY &&
5482       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5483     {
5484       if (AOP_TYPE (right) == AOP_LIT)
5485         {
5486           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5487           if (lit == 0L)
5488             {
5489               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5490               emitcode ("cpl", "c");
5491             }
5492           else if (lit == 1L)
5493             {
5494               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5495             }
5496           else
5497             {
5498               emitcode ("clr", "c");
5499             }
5500           /* AOP_TYPE(right) == AOP_CRY */
5501         }
5502       else
5503         {
5504           symbol *lbl = newiTempLabel (NULL);
5505           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5506           emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5507           emitcode ("cpl", "c");
5508           emitcode ("", "!tlabeldef", (lbl->key + 100));
5509         }
5510
5511       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5512       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5513
5514       aopOp (result, ic, TRUE, FALSE);
5515
5516       /* c = 1 if egal */
5517       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5518         {
5519           outBitC (result);
5520           goto release;
5521         }
5522       if (ifx)
5523         {
5524           genIfxJump (ifx, "c");
5525           goto release;
5526         }
5527       /* if the result is used in an arithmetic operation
5528          then put the result in place */
5529       outBitC (result);
5530     }
5531   else
5532     {
5533       gencjne (left, right, newiTempLabel (NULL));
5534
5535       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5536       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5537
5538       aopOp (result, ic, TRUE, FALSE);
5539
5540       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5541         {
5542           aopPut (AOP (result), "a", 0);
5543           goto release;
5544         }
5545       if (ifx)
5546         {
5547           genIfxJump (ifx, "a");
5548           goto release;
5549         }
5550       /* if the result is used in an arithmetic operation
5551          then put the result in place */
5552       if (AOP_TYPE (result) != AOP_CRY)
5553         outAcc (result);
5554       /* leave the result in acc */
5555     }
5556
5557 release:
5558   freeAsmop (result, NULL, ic, TRUE);
5559 }
5560
5561 /*-----------------------------------------------------------------*/
5562 /* ifxForOp - returns the icode containing the ifx for operand     */
5563 /*-----------------------------------------------------------------*/
5564 static iCode *
5565 ifxForOp (operand * op, iCode * ic)
5566 {
5567   /* if true symbol then needs to be assigned */
5568   if (IS_TRUE_SYMOP (op))
5569     return NULL;
5570
5571   /* if this has register type condition and
5572      the next instruction is ifx with the same operand
5573      and live to of the operand is upto the ifx only then */
5574   if (ic->next &&
5575       ic->next->op == IFX &&
5576       IC_COND (ic->next)->key == op->key &&
5577       OP_SYMBOL (op)->liveTo <= ic->next->seq)
5578     return ic->next;
5579
5580   return NULL;
5581 }
5582 /*-----------------------------------------------------------------*/
5583 /* hasInc - operand is incremented before any other use            */
5584 /*-----------------------------------------------------------------*/
5585 static iCode *
5586 hasInc (operand *op, iCode *ic, int osize)
5587 {
5588   sym_link *type = operandType(op);
5589   sym_link *retype = getSpec (type);
5590   iCode *lic = ic->next;
5591   int isize ;
5592   
5593   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5594   if (!IS_SYMOP(op)) return NULL;
5595
5596   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5597   if (osize != (isize = getSize(type->next))) return NULL;
5598   while (lic) {
5599       /* if operand of the form op = op + <sizeof *op> */
5600       if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5601           isOperandEqual(IC_RESULT(lic),op) && 
5602           isOperandLiteral(IC_RIGHT(lic)) &&
5603           operandLitValue(IC_RIGHT(lic)) == isize) {
5604           return lic;
5605       }
5606       /* if the operand used or deffed */
5607       if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5608           return NULL;
5609       }
5610       /* if GOTO or IFX */
5611       if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5612       lic = lic->next;
5613   }
5614   return NULL;
5615 }
5616
5617 /*-----------------------------------------------------------------*/
5618 /* genAndOp - for && operation                                     */
5619 /*-----------------------------------------------------------------*/
5620 static void
5621 genAndOp (iCode * ic)
5622 {
5623   operand *left, *right, *result;
5624   symbol *tlbl;
5625
5626   D (emitcode (";", "genAndOp "););
5627
5628   /* note here that && operations that are in an
5629      if statement are taken away by backPatchLabels
5630      only those used in arthmetic operations remain */
5631   AOP_OP_2 (ic);
5632   AOP_SET_LOCALS (ic);
5633
5634   /* if both are bit variables */
5635   if (AOP_TYPE (left) == AOP_CRY &&
5636       AOP_TYPE (right) == AOP_CRY)
5637     {
5638       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5639       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5640       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5641       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5642   
5643       aopOp (result,ic,FALSE, FALSE);
5644       outBitC (result);
5645     }
5646   else
5647     {
5648       tlbl = newiTempLabel (NULL);
5649       toBoolean (left);
5650       emitcode ("jz", "!tlabel", tlbl->key + 100);
5651       toBoolean (right);
5652       emitcode ("", "!tlabeldef", tlbl->key + 100);
5653       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5654       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5655   
5656       aopOp (result,ic,FALSE, FALSE);
5657       outBitAcc (result);
5658     }
5659     freeAsmop (result, NULL, ic, TRUE);
5660 }
5661
5662
5663 /*-----------------------------------------------------------------*/
5664 /* genOrOp - for || operation                                      */
5665 /*-----------------------------------------------------------------*/
5666 static void
5667 genOrOp (iCode * ic)
5668 {
5669   operand *left, *right, *result;
5670   symbol *tlbl;
5671
5672   D (emitcode (";", "genOrOp "););
5673
5674   /* note here that || operations that are in an
5675      if statement are taken away by backPatchLabels
5676      only those used in arthmetic operations remain */
5677   AOP_OP_2 (ic);
5678   AOP_SET_LOCALS (ic);
5679
5680   /* if both are bit variables */
5681   if (AOP_TYPE (left) == AOP_CRY &&
5682       AOP_TYPE (right) == AOP_CRY)
5683     {
5684       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5685       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5686       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5687       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5688   
5689       aopOp (result,ic,FALSE, FALSE);
5690       
5691       outBitC (result);
5692     }
5693   else
5694     {
5695       tlbl = newiTempLabel (NULL);
5696       toBoolean (left);
5697       emitcode ("jnz", "!tlabel", tlbl->key + 100);
5698       toBoolean (right);
5699       emitcode ("", "!tlabeldef", tlbl->key + 100);
5700       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5701       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5702   
5703       aopOp (result,ic,FALSE, FALSE);
5704       
5705       outBitAcc (result);
5706     }
5707
5708   freeAsmop (result, NULL, ic, TRUE);
5709 }
5710
5711 /*-----------------------------------------------------------------*/
5712 /* isLiteralBit - test if lit == 2^n                               */
5713 /*-----------------------------------------------------------------*/
5714 static int
5715 isLiteralBit (unsigned long lit)
5716 {
5717   unsigned long pw[32] =
5718   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5719    0x100L, 0x200L, 0x400L, 0x800L,
5720    0x1000L, 0x2000L, 0x4000L, 0x8000L,
5721    0x10000L, 0x20000L, 0x40000L, 0x80000L,
5722    0x100000L, 0x200000L, 0x400000L, 0x800000L,
5723    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5724    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5725   int idx;
5726
5727   for (idx = 0; idx < 32; idx++)
5728     if (lit == pw[idx])
5729       return idx + 1;
5730   return 0;
5731 }
5732
5733 /*-----------------------------------------------------------------*/
5734 /* continueIfTrue -                                                */
5735 /*-----------------------------------------------------------------*/
5736 static void
5737 continueIfTrue (iCode * ic)
5738 {
5739   if (IC_TRUE (ic))
5740     emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
5741   ic->generated = 1;
5742 }
5743
5744 /*-----------------------------------------------------------------*/
5745 /* jmpIfTrue -                                                     */
5746 /*-----------------------------------------------------------------*/
5747 static void
5748 jumpIfTrue (iCode * ic)
5749 {
5750   if (!IC_TRUE (ic))
5751     emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
5752   ic->generated = 1;
5753 }
5754
5755 /*-----------------------------------------------------------------*/
5756 /* jmpTrueOrFalse -                                                */
5757 /*-----------------------------------------------------------------*/
5758 static void
5759 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
5760 {
5761   // ugly but optimized by peephole
5762   if (IC_TRUE (ic))
5763     {
5764       symbol *nlbl = newiTempLabel (NULL);
5765       emitcode ("sjmp", "!tlabel", nlbl->key + 100);
5766       emitcode ("", "!tlabeldef", tlbl->key + 100);
5767       emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
5768       emitcode ("", "!tlabeldef", nlbl->key + 100);
5769     }
5770   else
5771     {
5772       emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
5773       emitcode ("", "!tlabeldef", tlbl->key + 100);
5774     }
5775   ic->generated = 1;
5776 }
5777
5778 // Generate code to perform a bit-wise logic operation
5779 // on two operands in far space (assumed to already have been 
5780 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
5781 // in far space. This requires pushing the result on the stack
5782 // then popping it into the result.
5783 static void
5784 genFarFarLogicOp(iCode *ic, char *logicOp)
5785 {
5786       int size, resultSize, compSize;
5787       int offset = 0;
5788       
5789       TR_AP("#5");
5790       D(emitcode(";", "%s special case for 3 far operands.", logicOp););
5791       compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ? 
5792                   AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
5793       
5794       _startLazyDPSEvaluation();
5795       for (size = compSize; (size--); offset++)
5796       {
5797           MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
5798           emitcode ("mov", "%s, acc", DP2_RESULT_REG);
5799           MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
5800           
5801           emitcode (logicOp, "a,%s", DP2_RESULT_REG);
5802           emitcode ("push", "acc");
5803       }
5804       _endLazyDPSEvaluation();
5805      
5806       freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5807       freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5808       aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
5809      
5810       resultSize = AOP_SIZE(IC_RESULT(ic));
5811
5812       ADJUST_PUSHED_RESULT(compSize, resultSize);
5813
5814       _startLazyDPSEvaluation();
5815       while (compSize--)
5816       {
5817           emitcode ("pop", "acc");
5818           aopPut (AOP (IC_RESULT (ic)), "a", compSize);
5819       }
5820       _endLazyDPSEvaluation();
5821       freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
5822 }
5823
5824
5825 /*-----------------------------------------------------------------*/
5826 /* genAnd  - code for and                                          */
5827 /*-----------------------------------------------------------------*/
5828 static void
5829 genAnd (iCode * ic, iCode * ifx)
5830 {
5831   operand *left, *right, *result;
5832   int size, offset = 0;
5833   unsigned long lit = 0L;
5834   int bytelit = 0;
5835   char buffer[10];
5836   bool pushResult;
5837
5838   D (emitcode (";", "genAnd "););
5839
5840   AOP_OP_3_NOFATAL (ic, pushResult);
5841   AOP_SET_LOCALS (ic);
5842
5843   if (pushResult)
5844   {
5845       genFarFarLogicOp(ic, "anl");
5846       return;
5847   }  
5848
5849 #ifdef DEBUG_TYPE
5850   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5851             AOP_TYPE (result),
5852             AOP_TYPE (left), AOP_TYPE (right));
5853   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5854             AOP_SIZE (result),
5855             AOP_SIZE (left), AOP_SIZE (right));
5856 #endif
5857
5858   /* if left is a literal & right is not then exchange them */
5859   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5860 #ifdef LOGIC_OPS_BROKEN      
5861     ||  AOP_NEEDSACC (left)
5862 #endif
5863     )
5864     {
5865       operand *tmp = right;
5866       right = left;
5867       left = tmp;
5868     }
5869
5870   /* if result = right then exchange them */
5871   if (sameRegs (AOP (result), AOP (right)))
5872     {
5873       operand *tmp = right;
5874       right = left;
5875       left = tmp;
5876     }
5877
5878   /* if right is bit then exchange them */
5879   if (AOP_TYPE (right) == AOP_CRY &&
5880       AOP_TYPE (left) != AOP_CRY)
5881     {
5882       operand *tmp = right;
5883       right = left;
5884       left = tmp;
5885     }
5886   if (AOP_TYPE (right) == AOP_LIT)
5887     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5888
5889   size = AOP_SIZE (result);
5890
5891   // if(bit & yy)
5892   // result = bit & yy;
5893   if (AOP_TYPE (left) == AOP_CRY)
5894     {
5895       // c = bit & literal;
5896       if (AOP_TYPE (right) == AOP_LIT)
5897         {
5898           if (lit & 1)
5899             {
5900               if (size && sameRegs (AOP (result), AOP (left)))
5901                 // no change
5902                 goto release;
5903               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5904             }
5905           else
5906             {
5907               // bit(result) = 0;
5908               if (size && (AOP_TYPE (result) == AOP_CRY))
5909                 {
5910                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5911                   goto release;
5912                 }
5913               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5914                 {
5915                   jumpIfTrue (ifx);
5916                   goto release;
5917                 }
5918               emitcode ("clr", "c");
5919             }
5920         }
5921       else
5922         {
5923           if (AOP_TYPE (right) == AOP_CRY)
5924             {
5925               // c = bit & bit;
5926               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5927               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5928             }
5929           else
5930             {
5931               // c = bit & val;
5932               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
5933               // c = lsb
5934               emitcode ("rrc", "a");
5935               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5936             }
5937         }
5938       // bit = c
5939       // val = c
5940       if (size)
5941         outBitC (result);
5942       // if(bit & ...)
5943       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5944         genIfxJump (ifx, "c");
5945       goto release;
5946     }
5947
5948   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5949   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5950   if ((AOP_TYPE (right) == AOP_LIT) &&
5951       (AOP_TYPE (result) == AOP_CRY) &&
5952       (AOP_TYPE (left) != AOP_CRY))
5953     {
5954       int posbit = isLiteralBit (lit);
5955       /* left &  2^n */
5956       if (posbit)
5957         {
5958           posbit--;
5959           MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
5960           // bit = left & 2^n
5961           if (size)
5962             emitcode ("mov", "c,acc.%d", posbit & 0x07);
5963           // if(left &  2^n)
5964           else
5965             {
5966               if (ifx)
5967                 {
5968                   sprintf (buffer, "acc.%d", posbit & 0x07);
5969                   genIfxJump (ifx, buffer);
5970                 }
5971               goto release;
5972             }
5973         }
5974       else
5975         {
5976           symbol *tlbl = newiTempLabel (NULL);
5977           int sizel = AOP_SIZE (left);
5978           if (size)
5979             emitcode ("setb", "c");
5980           while (sizel--)
5981             {
5982               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5983                 {
5984                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5985                   // byte ==  2^n ?
5986                   if ((posbit = isLiteralBit (bytelit)) != 0)
5987                     emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
5988                   else
5989                     {
5990                       if (bytelit != 0x0FFL)
5991                         emitcode ("anl", "a,%s",
5992                           aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
5993                       emitcode ("jnz", "!tlabel", tlbl->key + 100);
5994                     }
5995                 }
5996               offset++;
5997             }
5998           // bit = left & literal
5999           if (size)
6000             {
6001               emitcode ("clr", "c");
6002               emitcode ("", "!tlabeldef", tlbl->key + 100);
6003             }
6004           // if(left & literal)
6005           else
6006             {
6007               if (ifx)
6008                 jmpTrueOrFalse (ifx, tlbl);
6009               goto release;
6010             }
6011         }
6012       outBitC (result);
6013       goto release;
6014     }
6015
6016   /* if left is same as result */
6017   if (sameRegs (AOP (result), AOP (left)))
6018     {
6019       for (; size--; offset++)
6020         {
6021           if (AOP_TYPE (right) == AOP_LIT)
6022             {
6023               if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6024                 continue;
6025               else if (bytelit == 0)
6026                 aopPut (AOP (result), zero, offset);
6027               else if (IS_AOP_PREG (result))
6028                 {
6029                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6030                   emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6031                   aopPut (AOP (result), "a", offset);
6032                 }
6033               else
6034                 emitcode ("anl", "%s,%s",
6035                           aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6036                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6037             }
6038           else
6039             {
6040               if (AOP_TYPE (left) == AOP_ACC)
6041                 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6042               else
6043                 {
6044                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6045                   if (IS_AOP_PREG (result))
6046                     {
6047                       emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6048                       aopPut (AOP (result), "a", offset);
6049
6050                     }
6051                   else
6052                     emitcode ("anl", "%s,a",
6053                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6054                 }
6055             }
6056         }
6057     }
6058   else
6059     {
6060       // left & result in different registers
6061       if (AOP_TYPE (result) == AOP_CRY)
6062         {
6063           // result = bit
6064           // if(size), result in bit
6065           // if(!size && ifx), conditional oper: if(left & right)
6066           symbol *tlbl = newiTempLabel (NULL);
6067           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6068           if (size)
6069             emitcode ("setb", "c");
6070           while (sizer--)
6071             {
6072               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6073                 emitcode ("anl", "a,%s",
6074                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6075               } else {
6076                 if (AOP_TYPE(left)==AOP_ACC) {
6077                   emitcode("mov", "b,a");
6078                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6079                   emitcode("anl", "a,b");
6080                 }else {
6081                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6082                   emitcode ("anl", "a,%s",
6083                             aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6084                 }
6085               }
6086               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6087               offset++;
6088             }
6089           if (size)
6090             {
6091               CLRC;
6092               emitcode ("", "!tlabeldef", tlbl->key + 100);
6093               outBitC (result);
6094             }
6095           else if (ifx)
6096             jmpTrueOrFalse (ifx, tlbl);
6097         }
6098       else
6099         {
6100           for (; (size--); offset++)
6101             {
6102               // normal case
6103               // result = left & right
6104               if (AOP_TYPE (right) == AOP_LIT)
6105                 {
6106                   if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6107                     {
6108                       aopPut (AOP (result),
6109                            aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6110                               offset);
6111                       continue;
6112                     }
6113                   else if (bytelit == 0)
6114                     {
6115                       aopPut (AOP (result), zero, offset);
6116                       continue;
6117                     }
6118                   D (emitcode (";", "better literal AND."););
6119                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6120                   emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6121                                                     FALSE, FALSE, FALSE));
6122
6123                 }
6124               else
6125                 {
6126                   // faster than result <- left, anl result,right
6127                   // and better if result is SFR
6128                   if (AOP_TYPE (left) == AOP_ACC)
6129                     {
6130                       emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
6131                                                        FALSE, FALSE, FALSE));
6132                     }
6133                   else
6134                     {
6135                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6136                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6137                       {
6138                           emitcode("mov", "b,a");
6139                           rOp = "b";
6140                       }
6141                         
6142                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6143                       emitcode ("anl", "a,%s", rOp);
6144                     }                   
6145                 }
6146               aopPut (AOP (result), "a", offset);
6147             }
6148         }
6149     }
6150
6151 release:
6152   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6153   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6154   freeAsmop (result, NULL, ic, TRUE);
6155 }
6156
6157
6158 /*-----------------------------------------------------------------*/
6159 /* genOr  - code for or                                            */
6160 /*-----------------------------------------------------------------*/
6161 static void
6162 genOr (iCode * ic, iCode * ifx)
6163 {
6164   operand *left, *right, *result;
6165   int size, offset = 0;
6166   unsigned long lit = 0L;
6167   bool     pushResult;
6168
6169   D (emitcode (";", "genOr "););
6170
6171   AOP_OP_3_NOFATAL (ic, pushResult);
6172   AOP_SET_LOCALS (ic);
6173
6174   if (pushResult)
6175   {
6176       genFarFarLogicOp(ic, "orl");
6177       return;
6178   }
6179
6180
6181 #ifdef DEBUG_TYPE
6182   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6183             AOP_TYPE (result),
6184             AOP_TYPE (left), AOP_TYPE (right));
6185   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6186             AOP_SIZE (result),
6187             AOP_SIZE (left), AOP_SIZE (right));
6188 #endif
6189
6190   /* if left is a literal & right is not then exchange them */
6191   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6192 #ifdef LOGIC_OPS_BROKEN
6193    || AOP_NEEDSACC (left) // I think this is a net loss now.
6194 #endif      
6195       )
6196     {
6197       operand *tmp = right;
6198       right = left;
6199       left = tmp;
6200     }
6201
6202   /* if result = right then exchange them */
6203   if (sameRegs (AOP (result), AOP (right)))
6204     {
6205       operand *tmp = right;
6206       right = left;
6207       left = tmp;
6208     }
6209
6210   /* if right is bit then exchange them */
6211   if (AOP_TYPE (right) == AOP_CRY &&
6212       AOP_TYPE (left) != AOP_CRY)
6213     {
6214       operand *tmp = right;
6215       right = left;
6216       left = tmp;
6217     }
6218   if (AOP_TYPE (right) == AOP_LIT)
6219     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6220
6221   size = AOP_SIZE (result);
6222
6223   // if(bit | yy)
6224   // xx = bit | yy;
6225   if (AOP_TYPE (left) == AOP_CRY)
6226     {
6227       if (AOP_TYPE (right) == AOP_LIT)
6228         {
6229           // c = bit & literal;
6230           if (lit)
6231             {
6232               // lit != 0 => result = 1
6233               if (AOP_TYPE (result) == AOP_CRY)
6234                 {
6235                   if (size)
6236                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6237                   else if (ifx)
6238                     continueIfTrue (ifx);
6239                   goto release;
6240                 }
6241               emitcode ("setb", "c");
6242             }
6243           else
6244             {
6245               // lit == 0 => result = left
6246               if (size && sameRegs (AOP (result), AOP (left)))
6247                 goto release;
6248               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6249             }
6250         }
6251       else
6252         {
6253           if (AOP_TYPE (right) == AOP_CRY)
6254             {
6255               // c = bit | bit;
6256               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6257               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6258             }
6259           else
6260             {
6261               // c = bit | val;
6262               symbol *tlbl = newiTempLabel (NULL);
6263               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6264                 emitcode ("setb", "c");
6265               emitcode ("jb", "%s,!tlabel",
6266                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
6267               toBoolean (right);
6268               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6269               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6270                 {
6271                   jmpTrueOrFalse (ifx, tlbl);
6272                   goto release;
6273                 }
6274               else
6275                 {
6276                   CLRC;
6277                   emitcode ("", "!tlabeldef", tlbl->key + 100);
6278                 }
6279             }
6280         }
6281       // bit = c
6282       // val = c
6283       if (size)
6284         outBitC (result);
6285       // if(bit | ...)
6286       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6287         genIfxJump (ifx, "c");
6288       goto release;
6289     }
6290
6291   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6292   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6293   if ((AOP_TYPE (right) == AOP_LIT) &&
6294       (AOP_TYPE (result) == AOP_CRY) &&
6295       (AOP_TYPE (left) != AOP_CRY))
6296     {
6297       if (lit)
6298         {
6299           // result = 1
6300           if (size)
6301             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6302           else
6303             continueIfTrue (ifx);
6304           goto release;
6305         }
6306       else
6307         {
6308           // lit = 0, result = boolean(left)
6309           if (size)
6310             emitcode ("setb", "c");
6311           toBoolean (right);
6312           if (size)
6313             {
6314               symbol *tlbl = newiTempLabel (NULL);
6315               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6316               CLRC;
6317               emitcode ("", "!tlabeldef", tlbl->key + 100);
6318             }
6319           else
6320             {
6321               genIfxJump (ifx, "a");
6322               goto release;
6323             }
6324         }
6325       outBitC (result);
6326       goto release;
6327     }
6328
6329   /* if left is same as result */
6330   if (sameRegs (AOP (result), AOP (left)))
6331     {
6332       for (; size--; offset++)
6333         {
6334           if (AOP_TYPE (right) == AOP_LIT)
6335             {
6336               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6337                 {
6338                   continue;
6339                 }
6340               else
6341                 {
6342                   if (IS_AOP_PREG (left))
6343                     {
6344                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6345                       emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6346                       aopPut (AOP (result), "a", offset);
6347                     }
6348                   else
6349                     {
6350                       emitcode ("orl", "%s,%s",
6351                             aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6352                          aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6353                     }
6354                 }
6355             }
6356           else
6357             {
6358               if (AOP_TYPE (left) == AOP_ACC)
6359                 {
6360                   emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6361                 }
6362               else
6363                 {
6364                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6365                   if (IS_AOP_PREG (left))
6366                     {
6367                       emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6368                       aopPut (AOP (result), "a", offset);
6369                     }
6370                   else
6371                     {
6372                       emitcode ("orl", "%s,a",
6373                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6374                     }
6375                 }
6376             }
6377         }
6378     }
6379   else
6380     {
6381       // left & result in different registers
6382       if (AOP_TYPE (result) == AOP_CRY)
6383         {
6384           // result = bit
6385           // if(size), result in bit
6386           // if(!size && ifx), conditional oper: if(left | right)
6387           symbol *tlbl = newiTempLabel (NULL);
6388           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6389           if (size)
6390             emitcode ("setb", "c");
6391           while (sizer--)
6392             {
6393               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6394                 emitcode ("orl", "a,%s",
6395                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6396               } else {
6397                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6398                 emitcode ("orl", "a,%s",
6399                           aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6400               }
6401               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6402               offset++;
6403             }
6404           if (size)
6405             {
6406               CLRC;
6407               emitcode ("", "!tlabeldef", tlbl->key + 100);
6408               outBitC (result);
6409             }
6410           else if (ifx)
6411             jmpTrueOrFalse (ifx, tlbl);
6412         }
6413       else
6414         {
6415             _startLazyDPSEvaluation();
6416           for (; (size--); offset++)
6417             {
6418               // normal case
6419               // result = left & right
6420               if (AOP_TYPE (right) == AOP_LIT)
6421                 {
6422                   if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6423                     {
6424                       aopPut (AOP (result),
6425                            aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6426                               offset);
6427                       continue;
6428                     }
6429                   D (emitcode (";", "better literal OR."););
6430                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6431                   emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
6432                                                     FALSE, FALSE, FALSE));
6433
6434                 }
6435               else
6436                 {
6437                   // faster than result <- left, anl result,right
6438                   // and better if result is SFR
6439                   if (AOP_TYPE (left) == AOP_ACC)
6440                     {
6441                       emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
6442                                                        FALSE, FALSE, FALSE));
6443                     }
6444                   else
6445                     {
6446                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6447                         
6448                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6449                       {
6450                           emitcode("mov", "b,a");
6451                           rOp = "b";
6452                       }
6453                         
6454                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6455                       emitcode ("orl", "a,%s", rOp);
6456                     }
6457                 }
6458               aopPut (AOP (result), "a", offset);
6459             }
6460             _endLazyDPSEvaluation();
6461         }
6462     }
6463
6464 release:
6465   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6466   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6467   freeAsmop (result, NULL, ic, TRUE);
6468 }
6469
6470 /*-----------------------------------------------------------------*/
6471 /* genXor - code for xclusive or                                   */
6472 /*-----------------------------------------------------------------*/
6473 static void
6474 genXor (iCode * ic, iCode * ifx)
6475 {
6476   operand *left, *right, *result;
6477   int size, offset = 0;
6478   unsigned long lit = 0L;
6479   bool pushResult;
6480
6481   D (emitcode (";", "genXor "););
6482
6483   AOP_OP_3_NOFATAL (ic, pushResult);
6484   AOP_SET_LOCALS (ic);
6485
6486   if (pushResult)
6487   {
6488       genFarFarLogicOp(ic, "xrl");
6489       return;
6490   }  
6491
6492 #ifdef DEBUG_TYPE
6493   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6494             AOP_TYPE (result),
6495             AOP_TYPE (left), AOP_TYPE (right));
6496   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6497             AOP_SIZE (result),
6498             AOP_SIZE (left), AOP_SIZE (right));
6499 #endif
6500
6501   /* if left is a literal & right is not ||
6502      if left needs acc & right does not */
6503   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) 
6504 #ifdef LOGIC_OPS_BROKEN      
6505       || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6506 #endif
6507      )
6508     {
6509       operand *tmp = right;
6510       right = left;
6511       left = tmp;
6512     }
6513
6514   /* if result = right then exchange them */
6515   if (sameRegs (AOP (result), AOP (right)))
6516     {
6517       operand *tmp = right;
6518       right = left;
6519       left = tmp;
6520     }
6521
6522   /* if right is bit then exchange them */
6523   if (AOP_TYPE (right) == AOP_CRY &&
6524       AOP_TYPE (left) != AOP_CRY)
6525     {
6526       operand *tmp = right;
6527       right = left;
6528       left = tmp;
6529     }
6530   if (AOP_TYPE (right) == AOP_LIT)
6531     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6532
6533   size = AOP_SIZE (result);
6534
6535   // if(bit ^ yy)
6536   // xx = bit ^ yy;
6537   if (AOP_TYPE (left) == AOP_CRY)
6538     {
6539       if (AOP_TYPE (right) == AOP_LIT)
6540         {
6541           // c = bit & literal;
6542           if (lit >> 1)
6543             {
6544               // lit>>1  != 0 => result = 1
6545               if (AOP_TYPE (result) == AOP_CRY)
6546                 {
6547                   if (size)
6548                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6549                   else if (ifx)
6550                     continueIfTrue (ifx);
6551                   goto release;
6552                 }
6553               emitcode ("setb", "c");
6554             }
6555           else
6556             {
6557               // lit == (0 or 1)
6558               if (lit == 0)
6559                 {
6560                   // lit == 0, result = left
6561                   if (size && sameRegs (AOP (result), AOP (left)))
6562                     goto release;
6563                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6564                 }
6565               else
6566                 {
6567                   // lit == 1, result = not(left)
6568                   if (size && sameRegs (AOP (result), AOP (left)))
6569                     {
6570                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6571                       goto release;
6572                     }
6573                   else
6574                     {
6575                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6576                       emitcode ("cpl", "c");
6577                     }
6578                 }
6579             }
6580
6581         }
6582       else
6583         {
6584           // right != literal
6585           symbol *tlbl = newiTempLabel (NULL);
6586           if (AOP_TYPE (right) == AOP_CRY)
6587             {
6588               // c = bit ^ bit;
6589               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6590             }
6591           else
6592             {
6593               int sizer = AOP_SIZE (right);
6594               // c = bit ^ val
6595               // if val>>1 != 0, result = 1
6596               emitcode ("setb", "c");
6597               while (sizer)
6598                 {
6599                   MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
6600                   if (sizer == 1)
6601                     // test the msb of the lsb
6602                     emitcode ("anl", "a,#!constbyte",0xfe);
6603                   emitcode ("jnz", "!tlabel", tlbl->key + 100);
6604                   sizer--;
6605                 }
6606               // val = (0,1)
6607               emitcode ("rrc", "a");
6608             }
6609           emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6610           emitcode ("cpl", "c");
6611           emitcode ("", "!tlabeldef", (tlbl->key + 100));
6612         }
6613       // bit = c
6614       // val = c
6615       if (size)
6616         outBitC (result);
6617       // if(bit | ...)
6618       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6619         genIfxJump (ifx, "c");
6620       goto release;
6621     }
6622
6623   if (sameRegs (AOP (result), AOP (left)))
6624     {
6625       /* if left is same as result */
6626       for (; size--; offset++)
6627         {
6628           if (AOP_TYPE (right) == AOP_LIT)
6629             {
6630               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6631                 continue;
6632               else if (IS_AOP_PREG (left))
6633                 {
6634                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6635                   emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6636                   aopPut (AOP (result), "a", offset);
6637                 }
6638               else
6639                 emitcode ("xrl", "%s,%s",
6640                           aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6641                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6642             }
6643           else
6644             {
6645               if (AOP_TYPE (left) == AOP_ACC)
6646                 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6647               else
6648                 {
6649                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6650                   if (IS_AOP_PREG (left))
6651                     {
6652                       emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6653                       aopPut (AOP (result), "a", offset);
6654                     }
6655                   else
6656                     emitcode ("xrl", "%s,a",
6657                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6658                 }
6659             }
6660         }
6661     }
6662   else
6663     {
6664       // left & result in different registers
6665       if (AOP_TYPE (result) == AOP_CRY)
6666         {
6667           // result = bit
6668           // if(size), result in bit
6669           // if(!size && ifx), conditional oper: if(left ^ right)
6670           symbol *tlbl = newiTempLabel (NULL);
6671           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6672                   
6673           if (size)
6674             emitcode ("setb", "c");
6675           while (sizer--)
6676             {
6677               if ((AOP_TYPE (right) == AOP_LIT) &&
6678                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6679                 {
6680                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6681                 }
6682               else
6683                 {
6684                   if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6685                     emitcode ("xrl", "a,%s",
6686                               aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6687                   } else {
6688                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6689                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6690                       {
6691                           emitcode("mov", "b,a");
6692                           rOp = "b";
6693                       }
6694                         
6695                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6696                       emitcode ("xrl", "a,%s", rOp);                  
6697                   }
6698                 }
6699               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6700               offset++;
6701             }
6702           if (size)
6703             {
6704               CLRC;
6705               emitcode ("", "!tlabeldef", tlbl->key + 100);
6706               outBitC (result);
6707             }
6708           else if (ifx)
6709             jmpTrueOrFalse (ifx, tlbl);
6710         }
6711       else
6712         {
6713         for (; (size--); offset++)
6714           {
6715             // normal case
6716             // result = left & right
6717             if (AOP_TYPE (right) == AOP_LIT)
6718               {
6719                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6720                   {
6721                     aopPut (AOP (result),
6722                             aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6723                             offset);
6724                     continue;
6725                   }
6726                 D (emitcode (";", "better literal XOR."););
6727                 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6728                 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
6729                                                   FALSE, FALSE, FALSE));
6730               }
6731             else
6732               {
6733                 // faster than result <- left, anl result,right
6734                 // and better if result is SFR
6735                 if (AOP_TYPE (left) == AOP_ACC)
6736                   {
6737                     emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
6738                                                      FALSE, FALSE, FALSE));
6739                   }
6740                 else
6741                   {
6742                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6743                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6744                       {
6745                           emitcode("mov", "b,a");
6746                           rOp = "b";
6747                       }
6748                         
6749                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6750                       emitcode ("xrl", "a,%s", rOp);
6751                   }
6752               }
6753             aopPut (AOP (result), "a", offset);
6754           }
6755         }
6756         
6757     }
6758
6759 release:
6760   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6761   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6762   freeAsmop (result, NULL, ic, TRUE);
6763 }
6764
6765 /*-----------------------------------------------------------------*/
6766 /* genInline - write the inline code out                           */
6767 /*-----------------------------------------------------------------*/
6768 static void
6769 genInline (iCode * ic)
6770 {
6771   char *buffer, *bp, *bp1;
6772
6773   D (emitcode (";", "genInline ");
6774     );
6775
6776   _G.inLine += (!options.asmpeep);
6777
6778   buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6779   strcpy (buffer, IC_INLINE (ic));
6780
6781   /* emit each line as a code */
6782   while (*bp)
6783     {
6784       if (*bp == '\n')
6785         {
6786           *bp++ = '\0';
6787           emitcode (bp1, "");
6788           bp1 = bp;
6789         }
6790       else
6791         {
6792           if (*bp == ':')
6793             {
6794               bp++;
6795               *bp = '\0';
6796               bp++;
6797               emitcode (bp1, "");
6798               bp1 = bp;
6799             }
6800           else
6801             bp++;
6802         }
6803     }
6804   if (bp1 != bp)
6805     emitcode (bp1, "");
6806   /*     emitcode("",buffer); */
6807   _G.inLine -= (!options.asmpeep);
6808 }
6809
6810 /*-----------------------------------------------------------------*/
6811 /* genRRC - rotate right with carry                                */
6812 /*-----------------------------------------------------------------*/
6813 static void
6814 genRRC (iCode * ic)
6815 {
6816   operand *left, *result;
6817   int size, offset = 0;
6818   char *l;
6819
6820   D (emitcode (";", "genRRC ");
6821     );
6822
6823   /* rotate right with carry */
6824   left = IC_LEFT (ic);
6825   result = IC_RESULT (ic);
6826   aopOp (left, ic, FALSE, FALSE);
6827   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6828
6829   /* move it to the result */
6830   size = AOP_SIZE (result);
6831   offset = size - 1;
6832   CLRC;
6833
6834   _startLazyDPSEvaluation ();
6835   while (size--)
6836     {
6837       l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6838       MOVA (l);
6839       emitcode ("rrc", "a");
6840       if (AOP_SIZE (result) > 1)
6841         aopPut (AOP (result), "a", offset--);
6842     }
6843   _endLazyDPSEvaluation ();
6844
6845   /* now we need to put the carry into the
6846      highest order byte of the result */
6847   if (AOP_SIZE (result) > 1)
6848     {
6849       l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
6850       MOVA (l);
6851     }
6852   emitcode ("mov", "acc.7,c");
6853   aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
6854   freeAsmop (left, NULL, ic, TRUE);
6855   freeAsmop (result, NULL, ic, TRUE);
6856 }
6857
6858 /*-----------------------------------------------------------------*/
6859 /* genRLC - generate code for rotate left with carry               */
6860 /*-----------------------------------------------------------------*/
6861 static void
6862 genRLC (iCode * ic)
6863 {
6864   operand *left, *result;
6865   int size, offset = 0;
6866   char *l;
6867
6868   D (emitcode (";", "genRLC ");
6869     );
6870
6871   /* rotate right with carry */
6872   left = IC_LEFT (ic);
6873   result = IC_RESULT (ic);
6874   aopOp (left, ic, FALSE, FALSE);
6875   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6876
6877   /* move it to the result */
6878   size = AOP_SIZE (result);
6879   offset = 0;
6880   if (size--)
6881     {
6882       l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6883       MOVA (l);
6884       emitcode ("add", "a,acc");
6885       if (AOP_SIZE (result) > 1)
6886         {
6887           aopPut (AOP (result), "a", offset++);
6888         }
6889
6890       _startLazyDPSEvaluation ();
6891       while (size--)
6892         {
6893           l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6894           MOVA (l);
6895           emitcode ("rlc", "a");
6896           if (AOP_SIZE (result) > 1)
6897             aopPut (AOP (result), "a", offset++);
6898         }
6899       _endLazyDPSEvaluation ();
6900     }
6901   /* now we need to put the carry into the
6902      highest order byte of the result */
6903   if (AOP_SIZE (result) > 1)
6904     {
6905       l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
6906       MOVA (l);
6907     }
6908   emitcode ("mov", "acc.0,c");
6909   aopPut (AOP (result), "a", 0);
6910   freeAsmop (left, NULL, ic, TRUE);
6911   freeAsmop (result, NULL, ic, TRUE);
6912 }
6913
6914 /*-----------------------------------------------------------------*/
6915 /* genGetHbit - generates code get highest order bit               */
6916 /*-----------------------------------------------------------------*/
6917 static void
6918 genGetHbit (iCode * ic)
6919 {
6920   operand *left, *result;
6921   left = IC_LEFT (ic);
6922   result = IC_RESULT (ic);
6923   aopOp (left, ic, FALSE, FALSE);
6924   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6925
6926   D (emitcode (";", "genGetHbit ");
6927     );
6928
6929   /* get the highest order byte into a */
6930   MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
6931   if (AOP_TYPE (result) == AOP_CRY)
6932     {
6933       emitcode ("rlc", "a");
6934       outBitC (result);
6935     }
6936   else
6937     {
6938       emitcode ("rl", "a");
6939       emitcode ("anl", "a,#1");
6940       outAcc (result);
6941     }
6942
6943
6944   freeAsmop (left, NULL, ic, TRUE);
6945   freeAsmop (result, NULL, ic, TRUE);
6946 }
6947
6948 /*-----------------------------------------------------------------*/
6949 /* AccRol - rotate left accumulator by known count                 */
6950 /*-----------------------------------------------------------------*/
6951 static void
6952 AccRol (int shCount)
6953 {
6954   shCount &= 0x0007;            // shCount : 0..7
6955
6956   switch (shCount)
6957     {
6958     case 0:
6959       break;
6960     case 1:
6961       emitcode ("rl", "a");
6962       break;
6963     case 2:
6964       emitcode ("rl", "a");
6965       emitcode ("rl", "a");
6966       break;
6967     case 3:
6968       emitcode ("swap", "a");
6969       emitcode ("rr", "a");
6970       break;
6971     case 4:
6972       emitcode ("swap", "a");
6973       break;
6974     case 5:
6975       emitcode ("swap", "a");
6976       emitcode ("rl", "a");
6977       break;
6978     case 6:
6979       emitcode ("rr", "a");
6980       emitcode ("rr", "a");
6981       break;
6982     case 7:
6983       emitcode ("rr", "a");
6984       break;
6985     }
6986 }
6987
6988 /*-----------------------------------------------------------------*/
6989 /* AccLsh - left shift accumulator by known count                  */
6990 /*-----------------------------------------------------------------*/
6991 static void
6992 AccLsh (int shCount)
6993 {
6994   if (shCount != 0)
6995     {
6996       if (shCount == 1)
6997         emitcode ("add", "a,acc");
6998       else if (shCount == 2)
6999         {
7000           emitcode ("add", "a,acc");
7001           emitcode ("add", "a,acc");
7002         }
7003       else
7004         {
7005           /* rotate left accumulator */
7006           AccRol (shCount);
7007           /* and kill the lower order bits */
7008           emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7009         }
7010     }
7011 }
7012
7013 /*-----------------------------------------------------------------*/
7014 /* AccRsh - right shift accumulator by known count                 */
7015 /*-----------------------------------------------------------------*/
7016 static void
7017 AccRsh (int shCount)
7018 {
7019   if (shCount != 0)
7020     {
7021       if (shCount == 1)
7022         {
7023           CLRC;
7024           emitcode ("rrc", "a");
7025         }
7026       else
7027         {
7028           /* rotate right accumulator */
7029           AccRol (8 - shCount);
7030           /* and kill the higher order bits */
7031           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7032         }
7033     }
7034 }
7035
7036 #ifdef BETTER_LITERAL_SHIFT
7037 /*-----------------------------------------------------------------*/
7038 /* AccSRsh - signed right shift accumulator by known count                 */
7039 /*-----------------------------------------------------------------*/
7040 static void
7041 AccSRsh (int shCount)
7042 {
7043   symbol *tlbl;
7044   if (shCount != 0)
7045     {
7046       if (shCount == 1)
7047         {
7048           emitcode ("mov", "c,acc.7");
7049           emitcode ("rrc", "a");
7050         }
7051       else if (shCount == 2)
7052         {
7053           emitcode ("mov", "c,acc.7");
7054           emitcode ("rrc", "a");
7055           emitcode ("mov", "c,acc.7");
7056           emitcode ("rrc", "a");
7057         }
7058       else
7059         {
7060           tlbl = newiTempLabel (NULL);
7061           /* rotate right accumulator */
7062           AccRol (8 - shCount);
7063           /* and kill the higher order bits */
7064           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7065           emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7066           emitcode ("orl", "a,#!constbyte",
7067                     (unsigned char) ~SRMask[shCount]);
7068           emitcode ("", "!tlabeldef", tlbl->key + 100);
7069         }
7070     }
7071 }
7072 #endif
7073
7074 #ifdef BETTER_LITERAL_SHIFT
7075 /*-----------------------------------------------------------------*/
7076 /* shiftR1Left2Result - shift right one byte from left to result   */
7077 /*-----------------------------------------------------------------*/
7078 static void
7079 shiftR1Left2Result (operand * left, int offl,
7080                     operand * result, int offr,
7081                     int shCount, int sign)
7082 {
7083   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7084   /* shift right accumulator */
7085   if (sign)
7086     AccSRsh (shCount);
7087   else
7088     AccRsh (shCount);
7089   aopPut (AOP (result), "a", offr);
7090 }
7091 #endif
7092
7093 #ifdef BETTER_LITERAL_SHIFT
7094 /*-----------------------------------------------------------------*/
7095 /* shiftL1Left2Result - shift left one byte from left to result    */
7096 /*-----------------------------------------------------------------*/
7097 static void
7098 shiftL1Left2Result (operand * left, int offl,
7099                     operand * result, int offr, int shCount)
7100 {
7101   MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7102   /* shift left accumulator */
7103   AccLsh (shCount);
7104   aopPut (AOP (result), "a", offr);
7105 }
7106 #endif
7107
7108 #ifdef BETTER_LITERAL_SHIFT
7109 /*-----------------------------------------------------------------*/
7110 /* movLeft2Result - move byte from left to result                  */
7111 /*-----------------------------------------------------------------*/
7112 static void
7113 movLeft2Result (operand * left, int offl,
7114                 operand * result, int offr, int sign)
7115 {
7116   char *l;
7117   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7118   {
7119       l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
7120
7121       if (*l == '@' && (IS_AOP_PREG (result)))
7122       {
7123           emitcode ("mov", "a,%s", l);
7124           aopPut (AOP (result), "a", offr);
7125       }
7126       else
7127       {
7128           if (!sign)
7129           {
7130             aopPut (AOP (result), l, offr);
7131           }
7132           else
7133             {
7134               /* MSB sign in acc.7 ! */
7135               if (getDataSize (left) == offl + 1)
7136                 {
7137                   emitcode ("mov", "a,%s", l);
7138                   aopPut (AOP (result), "a", offr);
7139                 }
7140             }
7141       }
7142   }
7143 }
7144 #endif
7145
7146 #ifdef BETTER_LITERAL_SHIFT
7147 /*-----------------------------------------------------------------*/
7148 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
7149 /*-----------------------------------------------------------------*/
7150 static void
7151 AccAXRrl1 (char *x)
7152 {
7153   emitcode ("rrc", "a");
7154   emitcode ("xch", "a,%s", x);
7155   emitcode ("rrc", "a");
7156   emitcode ("xch", "a,%s", x);
7157 }
7158 #endif
7159
7160 #ifdef BETTER_LITERAL_SHIFT
7161 //REMOVE ME!!!
7162 /*-----------------------------------------------------------------*/
7163 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
7164 /*-----------------------------------------------------------------*/
7165 static void
7166 AccAXLrl1 (char *x)
7167 {
7168   emitcode ("xch", "a,%s", x);
7169   emitcode ("rlc", "a");
7170   emitcode ("xch", "a,%s", x);
7171   emitcode ("rlc", "a");
7172 }
7173 #endif
7174
7175 #ifdef BETTER_LITERAL_SHIFT
7176 /*-----------------------------------------------------------------*/
7177 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
7178 /*-----------------------------------------------------------------*/
7179 static void
7180 AccAXLsh1 (char *x)
7181 {
7182   emitcode ("xch", "a,%s", x);
7183   emitcode ("add", "a,acc");
7184   emitcode ("xch", "a,%s", x);
7185   emitcode ("rlc", "a");
7186 }
7187 #endif
7188
7189 #ifdef BETTER_LITERAL_SHIFT
7190 /*-----------------------------------------------------------------*/
7191 /* AccAXLsh - left shift a:x by known count (0..7)                 */
7192 /*-----------------------------------------------------------------*/
7193 static void
7194 AccAXLsh (char *x, int shCount)
7195 {
7196   switch (shCount)
7197     {
7198     case 0:
7199       break;
7200     case 1:
7201       AccAXLsh1 (x);
7202       break;
7203     case 2:
7204       AccAXLsh1 (x);
7205       AccAXLsh1 (x);
7206       break;
7207     case 3:
7208     case 4:
7209     case 5:                     // AAAAABBB:CCCCCDDD
7210
7211       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
7212
7213       emitcode ("anl", "a,#!constbyte",
7214                 SLMask[shCount]);       // BBB00000:CCCCCDDD
7215
7216       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
7217
7218       AccRol (shCount);         // DDDCCCCC:BBB00000
7219
7220       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
7221
7222       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
7223
7224       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
7225
7226       emitcode ("anl", "a,#!constbyte",
7227                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
7228
7229       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
7230
7231       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
7232
7233       break;
7234     case 6:                     // AAAAAABB:CCCCCCDD
7235       emitcode ("anl", "a,#!constbyte",
7236                 SRMask[shCount]);       // 000000BB:CCCCCCDD
7237       emitcode ("mov", "c,acc.0");      // c = B
7238       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
7239 #if 0
7240       AccAXRrl1 (x);            // BCCCCCCD:D000000B
7241       AccAXRrl1 (x);            // BBCCCCCC:DD000000
7242 #else
7243       emitcode("rrc","a"); 
7244       emitcode("xch","a,%s", x); 
7245       emitcode("rrc","a"); 
7246       emitcode("mov","c,acc.0"); //<< get correct bit 
7247       emitcode("xch","a,%s", x); 
7248
7249       emitcode("rrc","a"); 
7250       emitcode("xch","a,%s", x); 
7251       emitcode("rrc","a"); 
7252       emitcode("xch","a,%s", x); 
7253 #endif
7254       break;
7255     case 7:                     // a:x <<= 7
7256
7257       emitcode ("anl", "a,#!constbyte",
7258                 SRMask[shCount]);       // 0000000B:CCCCCCCD
7259
7260       emitcode ("mov", "c,acc.0");      // c = B
7261
7262       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
7263
7264       AccAXRrl1 (x);            // BCCCCCCC:D0000000
7265
7266       break;
7267     default:
7268       break;
7269     }
7270 }
7271 #endif
7272
7273 #ifdef BETTER_LITERAL_SHIFT
7274 //REMOVE ME!!!
7275 /*-----------------------------------------------------------------*/
7276 /* AccAXRsh - right shift a:x known count (0..7)                   */
7277 /*-----------------------------------------------------------------*/
7278 static void
7279 AccAXRsh (char *x, int shCount)
7280 {
7281   switch (shCount)
7282     {
7283     case 0:
7284       break;
7285     case 1:
7286       CLRC;
7287       AccAXRrl1 (x);            // 0->a:x
7288
7289       break;
7290     case 2:
7291       CLRC;
7292       AccAXRrl1 (x);            // 0->a:x
7293
7294       CLRC;
7295       AccAXRrl1 (x);            // 0->a:x
7296
7297       break;
7298     case 3:
7299     case 4:
7300     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7301
7302       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
7303
7304       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7305
7306       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7307
7308       emitcode ("anl", "a,#!constbyte",
7309                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7310
7311       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7312
7313       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7314
7315       emitcode ("anl", "a,#!constbyte",
7316                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7317
7318       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7319
7320       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7321
7322       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
7323
7324       break;
7325     case 6:                     // AABBBBBB:CCDDDDDD
7326
7327       emitcode ("mov", "c,acc.7");
7328       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7329
7330       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7331
7332       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7333
7334       emitcode ("anl", "a,#!constbyte",
7335                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7336
7337       break;
7338     case 7:                     // ABBBBBBB:CDDDDDDD
7339
7340       emitcode ("mov", "c,acc.7");      // c = A
7341
7342       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7343
7344       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7345
7346       emitcode ("anl", "a,#!constbyte",
7347                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7348
7349       break;
7350     default:
7351       break;
7352     }
7353 }
7354 #endif
7355
7356 #ifdef BETTER_LITERAL_SHIFT
7357 /*-----------------------------------------------------------------*/
7358 /* AccAXRshS - right shift signed a:x known count (0..7)           */
7359 /*-----------------------------------------------------------------*/
7360 static void
7361 AccAXRshS (char *x, int shCount)
7362 {
7363   symbol *tlbl;
7364   switch (shCount)
7365     {
7366     case 0:
7367       break;
7368     case 1:
7369       emitcode ("mov", "c,acc.7");
7370       AccAXRrl1 (x);            // s->a:x
7371
7372       break;
7373     case 2:
7374       emitcode ("mov", "c,acc.7");
7375       AccAXRrl1 (x);            // s->a:x
7376
7377       emitcode ("mov", "c,acc.7");
7378       AccAXRrl1 (x);            // s->a:x
7379
7380       break;
7381     case 3:
7382     case 4:
7383     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7384
7385       tlbl = newiTempLabel (NULL);
7386       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
7387
7388       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7389
7390       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7391
7392       emitcode ("anl", "a,#!constbyte",
7393                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7394
7395       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7396
7397       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7398
7399       emitcode ("anl", "a,#!constbyte",
7400                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7401
7402       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7403
7404       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7405
7406       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
7407
7408       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7409       emitcode ("orl", "a,#!constbyte",
7410                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
7411
7412       emitcode ("", "!tlabeldef", tlbl->key + 100);
7413       break;                    // SSSSAAAA:BBBCCCCC
7414
7415     case 6:                     // AABBBBBB:CCDDDDDD
7416
7417       tlbl = newiTempLabel (NULL);
7418       emitcode ("mov", "c,acc.7");
7419       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7420
7421       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7422
7423       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7424
7425       emitcode ("anl", "a,#!constbyte",
7426                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7427
7428       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7429       emitcode ("orl", "a,#!constbyte",
7430                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
7431
7432       emitcode ("", "!tlabeldef", tlbl->key + 100);
7433       break;
7434     case 7:                     // ABBBBBBB:CDDDDDDD
7435
7436       tlbl = newiTempLabel (NULL);
7437       emitcode ("mov", "c,acc.7");      // c = A
7438
7439       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7440
7441       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7442
7443       emitcode ("anl", "a,#!constbyte",
7444                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7445
7446       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7447       emitcode ("orl", "a,#!constbyte",
7448                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
7449
7450       emitcode ("", "!tlabeldef", tlbl->key + 100);
7451       break;
7452     default:
7453       break;
7454     }
7455 }
7456 #endif
7457
7458 #ifdef BETTER_LITERAL_SHIFT
7459 static void
7460 _loadLeftIntoAx(char    **lsb, 
7461                 operand *left, 
7462                 operand *result,
7463                 int     offl,
7464                 int     offr)
7465 {
7466   // Get the initial value from left into a pair of registers.
7467   // MSB must be in A, LSB can be any register.
7468   //
7469   // If the result is held in registers, it is an optimization
7470   // if the LSB can be held in the register which will hold the,
7471   // result LSB since this saves us from having to copy it into
7472   // the result following AccAXLsh.
7473   //
7474   // If the result is addressed indirectly, this is not a gain.
7475   if (AOP_NEEDSACC(result))
7476   {
7477        char *leftByte;
7478        
7479        _startLazyDPSEvaluation();
7480       if (AOP_TYPE(left) == AOP_DPTR2)
7481        {
7482            // Get MSB in A.
7483            MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
7484            // get LSB in DP2_RESULT_REG.
7485            leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
7486            assert(!strcmp(leftByte, DP2_RESULT_REG));
7487        }
7488        else
7489        {
7490            // get LSB into DP2_RESULT_REG
7491            leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
7492            if (strcmp(leftByte, DP2_RESULT_REG))
7493            {
7494                TR_AP("#7");
7495                emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7496            }
7497            // And MSB in A.
7498            leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
7499            assert(strcmp(leftByte, DP2_RESULT_REG));
7500            MOVA(leftByte);
7501        }
7502        _endLazyDPSEvaluation();
7503        *lsb = DP2_RESULT_REG;
7504   }
7505   else
7506   {
7507       if (sameRegs (AOP (result), AOP (left)) &&
7508         ((offl + MSB16) == offr))
7509       {
7510           /* don't crash result[offr] */
7511           MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
7512           emitcode ("xch", "a,%s", 
7513                     aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
7514       }
7515       else
7516       {
7517           movLeft2Result (left, offl, result, offr, 0);
7518           MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
7519       }
7520       *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
7521       assert(strcmp(*lsb,"a"));      
7522   }
7523 }
7524
7525 static void
7526 _storeAxResults(char    *lsb,
7527                 operand *result,
7528                 int     offr)
7529 {
7530   _startLazyDPSEvaluation();
7531   if (AOP_NEEDSACC(result))
7532   {
7533       /* We have to explicitly update the result LSB.
7534        */
7535       emitcode("xch","a,%s", lsb);
7536       aopPut(AOP(result), "a", offr);
7537       emitcode("mov","a,%s", lsb);
7538   }
7539   if (getDataSize (result) > 1)
7540   {
7541       aopPut (AOP (result), "a", offr + MSB16);
7542   }
7543   _endLazyDPSEvaluation();
7544 }
7545
7546 /*-----------------------------------------------------------------*/
7547 /* shiftL2Left2Result - shift left two bytes from left to result   */
7548 /*-----------------------------------------------------------------*/
7549 static void
7550 shiftL2Left2Result (operand * left, int offl,
7551                     operand * result, int offr, int shCount)
7552 {
7553   char *lsb;
7554
7555   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7556   
7557   AccAXLsh (lsb, shCount);
7558   
7559   _storeAxResults(lsb, result, offr);
7560 }
7561 #endif
7562
7563 #ifdef BETTER_LITERAL_SHIFT
7564 /*-----------------------------------------------------------------*/
7565 /* shiftR2Left2Result - shift right two bytes from left to result  */
7566 /*-----------------------------------------------------------------*/
7567 static void
7568 shiftR2Left2Result (operand * left, int offl,
7569                     operand * result, int offr,
7570                     int shCount, int sign)
7571 {
7572   char *lsb;
7573   
7574   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7575   
7576   /* a:x >> shCount (x = lsb(result)) */
7577   if (sign)
7578   {
7579      AccAXRshS(lsb, shCount);
7580   }
7581   else
7582   {
7583     AccAXRsh(lsb, shCount);
7584   }
7585   
7586   _storeAxResults(lsb, result, offr);
7587 }
7588 #endif
7589
7590 #if 0
7591 //REMOVE ME!!!
7592 /*-----------------------------------------------------------------*/
7593 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7594 /*-----------------------------------------------------------------*/
7595 static void
7596 shiftLLeftOrResult (operand * left, int offl,
7597                     operand * result, int offr, int shCount)
7598 {
7599   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7600   /* shift left accumulator */
7601   AccLsh (shCount);
7602   /* or with result */
7603   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7604   /* back to result */
7605   aopPut (AOP (result), "a", offr);
7606 }
7607 #endif
7608
7609 #if 0
7610 //REMOVE ME!!!
7611 /*-----------------------------------------------------------------*/
7612 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7613 /*-----------------------------------------------------------------*/
7614 static void
7615 shiftRLeftOrResult (operand * left, int offl,
7616                     operand * result, int offr, int shCount)
7617 {
7618   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7619   /* shift right accumulator */
7620   AccRsh (shCount);
7621   /* or with result */
7622   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7623   /* back to result */
7624   aopPut (AOP (result), "a", offr);
7625 }
7626 #endif
7627
7628 #ifdef BETTER_LITERAL_SHIFT
7629 /*-----------------------------------------------------------------*/
7630 /* genlshOne - left shift a one byte quantity by known count       */
7631 /*-----------------------------------------------------------------*/
7632 static void
7633 genlshOne (operand * result, operand * left, int shCount)
7634 {
7635   D (emitcode (";", "genlshOne "););
7636   shiftL1Left2Result (left, LSB, result, LSB, shCount);
7637 }
7638 #endif
7639
7640 #ifdef BETTER_LITERAL_SHIFT
7641 /*-----------------------------------------------------------------*/
7642 /* genlshTwo - left shift two bytes by known amount != 0           */
7643 /*-----------------------------------------------------------------*/
7644 static void
7645 genlshTwo (operand * result, operand * left, int shCount)
7646 {
7647   int size;
7648
7649   D (emitcode (";", "genlshTwo "););
7650
7651   size = getDataSize (result);
7652
7653   /* if shCount >= 8 */
7654   if (shCount >= 8)
7655   {
7656       shCount -= 8;
7657
7658       _startLazyDPSEvaluation();
7659
7660       if (size > 1)
7661         {
7662           if (shCount)
7663           {
7664             _endLazyDPSEvaluation();
7665             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7666             aopPut (AOP (result), zero, LSB);       
7667           }
7668           else
7669           {
7670             movLeft2Result (left, LSB, result, MSB16, 0);
7671             aopPut (AOP (result), zero, LSB);
7672             _endLazyDPSEvaluation();
7673           }
7674         }
7675         else
7676         {
7677           aopPut (AOP (result), zero, LSB);
7678           _endLazyDPSEvaluation();
7679         }
7680   }
7681
7682   /*  1 <= shCount <= 7 */
7683   else
7684     {
7685       if (size == 1)
7686       {
7687         shiftL1Left2Result (left, LSB, result, LSB, shCount);
7688       }
7689       else
7690       {
7691         shiftL2Left2Result (left, LSB, result, LSB, shCount);
7692       }
7693     }
7694 }
7695 #endif
7696
7697 #if 0
7698 //REMOVE ME!!!
7699 /*-----------------------------------------------------------------*/
7700 /* shiftLLong - shift left one long from left to result            */
7701 /* offl = LSB or MSB16                                             */
7702 /*-----------------------------------------------------------------*/
7703 static void
7704 shiftLLong (operand * left, operand * result, int offr)
7705 {
7706   char *l;
7707   int size = AOP_SIZE (result);
7708
7709   if (size >= LSB + offr)
7710     {
7711       l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
7712       MOVA (l);
7713       emitcode ("add", "a,acc");
7714       if (sameRegs (AOP (left), AOP (result)) &&
7715           size >= MSB16 + offr && offr != LSB)
7716         emitcode ("xch", "a,%s",
7717                   aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
7718       else
7719         aopPut (AOP (result), "a", LSB + offr);
7720     }
7721
7722   if (size >= MSB16 + offr)
7723     {
7724       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7725         {
7726           l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
7727           MOVA (l);
7728         }
7729       emitcode ("rlc", "a");
7730       if (sameRegs (AOP (left), AOP (result)) &&
7731           size >= MSB24 + offr && offr != LSB)
7732         emitcode ("xch", "a,%s",
7733                   aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
7734       else
7735         aopPut (AOP (result), "a", MSB16 + offr);
7736     }
7737
7738   if (size >= MSB24 + offr)
7739     {
7740       if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7741         {
7742           l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
7743           MOVA (l);
7744         }
7745       emitcode ("rlc", "a");
7746       if (sameRegs (AOP (left), AOP (result)) &&
7747           size >= MSB32 + offr && offr != LSB)
7748         emitcode ("xch", "a,%s",
7749                   aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
7750       else
7751         aopPut (AOP (result), "a", MSB24 + offr);
7752     }
7753
7754   if (size > MSB32 + offr)
7755     {
7756       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7757         {
7758           l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
7759           MOVA (l);
7760         }
7761       emitcode ("rlc", "a");
7762       aopPut (AOP (result), "a", MSB32 + offr);
7763     }
7764   if (offr != LSB)
7765     aopPut (AOP (result), zero, LSB);
7766 }
7767 #endif
7768
7769 #if 0
7770 //REMOVE ME!!!
7771 /*-----------------------------------------------------------------*/
7772 /* genlshFour - shift four byte by a known amount != 0             */
7773 /*-----------------------------------------------------------------*/
7774 static void
7775 genlshFour (operand * result, operand * left, int shCount)
7776 {
7777   int size;
7778
7779   D (emitcode (";", "genlshFour ");
7780     );
7781
7782   size = AOP_SIZE (result);
7783
7784   /* if shifting more that 3 bytes */
7785   if (shCount >= 24)
7786     {
7787       shCount -= 24;
7788       if (shCount)
7789         /* lowest order of left goes to the highest
7790            order of the destination */
7791         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7792       else
7793         movLeft2Result (left, LSB, result, MSB32, 0);
7794       aopPut (AOP (result), zero, LSB);
7795       aopPut (AOP (result), zero, MSB16);
7796       aopPut (AOP (result), zero, MSB24);
7797       return;
7798     }
7799
7800   /* more than two bytes */
7801   else if (shCount >= 16)
7802     {
7803       /* lower order two bytes goes to higher order two bytes */
7804       shCount -= 16;
7805       /* if some more remaining */
7806       if (shCount)
7807         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7808       else
7809         {
7810           movLeft2Result (left, MSB16, result, MSB32, 0);
7811           movLeft2Result (left, LSB, result, MSB24, 0);
7812         }
7813       aopPut (AOP (result), zero, MSB16);
7814       aopPut (AOP (result), zero, LSB);
7815       return;
7816     }
7817
7818   /* if more than 1 byte */
7819   else if (shCount >= 8)
7820     {
7821       /* lower order three bytes goes to higher order  three bytes */
7822       shCount -= 8;
7823       if (size == 2)
7824         {
7825           if (shCount)
7826             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7827           else
7828             movLeft2Result (left, LSB, result, MSB16, 0);
7829         }
7830       else
7831         {                       /* size = 4 */
7832           if (shCount == 0)
7833             {
7834               movLeft2Result (left, MSB24, result, MSB32, 0);
7835               movLeft2Result (left, MSB16, result, MSB24, 0);
7836               movLeft2Result (left, LSB, result, MSB16, 0);
7837               aopPut (AOP (result), zero, LSB);
7838             }
7839           else if (shCount == 1)
7840             shiftLLong (left, result, MSB16);
7841           else
7842             {
7843               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7844               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7845               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7846               aopPut (AOP (result), zero, LSB);
7847             }
7848         }
7849     }
7850
7851   /* 1 <= shCount <= 7 */
7852   else if (shCount <= 2)
7853     {
7854       shiftLLong (left, result, LSB);
7855       if (shCount == 2)
7856         shiftLLong (result, result, LSB);
7857     }
7858   /* 3 <= shCount <= 7, optimize */
7859   else
7860     {
7861       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7862       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7863       shiftL2Left2Result (left, LSB, result, LSB, shCount);
7864     }
7865 }
7866 #endif
7867
7868 #ifdef BETTER_LITERAL_SHIFT
7869 /*-----------------------------------------------------------------*/
7870 /* genLeftShiftLiteral - left shifting by known count              */
7871 /*-----------------------------------------------------------------*/
7872 static bool
7873 genLeftShiftLiteral (operand * left,
7874                      operand * right,
7875                      operand * result,
7876                      iCode * ic)
7877 {
7878   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7879   int size;
7880
7881   size = getSize (operandType (result));
7882
7883   D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
7884
7885   /* We only handle certain easy cases so far. */
7886   if ((shCount != 0)
7887    && (shCount < (size * 8))
7888    && (size != 1)
7889    && (size != 2))
7890   {
7891       D(emitcode (";", "genLeftShiftLiteral wimping out"););    
7892       return FALSE;
7893   }
7894
7895   freeAsmop (right, NULL, ic, TRUE);
7896
7897   aopOp(left, ic, FALSE, FALSE);
7898   aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
7899
7900 #if 0 // debug spew
7901   if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
7902   {
7903         emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
7904         if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
7905         {
7906            emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
7907         }
7908   }
7909   if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
7910   {
7911         emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
7912         if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
7913         {
7914            emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
7915         }       
7916   }  
7917 #endif
7918   
7919 #if VIEW_SIZE
7920   emitcode ("; shift left ", "result %d, left %d", size,
7921             AOP_SIZE (left));
7922 #endif
7923
7924   /* I suppose that the left size >= result size */
7925   if (shCount == 0)
7926   {
7927         _startLazyDPSEvaluation();
7928         while (size--)
7929         {
7930           movLeft2Result (left, size, result, size, 0);
7931         }
7932         _endLazyDPSEvaluation();
7933   }
7934   else if (shCount >= (size * 8))
7935   {
7936     _startLazyDPSEvaluation();
7937     while (size--)
7938     {
7939       aopPut (AOP (result), zero, size);
7940     }
7941     _endLazyDPSEvaluation();
7942   }
7943   else
7944   {
7945       switch (size)
7946         {
7947         case 1:
7948           genlshOne (result, left, shCount);
7949           break;
7950
7951         case 2:
7952           genlshTwo (result, left, shCount);
7953           break;
7954 #if 0
7955         case 4:
7956           genlshFour (result, left, shCount);
7957           break;
7958 #endif
7959         default:
7960           fprintf(stderr, "*** ack! mystery literal shift!\n");   
7961           break;
7962         }
7963     }
7964   freeAsmop (left, NULL, ic, TRUE);
7965   freeAsmop (result, NULL, ic, TRUE);
7966   return TRUE;
7967 }
7968 #endif
7969
7970 /*-----------------------------------------------------------------*/
7971 /* genLeftShift - generates code for left shifting                 */
7972 /*-----------------------------------------------------------------*/
7973 static void
7974 genLeftShift (iCode * ic)
7975 {
7976   operand *left, *right, *result;
7977   int size, offset;
7978   char *l;
7979   symbol *tlbl, *tlbl1;
7980
7981   D (emitcode (";", "genLeftShift "););
7982
7983   right = IC_RIGHT (ic);
7984   left = IC_LEFT (ic);
7985   result = IC_RESULT (ic);
7986
7987   aopOp (right, ic, FALSE, FALSE);
7988
7989
7990 #ifdef BETTER_LITERAL_SHIFT
7991   /* if the shift count is known then do it
7992      as efficiently as possible */
7993   if (AOP_TYPE (right) == AOP_LIT)
7994     {
7995       if (genLeftShiftLiteral (left, right, result, ic))
7996       {
7997         return;
7998       }
7999     }
8000 #endif
8001
8002   /* shift count is unknown then we have to form
8003      a loop get the loop count in B : Note: we take
8004      only the lower order byte since shifting
8005      more that 32 bits make no sense anyway, ( the
8006      largest size of an object can be only 32 bits ) */
8007
8008   if (AOP_TYPE (right) == AOP_LIT)
8009   {
8010       /* Really should be handled by genLeftShiftLiteral,
8011        * but since I'm too lazy to fix that today, at least we can make
8012        * some small improvement.
8013        */
8014        emitcode("mov", "b,#!constbyte",
8015                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8016   }
8017   else
8018   {
8019         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8020         emitcode ("inc", "b");
8021   }
8022   freeAsmop (right, NULL, ic, TRUE);
8023   aopOp (left, ic, FALSE, FALSE);
8024   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8025
8026   /* now move the left to the result if they are not the
8027      same */
8028   if (!sameRegs (AOP (left), AOP (result)) &&
8029       AOP_SIZE (result) > 1)
8030     {
8031
8032       size = AOP_SIZE (result);
8033       offset = 0;
8034       _startLazyDPSEvaluation ();
8035       while (size--)
8036         {
8037           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8038           if (*l == '@' && (IS_AOP_PREG (result)))
8039             {
8040
8041               emitcode ("mov", "a,%s", l);
8042               aopPut (AOP (result), "a", offset);
8043             }
8044           else
8045             aopPut (AOP (result), l, offset);
8046           offset++;
8047         }
8048       _endLazyDPSEvaluation ();
8049     }
8050
8051   tlbl = newiTempLabel (NULL);
8052   size = AOP_SIZE (result);
8053   offset = 0;
8054   tlbl1 = newiTempLabel (NULL);
8055
8056   /* if it is only one byte then */
8057   if (size == 1)
8058     {
8059       symbol *tlbl1 = newiTempLabel (NULL);
8060
8061       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8062       MOVA (l);
8063       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8064       emitcode ("", "!tlabeldef", tlbl->key + 100);
8065       emitcode ("add", "a,acc");
8066       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8067       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8068       aopPut (AOP (result), "a", 0);
8069       goto release;
8070     }
8071
8072   reAdjustPreg (AOP (result));
8073
8074   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8075   emitcode ("", "!tlabeldef", tlbl->key + 100);
8076   l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8077   MOVA (l);
8078   emitcode ("add", "a,acc");
8079   aopPut (AOP (result), "a", offset++);
8080   _startLazyDPSEvaluation ();
8081   while (--size)
8082     {
8083       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8084       MOVA (l);
8085       emitcode ("rlc", "a");
8086       aopPut (AOP (result), "a", offset++);
8087     }
8088   _endLazyDPSEvaluation ();
8089   reAdjustPreg (AOP (result));
8090
8091   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8092   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8093 release:
8094   freeAsmop (left, NULL, ic, TRUE);
8095   freeAsmop (result, NULL, ic, TRUE);
8096 }
8097
8098 #ifdef BETTER_LITERAL_SHIFT
8099 /*-----------------------------------------------------------------*/
8100 /* genrshOne - right shift a one byte quantity by known count      */
8101 /*-----------------------------------------------------------------*/
8102 static void
8103 genrshOne (operand * result, operand * left,
8104            int shCount, int sign)
8105 {
8106   D (emitcode (";", "genrshOne"););
8107   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8108 }
8109 #endif
8110
8111 #ifdef BETTER_LITERAL_SHIFT
8112 /*-----------------------------------------------------------------*/
8113 /* genrshTwo - right shift two bytes by known amount != 0          */
8114 /*-----------------------------------------------------------------*/
8115 static void
8116 genrshTwo (operand * result, operand * left,
8117            int shCount, int sign)
8118 {
8119   D (emitcode (";", "genrshTwo"););
8120
8121   /* if shCount >= 8 */
8122   if (shCount >= 8)
8123     {
8124       shCount -= 8;
8125       _startLazyDPSEvaluation();
8126       if (shCount)
8127       {
8128         shiftR1Left2Result (left, MSB16, result, LSB,
8129                             shCount, sign);
8130       }                     
8131       else
8132       {
8133         movLeft2Result (left, MSB16, result, LSB, sign);
8134       }
8135       addSign (result, MSB16, sign);
8136       _endLazyDPSEvaluation();
8137     }
8138
8139   /*  1 <= shCount <= 7 */
8140   else
8141   {
8142     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8143   }
8144 }
8145 #endif
8146
8147 #if 0
8148 //REMOVE ME!!!
8149 /*-----------------------------------------------------------------*/
8150 /* shiftRLong - shift right one long from left to result           */
8151 /* offl = LSB or MSB16                                             */
8152 /*-----------------------------------------------------------------*/
8153 static void
8154 shiftRLong (operand * left, int offl,
8155             operand * result, int sign)
8156 {
8157   int isSameRegs=sameRegs(AOP(left),AOP(result));
8158
8159   if (isSameRegs && offl>1) {
8160     // we are in big trouble, but this shouldn't happen
8161     werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8162   }
8163
8164   MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
8165   
8166   if (offl==MSB16) {
8167     // shift is > 8
8168     if (sign) {
8169       emitcode ("rlc", "a");
8170       emitcode ("subb", "a,acc");
8171       emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
8172     } else {
8173       aopPut (AOP(result), zero, MSB32);
8174     }
8175   }
8176
8177   if (!sign) {
8178     emitcode ("clr", "c");
8179   } else {
8180     emitcode ("mov", "c,acc.7");
8181   }
8182
8183   emitcode ("rrc", "a");
8184
8185   if (isSameRegs && offl==MSB16) {
8186     emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
8187   } else {
8188     aopPut (AOP (result), "a", MSB32);
8189     MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
8190   }
8191
8192   emitcode ("rrc", "a");
8193   if (isSameRegs && offl==1) {
8194     emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
8195   } else {
8196     aopPut (AOP (result), "a", MSB24);
8197     MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
8198   }
8199   emitcode ("rrc", "a");
8200   aopPut (AOP (result), "a", MSB16 - offl);
8201
8202   if (offl == LSB)
8203     {
8204       MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
8205       emitcode ("rrc", "a");
8206       aopPut (AOP (result), "a", LSB);
8207     }
8208 }
8209 #endif
8210
8211 #if 0
8212 //REMOVE ME!!!
8213 /*-----------------------------------------------------------------*/
8214 /* genrshFour - shift four byte by a known amount != 0             */
8215 /*-----------------------------------------------------------------*/
8216 static void
8217 genrshFour (operand * result, operand * left,
8218             int shCount, int sign)
8219 {
8220   D (emitcode (";", "genrshFour");
8221     );
8222
8223   /* if shifting more that 3 bytes */
8224   if (shCount >= 24)
8225     {
8226       shCount -= 24;
8227       if (shCount)
8228         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8229       else
8230         movLeft2Result (left, MSB32, result, LSB, sign);
8231       addSign (result, MSB16, sign);
8232     }
8233   else if (shCount >= 16)
8234     {
8235       shCount -= 16;
8236       if (shCount)
8237         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8238       else
8239         {
8240           movLeft2Result (left, MSB24, result, LSB, 0);
8241           movLeft2Result (left, MSB32, result, MSB16, sign);
8242         }
8243       addSign (result, MSB24, sign);
8244     }
8245   else if (shCount >= 8)
8246     {
8247       shCount -= 8;
8248       if (shCount == 1)
8249         shiftRLong (left, MSB16, result, sign);
8250       else if (shCount == 0)
8251         {
8252           movLeft2Result (left, MSB16, result, LSB, 0);
8253           movLeft2Result (left, MSB24, result, MSB16, 0);
8254           movLeft2Result (left, MSB32, result, MSB24, sign);
8255           addSign (result, MSB32, sign);
8256         }
8257       else
8258         {
8259           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8260           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8261           /* the last shift is signed */
8262           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8263           addSign (result, MSB32, sign);
8264         }
8265     }
8266   else
8267     {                           /* 1 <= shCount <= 7 */
8268       if (shCount <= 2)
8269         {
8270           shiftRLong (left, LSB, result, sign);
8271           if (shCount == 2)
8272             shiftRLong (result, LSB, result, sign);
8273         }
8274       else
8275         {
8276           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8277           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8278           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8279         }
8280     }
8281 }
8282 #endif
8283
8284 #ifdef BETTER_LITERAL_SHIFT
8285 /*-----------------------------------------------------------------*/
8286 /* genRightShiftLiteral - right shifting by known count            */
8287 /*-----------------------------------------------------------------*/
8288 static bool
8289 genRightShiftLiteral (operand * left,
8290                       operand * right,
8291                       operand * result,
8292                       iCode * ic,
8293                       int sign)
8294 {
8295   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8296   int size;
8297
8298   size = getSize (operandType (result));
8299
8300   D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8301
8302   /* We only handle certain easy cases so far. */
8303   if ((shCount != 0)
8304    && (shCount < (size * 8))
8305    && (size != 1)
8306    && (size != 2))
8307   {
8308       D(emitcode (";", "genRightShiftLiteral wimping out"););   
8309       return FALSE;
8310   }
8311
8312   freeAsmop (right, NULL, ic, TRUE);
8313
8314   aopOp (left, ic, FALSE, FALSE);
8315   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8316
8317 #if VIEW_SIZE
8318   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8319             AOP_SIZE (left));
8320 #endif
8321
8322   /* test the LEFT size !!! */
8323
8324   /* I suppose that the left size >= result size */
8325   if (shCount == 0)
8326   {
8327       size = getDataSize (result);
8328       _startLazyDPSEvaluation();
8329       while (size--)
8330       {
8331         movLeft2Result (left, size, result, size, 0);
8332       }
8333       _endLazyDPSEvaluation();
8334   }
8335   else if (shCount >= (size * 8))
8336     {
8337       if (sign)
8338       {
8339         /* get sign in acc.7 */
8340         MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
8341       }
8342       addSign (result, LSB, sign);
8343     }
8344   else
8345     {
8346       switch (size)
8347         {
8348         case 1:
8349           genrshOne (result, left, shCount, sign);
8350           break;
8351
8352         case 2:
8353           genrshTwo (result, left, shCount, sign);
8354           break;
8355 #if 0
8356         case 4:
8357           genrshFour (result, left, shCount, sign);
8358           break;
8359 #endif    
8360         default:
8361           break;
8362         }
8363
8364       freeAsmop (left, NULL, ic, TRUE);
8365       freeAsmop (result, NULL, ic, TRUE);
8366     }
8367     return TRUE;
8368 }
8369 #endif
8370
8371 /*-----------------------------------------------------------------*/
8372 /* genSignedRightShift - right shift of signed number              */
8373 /*-----------------------------------------------------------------*/
8374 static void
8375 genSignedRightShift (iCode * ic)
8376 {
8377   operand *right, *left, *result;
8378   int size, offset;
8379   char *l;
8380   symbol *tlbl, *tlbl1;
8381
8382   D (emitcode (";", "genSignedRightShift "););
8383
8384   /* we do it the hard way put the shift count in b
8385      and loop thru preserving the sign */
8386
8387   right = IC_RIGHT (ic);
8388   left = IC_LEFT (ic);
8389   result = IC_RESULT (ic);
8390
8391   aopOp (right, ic, FALSE, FALSE);
8392
8393 #ifdef BETTER_LITERAL_SHIFT
8394   if (AOP_TYPE (right) == AOP_LIT)
8395     {
8396       if (genRightShiftLiteral (left, right, result, ic, 1))
8397       {
8398         return;
8399       }
8400     }
8401 #endif
8402   /* shift count is unknown then we have to form
8403      a loop get the loop count in B : Note: we take
8404      only the lower order byte since shifting
8405      more that 32 bits make no sense anyway, ( the
8406      largest size of an object can be only 32 bits ) */
8407
8408   if (AOP_TYPE (right) == AOP_LIT)
8409   {
8410       /* Really should be handled by genRightShiftLiteral,
8411        * but since I'm too lazy to fix that today, at least we can make
8412        * some small improvement.
8413        */
8414        emitcode("mov", "b,#!constbyte",
8415                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8416   }
8417   else
8418   {
8419         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8420         emitcode ("inc", "b");
8421   }
8422   freeAsmop (right, NULL, ic, TRUE);
8423   aopOp (left, ic, FALSE, FALSE);
8424   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8425
8426   /* now move the left to the result if they are not the
8427      same */
8428   if (!sameRegs (AOP (left), AOP (result)) &&
8429       AOP_SIZE (result) > 1)
8430     {
8431
8432       size = AOP_SIZE (result);
8433       offset = 0;
8434       _startLazyDPSEvaluation ();
8435       while (size--)
8436         {
8437           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8438           if (*l == '@' && IS_AOP_PREG (result))
8439             {
8440
8441               emitcode ("mov", "a,%s", l);
8442               aopPut (AOP (result), "a", offset);
8443             }
8444           else
8445             aopPut (AOP (result), l, offset);
8446           offset++;
8447         }
8448       _endLazyDPSEvaluation ();
8449     }
8450
8451   /* mov the highest order bit to OVR */
8452   tlbl = newiTempLabel (NULL);
8453   tlbl1 = newiTempLabel (NULL);
8454
8455   size = AOP_SIZE (result);
8456   offset = size - 1;
8457   emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
8458   emitcode ("rlc", "a");
8459   emitcode ("mov", "ov,c");
8460   /* if it is only one byte then */
8461   if (size == 1)
8462     {
8463       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8464       MOVA (l);
8465       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8466       emitcode ("", "!tlabeldef", tlbl->key + 100);
8467       emitcode ("mov", "c,ov");
8468       emitcode ("rrc", "a");
8469       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8470       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8471       aopPut (AOP (result), "a", 0);
8472       goto release;
8473     }
8474
8475   reAdjustPreg (AOP (result));
8476   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8477   emitcode ("", "!tlabeldef", tlbl->key + 100);
8478   emitcode ("mov", "c,ov");
8479   _startLazyDPSEvaluation ();
8480   while (size--)
8481     {
8482       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8483       MOVA (l);
8484       emitcode ("rrc", "a");
8485       aopPut (AOP (result), "a", offset--);
8486     }
8487   _endLazyDPSEvaluation ();
8488   reAdjustPreg (AOP (result));
8489   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8490   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8491
8492 release:
8493   freeAsmop (left, NULL, ic, TRUE);
8494   freeAsmop (result, NULL, ic, TRUE);
8495 }
8496
8497 /*-----------------------------------------------------------------*/
8498 /* genRightShift - generate code for right shifting                */
8499 /*-----------------------------------------------------------------*/
8500 static void
8501 genRightShift (iCode * ic)
8502 {
8503   operand *right, *left, *result;
8504   sym_link *retype;
8505   int size, offset;
8506   char *l;
8507   symbol *tlbl, *tlbl1;
8508
8509   D (emitcode (";", "genRightShift "););
8510
8511   /* if signed then we do it the hard way preserve the
8512      sign bit moving it inwards */
8513   retype = getSpec (operandType (IC_RESULT (ic)));
8514
8515   if (!SPEC_USIGN (retype))
8516     {
8517       genSignedRightShift (ic);
8518       return;
8519     }
8520
8521   /* signed & unsigned types are treated the same : i.e. the
8522      signed is NOT propagated inwards : quoting from the
8523      ANSI - standard : "for E1 >> E2, is equivalent to division
8524      by 2**E2 if unsigned or if it has a non-negative value,
8525      otherwise the result is implementation defined ", MY definition
8526      is that the sign does not get propagated */
8527
8528   right = IC_RIGHT (ic);
8529   left = IC_LEFT (ic);
8530   result = IC_RESULT (ic);
8531
8532   aopOp (right, ic, FALSE, FALSE);
8533
8534 #ifdef BETTER_LITERAL_SHIFT
8535   /* if the shift count is known then do it
8536      as efficiently as possible */
8537   if (AOP_TYPE (right) == AOP_LIT)
8538     {
8539       if (genRightShiftLiteral (left, right, result, ic, 0))
8540       {
8541         return;
8542       }
8543     }
8544 #endif
8545
8546   /* shift count is unknown then we have to form
8547      a loop get the loop count in B : Note: we take
8548      only the lower order byte since shifting
8549      more that 32 bits make no sense anyway, ( the
8550      largest size of an object can be only 32 bits ) */
8551   
8552   if (AOP_TYPE (right) == AOP_LIT)
8553   {
8554       /* Really should be handled by genRightShiftLiteral,
8555        * but since I'm too lazy to fix that today, at least we can make
8556        * some small improvement.
8557        */
8558        emitcode("mov", "b,#!constbyte",
8559                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8560   }
8561   else
8562   {
8563         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8564         emitcode ("inc", "b");
8565   }
8566   freeAsmop (right, NULL, ic, TRUE);
8567   aopOp (left, ic, FALSE, FALSE);
8568   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8569
8570   /* now move the left to the result if they are not the
8571      same */
8572   if (!sameRegs (AOP (left), AOP (result)) &&
8573       AOP_SIZE (result) > 1)
8574     {
8575
8576       size = AOP_SIZE (result);
8577       offset = 0;
8578       _startLazyDPSEvaluation ();
8579       while (size--)
8580         {
8581           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8582           if (*l == '@' && IS_AOP_PREG (result))
8583             {
8584
8585               emitcode ("mov", "a,%s", l);
8586               aopPut (AOP (result), "a", offset);
8587             }
8588           else
8589             aopPut (AOP (result), l, offset);
8590           offset++;
8591         }
8592       _endLazyDPSEvaluation ();
8593     }
8594
8595   tlbl = newiTempLabel (NULL);
8596   tlbl1 = newiTempLabel (NULL);
8597   size = AOP_SIZE (result);
8598   offset = size - 1;
8599
8600   /* if it is only one byte then */
8601   if (size == 1)
8602     {
8603       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8604       MOVA (l);
8605       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8606       emitcode ("", "!tlabeldef", tlbl->key + 100);
8607       CLRC;
8608       emitcode ("rrc", "a");
8609       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8610       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8611       aopPut (AOP (result), "a", 0);
8612       goto release;
8613     }
8614
8615   reAdjustPreg (AOP (result));
8616   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8617   emitcode ("", "!tlabeldef", tlbl->key + 100);
8618   CLRC;
8619   _startLazyDPSEvaluation ();
8620   while (size--)
8621     {
8622       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8623       MOVA (l);
8624       emitcode ("rrc", "a");
8625       aopPut (AOP (result), "a", offset--);
8626     }
8627   _endLazyDPSEvaluation ();
8628   reAdjustPreg (AOP (result));
8629
8630   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8631   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8632
8633 release:
8634   freeAsmop (left, NULL, ic, TRUE);
8635   freeAsmop (result, NULL, ic, TRUE);
8636 }
8637
8638 /*-----------------------------------------------------------------*/
8639 /* genUnpackBits - generates code for unpacking bits               */
8640 /*-----------------------------------------------------------------*/
8641 static void
8642 genUnpackBits (operand * result, char *rname, int ptype)
8643 {
8644   int shCnt;
8645   int rlen = 0;
8646   sym_link *etype;
8647   int offset = 0;
8648
8649   D (emitcode (";", "genUnpackBits ");
8650     );
8651
8652   etype = getSpec (operandType (result));
8653
8654   /* read the first byte  */
8655   switch (ptype)
8656     {
8657
8658     case POINTER:
8659     case IPOINTER:
8660       emitcode ("mov", "a,@%s", rname);
8661       break;
8662
8663     case PPOINTER:
8664       emitcode ("movx", "a,@%s", rname);
8665       break;
8666
8667     case FPOINTER:
8668       emitcode ("movx", "a,@dptr");
8669       break;
8670
8671     case CPOINTER:
8672       emitcode ("clr", "a");
8673       emitcode ("movc", "a,@a+dptr");
8674       break;
8675
8676     case GPOINTER:
8677       emitcode ("lcall", "__gptrget");
8678       break;
8679     }
8680
8681   /* if we have bitdisplacement then it fits   */
8682   /* into this byte completely or if length is */
8683   /* less than a byte                          */
8684   if ((shCnt = SPEC_BSTR (etype)) ||
8685       (SPEC_BLEN (etype) <= 8))
8686     {
8687
8688       /* shift right acc */
8689       AccRsh (shCnt);
8690
8691       emitcode ("anl", "a,#!constbyte",
8692                 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
8693       aopPut (AOP (result), "a", offset);
8694       return;
8695     }
8696
8697   /* bit field did not fit in a byte  */
8698   rlen = SPEC_BLEN (etype) - 8;
8699   aopPut (AOP (result), "a", offset++);
8700
8701   while (1)
8702     {
8703
8704       switch (ptype)
8705         {
8706         case POINTER:
8707         case IPOINTER:
8708           emitcode ("inc", "%s", rname);
8709           emitcode ("mov", "a,@%s", rname);
8710           break;
8711
8712         case PPOINTER:
8713           emitcode ("inc", "%s", rname);
8714           emitcode ("movx", "a,@%s", rname);
8715           break;
8716
8717         case FPOINTER:
8718           emitcode ("inc", "dptr");
8719           emitcode ("movx", "a,@dptr");
8720           break;
8721
8722         case CPOINTER:
8723           emitcode ("clr", "a");
8724           emitcode ("inc", "dptr");
8725           emitcode ("movc", "a,@a+dptr");
8726           break;
8727
8728         case GPOINTER:
8729           emitcode ("inc", "dptr");
8730           emitcode ("lcall", "__gptrget");
8731           break;
8732         }
8733
8734       rlen -= 8;
8735       /* if we are done */
8736       if (rlen < 8)
8737         break;
8738
8739       aopPut (AOP (result), "a", offset++);
8740
8741     }
8742
8743   if (rlen)
8744     {
8745       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (rlen));
8746       aopPut (AOP (result), "a", offset);
8747     }
8748
8749   return;
8750 }
8751
8752
8753 /*-----------------------------------------------------------------*/
8754 /* genDataPointerGet - generates code when ptr offset is known     */
8755 /*-----------------------------------------------------------------*/
8756 static void
8757 genDataPointerGet (operand * left,
8758                    operand * result,
8759                    iCode * ic)
8760 {
8761   char *l;
8762   char buffer[256];
8763   int size, offset = 0;
8764   aopOp (result, ic, TRUE, FALSE);
8765
8766   /* get the string representation of the name */
8767   l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
8768   size = AOP_SIZE (result);
8769   _startLazyDPSEvaluation ();
8770   while (size--)
8771     {
8772       if (offset)
8773         sprintf (buffer, "(%s + %d)", l + 1, offset);
8774       else
8775         sprintf (buffer, "%s", l + 1);
8776       aopPut (AOP (result), buffer, offset++);
8777     }
8778   _endLazyDPSEvaluation ();
8779
8780   freeAsmop (left, NULL, ic, TRUE);
8781   freeAsmop (result, NULL, ic, TRUE);
8782 }
8783
8784 /*-----------------------------------------------------------------*/
8785 /* genNearPointerGet - emitcode for near pointer fetch             */
8786 /*-----------------------------------------------------------------*/
8787 static void
8788 genNearPointerGet (operand * left,
8789                    operand * result,
8790                    iCode * ic,
8791                    iCode *pi)
8792 {
8793   asmop *aop = NULL;
8794   regs *preg = NULL;
8795   char *rname;
8796   sym_link *rtype, *retype, *letype;
8797   sym_link *ltype = operandType (left);
8798   char buffer[80];
8799
8800   rtype = operandType (result);
8801   retype = getSpec (rtype);
8802   letype = getSpec (ltype);
8803
8804   aopOp (left, ic, FALSE, FALSE);
8805
8806   /* if left is rematerialisable and
8807      result is not bit variable type and
8808      the left is pointer to data space i.e
8809      lower 128 bytes of space */
8810   if (AOP_TYPE (left) == AOP_IMMD &&
8811       !IS_BITVAR (retype) &&
8812       !IS_BITVAR (letype) &&
8813       DCL_TYPE (ltype) == POINTER)
8814     {
8815       genDataPointerGet (left, result, ic);
8816       return;
8817     }
8818
8819   /* if the value is already in a pointer register
8820      then don't need anything more */
8821   if (!AOP_INPREG (AOP (left)))
8822     {
8823       /* otherwise get a free pointer register */
8824       aop = newAsmop (0);
8825       preg = getFreePtr (ic, &aop, FALSE);
8826       emitcode ("mov", "%s,%s",
8827                 preg->name,
8828                 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8829       rname = preg->name;
8830     }
8831   else
8832     rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8833
8834   freeAsmop (left, NULL, ic, TRUE);
8835   aopOp (result, ic, FALSE, FALSE);
8836
8837   /* if bitfield then unpack the bits */
8838   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8839     genUnpackBits (result, rname, POINTER);
8840   else
8841     {
8842       /* we have can just get the values */
8843       int size = AOP_SIZE (result);
8844       int offset = 0;
8845
8846       while (size--)
8847         {
8848           if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8849             {
8850
8851               emitcode ("mov", "a,@%s", rname);
8852               aopPut (AOP (result), "a", offset);
8853             }
8854           else
8855             {
8856               sprintf (buffer, "@%s", rname);
8857               aopPut (AOP (result), buffer, offset);
8858             }
8859           offset++;
8860           if (size || pi)
8861             emitcode ("inc", "%s", rname);
8862         }
8863     }
8864
8865   /* now some housekeeping stuff */
8866   if (aop)
8867     {
8868       /* we had to allocate for this iCode */
8869       if (pi) { /* post increment present */
8870         aopPut(AOP ( left ),rname,0);
8871       }
8872       freeAsmop (NULL, aop, ic, TRUE);
8873     }
8874   else
8875     {
8876       /* we did not allocate which means left
8877          already in a pointer register, then
8878          if size > 0 && this could be used again
8879          we have to point it back to where it
8880          belongs */
8881       if (AOP_SIZE (result) > 1 &&
8882           !OP_SYMBOL (left)->remat &&
8883           (OP_SYMBOL (left)->liveTo > ic->seq ||
8884            ic->depth) &&
8885           !pi)
8886         {
8887           int size = AOP_SIZE (result) - 1;
8888           while (size--)
8889             emitcode ("dec", "%s", rname);
8890         }
8891     }
8892
8893   /* done */
8894   freeAsmop (result, NULL, ic, TRUE);
8895   if (pi) pi->generated = 1;
8896 }
8897
8898 /*-----------------------------------------------------------------*/
8899 /* genPagedPointerGet - emitcode for paged pointer fetch           */
8900 /*-----------------------------------------------------------------*/
8901 static void
8902 genPagedPointerGet (operand * left,
8903                     operand * result,
8904                     iCode * ic,
8905                     iCode * pi)
8906 {
8907   asmop *aop = NULL;
8908   regs *preg = NULL;
8909   char *rname;
8910   sym_link *rtype, *retype, *letype;
8911
8912   rtype = operandType (result);
8913   retype = getSpec (rtype);
8914   letype = getSpec (operandType (left));
8915   aopOp (left, ic, FALSE, FALSE);
8916
8917   /* if the value is already in a pointer register
8918      then don't need anything more */
8919   if (!AOP_INPREG (AOP (left)))
8920     {
8921       /* otherwise get a free pointer register */
8922       aop = newAsmop (0);
8923       preg = getFreePtr (ic, &aop, FALSE);
8924       emitcode ("mov", "%s,%s",
8925                 preg->name,
8926                 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8927       rname = preg->name;
8928     }
8929   else
8930     rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8931
8932   freeAsmop (left, NULL, ic, TRUE);
8933   aopOp (result, ic, FALSE, FALSE);
8934
8935   /* if bitfield then unpack the bits */
8936   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8937     genUnpackBits (result, rname, PPOINTER);
8938   else
8939     {
8940       /* we have can just get the values */
8941       int size = AOP_SIZE (result);
8942       int offset = 0;
8943
8944       while (size--)
8945         {
8946
8947           emitcode ("movx", "a,@%s", rname);
8948           aopPut (AOP (result), "a", offset);
8949
8950           offset++;
8951
8952           if (size || pi)
8953             emitcode ("inc", "%s", rname);
8954         }
8955     }
8956
8957   /* now some housekeeping stuff */
8958   if (aop)
8959     {
8960       /* we had to allocate for this iCode */
8961       if (pi) aopPut ( AOP (left), rname, 0);
8962       freeAsmop (NULL, aop, ic, TRUE);
8963     }
8964   else
8965     {
8966       /* we did not allocate which means left
8967          already in a pointer register, then
8968          if size > 0 && this could be used again
8969          we have to point it back to where it
8970          belongs */
8971       if (AOP_SIZE (result) > 1 &&
8972           !OP_SYMBOL (left)->remat &&
8973           (OP_SYMBOL (left)->liveTo > ic->seq ||
8974            ic->depth) &&
8975           !pi)
8976         {
8977           int size = AOP_SIZE (result) - 1;
8978           while (size--)
8979             emitcode ("dec", "%s", rname);
8980         }
8981     }
8982
8983   /* done */
8984   freeAsmop (result, NULL, ic, TRUE);
8985   if (pi) pi->generated = 1;
8986 }
8987
8988 /*-----------------------------------------------------------------*/
8989 /* genFarPointerGet - gget value from far space                    */
8990 /*-----------------------------------------------------------------*/
8991 static void
8992 genFarPointerGet (operand * left,
8993                   operand * result, iCode * ic, iCode *pi)
8994 {
8995     int size, offset, dopi=1;
8996   sym_link *retype = getSpec (operandType (result));
8997   sym_link *letype = getSpec (operandType (left));
8998   D (emitcode (";", "genFarPointerGet");
8999     );
9000
9001   aopOp (left, ic, FALSE, FALSE);
9002
9003   /* if the operand is already in dptr
9004      then we do nothing else we move the value to dptr */
9005   if (AOP_TYPE (left) != AOP_STR)
9006     {
9007       /* if this is remateriazable */
9008       if (AOP_TYPE (left) == AOP_IMMD)
9009         {
9010           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9011         }
9012       else
9013         {
9014           /* we need to get it byte by byte */
9015           _startLazyDPSEvaluation ();
9016           if (AOP_TYPE (left) != AOP_DPTR)
9017             {
9018               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9019               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9020               if (options.model == MODEL_FLAT24)
9021                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9022             }
9023           else
9024             {
9025               /* We need to generate a load to DPTR indirect through DPTR. */
9026               D (emitcode (";", "genFarPointerGet -- indirection special case.");
9027                 );
9028               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
9029               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
9030               if (options.model == MODEL_FLAT24)
9031                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9032               emitcode ("pop", "dph");
9033               emitcode ("pop", "dpl");
9034               dopi =0;
9035             }
9036           _endLazyDPSEvaluation ();
9037         }
9038     }
9039   /* so dptr know contains the address */
9040   aopOp (result, ic, FALSE, TRUE);
9041
9042   /* if bit then unpack */
9043   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9044     genUnpackBits (result, "dptr", FPOINTER);
9045   else
9046     {
9047       size = AOP_SIZE (result);
9048       offset = 0;
9049
9050       _startLazyDPSEvaluation ();
9051       while (size--)
9052         {
9053
9054           genSetDPTR (0);
9055           _flushLazyDPS ();
9056
9057           emitcode ("movx", "a,@dptr");
9058           if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9059             emitcode ("inc", "dptr");
9060
9061           aopPut (AOP (result), "a", offset++);
9062         }
9063       _endLazyDPSEvaluation ();
9064     }
9065   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9066     aopPut ( AOP (left), "dpl", 0);
9067     aopPut ( AOP (left), "dph", 1);
9068     if (options.model == MODEL_FLAT24)
9069             aopPut ( AOP (left), "dpx", 2);
9070     pi->generated = 1;
9071   } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9072              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9073       
9074       size = AOP_SIZE (result) - 1;
9075       while (size--) emitcode ("lcall","__decdptr");
9076   }
9077
9078   freeAsmop (left, NULL, ic, TRUE);
9079   freeAsmop (result, NULL, ic, TRUE);
9080 }
9081
9082 /*-----------------------------------------------------------------*/
9083 /* emitcodePointerGet - gget value from code space                  */
9084 /*-----------------------------------------------------------------*/
9085 static void
9086 emitcodePointerGet (operand * left,
9087                     operand * result, iCode * ic, iCode *pi)
9088 {
9089   int size, offset, dopi=1;
9090   sym_link *retype = getSpec (operandType (result));
9091
9092   aopOp (left, ic, FALSE, FALSE);
9093
9094   /* if the operand is already in dptr
9095      then we do nothing else we move the value to dptr */
9096   if (AOP_TYPE (left) != AOP_STR)
9097     {
9098       /* if this is remateriazable */
9099       if (AOP_TYPE (left) == AOP_IMMD)
9100         {
9101           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9102         }
9103       else
9104         {                       /* we need to get it byte by byte */
9105           _startLazyDPSEvaluation ();
9106           if (AOP_TYPE (left) != AOP_DPTR)
9107             {
9108               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9109               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9110               if (options.model == MODEL_FLAT24)
9111                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9112             }
9113           else
9114             {
9115               /* We need to generate a load to DPTR indirect through DPTR. */
9116               D (emitcode (";", "gencodePointerGet -- indirection special case.");
9117                 );
9118               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
9119               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
9120               if (options.model == MODEL_FLAT24)
9121                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9122               emitcode ("pop", "dph");
9123               emitcode ("pop", "dpl");
9124               dopi=0;
9125             }
9126           _endLazyDPSEvaluation ();
9127         }
9128     }
9129   /* so dptr know contains the address */
9130   aopOp (result, ic, FALSE, TRUE);
9131
9132   /* if bit then unpack */
9133   if (IS_BITVAR (retype))
9134     genUnpackBits (result, "dptr", CPOINTER);
9135   else
9136     {
9137       size = AOP_SIZE (result);
9138       offset = 0;
9139
9140       _startLazyDPSEvaluation ();
9141       while (size--)
9142         {
9143           genSetDPTR (0);
9144           _flushLazyDPS ();
9145
9146           emitcode ("clr", "a");
9147           emitcode ("movc", "a,@a+dptr");
9148           if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9149             emitcode ("inc", "dptr");
9150           aopPut (AOP (result), "a", offset++);
9151         }
9152       _endLazyDPSEvaluation ();
9153     }
9154   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9155       aopPut ( AOP (left), "dpl", 0);
9156       aopPut ( AOP (left), "dph", 1);
9157       if (options.model == MODEL_FLAT24)
9158           aopPut ( AOP (left), "dpx", 2);
9159       pi->generated = 1;
9160   } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9161              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9162       
9163       size = AOP_SIZE (result) - 1;
9164       while (size--) emitcode ("lcall","__decdptr");
9165   }
9166   
9167   freeAsmop (left, NULL, ic, TRUE);
9168   freeAsmop (result, NULL, ic, TRUE);
9169 }
9170
9171 /*-----------------------------------------------------------------*/
9172 /* genGenPointerGet - gget value from generic pointer space        */
9173 /*-----------------------------------------------------------------*/
9174 static void
9175 genGenPointerGet (operand * left,
9176                   operand * result, iCode * ic, iCode * pi)
9177 {
9178   int size, offset;
9179   sym_link *retype = getSpec (operandType (result));
9180   sym_link *letype = getSpec (operandType (left));
9181
9182   D (emitcode (";", "genGenPointerGet "); );
9183
9184   aopOp (left, ic, FALSE, (OP_SYMBOL(left)->ruonly ? FALSE : TRUE));
9185
9186   /* if the operand is already in dptr
9187      then we do nothing else we move the value to dptr */
9188   if (AOP_TYPE (left) != AOP_STR)
9189     {
9190       /* if this is remateriazable */
9191       if (AOP_TYPE (left) == AOP_IMMD)
9192         {
9193           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9194           if (AOP(left)->aopu.aop_immd.from_cast_remat) 
9195                   emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, FALSE));
9196           else
9197                   emitcode ("mov", "b,#%d", pointerCode (retype));
9198         }
9199       else
9200         {                       /* we need to get it byte by byte */
9201           _startLazyDPSEvaluation ();
9202           if (AOP(left)->type==AOP_DPTR2) {
9203             char *l;
9204             l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
9205             genSetDPTR(0);
9206             _flushLazyDPS();
9207             emitcode ("mov", "dpl,%s", l);
9208             l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
9209             genSetDPTR(0);
9210             _flushLazyDPS();
9211             emitcode ("mov", "dph,%s", l);
9212             if (options.model == MODEL_FLAT24) {
9213               l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
9214               genSetDPTR(0);
9215               _flushLazyDPS();
9216               emitcode ("mov", "dpx,%s", l);
9217               emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
9218             } else {
9219               emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9220             }
9221           } else {
9222             emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
9223             emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
9224             if (options.model == MODEL_FLAT24) {
9225               emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9226               emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
9227             } else {
9228               emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9229             }
9230           }
9231           _endLazyDPSEvaluation ();
9232         }
9233     }
9234   /* so dptr know contains the address */
9235   aopOp (result, ic, FALSE, TRUE);
9236
9237   /* if bit then unpack */
9238   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9239     genUnpackBits (result, "dptr", GPOINTER);
9240   else
9241     {
9242       size = AOP_SIZE (result);
9243       offset = 0;
9244
9245       while (size--)
9246         {
9247           emitcode ("lcall", "__gptrget");
9248           aopPut (AOP (result), "a", offset++);
9249           if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9250             emitcode ("inc", "dptr");
9251         }
9252     }
9253
9254   if (pi && AOP_TYPE (left) != AOP_IMMD) {
9255     aopPut ( AOP (left), "dpl", 0);
9256     aopPut ( AOP (left), "dph", 1);
9257     if (options.model == MODEL_FLAT24) {
9258         aopPut ( AOP (left), "dpx", 2);
9259         aopPut ( AOP (left), "b", 3);   
9260     } else  aopPut ( AOP (left), "b", 2);       
9261     pi->generated = 1;
9262   } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9263              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9264       
9265       size = AOP_SIZE (result) - 1;
9266       while (size--) emitcode ("lcall","__decdptr");
9267   }
9268
9269   freeAsmop (left, NULL, ic, TRUE);
9270   freeAsmop (result, NULL, ic, TRUE);
9271 }
9272
9273 /*-----------------------------------------------------------------*/
9274 /* genPointerGet - generate code for pointer get                   */
9275 /*-----------------------------------------------------------------*/
9276 static void
9277 genPointerGet (iCode * ic, iCode *pi)
9278 {
9279   operand *left, *result;
9280   sym_link *type, *etype;
9281   int p_type;
9282
9283   D (emitcode (";", "genPointerGet ");
9284     );
9285
9286   left = IC_LEFT (ic);
9287   result = IC_RESULT (ic);
9288
9289   /* depending on the type of pointer we need to
9290      move it to the correct pointer register */
9291   type = operandType (left);
9292   etype = getSpec (type);
9293   /* if left is of type of pointer then it is simple */
9294   if (IS_PTR (type) && !IS_FUNC (type->next))
9295     p_type = DCL_TYPE (type);
9296   else
9297     {
9298       /* we have to go by the storage class */
9299       p_type = PTR_TYPE (SPEC_OCLS (etype));
9300     }
9301   /* special case when cast remat */
9302   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9303       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9304           left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9305           type =   type = operandType (left);
9306           p_type = DCL_TYPE (type);
9307   }
9308   /* now that we have the pointer type we assign
9309      the pointer values */
9310   switch (p_type)
9311     {
9312
9313     case POINTER:
9314     case IPOINTER:
9315       genNearPointerGet (left, result, ic, pi);
9316       break;
9317
9318     case PPOINTER:
9319       genPagedPointerGet (left, result, ic, pi);
9320       break;
9321
9322     case FPOINTER:
9323       genFarPointerGet (left, result, ic, pi);
9324       break;
9325
9326     case CPOINTER:
9327       emitcodePointerGet (left, result, ic, pi);
9328       break;
9329
9330     case GPOINTER:
9331       genGenPointerGet (left, result, ic, pi);
9332       break;
9333     }
9334
9335 }
9336
9337 /*-----------------------------------------------------------------*/
9338 /* genPackBits - generates code for packed bit storage             */
9339 /*-----------------------------------------------------------------*/
9340 static void
9341 genPackBits (sym_link * etype,
9342              operand * right,
9343              char *rname, int p_type)
9344 {
9345   int shCount = 0;
9346   int offset = 0;
9347   int rLen = 0;
9348   int blen, bstr;
9349   char *l;
9350
9351   blen = SPEC_BLEN (etype);
9352   bstr = SPEC_BSTR (etype);
9353
9354   l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9355   MOVA (l);
9356
9357   /* if the bit lenth is less than or    */
9358   /* it exactly fits a byte then         */
9359   if (SPEC_BLEN (etype) <= 8)
9360     {
9361       shCount = SPEC_BSTR (etype);
9362
9363       /* shift left acc */
9364       AccLsh (shCount);
9365
9366       if (SPEC_BLEN (etype) < 8)
9367         {                       /* if smaller than a byte */
9368
9369
9370           switch (p_type)
9371             {
9372             case POINTER:
9373               emitcode ("mov", "b,a");
9374               emitcode ("mov", "a,@%s", rname);
9375               break;
9376
9377             case FPOINTER:
9378               emitcode ("mov", "b,a");
9379               emitcode ("movx", "a,@dptr");
9380               break;
9381
9382             case GPOINTER:
9383               emitcode ("push", "b");
9384               emitcode ("push", "acc");
9385               emitcode ("lcall", "__gptrget");
9386               emitcode ("pop", "b");
9387               break;
9388             }
9389
9390           emitcode ("anl", "a,#!constbyte", (unsigned char)
9391                     ((unsigned char) (0xFF << (blen + bstr)) |
9392                      (unsigned char) (0xFF >> (8 - bstr))));
9393           emitcode ("orl", "a,b");
9394           if (p_type == GPOINTER)
9395             emitcode ("pop", "b");
9396         }
9397     }
9398
9399   switch (p_type)
9400     {
9401     case POINTER:
9402       emitcode ("mov", "@%s,a", rname);
9403       break;
9404
9405     case FPOINTER:
9406       emitcode ("movx", "@dptr,a");
9407       break;
9408
9409     case GPOINTER:
9410       emitcode ("lcall", "__gptrput");
9411       break;
9412     }
9413
9414   /* if we r done */
9415   if (SPEC_BLEN (etype) <= 8)
9416     return;
9417
9418   emitcode ("inc", "%s", rname);
9419   rLen = SPEC_BLEN (etype);
9420
9421   /* now generate for lengths greater than one byte */
9422   while (1)
9423     {
9424
9425       l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
9426
9427       rLen -= 8;
9428       if (rLen < 8)
9429         break;
9430
9431       switch (p_type)
9432         {
9433         case POINTER:
9434           if (*l == '@')
9435             {
9436               MOVA (l);
9437               emitcode ("mov", "@%s,a", rname);
9438             }
9439           else
9440             emitcode ("mov", "@%s,%s", rname, l);
9441           break;
9442
9443         case FPOINTER:
9444           MOVA (l);
9445           emitcode ("movx", "@dptr,a");
9446           break;
9447
9448         case GPOINTER:
9449           MOVA (l);
9450           emitcode ("lcall", "__gptrput");
9451           break;
9452         }
9453       emitcode ("inc", "%s", rname);
9454     }
9455
9456   MOVA (l);
9457
9458   /* last last was not complete */
9459   if (rLen)
9460     {
9461       /* save the byte & read byte */
9462       switch (p_type)
9463         {
9464         case POINTER:
9465           emitcode ("mov", "b,a");
9466           emitcode ("mov", "a,@%s", rname);
9467           break;
9468
9469         case FPOINTER:
9470           emitcode ("mov", "b,a");
9471           emitcode ("movx", "a,@dptr");
9472           break;
9473
9474         case GPOINTER:
9475           emitcode ("push", "b");
9476           emitcode ("push", "acc");
9477           emitcode ("lcall", "__gptrget");
9478           emitcode ("pop", "b");
9479           break;
9480         }
9481
9482       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1 << rLen));
9483       emitcode ("orl", "a,b");
9484     }
9485
9486   if (p_type == GPOINTER)
9487     emitcode ("pop", "b");
9488
9489   switch (p_type)
9490     {
9491
9492     case POINTER:
9493       emitcode ("mov", "@%s,a", rname);
9494       break;
9495
9496     case FPOINTER:
9497       emitcode ("movx", "@dptr,a");
9498       break;
9499
9500     case GPOINTER:
9501       emitcode ("lcall", "__gptrput");
9502       break;
9503     }
9504 }
9505 /*-----------------------------------------------------------------*/
9506 /* genDataPointerSet - remat pointer to data space                 */
9507 /*-----------------------------------------------------------------*/
9508 static void
9509 genDataPointerSet (operand * right,
9510                    operand * result,
9511                    iCode * ic)
9512 {
9513   int size, offset = 0;
9514   char *l, buffer[256];
9515
9516   aopOp (right, ic, FALSE, FALSE);
9517
9518   l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
9519   size = AOP_SIZE (right);
9520   while (size--)
9521     {
9522       if (offset)
9523         sprintf (buffer, "(%s + %d)", l + 1, offset);
9524       else
9525         sprintf (buffer, "%s", l + 1);
9526       emitcode ("mov", "%s,%s", buffer,
9527                 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
9528     }
9529
9530   freeAsmop (right, NULL, ic, TRUE);
9531   freeAsmop (result, NULL, ic, TRUE);
9532 }
9533
9534 /*-----------------------------------------------------------------*/
9535 /* genNearPointerSet - emitcode for near pointer put                */
9536 /*-----------------------------------------------------------------*/
9537 static void
9538 genNearPointerSet (operand * right,
9539                    operand * result,
9540                    iCode * ic,
9541                    iCode * pi)
9542 {
9543   asmop *aop = NULL;
9544   regs *preg = NULL;
9545   char *rname, *l;
9546   sym_link *retype, *letype;
9547   sym_link *ptype = operandType (result);
9548
9549   retype = getSpec (operandType (right));
9550   letype = getSpec (ptype);
9551
9552   aopOp (result, ic, FALSE, FALSE);
9553
9554   /* if the result is rematerializable &
9555      in data space & not a bit variable */
9556   if (AOP_TYPE (result) == AOP_IMMD &&
9557       DCL_TYPE (ptype) == POINTER &&
9558       !IS_BITVAR (retype) &&
9559       !IS_BITVAR (letype))
9560     {
9561       genDataPointerSet (right, result, ic);
9562       return;
9563     }
9564
9565   /* if the value is already in a pointer register
9566      then don't need anything more */
9567   if (!AOP_INPREG (AOP (result)))
9568     {
9569       /* otherwise get a free pointer register */
9570       aop = newAsmop (0);
9571       preg = getFreePtr (ic, &aop, FALSE);
9572       emitcode ("mov", "%s,%s",
9573                 preg->name,
9574                 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9575       rname = preg->name;
9576     }
9577   else
9578     rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9579
9580   aopOp (right, ic, FALSE, FALSE);
9581
9582   /* if bitfield then unpack the bits */
9583   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9584     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
9585   else
9586     {
9587       /* we have can just get the values */
9588       int size = AOP_SIZE (right);
9589       int offset = 0;
9590
9591       while (size--)
9592         {
9593           l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
9594           if (*l == '@')
9595             {
9596               MOVA (l);
9597               emitcode ("mov", "@%s,a", rname);
9598             }
9599           else
9600             emitcode ("mov", "@%s,%s", rname, l);
9601           if (size || pi)
9602             emitcode ("inc", "%s", rname);
9603           offset++;
9604         }
9605     }
9606
9607   /* now some housekeeping stuff */
9608   if (aop)
9609     {
9610       /* we had to allocate for this iCode */
9611       if (pi) aopPut (AOP (result),rname,0);
9612       freeAsmop (NULL, aop, ic, TRUE);
9613     }
9614   else
9615     {
9616       /* we did not allocate which means left
9617          already in a pointer register, then
9618          if size > 0 && this could be used again
9619          we have to point it back to where it
9620          belongs */
9621       if (AOP_SIZE (right) > 1 &&
9622           !OP_SYMBOL (result)->remat &&
9623           (OP_SYMBOL (result)->liveTo > ic->seq ||
9624            ic->depth) &&
9625           !pi)
9626         {
9627           int size = AOP_SIZE (right) - 1;
9628           while (size--)
9629             emitcode ("dec", "%s", rname);
9630         }
9631     }
9632
9633   /* done */
9634   if (pi) pi->generated = 1;
9635   freeAsmop (result, NULL, ic, TRUE);
9636   freeAsmop (right, NULL, ic, TRUE);
9637
9638
9639 }
9640
9641 /*-----------------------------------------------------------------*/
9642 /* genPagedPointerSet - emitcode for Paged pointer put             */
9643 /*-----------------------------------------------------------------*/
9644 static void
9645 genPagedPointerSet (operand * right,
9646                     operand * result,
9647                     iCode * ic,
9648                     iCode *pi)
9649 {
9650   asmop *aop = NULL;
9651   regs *preg = NULL;
9652   char *rname, *l;
9653   sym_link *retype, *letype;
9654
9655   retype = getSpec (operandType (right));
9656   letype = getSpec (operandType (result));
9657
9658   aopOp (result, ic, FALSE, FALSE);
9659
9660   /* if the value is already in a pointer register
9661      then don't need anything more */
9662   if (!AOP_INPREG (AOP (result)))
9663     {
9664       /* otherwise get a free pointer register */
9665       aop = newAsmop (0);
9666       preg = getFreePtr (ic, &aop, FALSE);
9667       emitcode ("mov", "%s,%s",
9668                 preg->name,
9669                 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9670       rname = preg->name;
9671     }
9672   else
9673     rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9674
9675   aopOp (right, ic, FALSE, FALSE);
9676
9677   /* if bitfield then unpack the bits */
9678   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9679     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
9680   else
9681     {
9682       /* we have can just get the values */
9683       int size = AOP_SIZE (right);
9684       int offset = 0;
9685
9686       while (size--)
9687         {
9688           l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
9689
9690           MOVA (l);
9691           emitcode ("movx", "@%s,a", rname);
9692
9693           if (size || pi)
9694             emitcode ("inc", "%s", rname);
9695
9696           offset++;
9697         }
9698     }
9699
9700   /* now some housekeeping stuff */
9701   if (aop)
9702     {
9703       if (pi) aopPut (AOP (result),rname,0);
9704       /* we had to allocate for this iCode */
9705       freeAsmop (NULL, aop, ic, TRUE);
9706     }
9707   else
9708     {
9709       /* we did not allocate which means left
9710          already in a pointer register, then
9711          if size > 0 && this could be used again
9712          we have to point it back to where it
9713          belongs */
9714       if (AOP_SIZE (right) > 1 &&
9715           !OP_SYMBOL (result)->remat &&
9716           (OP_SYMBOL (result)->liveTo > ic->seq ||
9717            ic->depth) &&
9718           !pi)
9719         {
9720           int size = AOP_SIZE (right) - 1;
9721           while (size--)
9722             emitcode ("dec", "%s", rname);
9723         }
9724     }
9725
9726   /* done */
9727   if (pi) pi->generated = 1;
9728   freeAsmop (result, NULL, ic, TRUE);
9729   freeAsmop (right, NULL, ic, TRUE);
9730
9731
9732 }
9733
9734 /*-----------------------------------------------------------------*/
9735 /* genFarPointerSet - set value from far space                     */
9736 /*-----------------------------------------------------------------*/
9737 static void
9738 genFarPointerSet (operand * right,
9739                   operand * result, iCode * ic, iCode *pi)
9740 {
9741   int size, offset, dopi=1;
9742   sym_link *retype = getSpec (operandType (right));
9743   sym_link *letype = getSpec (operandType (result));
9744
9745   aopOp (result, ic, FALSE, FALSE);
9746
9747   /* if the operand is already in dptr
9748      then we do nothing else we move the value to dptr */
9749   if (AOP_TYPE (result) != AOP_STR)
9750     {
9751       /* if this is remateriazable */
9752       if (AOP_TYPE (result) == AOP_IMMD)
9753         emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9754       else
9755         {
9756           /* we need to get it byte by byte */
9757           _startLazyDPSEvaluation ();
9758           if (AOP_TYPE (result) != AOP_DPTR)
9759             {
9760               emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9761               emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9762               if (options.model == MODEL_FLAT24)
9763                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9764             }
9765           else
9766             {
9767               /* We need to generate a load to DPTR indirect through DPTR. */
9768               D (emitcode (";", "genFarPointerSet -- indirection special case.");
9769                 );
9770               emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
9771               emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
9772               if (options.model == MODEL_FLAT24)
9773                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9774               emitcode ("pop", "dph");
9775               emitcode ("pop", "dpl");
9776               dopi=0;
9777             }
9778           _endLazyDPSEvaluation ();
9779         }
9780     }
9781   /* so dptr know contains the address */
9782   aopOp (right, ic, FALSE, TRUE);
9783
9784   /* if bit then unpack */
9785   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9786     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
9787   else
9788     {
9789       size = AOP_SIZE (right);
9790       offset = 0;
9791
9792       _startLazyDPSEvaluation ();
9793       while (size--)
9794         {
9795           char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9796           MOVA (l);
9797
9798           genSetDPTR (0);
9799           _flushLazyDPS ();
9800
9801           emitcode ("movx", "@dptr,a");
9802           if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
9803             emitcode ("inc", "dptr");
9804         }
9805       _endLazyDPSEvaluation ();
9806     }
9807
9808   if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
9809       aopPut (AOP(result),"dpl",0);
9810       aopPut (AOP(result),"dph",1);
9811       if (options.model == MODEL_FLAT24)
9812           aopPut (AOP(result),"dpx",2);
9813       pi->generated=1;
9814   } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
9815              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
9816       
9817       size = AOP_SIZE (right) - 1;
9818       while (size--) emitcode ("lcall","__decdptr");
9819   }
9820   freeAsmop (result, NULL, ic, TRUE);
9821   freeAsmop (right, NULL, ic, TRUE);
9822 }
9823
9824 /*-----------------------------------------------------------------*/
9825 /* genGenPointerSet - set value from generic pointer space         */
9826 /*-----------------------------------------------------------------*/
9827 static void
9828 genGenPointerSet (operand * right,
9829                   operand * result, iCode * ic, iCode *pi)
9830 {
9831   int size, offset;
9832   sym_link *retype = getSpec (operandType (right));
9833   sym_link *letype = getSpec (operandType (result));
9834
9835   aopOp (result, ic, FALSE, OP_SYMBOL(result)->ruonly ? FALSE : TRUE);
9836
9837   /* if the operand is already in dptr
9838      then we do nothing else we move the value to dptr */
9839   if (AOP_TYPE (result) != AOP_STR)
9840     {
9841       _startLazyDPSEvaluation ();
9842       /* if this is remateriazable */
9843       if (AOP_TYPE (result) == AOP_IMMD)
9844         {
9845           emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9846           if (AOP(result)->aopu.aop_immd.from_cast_remat) 
9847                   emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, FALSE));
9848           else
9849                   emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9850         }
9851       else
9852         {                       /* we need to get it byte by byte */
9853           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9854           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9855           if (options.model == MODEL_FLAT24) {
9856             emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9857             emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
9858           } else {
9859             emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9860           }
9861         }
9862       _endLazyDPSEvaluation ();
9863     }
9864   /* so dptr know contains the address */
9865   aopOp (right, ic, FALSE, TRUE);
9866
9867   /* if bit then unpack */
9868   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9869     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
9870   else
9871     {
9872       size = AOP_SIZE (right);
9873       offset = 0;
9874
9875       _startLazyDPSEvaluation ();
9876       while (size--)
9877         {
9878           char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9879           MOVA (l);
9880
9881           genSetDPTR (0);
9882           _flushLazyDPS ();
9883
9884           emitcode ("lcall", "__gptrput");
9885           if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
9886             emitcode ("inc", "dptr");
9887         }
9888       _endLazyDPSEvaluation ();
9889     }
9890
9891   if (pi && AOP_TYPE (result) != AOP_IMMD) {
9892       aopPut (AOP(result),"dpl",0);
9893       aopPut (AOP(result),"dph",1);
9894       if (options.model == MODEL_FLAT24) {
9895           aopPut (AOP(result),"dpx",2);
9896           aopPut (AOP(result),"b",3);
9897       } else {
9898           aopPut (AOP(result),"b",2);
9899       }
9900       pi->generated=1;
9901   } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
9902              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
9903       
9904       size = AOP_SIZE (right) - 1;
9905       while (size--) emitcode ("lcall","__decdptr");
9906   }
9907   freeAsmop (result, NULL, ic, TRUE);
9908   freeAsmop (right, NULL, ic, TRUE);
9909 }
9910
9911 /*-----------------------------------------------------------------*/
9912 /* genPointerSet - stores the value into a pointer location        */
9913 /*-----------------------------------------------------------------*/
9914 static void
9915 genPointerSet (iCode * ic, iCode *pi)
9916 {
9917   operand *right, *result;
9918   sym_link *type, *etype;
9919   int p_type;
9920
9921   D (emitcode (";", "genPointerSet ");
9922     );
9923
9924   right = IC_RIGHT (ic);
9925   result = IC_RESULT (ic);
9926
9927   /* depending on the type of pointer we need to
9928      move it to the correct pointer register */
9929   type = operandType (result);
9930   etype = getSpec (type);
9931   /* if left is of type of pointer then it is simple */
9932   if (IS_PTR (type) && !IS_FUNC (type->next))
9933     {
9934       p_type = DCL_TYPE (type);
9935     }
9936   else
9937     {
9938       /* we have to go by the storage class */
9939       p_type = PTR_TYPE (SPEC_OCLS (etype));
9940     }
9941   /* special case when cast remat */
9942   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
9943       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
9944           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
9945           type =   type = operandType (result);
9946           p_type = DCL_TYPE (type);
9947   }
9948
9949   /* now that we have the pointer type we assign
9950      the pointer values */
9951   switch (p_type)
9952     {
9953
9954     case POINTER:
9955     case IPOINTER:
9956       genNearPointerSet (right, result, ic, pi);
9957       break;
9958
9959     case PPOINTER:
9960       genPagedPointerSet (right, result, ic, pi);
9961       break;
9962
9963     case FPOINTER:
9964       genFarPointerSet (right, result, ic, pi);
9965       break;
9966
9967     case GPOINTER:
9968       genGenPointerSet (right, result, ic, pi);
9969       break;
9970     }
9971
9972 }
9973
9974 /*-----------------------------------------------------------------*/
9975 /* genIfx - generate code for Ifx statement                        */
9976 /*-----------------------------------------------------------------*/
9977 static void
9978 genIfx (iCode * ic, iCode * popIc)
9979 {
9980   operand *cond = IC_COND (ic);
9981   int isbit = 0;
9982
9983   D (emitcode (";", "genIfx "););
9984
9985   aopOp (cond, ic, FALSE, FALSE);
9986
9987   /* get the value into acc */
9988   if (AOP_TYPE (cond) != AOP_CRY)
9989     toBoolean (cond);
9990   else
9991     isbit = 1;
9992   /* the result is now in the accumulator */
9993   freeAsmop (cond, NULL, ic, TRUE);
9994
9995   /* if there was something to be popped then do it */
9996   if (popIc)
9997     genIpop (popIc);
9998
9999   /* if the condition is  a bit variable */
10000   if (isbit && IS_ITEMP (cond) &&
10001       SPIL_LOC (cond))
10002     genIfxJump (ic, SPIL_LOC (cond)->rname);
10003   else if (isbit && !IS_ITEMP (cond))
10004     genIfxJump (ic, OP_SYMBOL (cond)->rname);
10005   else
10006     genIfxJump (ic, "a");
10007
10008   ic->generated = 1;
10009 }
10010
10011 /*-----------------------------------------------------------------*/
10012 /* genAddrOf - generates code for address of                       */
10013 /*-----------------------------------------------------------------*/
10014 static void
10015 genAddrOf (iCode * ic)
10016 {
10017   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10018   int size, offset;
10019
10020   D (emitcode (";", "genAddrOf ");
10021     );
10022
10023   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10024
10025   /* if the operand is on the stack then we
10026      need to get the stack offset of this
10027      variable */
10028   if (sym->onStack) {
10029       
10030       /* if 10 bit stack */
10031       if (options.stack10bit) {
10032           char buff[10];
10033           tsprintf(buff,"#!constbyte",(options.stack_loc >> 16) & 0xff);
10034           /* if it has an offset then we need to compute it */
10035           emitcode ("subb", "a,#!constbyte",
10036                     -((sym->stack < 0) ?
10037                       ((short) (sym->stack - _G.nRegsSaved)) :
10038                       ((short) sym->stack)) & 0xff);
10039           emitcode ("mov","b,a");
10040           emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ?
10041                                          ((short) (sym->stack - _G.nRegsSaved)) :
10042                                          ((short) sym->stack)) >> 8) & 0xff);
10043           if (sym->stack) {
10044               emitcode ("mov", "a,_bpx");
10045               emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ? 
10046                                              ((char) (sym->stack - _G.nRegsSaved)) :
10047                                              ((char) sym->stack )) & 0xff);
10048               emitcode ("mov", "b,a");
10049               emitcode ("mov", "a,_bpx+1");
10050               emitcode ("addc","a,#!constbyte", (((sym->stack < 0) ? 
10051                                               ((short) (sym->stack - _G.nRegsSaved)) :
10052                                               ((short) sym->stack )) >> 8) & 0xff);
10053               aopPut (AOP (IC_RESULT (ic)), "b", 0);
10054               aopPut (AOP (IC_RESULT (ic)), "a", 1);
10055               aopPut (AOP (IC_RESULT (ic)), buff, 2);
10056           } else {
10057               /* we can just move _bp */
10058               aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
10059               aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
10060               aopPut (AOP (IC_RESULT (ic)), buff, 2);
10061           }       
10062       } else {
10063           /* if it has an offset then we need to compute it */
10064           if (sym->stack) {
10065               emitcode ("mov", "a,_bp");
10066               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
10067               aopPut (AOP (IC_RESULT (ic)), "a", 0);
10068           } else {
10069               /* we can just move _bp */
10070               aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
10071           }
10072           /* fill the result with zero */
10073           size = AOP_SIZE (IC_RESULT (ic)) - 1;
10074           
10075           
10076           if (options.stack10bit && size < (FPTRSIZE - 1)) {
10077               fprintf (stderr,
10078                        "*** warning: pointer to stack var truncated.\n");
10079           }
10080
10081           offset = 1;
10082           while (size--) {
10083               aopPut (AOP (IC_RESULT (ic)), zero, offset++);
10084           }      
10085       }
10086       goto release;
10087   }
10088
10089   /* object not on stack then we need the name */
10090   size = AOP_SIZE (IC_RESULT (ic));
10091   offset = 0;
10092
10093   while (size--)
10094     {
10095       char s[SDCC_NAME_MAX];
10096       if (offset) {
10097           switch (offset) {
10098           case 1:
10099               tsprintf(s,"!his",sym->rname);
10100               break;
10101           case 2:
10102               tsprintf(s,"!hihis",sym->rname);
10103               break;
10104           case 3:
10105               tsprintf(s,"!hihihis",sym->rname);
10106               break;
10107           default: /* should not need this (just in case) */
10108               sprintf (s, "#(%s >> %d)",
10109                        sym->rname,
10110                        offset * 8);
10111           }
10112       } else
10113           sprintf (s, "#%s", sym->rname);
10114       aopPut (AOP (IC_RESULT (ic)), s, offset++);
10115     }
10116
10117 release:
10118   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10119
10120 }
10121
10122 /*-----------------------------------------------------------------*/
10123 /* genArrayInit - generates code for address of                       */
10124 /*-----------------------------------------------------------------*/
10125 static void
10126 genArrayInit (iCode * ic)
10127 {
10128     literalList *iLoop;
10129     int         ix, count;
10130     int         elementSize = 0, eIndex;
10131     unsigned    val, lastVal;
10132     sym_link    *type;
10133     operand     *left=IC_LEFT(ic);
10134     
10135     D (emitcode (";", "genArrayInit "););
10136
10137     aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10138     
10139     if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10140     {
10141         // Load immediate value into DPTR.
10142         emitcode("mov", "dptr, %s",
10143              aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, TRUE));
10144     }
10145     else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10146     {
10147 #if 0
10148       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10149               "Unexpected operand to genArrayInit.\n");
10150       exit(1);
10151 #else
10152       // a regression because of SDCCcse.c:1.52
10153       emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
10154       emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
10155       if (options.model == MODEL_FLAT24)
10156         emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
10157 #endif
10158     }
10159     
10160     type = operandType(IC_LEFT(ic));
10161     
10162     if (type && type->next)
10163     {
10164         elementSize = getSize(type->next);
10165     }
10166     else
10167     {
10168         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10169                                 "can't determine element size in genArrayInit.\n");
10170         exit(1);
10171     }
10172     
10173     iLoop = IC_ARRAYILIST(ic);
10174     lastVal = 0xffff;
10175     
10176     while (iLoop)
10177     {
10178         bool firstpass = TRUE;
10179         
10180         emitcode(";", "store %d x 0x%x to DPTR (element size %d)", 
10181                  iLoop->count, (int)iLoop->literalValue, elementSize);
10182         
10183         ix = iLoop->count;
10184         
10185         while (ix)
10186         {
10187             symbol *tlbl = NULL;
10188             
10189             count = ix > 256 ? 256 : ix;
10190             
10191             if (count > 1)
10192             {
10193                 tlbl = newiTempLabel (NULL);
10194                 if (firstpass || (count & 0xff))
10195                 {
10196                     emitcode("mov", "b, #!constbyte", count & 0xff);
10197                 }
10198                 
10199                 emitcode ("", "!tlabeldef", tlbl->key + 100);
10200             }
10201             
10202             firstpass = FALSE;
10203                 
10204             for (eIndex = 0; eIndex < elementSize; eIndex++)
10205             {
10206                 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10207                 if (val != lastVal)
10208                 {
10209                     emitcode("mov", "a, #!constbyte", val);
10210                     lastVal = val;
10211                 }
10212                 
10213                 emitcode("movx", "@dptr, a");
10214                 emitcode("inc", "dptr");
10215             }
10216             
10217             if (count > 1)
10218             {
10219                 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
10220             }
10221             
10222             ix -= count;
10223         }
10224         
10225         iLoop = iLoop->next;
10226     }
10227     
10228     freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10229 }
10230
10231 /*-----------------------------------------------------------------*/
10232 /* genFarFarAssign - assignment when both are in far space         */
10233 /*-----------------------------------------------------------------*/
10234 static void
10235 genFarFarAssign (operand * result, operand * right, iCode * ic)
10236 {
10237   int size = AOP_SIZE (right);
10238   int offset = 0;
10239   symbol *rSym = NULL;
10240
10241   if (size == 1)
10242   {
10243       /* quick & easy case. */
10244       D(emitcode(";","genFarFarAssign (1 byte case)"););      
10245       MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
10246       freeAsmop (right, NULL, ic, FALSE);
10247       /* now assign DPTR to result */
10248       _G.accInUse++;
10249       aopOp(result, ic, FALSE, FALSE);
10250       _G.accInUse--;
10251       aopPut(AOP(result), "a", 0);
10252       freeAsmop(result, NULL, ic, FALSE);
10253       return;
10254   }
10255   
10256   /* See if we've got an underlying symbol to abuse. */
10257   if (IS_SYMOP(result) && OP_SYMBOL(result))
10258   {
10259       if (IS_TRUE_SYMOP(result))
10260       {
10261           rSym = OP_SYMBOL(result);
10262       }
10263       else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10264       {
10265           rSym = OP_SYMBOL(result)->usl.spillLoc;
10266       }
10267   }
10268              
10269   if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10270   {
10271       /* We can use the '390 auto-toggle feature to good effect here. */
10272       
10273       D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10274       emitcode("mov", "dps,#!constbyte",0x21);  /* Select DPTR2 & auto-toggle. */
10275       emitcode ("mov", "dptr,#%s", rSym->rname); 
10276       /* DP2 = result, DP1 = right, DP1 is current. */
10277       while (size)
10278       {
10279           emitcode("movx", "a,@dptr");
10280           emitcode("movx", "@dptr,a");
10281           if (--size)
10282           {
10283                emitcode("inc", "dptr");
10284                emitcode("inc", "dptr");
10285           }
10286       }
10287       emitcode("mov", "dps,#0");
10288       freeAsmop (right, NULL, ic, FALSE);
10289 #if 0
10290 some alternative code for processors without auto-toggle
10291 no time to test now, so later well put in...kpb
10292         D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10293         emitcode("mov", "dps,#1");      /* Select DPTR2. */
10294         emitcode ("mov", "dptr,#%s", rSym->rname); 
10295         /* DP2 = result, DP1 = right, DP1 is current. */
10296         while (size)
10297         {
10298           --size;
10299           emitcode("movx", "a,@dptr");
10300           if (size)
10301             emitcode("inc", "dptr");
10302           emitcode("inc", "dps");
10303           emitcode("movx", "@dptr,a");
10304           if (size)
10305             emitcode("inc", "dptr");
10306           emitcode("inc", "dps");
10307         }
10308         emitcode("mov", "dps,#0");
10309         freeAsmop (right, NULL, ic, FALSE);
10310 #endif
10311   }
10312   else
10313   {
10314       D (emitcode (";", "genFarFarAssign"););
10315       aopOp (result, ic, TRUE, TRUE);
10316
10317       _startLazyDPSEvaluation ();
10318       
10319       while (size--)
10320         {
10321           aopPut (AOP (result),
10322                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
10323           offset++;
10324         }
10325       _endLazyDPSEvaluation ();
10326       freeAsmop (result, NULL, ic, FALSE);
10327       freeAsmop (right, NULL, ic, FALSE);
10328   }
10329 }
10330
10331 /*-----------------------------------------------------------------*/
10332 /* genAssign - generate code for assignment                        */
10333 /*-----------------------------------------------------------------*/
10334 static void
10335 genAssign (iCode * ic)
10336 {
10337   operand *result, *right;
10338   int size, offset;
10339   unsigned long lit = 0L;
10340
10341   D (emitcode (";", "genAssign ");
10342     );
10343
10344   result = IC_RESULT (ic);
10345   right = IC_RIGHT (ic);
10346
10347   /* if they are the same */
10348   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10349     return;
10350
10351   aopOp (right, ic, FALSE, FALSE);
10352
10353   emitcode (";", "genAssign: resultIsFar = %s",
10354             isOperandInFarSpace (result) ?
10355             "TRUE" : "FALSE");
10356
10357   /* special case both in far space */
10358   if ((AOP_TYPE (right) == AOP_DPTR ||
10359        AOP_TYPE (right) == AOP_DPTR2) &&
10360   /* IS_TRUE_SYMOP(result)       && */
10361       isOperandInFarSpace (result))
10362     {
10363       genFarFarAssign (result, right, ic);
10364       return;
10365     }
10366
10367   aopOp (result, ic, TRUE, FALSE);
10368
10369   /* if they are the same registers */
10370   if (sameRegs (AOP (right), AOP (result)))
10371     goto release;
10372
10373   /* if the result is a bit */
10374   if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10375     {
10376       /* if the right size is a literal then
10377          we know what the value is */
10378       if (AOP_TYPE (right) == AOP_LIT)
10379         {
10380           if (((int) operandLitValue (right)))
10381             aopPut (AOP (result), one, 0);
10382           else
10383             aopPut (AOP (result), zero, 0);
10384           goto release;
10385         }
10386
10387       /* the right is also a bit variable */
10388       if (AOP_TYPE (right) == AOP_CRY)
10389         {
10390           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10391           aopPut (AOP (result), "c", 0);
10392           goto release;
10393         }
10394
10395       /* we need to or */
10396       toBoolean (right);
10397       aopPut (AOP (result), "a", 0);
10398       goto release;
10399     }
10400
10401   /* bit variables done */
10402   /* general case */
10403   size = AOP_SIZE (result);
10404   offset = 0;
10405   if (AOP_TYPE (right) == AOP_LIT)
10406     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10407
10408   if ((size > 1) &&
10409       (AOP_TYPE (result) != AOP_REG) &&
10410       (AOP_TYPE (right) == AOP_LIT) &&
10411       !IS_FLOAT (operandType (right)))
10412     {
10413       _startLazyDPSEvaluation ();
10414       while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10415         {
10416           aopPut (AOP (result),
10417                   aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
10418                   offset);
10419           offset++;
10420           size--;
10421         }
10422       /* And now fill the rest with zeros. */
10423       if (size)
10424         {
10425           emitcode ("clr", "a");
10426         }
10427       while (size--)
10428         {
10429           aopPut (AOP (result), "a", offset++);
10430         }
10431       _endLazyDPSEvaluation ();
10432     }
10433   else
10434     {
10435       _startLazyDPSEvaluation ();
10436       while (size--)
10437         {
10438           aopPut (AOP (result),
10439                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10440                   offset);
10441           offset++;
10442         }
10443       _endLazyDPSEvaluation ();
10444     }
10445
10446 release:
10447   freeAsmop (right, NULL, ic, FALSE);
10448   freeAsmop (result, NULL, ic, TRUE);
10449 }
10450
10451 /*-----------------------------------------------------------------*/
10452 /* genJumpTab - generates code for jump table                      */
10453 /*-----------------------------------------------------------------*/
10454 static void
10455 genJumpTab (iCode * ic)
10456 {
10457   symbol *jtab;
10458   char *l;
10459
10460   D (emitcode (";", "genJumpTab ");
10461     );
10462
10463   aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10464   /* get the condition into accumulator */
10465   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
10466   MOVA (l);
10467   /* multiply by four! */
10468   emitcode ("add", "a,acc");
10469   emitcode ("add", "a,acc");
10470   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10471
10472   jtab = newiTempLabel (NULL);
10473   emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
10474   emitcode ("jmp", "@a+dptr");
10475   emitcode ("", "!tlabeldef", jtab->key + 100);
10476   /* now generate the jump labels */
10477   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10478        jtab = setNextItem (IC_JTLABELS (ic)))
10479     emitcode ("ljmp", "!tlabel", jtab->key + 100);
10480
10481 }
10482
10483 /*-----------------------------------------------------------------*/
10484 /* genCast - gen code for casting                                  */
10485 /*-----------------------------------------------------------------*/
10486 static void
10487 genCast (iCode * ic)
10488 {
10489   operand *result = IC_RESULT (ic);
10490   sym_link *ctype = operandType (IC_LEFT (ic));
10491   sym_link *rtype = operandType (IC_RIGHT (ic));
10492   operand *right = IC_RIGHT (ic);
10493   int size, offset;
10494
10495   D (emitcode (";", "genCast ");
10496     );
10497
10498   /* if they are equivalent then do nothing */
10499   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10500     return;
10501
10502   aopOp (right, ic, FALSE, FALSE);
10503   aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
10504
10505   /* if the result is a bit */
10506   // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10507   if (IS_BITVAR(OP_SYMBOL(result)->type))
10508     {
10509       /* if the right size is a literal then
10510          we know what the value is */
10511       if (AOP_TYPE (right) == AOP_LIT)
10512         {
10513           if (((int) operandLitValue (right)))
10514             aopPut (AOP (result), one, 0);
10515           else
10516             aopPut (AOP (result), zero, 0);
10517
10518           goto release;
10519         }
10520
10521       /* the right is also a bit variable */
10522       if (AOP_TYPE (right) == AOP_CRY)
10523         {
10524           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10525           aopPut (AOP (result), "c", 0);
10526           goto release;
10527         }
10528
10529       /* we need to or */
10530       toBoolean (right);
10531       aopPut (AOP (result), "a", 0);
10532       goto release;
10533     }
10534
10535   /* if they are the same size : or less */
10536   if (AOP_SIZE (result) <= AOP_SIZE (right))
10537     {
10538
10539       /* if they are in the same place */
10540       if (sameRegs (AOP (right), AOP (result)))
10541         goto release;
10542
10543       /* if they in different places then copy */
10544       size = AOP_SIZE (result);
10545       offset = 0;
10546       _startLazyDPSEvaluation ();
10547       while (size--)
10548         {
10549           aopPut (AOP (result),
10550                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10551                   offset);
10552           offset++;
10553         }
10554       _endLazyDPSEvaluation ();
10555       goto release;
10556     }
10557
10558
10559   /* if the result is of type pointer */
10560   if (IS_PTR (ctype))
10561     {
10562
10563       int p_type;
10564       sym_link *type = operandType (right);
10565
10566       /* pointer to generic pointer */
10567       if (IS_GENPTR (ctype))
10568         {
10569           char *l = zero;
10570
10571           if (IS_PTR (type))
10572             {
10573               p_type = DCL_TYPE (type);
10574             }
10575           else
10576             {
10577 #if OLD_CAST_BEHAVIOR
10578               /* KV: we are converting a non-pointer type to
10579                * a generic pointer. This (ifdef'd out) code
10580                * says that the resulting generic pointer
10581                * should have the same class as the storage
10582                * location of the non-pointer variable.
10583                *
10584                * For example, converting an int (which happens
10585                * to be stored in DATA space) to a pointer results
10586                * in a DATA generic pointer; if the original int
10587                * in XDATA space, so will be the resulting pointer.
10588                *
10589                * I don't like that behavior, and thus this change:
10590                * all such conversions will be forced to XDATA and
10591                * throw a warning. If you want some non-XDATA
10592                * type, or you want to suppress the warning, you
10593                * must go through an intermediate cast, like so:
10594                *
10595                * char _generic *gp = (char _xdata *)(intVar);
10596                */
10597               sym_link *etype = getSpec (type);
10598
10599               /* we have to go by the storage class */
10600               if (SPEC_OCLS (etype) != generic)
10601                 {
10602                   p_type = PTR_TYPE (SPEC_OCLS (etype));
10603                 }
10604               else
10605 #endif
10606                 {
10607                   /* Converting unknown class (i.e. register variable)
10608                    * to generic pointer. This is not good, but
10609                    * we'll make a guess (and throw a warning).
10610                    */
10611                   p_type = FPOINTER;
10612                   werror (W_INT_TO_GEN_PTR_CAST);
10613                 }
10614             }
10615
10616           /* the first two bytes are known */
10617           size = GPTRSIZE - 1;
10618           offset = 0;
10619           _startLazyDPSEvaluation ();
10620           while (size--)
10621             {
10622               aopPut (AOP (result),
10623                       aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10624                       offset);
10625               offset++;
10626             }
10627           _endLazyDPSEvaluation ();
10628
10629           /* the last byte depending on type */
10630           switch (p_type)
10631             {
10632             case IPOINTER:
10633             case POINTER:
10634               l = zero;
10635               break;
10636             case FPOINTER:
10637               l = one;
10638               break;
10639             case CPOINTER:
10640               l = "#0x02";
10641               break;
10642             case PPOINTER:
10643               l = "#0x03";
10644               break;
10645
10646             default:
10647               /* this should never happen */
10648               werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10649                       "got unknown pointer type");
10650               exit (1);
10651             }
10652           aopPut (AOP (result), l, GPTRSIZE - 1);
10653           goto release;
10654         }
10655
10656       /* just copy the pointers */
10657       size = AOP_SIZE (result);
10658       offset = 0;
10659       _startLazyDPSEvaluation ();
10660       while (size--)
10661         {
10662           aopPut (AOP (result),
10663                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10664                   offset);
10665           offset++;
10666         }
10667       _endLazyDPSEvaluation ();
10668       goto release;
10669     }
10670
10671   /* so we now know that the size of destination is greater
10672      than the size of the source */
10673   /* we move to result for the size of source */
10674   size = AOP_SIZE (right);
10675   offset = 0;
10676   _startLazyDPSEvaluation ();
10677   while (size--)
10678     {
10679       aopPut (AOP (result),
10680               aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10681               offset);
10682       offset++;
10683     }
10684   _endLazyDPSEvaluation ();
10685
10686   /* now depending on the sign of the source && destination */
10687   size = AOP_SIZE (result) - AOP_SIZE (right);
10688   /* if unsigned or not an integral type */
10689   /* also, if the source is a bit, we don't need to sign extend, because
10690    * it can't possibly have set the sign bit.
10691    */
10692   if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
10693     {
10694       while (size--)
10695         {
10696           aopPut (AOP (result), zero, offset++);
10697         }
10698     }
10699   else
10700     {
10701       /* we need to extend the sign :{ */
10702       char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
10703                         FALSE, FALSE, TRUE);
10704       MOVA (l);
10705       emitcode ("rlc", "a");
10706       emitcode ("subb", "a,acc");
10707       while (size--)
10708         aopPut (AOP (result), "a", offset++);
10709     }
10710
10711   /* we are done hurray !!!! */
10712
10713 release:
10714   freeAsmop (right, NULL, ic, TRUE);
10715   freeAsmop (result, NULL, ic, TRUE);
10716
10717 }
10718
10719 /*-----------------------------------------------------------------*/
10720 /* genDjnz - generate decrement & jump if not zero instrucion      */
10721 /*-----------------------------------------------------------------*/
10722 static int
10723 genDjnz (iCode * ic, iCode * ifx)
10724 {
10725   symbol *lbl, *lbl1;
10726   if (!ifx)
10727     return 0;
10728
10729   /* if the if condition has a false label
10730      then we cannot save */
10731   if (IC_FALSE (ifx))
10732     return 0;
10733
10734   /* if the minus is not of the form
10735      a = a - 1 */
10736   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
10737       !IS_OP_LITERAL (IC_RIGHT (ic)))
10738     return 0;
10739
10740   if (operandLitValue (IC_RIGHT (ic)) != 1)
10741     return 0;
10742
10743   /* if the size of this greater than one then no
10744      saving */
10745   if (getSize (operandType (IC_RESULT (ic))) > 1)
10746     return 0;
10747
10748   /* otherwise we can save BIG */
10749   D(emitcode(";", "genDjnz"););
10750
10751   lbl = newiTempLabel (NULL);
10752   lbl1 = newiTempLabel (NULL);
10753
10754   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10755
10756   if (AOP_NEEDSACC(IC_RESULT(ic)))
10757   {
10758       /* If the result is accessed indirectly via
10759        * the accumulator, we must explicitly write
10760        * it back after the decrement.
10761        */
10762       char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
10763       
10764       if (strcmp(rByte, "a"))
10765       {
10766            /* Something is hopelessly wrong */
10767            fprintf(stderr, "*** warning: internal error at %s:%d\n",
10768                    __FILE__, __LINE__);
10769            /* We can just give up; the generated code will be inefficient,
10770             * but what the hey.
10771             */
10772            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10773            return 0;
10774       }
10775       emitcode ("dec", "%s", rByte);
10776       aopPut(AOP(IC_RESULT(ic)), rByte, 0);
10777       emitcode ("jnz", "!tlabel", lbl->key + 100);
10778   }
10779   else if (IS_AOP_PREG (IC_RESULT (ic)))
10780     {
10781       emitcode ("dec", "%s",
10782                 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10783       emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10784       emitcode ("jnz", "!tlabel", lbl->key + 100);
10785     }
10786   else
10787     {
10788       emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
10789                 lbl->key + 100);
10790     }
10791   emitcode ("sjmp", "!tlabel", lbl1->key + 100);
10792   emitcode ("", "!tlabeldef", lbl->key + 100);
10793   emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
10794   emitcode ("", "!tlabeldef", lbl1->key + 100);
10795
10796   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10797   ifx->generated = 1;
10798   return 1;
10799 }
10800
10801 /*-----------------------------------------------------------------*/
10802 /* genReceive - generate code for a receive iCode                  */
10803 /*-----------------------------------------------------------------*/
10804 static void
10805 genReceive (iCode * ic)
10806 {
10807
10808   D (emitcode (";", "genReceive ");
10809     );
10810
10811   if (isOperandInFarSpace (IC_RESULT (ic)) &&
10812       (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
10813        IS_TRUE_SYMOP (IC_RESULT (ic))))
10814     {
10815       int size = getSize (operandType (IC_RESULT (ic)));
10816       int offset = fReturnSizeDS390 - size;
10817       while (size--)
10818         {
10819           emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
10820                             fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
10821           offset++;
10822         }
10823       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10824       size = AOP_SIZE (IC_RESULT (ic));
10825       offset = 0;
10826       while (size--)
10827         {
10828           emitcode ("pop", "acc");
10829           aopPut (AOP (IC_RESULT (ic)), "a", offset++);
10830         }
10831
10832     }
10833   else
10834     {
10835       _G.accInUse++;
10836       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10837       _G.accInUse--;
10838       assignResultValue (IC_RESULT (ic));
10839     }
10840
10841   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10842 }
10843
10844 /*-----------------------------------------------------------------*/
10845 /* genMemcpyX2X - gen code for memcpy xdata to xdata               */
10846 /*-----------------------------------------------------------------*/
10847 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
10848 {
10849     operand *from , *to , *count;
10850     symbol *lbl;
10851     bitVect *rsave;
10852     int i;
10853
10854     /* we know it has to be 3 parameters */
10855     assert (nparms == 3);
10856     
10857     rsave = newBitVect(16);
10858     /* save DPTR if it needs to be saved */
10859     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
10860             if (bitVectBitValue(ic->rMask,i))
10861                     rsave = bitVectSetBit(rsave,i);
10862     }
10863     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
10864                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
10865     savermask(rsave);
10866     
10867     to = parms[0];
10868     from = parms[1];
10869     count = parms[2];
10870
10871     aopOp (from, ic->next, FALSE, FALSE);
10872
10873     /* get from into DPTR1 */
10874     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, TRUE));
10875     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, TRUE));
10876     if (options.model == MODEL_FLAT24) {
10877         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, TRUE));
10878     }
10879
10880     freeAsmop (from, NULL, ic, FALSE);
10881     aopOp (to, ic, FALSE, FALSE);
10882     /* get "to" into DPTR */
10883     /* if the operand is already in dptr
10884        then we do nothing else we move the value to dptr */
10885     if (AOP_TYPE (to) != AOP_STR) {
10886         /* if already in DPTR then we need to push */
10887         if (AOP_TYPE(to) == AOP_DPTR) {
10888             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
10889             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
10890             if (options.model == MODEL_FLAT24)
10891                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
10892             emitcode ("pop", "dph");
10893             emitcode ("pop", "dpl");        
10894         } else {
10895             _startLazyDPSEvaluation ();
10896             /* if this is remateriazable */
10897             if (AOP_TYPE (to) == AOP_IMMD) {
10898                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
10899             } else {                    /* we need to get it byte by byte */
10900                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
10901                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
10902                 if (options.model == MODEL_FLAT24) {
10903                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
10904                 }
10905             }
10906             _endLazyDPSEvaluation ();
10907         }
10908     }
10909     freeAsmop (to, NULL, ic, FALSE);
10910
10911     aopOp (count, ic->next->next, FALSE,FALSE);
10912     lbl =newiTempLabel(NULL);
10913
10914     /* now for the actual copy */
10915     if (AOP_TYPE(count) == AOP_LIT && 
10916         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
10917         emitcode (";","OH  JOY auto increment with djnz (very fast)");
10918         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
10919         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
10920         emitcode ("","!tlabeldef",lbl->key+100);
10921         if (fromc) {
10922             emitcode ("clr","a");
10923             emitcode ("movc", "a,@a+dptr");
10924         } else 
10925             emitcode ("movx", "a,@dptr");
10926         emitcode ("movx", "@dptr,a");
10927         emitcode ("inc", "dptr");
10928         emitcode ("inc", "dptr");
10929         emitcode ("djnz","b,!tlabel",lbl->key+100);
10930     } else {
10931         symbol *lbl1 = newiTempLabel(NULL);
10932         
10933         emitcode (";"," Auto increment but no djnz");
10934         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
10935         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
10936         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
10937         emitcode ("","!tlabeldef",lbl->key+100);
10938         if (fromc) {
10939             emitcode ("clr","a");
10940             emitcode ("movc", "a,@a+dptr");
10941         } else 
10942             emitcode ("movx", "a,@dptr");
10943         emitcode ("movx", "@dptr,a");
10944         emitcode ("inc", "dptr");
10945         emitcode ("inc", "dptr");
10946         emitcode ("mov","a,b");
10947         emitcode ("orl","a,_ap");
10948         emitcode ("jz","!tlabel",lbl1->key+100);
10949         emitcode ("mov","a,_ap");
10950         emitcode ("add","a,#!constbyte",0xFF);
10951         emitcode ("mov","_ap,a");
10952         emitcode ("mov","a,b");
10953         emitcode ("addc","a,#!constbyte",0xFF);
10954         emitcode ("mov","b,a");
10955         emitcode ("sjmp","!tlabel",lbl->key+100);
10956         emitcode ("","!tlabeldef",lbl1->key+100);
10957     }
10958     emitcode ("mov", "dps,#0"); 
10959     freeAsmop (count, NULL, ic, FALSE);
10960     unsavermask(rsave);
10961
10962 }
10963
10964 /*-----------------------------------------------------------------*/
10965 /* genMemsetX - gencode for memSetX data                           */
10966 /*-----------------------------------------------------------------*/
10967 static void genMemsetX(iCode *ic, int nparms, operand **parms)
10968 {
10969     operand *to , *val , *count;
10970     symbol *lbl;
10971     char *l;
10972     int i;
10973     bitVect *rsave = NULL;
10974
10975     /* we know it has to be 3 parameters */
10976     assert (nparms == 3);
10977     
10978     to = parms[0];
10979     val = parms[1];
10980     count = parms[2];
10981         
10982     /* save DPTR if it needs to be saved */
10983     rsave = newBitVect(16);
10984     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
10985             if (bitVectBitValue(ic->rMask,i))
10986                     rsave = bitVectSetBit(rsave,i);
10987     }
10988     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
10989                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
10990     savermask(rsave);
10991
10992     aopOp (to, ic, FALSE, FALSE);
10993     /* get "to" into DPTR */
10994     /* if the operand is already in dptr
10995        then we do nothing else we move the value to dptr */
10996     if (AOP_TYPE (to) != AOP_STR) {
10997         /* if already in DPTR then we need to push */
10998         if (AOP_TYPE(to) == AOP_DPTR) {
10999             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
11000             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
11001             if (options.model == MODEL_FLAT24)
11002                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11003             emitcode ("pop", "dph");
11004             emitcode ("pop", "dpl");        
11005         } else {
11006             _startLazyDPSEvaluation ();
11007             /* if this is remateriazable */
11008             if (AOP_TYPE (to) == AOP_IMMD) {
11009                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
11010             } else {                    /* we need to get it byte by byte */
11011                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
11012                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
11013                 if (options.model == MODEL_FLAT24) {
11014                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11015                 }
11016             }
11017             _endLazyDPSEvaluation ();
11018         }
11019     }
11020     freeAsmop (to, NULL, ic, FALSE);
11021
11022     aopOp (val, ic->next->next, FALSE,FALSE);
11023     aopOp (count, ic->next->next, FALSE,FALSE);    
11024     lbl =newiTempLabel(NULL);
11025     /* now for the actual copy */
11026     if (AOP_TYPE(count) == AOP_LIT && 
11027         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11028         l = aopGet(AOP (val), 0, FALSE, FALSE, TRUE);
11029         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
11030         MOVA(l);
11031         emitcode ("","!tlabeldef",lbl->key+100);
11032         emitcode ("movx", "@dptr,a");
11033         emitcode ("inc", "dptr");
11034         emitcode ("djnz","b,!tlabel",lbl->key+100);
11035     } else {
11036         symbol *lbl1 = newiTempLabel(NULL);
11037         
11038         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
11039         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
11040         emitcode ("","!tlabeldef",lbl->key+100);
11041         l = aopGet(AOP (val), 0, FALSE, FALSE, TRUE);
11042         MOVA(l);
11043         emitcode ("movx", "a,@dptr");
11044         emitcode ("inc", "dptr");
11045         emitcode ("mov","a,b");
11046         emitcode ("orl","a,_ap");
11047         emitcode ("jz","!tlabel",lbl1->key+100);
11048         emitcode ("mov","a,_ap");
11049         emitcode ("add","a,#!constbyte",0xFF);
11050         emitcode ("mov","_ap,a");
11051         emitcode ("mov","a,b");
11052         emitcode ("addc","a,#!constbyte",0xFF);
11053         emitcode ("mov","b,a");
11054         emitcode ("sjmp","!tlabel",lbl->key+100);
11055         emitcode ("","!tlabeldef",lbl1->key+100);
11056     }
11057     freeAsmop (count, NULL, ic, FALSE);
11058     unsavermask(rsave);
11059 }
11060
11061 /*-----------------------------------------------------------------*/
11062 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
11063 /*-----------------------------------------------------------------*/
11064 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
11065 {
11066         bitVect *rsave ;
11067         operand *pnum, *result;
11068         int i;
11069     
11070         assert (nparms==1);
11071         /* save registers that need to be saved */
11072         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11073                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11074     
11075         pnum = parms[0]; 
11076         aopOp (pnum, ic, FALSE, FALSE);
11077         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,FALSE));
11078         freeAsmop (pnum, NULL, ic, FALSE);
11079         emitcode ("lcall","NatLib_LoadPrimitive");
11080         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11081         if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) || 
11082             aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
11083                 for (i = (size-1) ; i >= 0 ; i-- ) {
11084                         emitcode ("push","a%s",javaRet[i]);
11085                 }
11086                 for (i=0; i < size ; i++ ) {
11087                         emitcode ("pop","a%s",aopGet(AOP(result),i,FALSE,FALSE,FALSE));
11088                 }
11089         } else {
11090                 for (i = 0 ; i < size ; i++ ) {
11091                         aopPut(AOP(result),javaRet[i],i);
11092                 }
11093         }    
11094         freeAsmop (result, NULL, ic, FALSE);
11095         unsavermask(rsave);
11096 }
11097
11098 /*-----------------------------------------------------------------*/
11099 /* genNatLibLoadPointer - calls TINI api function to load pointer  */
11100 /*-----------------------------------------------------------------*/
11101 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
11102 {
11103         bitVect *rsave ;
11104         operand *pnum, *result;
11105         int size = 3;
11106         int i;
11107     
11108         assert (nparms==1);
11109         /* save registers that need to be saved */
11110         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11111                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11112     
11113         pnum = parms[0]; 
11114         aopOp (pnum, ic, FALSE, FALSE);
11115         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,FALSE));
11116         freeAsmop (pnum, NULL, ic, FALSE);
11117         emitcode ("lcall","NatLib_LoadPointer");
11118         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11119         if (AOP_TYPE(result)!=AOP_STR) {
11120                 for (i = 0 ; i < size ; i++ ) {
11121                         aopPut(AOP(result),fReturn[i],i);
11122                 }
11123         }    
11124         freeAsmop (result, NULL, ic, FALSE);
11125         unsavermask(rsave);
11126 }
11127
11128 /*-----------------------------------------------------------------*/
11129 /* genNatLibInstallStateBlock -                                    */
11130 /*-----------------------------------------------------------------*/
11131 static void genNatLibInstallStateBlock(iCode *ic, int nparms, 
11132                                        operand **parms, const char *name)
11133 {
11134         bitVect *rsave ;
11135         operand *psb, *handle;
11136         assert (nparms==2);
11137
11138         /* save registers that need to be saved */
11139         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11140                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11141         psb = parms[0];
11142         handle = parms[1];
11143
11144         /* put pointer to state block into DPTR1 */
11145         aopOp (psb, ic, FALSE, FALSE);
11146         if (AOP_TYPE (psb) == AOP_IMMD) {
11147                 emitcode ("mov","dps,#1");
11148                 emitcode ("mov", "dptr,%s", aopGet (AOP (psb), 0, TRUE, FALSE, FALSE));
11149                 emitcode ("mov","dps,#0");
11150         } else {
11151                 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,FALSE));
11152                 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,FALSE));
11153                 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,FALSE));
11154         }
11155         freeAsmop (psb, NULL, ic, FALSE);
11156
11157         /* put libraryID into DPTR */
11158         emitcode ("mov","dptr,#LibraryID");
11159
11160         /* put handle into r3:r2 */
11161         aopOp (handle, ic, FALSE, FALSE);
11162         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11163                 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));  
11164                 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11165                 emitcode ("pop","ar3");
11166                 emitcode ("pop","ar2");
11167         } else {        
11168                 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));        
11169                 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11170         }
11171         freeAsmop (psb, NULL, ic, FALSE);
11172
11173         /* make the call */
11174         emitcode ("lcall","NatLib_Install%sStateBlock",name);
11175
11176         /* put return value into place*/
11177         _G.accInUse++;
11178         aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
11179         _G.accInUse--;
11180         aopPut(AOP(IC_RESULT(ic)),"a",0);
11181         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11182         unsavermask(rsave);
11183 }
11184
11185 /*-----------------------------------------------------------------*/
11186 /* genNatLibRemoveStateBlock -                                     */
11187 /*-----------------------------------------------------------------*/
11188 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
11189 {
11190         bitVect *rsave ;
11191
11192         assert(nparms==0);
11193
11194         /* save registers that need to be saved */
11195         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11196                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11197
11198         /* put libraryID into DPTR */
11199         emitcode ("mov","dptr,#LibraryID");
11200         /* make the call */
11201         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
11202         unsavermask(rsave);
11203 }
11204
11205 /*-----------------------------------------------------------------*/
11206 /* genNatLibGetStateBlock -                                        */
11207 /*-----------------------------------------------------------------*/
11208 static void genNatLibGetStateBlock(iCode *ic,int nparms,
11209                                    operand **parms,const char *name)
11210 {
11211         bitVect *rsave ;
11212         symbol *lbl = newiTempLabel(NULL);
11213         
11214         assert(nparms==0);
11215         /* save registers that need to be saved */
11216         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11217                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11218
11219         /* put libraryID into DPTR */
11220         emitcode ("mov","dptr,#LibraryID");
11221         /* make the call */
11222         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
11223         emitcode ("jnz","!tlabel",lbl->key+100);
11224
11225         /* put return value into place */
11226         aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
11227         if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
11228                 emitcode ("push","ar3");
11229                 emitcode ("push","ar2");
11230                 emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,FALSE));
11231                 emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,FALSE));
11232         } else {
11233                 aopPut(AOP(IC_RESULT(ic)),"r2",0);
11234                 aopPut(AOP(IC_RESULT(ic)),"r3",1);
11235         }
11236         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11237         emitcode ("","!tlabeldef",lbl->key+100);
11238         unsavermask(rsave);
11239 }
11240
11241 /*-----------------------------------------------------------------*/
11242 /* genMMMalloc -                                                   */
11243 /*-----------------------------------------------------------------*/
11244 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
11245                          int size, const char *name)
11246 {
11247         bitVect *rsave ;
11248         operand *bsize;
11249         symbol *rsym;
11250         symbol *lbl = newiTempLabel(NULL);
11251
11252         assert (nparms == 1);
11253         /* save registers that need to be saved */
11254         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11255                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
11256         
11257         bsize=parms[0];
11258         aopOp (bsize,ic,FALSE,FALSE);
11259
11260         /* put the size in R4-R2 */
11261         if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
11262                 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,FALSE));
11263                 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,FALSE));
11264                 if (size==3) {
11265                         emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,FALSE));
11266                         emitcode("pop","ar4");
11267                 }
11268                 emitcode("pop","ar3");
11269                 emitcode("pop","ar2");          
11270         } else {
11271                 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,FALSE));
11272                 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,FALSE));
11273                 if (size==3) {
11274                         emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,FALSE));
11275                 }
11276         }
11277         freeAsmop (bsize, NULL, ic, FALSE);
11278
11279         /* make the call */
11280         emitcode ("lcall","MM_%s",name);
11281         emitcode ("jz","!tlabel",lbl->key+100);
11282         emitcode ("mov","r2,#!constbyte",0xff);
11283         emitcode ("mov","r3,#!constbyte",0xff);
11284         emitcode ("","!tlabeldef",lbl->key+100);
11285         /* we don't care about the pointer : we just save the handle */
11286         rsym = OP_SYMBOL(IC_RESULT(ic));
11287         if (rsym->liveFrom != rsym->liveTo) {
11288                 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
11289                 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
11290                         emitcode ("push","ar3");
11291                         emitcode ("push","ar2");
11292                         emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,FALSE));
11293                         emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,FALSE));
11294                 } else {
11295                         aopPut(AOP(IC_RESULT(ic)),"r2",0);
11296                         aopPut(AOP(IC_RESULT(ic)),"r3",1);
11297                 }
11298                 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11299         }
11300         unsavermask(rsave);
11301 }
11302
11303 /*-----------------------------------------------------------------*/
11304 /* genMMDeref -                                                    */
11305 /*-----------------------------------------------------------------*/
11306 static void genMMDeref (iCode *ic,int nparms, operand **parms)
11307 {
11308         bitVect *rsave ;
11309         operand *handle;
11310
11311         assert (nparms == 1);
11312         /* save registers that need to be saved */
11313         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11314                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
11315         
11316         handle=parms[0];
11317         aopOp (handle,ic,FALSE,FALSE);
11318
11319         /* put the size in R4-R2 */
11320         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11321                 emitcode("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11322                 emitcode("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11323                 emitcode("pop","ar3");
11324                 emitcode("pop","ar2");          
11325         } else {
11326                 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11327                 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11328         }
11329         freeAsmop (handle, NULL, ic, FALSE);
11330
11331         /* make the call */
11332         emitcode ("lcall","MM_Deref");
11333         
11334         {
11335                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11336                 if (rsym->liveFrom != rsym->liveTo) {                   
11337                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11338                         if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
11339                                 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
11340                                 aopPut(AOP(IC_RESULT(ic)),"dph",1);
11341                                 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
11342                         }
11343                 }
11344         }
11345         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11346         unsavermask(rsave);
11347 }
11348
11349 /*-----------------------------------------------------------------*/
11350 /* genMMUnrestrictedPersist -                                      */
11351 /*-----------------------------------------------------------------*/
11352 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
11353 {
11354         bitVect *rsave ;
11355         operand *handle;
11356
11357         assert (nparms == 1);
11358         /* save registers that need to be saved */
11359         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11360                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
11361         
11362         handle=parms[0];
11363         aopOp (handle,ic,FALSE,FALSE);
11364
11365         /* put the size in R3-R2 */
11366         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11367                 emitcode("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11368                 emitcode("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11369                 emitcode("pop","ar3");
11370                 emitcode("pop","ar2");          
11371         } else {
11372                 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11373                 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11374         }
11375         freeAsmop (handle, NULL, ic, FALSE);
11376
11377         /* make the call */
11378         emitcode ("lcall","MM_UnrestrictedPersist");
11379
11380         {
11381                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11382                 if (rsym->liveFrom != rsym->liveTo) {   
11383                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11384                         aopPut(AOP(IC_RESULT(ic)),"a",0);
11385                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11386                 }
11387         }
11388         unsavermask(rsave);
11389 }
11390
11391 /*-----------------------------------------------------------------*/
11392 /* genSystemExecJavaProcess -                                      */
11393 /*-----------------------------------------------------------------*/
11394 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
11395 {
11396         bitVect *rsave ;
11397         operand *handle, *pp;
11398
11399         assert (nparms==2);
11400         /* save registers that need to be saved */
11401         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11402                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
11403         
11404         pp = parms[0];
11405         handle = parms[1];
11406         
11407         /* put the handle in R3-R2 */
11408         aopOp (handle,ic,FALSE,FALSE);
11409         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11410                 emitcode("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11411                 emitcode("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11412                 emitcode("pop","ar3");
11413                 emitcode("pop","ar2");          
11414         } else {
11415                 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11416                 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11417         }
11418         freeAsmop (handle, NULL, ic, FALSE);
11419         
11420         /* put pointer in DPTR */
11421         aopOp (pp,ic,FALSE,FALSE);
11422         if (AOP_TYPE(pp) == AOP_IMMD) {
11423                 emitcode ("mov", "dptr,%s", aopGet (AOP (pp), 0, TRUE, FALSE, FALSE));          
11424         } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
11425                 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,FALSE));
11426                 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,FALSE));
11427                 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,FALSE));
11428         }
11429         freeAsmop (handle, NULL, ic, FALSE);
11430
11431         /* make the call */
11432         emitcode ("lcall","System_ExecJavaProcess");
11433         
11434         /* put result in place */
11435         {
11436                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11437                 if (rsym->liveFrom != rsym->liveTo) {   
11438                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11439                         aopPut(AOP(IC_RESULT(ic)),"a",0);
11440                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11441                 }
11442         }
11443         
11444         unsavermask(rsave);
11445 }
11446
11447 /*-----------------------------------------------------------------*/
11448 /* genSystemRTCRegisters -                                         */
11449 /*-----------------------------------------------------------------*/
11450 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
11451                                   char *name)
11452 {
11453         bitVect *rsave ;
11454         operand *pp;
11455
11456         assert (nparms==1);
11457         /* save registers that need to be saved */
11458         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11459                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
11460         
11461         pp=parms[0];
11462         /* put pointer in DPTR */
11463         aopOp (pp,ic,FALSE,FALSE);
11464         if (AOP_TYPE (pp) == AOP_IMMD) {
11465                 emitcode ("mov","dps,#1");
11466                 emitcode ("mov", "dptr,%s", aopGet (AOP (pp), 0, TRUE, FALSE, FALSE));
11467                 emitcode ("mov","dps,#0");
11468         } else {
11469                 emitcode ("mov","dpl1,%s",aopGet(AOP(pp),0,FALSE,FALSE,FALSE));
11470                 emitcode ("mov","dph1,%s",aopGet(AOP(pp),1,FALSE,FALSE,FALSE));
11471                 emitcode ("mov","dpx1,%s",aopGet(AOP(pp),2,FALSE,FALSE,FALSE));
11472         }
11473         freeAsmop (pp, NULL, ic, FALSE);
11474
11475         /* make the call */
11476         emitcode ("lcall","System_%sRTCRegisters",name);
11477
11478         unsavermask(rsave);
11479 }
11480
11481 /*-----------------------------------------------------------------*/
11482 /* genSystemThreadSleep -                                          */
11483 /*-----------------------------------------------------------------*/
11484 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
11485 {
11486         bitVect *rsave ;
11487         operand *to, *s;
11488
11489         assert (nparms==1);
11490         /* save registers that need to be saved */
11491         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11492                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
11493
11494         to = parms[0];
11495         aopOp(to,ic,FALSE,FALSE);
11496         if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
11497             aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
11498                 emitcode ("push","%s",aopGet(AOP(to),0,FALSE,TRUE,FALSE));
11499                 emitcode ("push","%s",aopGet(AOP(to),1,FALSE,TRUE,FALSE));
11500                 emitcode ("push","%s",aopGet(AOP(to),2,FALSE,TRUE,FALSE));
11501                 emitcode ("push","%s",aopGet(AOP(to),3,FALSE,TRUE,FALSE));
11502                 emitcode ("pop","ar3");
11503                 emitcode ("pop","ar2");
11504                 emitcode ("pop","ar1");
11505                 emitcode ("pop","ar0");
11506         } else {
11507                 emitcode ("mov","r0,%s",aopGet(AOP(to),0,FALSE,TRUE,FALSE));
11508                 emitcode ("mov","r1,%s",aopGet(AOP(to),1,FALSE,TRUE,FALSE));
11509                 emitcode ("mov","r2,%s",aopGet(AOP(to),2,FALSE,TRUE,FALSE));
11510                 emitcode ("mov","r3,%s",aopGet(AOP(to),3,FALSE,TRUE,FALSE));
11511         }
11512         freeAsmop (to, NULL, ic, FALSE);
11513
11514         /* suspend in acc */
11515         s = parms[1];
11516         aopOp(s,ic,FALSE,FALSE);
11517         emitcode ("mov","a,%s",aopGet(AOP(s),0,FALSE,TRUE,FALSE));
11518         freeAsmop (s, NULL, ic, FALSE);
11519
11520         /* make the call */
11521         emitcode ("lcall","System_%s",name);
11522
11523         unsavermask(rsave);
11524 }
11525
11526 /*-----------------------------------------------------------------*/
11527 /* genSystemThreadResume -                                         */
11528 /*-----------------------------------------------------------------*/
11529 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
11530 {
11531         bitVect *rsave ;
11532         operand *tid,*pid;
11533
11534         assert (nparms==2);
11535         /* save registers that need to be saved */
11536         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11537                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11538         
11539         tid = parms[0];
11540         pid = parms[1];
11541         
11542         /* PID in R0 */
11543         aopOp(pid,ic,FALSE,FALSE);
11544         emitcode ("mov","r0,%s",aopGet(AOP(pid),0,FALSE,TRUE,FALSE));
11545         freeAsmop (pid, NULL, ic, FALSE);
11546         
11547         /* tid into ACC */
11548         aopOp(tid,ic,FALSE,FALSE);
11549         emitcode ("mov","a,%s",aopGet(AOP(tid),0,FALSE,TRUE,FALSE));
11550         freeAsmop (tid, NULL, ic, FALSE);
11551         
11552         emitcode ("lcall","System_ThreadResume");
11553
11554         /* put result into place */
11555         {
11556                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11557                 if (rsym->liveFrom != rsym->liveTo) {   
11558                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11559                         aopPut(AOP(IC_RESULT(ic)),"a",0);
11560                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11561                 }
11562         }
11563         unsavermask(rsave);
11564 }
11565
11566 /*-----------------------------------------------------------------*/
11567 /* genSystemProcessResume -                                        */
11568 /*-----------------------------------------------------------------*/
11569 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
11570 {
11571         bitVect *rsave ;
11572         operand *pid;
11573
11574         assert (nparms==1);
11575         /* save registers that need to be saved */
11576         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11577                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11578         
11579         pid = parms[0];
11580         
11581         /* pid into ACC */
11582         aopOp(pid,ic,FALSE,FALSE);
11583         emitcode ("mov","a,%s",aopGet(AOP(pid),0,FALSE,TRUE,FALSE));
11584         freeAsmop (pid, NULL, ic, FALSE);
11585         
11586         emitcode ("lcall","System_ProcessResume");
11587
11588         unsavermask(rsave);
11589 }
11590
11591 /*-----------------------------------------------------------------*/
11592 /* genSystem -                                                     */
11593 /*-----------------------------------------------------------------*/
11594 static void genSystem (iCode *ic,int nparms,char *name)
11595 {
11596         assert(nparms == 0);
11597
11598         emitcode ("lcall","System_%s",name);
11599 }
11600
11601 /*-----------------------------------------------------------------*/
11602 /* genSystemPoll -                                                  */
11603 /*-----------------------------------------------------------------*/
11604 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
11605 {
11606         bitVect *rsave ;
11607         operand *fp;
11608
11609         assert (nparms==1);
11610         /* save registers that need to be saved */
11611         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11612                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11613
11614         fp = parms[0];
11615         aopOp (fp,ic,FALSE,FALSE);
11616         if (AOP_TYPE (fp) == AOP_IMMD) {
11617                 emitcode ("mov", "dptr,%s", aopGet (AOP (fp), 0, TRUE, FALSE, FALSE));
11618         } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
11619                 emitcode ("mov","dpl,%s",aopGet(AOP(fp),0,FALSE,FALSE,FALSE));
11620                 emitcode ("mov","dph,%s",aopGet(AOP(fp),1,FALSE,FALSE,FALSE));
11621                 emitcode ("mov","dpx,%s",aopGet(AOP(fp),2,FALSE,FALSE,FALSE));
11622         }
11623         freeAsmop (fp, NULL, ic, FALSE);
11624
11625         emitcode ("lcall","System_%sPoll",name);
11626
11627         /* put result into place */
11628         {
11629                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11630                 if (rsym->liveFrom != rsym->liveTo) {   
11631                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11632                         aopPut(AOP(IC_RESULT(ic)),"a",0);
11633                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11634                 }
11635         }
11636         unsavermask(rsave);
11637 }
11638
11639 /*-----------------------------------------------------------------*/
11640 /* genSystemGetCurrentID -                                         */
11641 /*-----------------------------------------------------------------*/
11642 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
11643 {
11644         assert (nparms==0);
11645
11646         emitcode ("lcall","System_GetCurrent%sId",name);
11647         /* put result into place */
11648         {
11649                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11650                 if (rsym->liveFrom != rsym->liveTo) {   
11651                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11652                         aopPut(AOP(IC_RESULT(ic)),"a",0);
11653                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11654                 }
11655         }
11656 }
11657
11658 /*-----------------------------------------------------------------*/
11659 /* genBuiltIn - calls the appropriate function to  generating code */
11660 /* for a built in function                                         */
11661 /*-----------------------------------------------------------------*/
11662 static void genBuiltIn (iCode *ic)
11663 {
11664         operand *bi_parms[MAX_BUILTIN_ARGS];
11665         int nbi_parms;
11666         iCode *bi_iCode;
11667         symbol *bif;
11668
11669         /* get all the arguments for a built in function */
11670         bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
11671
11672         /* which function is it */
11673         bif = OP_SYMBOL(IC_LEFT(bi_iCode));
11674         if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
11675                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
11676         } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
11677                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
11678         } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
11679                 genMemsetX(bi_iCode,nbi_parms,bi_parms);
11680         } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
11681                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
11682         } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
11683                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
11684         } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
11685                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
11686         } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
11687                 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
11688         } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
11689                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
11690         } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
11691                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
11692         } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
11693                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
11694         } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
11695                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
11696         } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
11697                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
11698         } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
11699                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
11700         } else if (strcmp(bif->name,"MM_XMalloc")==0) {
11701                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
11702         } else if (strcmp(bif->name,"MM_Malloc")==0) {
11703                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
11704         } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
11705                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
11706         } else if (strcmp(bif->name,"MM_Free")==0) {
11707                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
11708         } else if (strcmp(bif->name,"MM_Deref")==0) {
11709                 genMMDeref(bi_iCode,nbi_parms,bi_parms);
11710         } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
11711                 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
11712         } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
11713                 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
11714         } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
11715                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
11716         } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
11717                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
11718         } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
11719                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
11720         } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
11721                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
11722         } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
11723                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
11724         } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
11725                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
11726         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
11727                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
11728         } else if (strcmp(bif->name,"System_SaveThread")==0) {
11729                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
11730         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
11731                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
11732         } else if (strcmp(bif->name,"System_ProcessResume")==0) {
11733                 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
11734         } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
11735                 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
11736         } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
11737                 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
11738         } else if (strcmp(bif->name,"System_ProcessYield")==0) {
11739                 genSystem(bi_iCode,nbi_parms,"ProcessYield");
11740         } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
11741                 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
11742         } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
11743                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
11744         } else if (strcmp(bif->name,"System_RemovePoll")==0) {
11745                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
11746         } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
11747                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
11748         } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
11749                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
11750         } else {
11751                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
11752                 return ;
11753         }
11754         return ;    
11755 }
11756
11757 /*-----------------------------------------------------------------*/
11758 /* gen390Code - generate code for Dallas 390 based controllers     */
11759 /*-----------------------------------------------------------------*/
11760 void
11761 gen390Code (iCode * lic)
11762 {
11763   iCode *ic;
11764   int cln = 0;
11765
11766   lineHead = lineCurr = NULL;
11767
11768   if (options.model == MODEL_FLAT24) {
11769     fReturnSizeDS390 = 5;
11770     fReturn = fReturn24;
11771   } else {
11772     fReturnSizeDS390 = 4;
11773     fReturn = fReturn16;
11774     options.stack10bit=0;
11775   }
11776 #if 0
11777   //REMOVE ME!!!
11778   /* print the allocation information */
11779   if (allocInfo)
11780     printAllocInfo (currFunc, codeOutFile);
11781 #endif
11782   /* if debug information required */
11783   if (options.debug && currFunc)
11784     {
11785       cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
11786       _G.debugLine = 1;
11787       if (IS_STATIC (currFunc->etype))
11788         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
11789       else
11790         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
11791       _G.debugLine = 0;
11792     }
11793   /* stack pointer name */
11794   if (options.useXstack)
11795     spname = "_spx";
11796   else
11797     spname = "sp";
11798
11799
11800   for (ic = lic; ic; ic = ic->next)
11801     {
11802
11803       if (cln != ic->lineno)
11804         {
11805           if (options.debug)
11806             {
11807               _G.debugLine = 1;
11808               emitcode ("", "C$%s$%d$%d$%d ==.",
11809                         FileBaseName (ic->filename), ic->lineno,
11810                         ic->level, ic->block);
11811               _G.debugLine = 0;
11812             }
11813           emitcode (";", "%s %d", ic->filename, ic->lineno);
11814           cln = ic->lineno;
11815         }
11816       /* if the result is marked as
11817          spilt and rematerializable or code for
11818          this has already been generated then
11819          do nothing */
11820       if (resultRemat (ic) || ic->generated)
11821         continue;
11822
11823       /* depending on the operation */
11824       switch (ic->op)
11825         {
11826         case '!':
11827           genNot (ic);
11828           break;
11829
11830         case '~':
11831           genCpl (ic);
11832           break;
11833
11834         case UNARYMINUS:
11835           genUminus (ic);
11836           break;
11837
11838         case IPUSH:
11839           genIpush (ic);
11840           break;
11841
11842         case IPOP:
11843           /* IPOP happens only when trying to restore a
11844              spilt live range, if there is an ifx statement
11845              following this pop then the if statement might
11846              be using some of the registers being popped which
11847              would destory the contents of the register so
11848              we need to check for this condition and handle it */
11849           if (ic->next &&
11850               ic->next->op == IFX &&
11851               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11852             genIfx (ic->next, ic);
11853           else
11854             genIpop (ic);
11855           break;
11856
11857         case CALL:
11858           genCall (ic);
11859           break;
11860
11861         case PCALL:
11862           genPcall (ic);
11863           break;
11864
11865         case FUNCTION:
11866           genFunction (ic);
11867           break;
11868
11869         case ENDFUNCTION:
11870           genEndFunction (ic);
11871           break;
11872
11873         case RETURN:
11874           genRet (ic);
11875           break;
11876
11877         case LABEL:
11878           genLabel (ic);
11879           break;
11880
11881         case GOTO:
11882           genGoto (ic);
11883           break;
11884
11885         case '+':
11886           genPlus (ic);
11887           break;
11888
11889         case '-':
11890           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11891             genMinus (ic);
11892           break;
11893
11894         case '*':
11895           genMult (ic);
11896           break;
11897
11898         case '/':
11899           genDiv (ic);
11900           break;
11901
11902         case '%':
11903           genMod (ic);
11904           break;
11905
11906         case '>':
11907           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11908           break;
11909
11910         case '<':
11911           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11912           break;
11913
11914         case LE_OP:
11915         case GE_OP:
11916         case NE_OP:
11917
11918           /* note these two are xlated by algebraic equivalence
11919              during parsing SDCC.y */
11920           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11921                   "got '>=' or '<=' shouldn't have come here");
11922           break;
11923
11924         case EQ_OP:
11925           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11926           break;
11927
11928         case AND_OP:
11929           genAndOp (ic);
11930           break;
11931
11932         case OR_OP:
11933           genOrOp (ic);
11934           break;
11935
11936         case '^':
11937           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11938           break;
11939
11940         case '|':
11941           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11942           break;
11943
11944         case BITWISEAND:
11945           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
11946           break;
11947
11948         case INLINEASM:
11949           genInline (ic);
11950           break;
11951
11952         case RRC:
11953           genRRC (ic);
11954           break;
11955
11956         case RLC:
11957           genRLC (ic);
11958           break;
11959
11960         case GETHBIT:
11961           genGetHbit (ic);
11962           break;
11963
11964         case LEFT_OP:
11965           genLeftShift (ic);
11966           break;
11967
11968         case RIGHT_OP:
11969           genRightShift (ic);
11970           break;
11971
11972         case GET_VALUE_AT_ADDRESS:
11973           genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_LEFT(ic)))));
11974           break;
11975
11976         case '=':
11977           if (POINTER_SET (ic))
11978             genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
11979           else
11980             genAssign (ic);
11981           break;
11982
11983         case IFX:
11984           genIfx (ic, NULL);
11985           break;
11986
11987         case ADDRESS_OF:
11988           genAddrOf (ic);
11989           break;
11990
11991         case JUMPTABLE:
11992           genJumpTab (ic);
11993           break;
11994
11995         case CAST:
11996           genCast (ic);
11997           break;
11998
11999         case RECEIVE:
12000           genReceive (ic);
12001           break;
12002
12003         case SEND:
12004           if (ic->builtinSEND) genBuiltIn(ic);
12005           else addSet (&_G.sendSet, ic);
12006           break;
12007
12008         case ARRAYINIT:
12009             genArrayInit(ic);
12010             break;
12011             
12012         default:
12013           ic = ic;
12014         }
12015     }
12016
12017
12018   /* now we are ready to call the
12019      peep hole optimizer */
12020   if (!options.nopeep)
12021     peepHole (&lineHead);
12022
12023   /* now do the actual printing */
12024   printLine (lineHead, codeOutFile);
12025   return;
12026 }