8c6190f5539bd74753baaa9e581235f306233ab1
[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 extern int allocInfo;
60
61 /* this is the down and dirty file with all kinds of
62    kludgy & hacky stuff. This is what it is all about
63    CODE GENERATION for a specific MCU . some of the
64    routines may be reusable, will have to see */
65
66 static char *zero = "#0";
67 static char *one = "#1";
68 static char *spname;
69
70 #define D(x) x
71
72 #define TR_DPTR(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_DPTR1 %s ", s); }
73 #define TR_AP(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_AP %s ", s); }
74
75 unsigned fReturnSizeDS390 = 5;  /* shared with ralloc.c */
76 static char *fReturn24[] =
77 {"dpl", "dph", "dpx", "b", "a"};
78 static char *fReturn16[] =
79 {"dpl", "dph", "b", "a"};
80 static char **fReturn = fReturn24;
81 static char *accUse[] =
82 {"a", "b"};
83 static char *javaRet[] = { "r0","r1","r2","r3"};
84 static short rbank = -1;
85
86 static struct
87   {
88     short r0Pushed;
89     short r1Pushed;
90     short accInUse;
91     short bInUse;
92     short inLine;
93     short debugLine;
94     short nRegsSaved;
95     set *sendSet;
96   }
97 _G;
98
99 static void saveRBank (int, iCode *, bool);
100
101 #define RESULTONSTACK(x) \
102                          (IC_RESULT(x) && IC_RESULT(x)->aop && \
103                          IC_RESULT(x)->aop->type == AOP_STK )
104
105 /* #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x); */
106 #define MOVA(x) { char *_mova_tmp = strdup(x); \
107                  if (strcmp(_mova_tmp,"a") && strcmp(_mova_tmp,"acc")) \
108                  { \
109                     emitcode("mov","a,%s",_mova_tmp); \
110                  } \
111                  free(_mova_tmp); \
112                 }
113 #define CLRC    emitcode("clr","c")
114 #define SETC    emitcode("setb","c")
115
116 // A scratch register which will be used to hold
117 // result bytes from operands in far space via DPTR2.
118 #define DP2_RESULT_REG  "_ap"
119
120 static lineNode *lineHead = NULL;
121 static lineNode *lineCurr = NULL;
122
123 static unsigned char SLMask[] =
124 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
125  0xE0, 0xC0, 0x80, 0x00};
126 static unsigned char SRMask[] =
127 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
128  0x07, 0x03, 0x01, 0x00};
129
130 #define LSB     0
131 #define MSB16   1
132 #define MSB24   2
133 #define MSB32   3
134
135 /*-----------------------------------------------------------------*/
136 /* emitcode - writes the code into a file : for now it is simple    */
137 /*-----------------------------------------------------------------*/
138 static void
139 emitcode (char *inst, char *fmt,...)
140 {
141   va_list ap;
142   char lb[INITIAL_INLINEASM];
143   char *lbp = lb;
144
145   va_start (ap, fmt);
146
147   if (inst && *inst)
148     {
149       if (fmt && *fmt)
150         sprintf (lb, "%s\t", inst);
151       else
152         sprintf (lb, "%s", inst);
153       tvsprintf (lb + (strlen (lb)), fmt, ap);
154     }
155   else
156     tvsprintf (lb, fmt, ap);
157
158   while (isspace (*lbp))
159     lbp++;
160
161   if (lbp && *lbp)
162     lineCurr = (lineCurr ?
163                 connectLine (lineCurr, newLineNode (lb)) :
164                 (lineHead = newLineNode (lb)));
165   lineCurr->isInline = _G.inLine;
166   lineCurr->isDebug = _G.debugLine;
167   va_end (ap);
168 }
169
170 /*-----------------------------------------------------------------*/
171 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
172 /*-----------------------------------------------------------------*/
173 static regs *
174 getFreePtr (iCode * ic, asmop ** aopp, bool result)
175 {
176   bool r0iu = FALSE, r1iu = FALSE;
177   bool r0ou = FALSE, r1ou = FALSE;
178
179   /* the logic: if r0 & r1 used in the instruction
180      then we are in trouble otherwise */
181
182   /* first check if r0 & r1 are used by this
183      instruction, in which case we are in trouble */
184   r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
185   r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
186   if (r0iu && r1iu) {
187       goto endOfWorld;
188     }
189
190   r0ou = bitVectBitValue (ic->rMask, R0_IDX);
191   r1ou = bitVectBitValue (ic->rMask, R1_IDX);
192
193   /* if no usage of r0 then return it */
194   if (!r0iu && !r0ou)
195     {
196       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
197       (*aopp)->type = AOP_R0;
198
199       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
200     }
201
202   /* if no usage of r1 then return it */
203   if (!r1iu && !r1ou)
204     {
205       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
206       (*aopp)->type = AOP_R1;
207
208       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R1_IDX);
209     }
210
211   /* now we know they both have usage */
212   /* if r0 not used in this instruction */
213   if (!r0iu)
214     {
215       /* push it if not already pushed */
216       if (!_G.r0Pushed)
217         {
218           emitcode ("push", "%s",
219                     ds390_regWithIdx (R0_IDX)->dname);
220           _G.r0Pushed++;
221         }
222
223       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
224       (*aopp)->type = AOP_R0;
225
226       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
227     }
228
229   /* if r1 not used then */
230
231   if (!r1iu)
232     {
233       /* push it if not already pushed */
234       if (!_G.r1Pushed)
235         {
236           emitcode ("push", "%s",
237                     ds390_regWithIdx (R1_IDX)->dname);
238           _G.r1Pushed++;
239         }
240
241       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
242       (*aopp)->type = AOP_R1;
243       return ds390_regWithIdx (R1_IDX);
244     }
245
246 endOfWorld:
247   /* I said end of world but not quite end of world yet */
248   /* if this is a result then we can push it on the stack */
249   if (result)
250     {
251       (*aopp)->type = AOP_STK;
252       return NULL;
253     }
254
255   /* other wise this is true end of the world */
256   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
257           "getFreePtr should never reach here");
258   exit (1);
259 }
260
261 /*-----------------------------------------------------------------*/
262 /* newAsmop - creates a new asmOp                                  */
263 /*-----------------------------------------------------------------*/
264 static asmop *
265 newAsmop (short type)
266 {
267   asmop *aop;
268
269   aop = Safe_calloc (1, sizeof (asmop));
270   aop->type = type;
271   return aop;
272 }
273
274 static int _currentDPS;         /* Current processor DPS. */
275 static int _desiredDPS;         /* DPS value compiler thinks we should be using. */
276 static int _lazyDPS = 0;        /* if non-zero, we are doing lazy evaluation of DPS changes. */
277
278 /*-----------------------------------------------------------------*/
279 /* genSetDPTR: generate code to select which DPTR is in use (zero  */
280 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390     */
281 /* alternate DPTR (DPL1/DPH1/DPX1).          */
282 /*-----------------------------------------------------------------*/
283 static void
284 genSetDPTR (int n)
285 {
286
287   /* If we are doing lazy evaluation, simply note the desired
288    * change, but don't emit any code yet.
289    */
290   if (_lazyDPS)
291     {
292       _desiredDPS = n;
293       return;
294     }
295
296   if (!n)
297     {
298       emitcode ("mov", "dps,#0");
299     }
300   else
301     {
302       TR_DPTR("#1");
303       emitcode ("mov", "dps,#1");
304     }
305 }
306
307 /*-----------------------------------------------------------------*/
308 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
309 /*                   */
310 /* Any code that operates on DPTR (NB: not on the individual     */
311 /* components, like DPH) *must* call _flushLazyDPS() before using  */
312 /* DPTR within a lazy DPS evaluation block.        */
313 /*                   */
314 /* Note that aopPut and aopGet already contain the proper calls to */
315 /* _flushLazyDPS, so it is safe to use these calls within a lazy   */
316 /* DPS evaluation block.             */
317 /*                   */
318 /* Also, _flushLazyDPS must be called before any flow control      */
319 /* operations that could potentially branch out of the block.    */
320 /*                         */
321 /* Lazy DPS evaluation is simply an optimization (though an      */
322 /* important one), so if in doubt, leave it out.       */
323 /*-----------------------------------------------------------------*/
324 static void
325 _startLazyDPSEvaluation (void)
326 {
327   _currentDPS = 0;
328   _desiredDPS = 0;
329 #ifdef BETTER_LITERAL_SHIFT  
330   _lazyDPS++;
331 #else
332   _lazyDPS = 1;
333 #endif  
334 }
335
336 /*-----------------------------------------------------------------*/
337 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
338 /* desired one. Call before using DPTR within a lazy DPS evaluation */
339 /* block.                */
340 /*-----------------------------------------------------------------*/
341 static void
342 _flushLazyDPS (void)
343 {
344   if (!_lazyDPS)
345     {
346       /* nothing to do. */
347       return;
348     }
349
350   if (_desiredDPS != _currentDPS)
351     {
352       if (_desiredDPS)
353         {
354           emitcode ("inc", "dps");
355         }
356       else
357         {
358           emitcode ("dec", "dps");
359         }
360       _currentDPS = _desiredDPS;
361     }
362 }
363
364 /*-----------------------------------------------------------------*/
365 /* _endLazyDPSEvaluation: end lazy DPS evaluation block.     */
366 /*                   */
367 /* Forces us back to the safe state (standard DPTR selected).    */
368 /*-----------------------------------------------------------------*/
369 static void
370 _endLazyDPSEvaluation (void)
371 {
372 #ifdef BETTER_LITERAL_SHIFT  
373   _lazyDPS--;
374 #else
375   _lazyDPS = 0;
376 #endif    
377   if (!_lazyDPS)
378   {
379     if (_currentDPS)
380     {
381       genSetDPTR (0);
382       _flushLazyDPS ();
383     }
384     _currentDPS = 0;
385     _desiredDPS = 0;
386   }
387 }
388
389
390
391 /*-----------------------------------------------------------------*/
392 /* pointerCode - returns the code for a pointer type               */
393 /*-----------------------------------------------------------------*/
394 static int
395 pointerCode (sym_link * etype)
396 {
397
398   return PTR_TYPE (SPEC_OCLS (etype));
399
400 }
401
402 /*-----------------------------------------------------------------*/
403 /* aopForSym - for a true symbol                                   */
404 /*-----------------------------------------------------------------*/
405 static asmop *
406 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
407 {
408   asmop *aop;
409   memmap *space = SPEC_OCLS (sym->etype);
410
411   /* if already has one */
412   if (sym->aop)
413     return sym->aop;
414
415   /* assign depending on the storage class */
416   /* if it is on the stack or indirectly addressable */
417   /* space we need to assign either r0 or r1 to it   */
418   if ((sym->onStack && !options.stack10bit) || sym->iaccess)
419     {
420       sym->aop = aop = newAsmop (0);
421       aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
422       aop->size = getSize (sym->type);
423
424       /* now assign the address of the variable to
425          the pointer register */
426       if (aop->type != AOP_STK)
427         {
428
429           if (sym->onStack)
430             {
431               if (_G.accInUse)
432                 emitcode ("push", "acc");
433
434               if (_G.bInUse)
435                 emitcode ("push", "b");
436
437               emitcode ("mov", "a,_bp");
438               emitcode ("add", "a,#!constbyte",
439                         ((sym->stack < 0) ?
440                          ((char) (sym->stack - _G.nRegsSaved)) :
441                          ((char) sym->stack)) & 0xff);
442               emitcode ("mov", "%s,a",
443                         aop->aopu.aop_ptr->name);
444
445               if (_G.bInUse)
446                 emitcode ("pop", "b");
447
448               if (_G.accInUse)
449                 emitcode ("pop", "acc");
450             }
451           else
452             emitcode ("mov", "%s,#%s",
453                       aop->aopu.aop_ptr->name,
454                       sym->rname);
455           aop->paged = space->paged;
456         }
457       else
458         aop->aopu.aop_stk = sym->stack;
459       return aop;
460     }
461
462   if (sym->onStack && options.stack10bit)
463     {
464         short stack_val = -((sym->stack < 0) ?
465                             ((short) (sym->stack - _G.nRegsSaved)) :
466                             ((short) sym->stack)) ;
467       /* It's on the 10 bit stack, which is located in
468        * far data space.
469        */
470         if (stack_val < 0 && stack_val > -3) { /* between -3 & -1 */
471             if (useDP2) {
472                 if (options.model == MODEL_FLAT24)
473                     emitcode ("mov", "dpx1,#!constbyte", (options.stack_loc >> 16) & 0xff);
474                 TR_DPTR("#2");
475                 emitcode ("mov", "dph1,_bpx+1");
476                 emitcode ("mov", "dpl1,_bpx");
477                 emitcode ("mov","dps,#1");
478             } else {
479                 if (options.model == MODEL_FLAT24)
480                     emitcode ("mov", "dpx,#!constbyte", (options.stack_loc >> 16) & 0xff);
481                 emitcode ("mov", "dph,_bpx+1");
482                 emitcode ("mov", "dpl,_bpx");
483             }
484             stack_val = -stack_val;
485             while (stack_val--) {
486                 emitcode ("inc","dptr");
487             }
488             if (useDP2) {
489                 emitcode("mov","dps,#0");
490             }
491         }  else {
492             if (_G.accInUse)
493                 emitcode ("push", "acc");
494             
495             if (_G.bInUse)
496                 emitcode ("push", "b");
497         
498             emitcode ("mov", "a,_bpx");
499             emitcode ("clr","c");
500             emitcode ("subb", "a,#!constbyte", stack_val & 0xff);
501             emitcode ("mov","b,a");
502             emitcode ("mov","a,_bpx+1");
503             emitcode ("subb","a,#!constbyte",(stack_val >> 8) & 0xff);
504             if (useDP2) {
505                 if (options.model == MODEL_FLAT24)
506                     emitcode ("mov", "dpx1,#!constbyte", (options.stack_loc >> 16) & 0xff);
507                 TR_DPTR("#2");
508                 emitcode ("mov", "dph1,a");
509                 emitcode ("mov", "dpl1,b");
510             } else {
511                 if (options.model == MODEL_FLAT24)
512                     emitcode ("mov", "dpx,#!constbyte", (options.stack_loc >> 16) & 0xff);
513                 emitcode ("mov", "dph,a");
514                 emitcode ("mov", "dpl,b");
515             }
516             
517             if (_G.bInUse)
518                 emitcode ("pop", "b");
519             
520             if (_G.accInUse)
521                 emitcode ("pop", "acc");
522         }
523         sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
524         aop->size = getSize (sym->type);
525         return aop;
526     }
527
528   /* if in bit space */
529   if (IN_BITSPACE (space))
530     {
531       sym->aop = aop = newAsmop (AOP_CRY);
532       aop->aopu.aop_dir = sym->rname;
533       aop->size = getSize (sym->type);
534       return aop;
535     }
536   /* if it is in direct space */
537   if (IN_DIRSPACE (space))
538     {
539       sym->aop = aop = newAsmop (AOP_DIR);
540       aop->aopu.aop_dir = sym->rname;
541       aop->size = getSize (sym->type);
542       return aop;
543     }
544
545   /* special case for a function */
546   if (IS_FUNC (sym->type))
547     {
548       sym->aop = aop = newAsmop (AOP_IMMD);
549       aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
550       strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
551       aop->size = FPTRSIZE;
552       return aop;
553     }
554
555   /* only remaining is far space */
556   /* in which case DPTR gets the address */
557   sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
558   if (useDP2)
559     {
560       genSetDPTR (1);
561       _flushLazyDPS ();
562       emitcode ("mov", "dptr,#%s", sym->rname);
563       genSetDPTR (0);
564     }
565   else
566     {
567       emitcode ("mov", "dptr,#%s", sym->rname);
568     }
569   aop->size = getSize (sym->type);
570
571   /* if it is in code space */
572   if (IN_CODESPACE (space))
573     aop->code = 1;
574
575   return aop;
576 }
577
578 /*-----------------------------------------------------------------*/
579 /* aopForRemat - rematerialzes an object                           */
580 /*-----------------------------------------------------------------*/
581 static asmop *
582 aopForRemat (symbol * sym)
583 {
584   iCode *ic = sym->rematiCode;
585   asmop *aop = newAsmop (AOP_IMMD);
586   int ptr_type =0;
587   int val = 0;
588
589   for (;;)
590     {
591       if (ic->op == '+')
592         val += (int) operandLitValue (IC_RIGHT (ic));
593       else if (ic->op == '-')
594         val -= (int) operandLitValue (IC_RIGHT (ic));
595       else if (IS_CAST_ICODE(ic)) {
596               sym_link *from_type = operandType(IC_RIGHT(ic));
597               aop->aopu.aop_immd.from_cast_remat = 1;
598               ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
599               ptr_type = DCL_TYPE(from_type);
600               if (ptr_type == IPOINTER) {
601                 // bug #481053
602                 ptr_type = POINTER;
603               }
604               continue ;
605       } else break;
606       
607       ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
608     }
609
610   if (val)
611     sprintf (buffer, "(%s %c 0x%04x)",
612              OP_SYMBOL (IC_LEFT (ic))->rname,
613              val >= 0 ? '+' : '-',
614              abs (val) & 0xffff);
615   else
616     strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
617
618   aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
619   strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
620   /* set immd2 field if required */
621   if (aop->aopu.aop_immd.from_cast_remat) {
622           tsprintf(buffer,"#!constbyte",ptr_type);
623           aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
624           strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
625   }
626
627   return aop;
628 }
629
630 /*-----------------------------------------------------------------*/
631 /* aopHasRegs - returns true if aop has regs between from-to       */
632 /*-----------------------------------------------------------------*/
633 static int aopHasRegs(asmop *aop, int from, int to)
634 {
635     int size =0;
636
637     if (aop->type != AOP_REG) return 0; /* if not assigned to regs */
638
639     for (; size < aop->size ; size++) {
640         int reg;
641         for (reg = from ; reg <= to ; reg++)
642             if (aop->aopu.aop_reg[size] == ds390_regWithIdx(reg)) return 1;
643     }
644     return 0;
645 }
646
647 /*-----------------------------------------------------------------*/
648 /* regsInCommon - two operands have some registers in common       */
649 /*-----------------------------------------------------------------*/
650 static bool
651 regsInCommon (operand * op1, operand * op2)
652 {
653   symbol *sym1, *sym2;
654   int i;
655
656   /* if they have registers in common */
657   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
658     return FALSE;
659
660   sym1 = OP_SYMBOL (op1);
661   sym2 = OP_SYMBOL (op2);
662
663   if (sym1->nRegs == 0 || sym2->nRegs == 0)
664     return FALSE;
665
666   for (i = 0; i < sym1->nRegs; i++)
667     {
668       int j;
669       if (!sym1->regs[i])
670         continue;
671
672       for (j = 0; j < sym2->nRegs; j++)
673         {
674           if (!sym2->regs[j])
675             continue;
676
677           if (sym2->regs[j] == sym1->regs[i])
678             return TRUE;
679         }
680     }
681
682   return FALSE;
683 }
684
685 /*-----------------------------------------------------------------*/
686 /* operandsEqu - equivalent                                        */
687 /*-----------------------------------------------------------------*/
688 static bool
689 operandsEqu (operand * op1, operand * op2)
690 {
691   symbol *sym1, *sym2;
692
693   /* if they not symbols */
694   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
695     return FALSE;
696
697   sym1 = OP_SYMBOL (op1);
698   sym2 = OP_SYMBOL (op2);
699
700   /* if both are itemps & one is spilt
701      and the other is not then false */
702   if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
703       sym1->isspilt != sym2->isspilt)
704     return FALSE;
705
706   /* if they are the same */
707   if (sym1 == sym2)
708     return TRUE;
709
710   if (strcmp (sym1->rname, sym2->rname) == 0)
711     return TRUE;
712
713
714   /* if left is a tmp & right is not */
715   if (IS_ITEMP (op1) &&
716       !IS_ITEMP (op2) &&
717       sym1->isspilt &&
718       (sym1->usl.spillLoc == sym2))
719     return TRUE;
720
721   if (IS_ITEMP (op2) &&
722       !IS_ITEMP (op1) &&
723       sym2->isspilt &&
724       sym1->level > 0 &&
725       (sym2->usl.spillLoc == sym1))
726     return TRUE;
727
728   return FALSE;
729 }
730
731 /*-----------------------------------------------------------------*/
732 /* sameRegs - two asmops have the same registers                   */
733 /*-----------------------------------------------------------------*/
734 static bool
735 sameRegs (asmop * aop1, asmop * aop2)
736 {
737   int i;
738
739   if (aop1 == aop2)
740     {
741       if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
742         {
743           return FALSE;
744         }
745       return TRUE;
746     }
747
748   if (aop1->type != AOP_REG ||
749       aop2->type != AOP_REG)
750     return FALSE;
751
752   if (aop1->size != aop2->size)
753     return FALSE;
754
755   for (i = 0; i < aop1->size; i++)
756     if (aop1->aopu.aop_reg[i] !=
757         aop2->aopu.aop_reg[i])
758       return FALSE;
759
760   return TRUE;
761 }
762
763 /*-----------------------------------------------------------------*/
764 /* aopOp - allocates an asmop for an operand  :                    */
765 /*-----------------------------------------------------------------*/
766 static void
767 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
768 {
769   asmop *aop;
770   symbol *sym;
771   int i;
772
773   if (!op)
774     return;
775
776   /* if this a literal */
777   if (IS_OP_LITERAL (op))
778     {
779       op->aop = aop = newAsmop (AOP_LIT);
780       aop->aopu.aop_lit = op->operand.valOperand;
781       aop->size = getSize (operandType (op));
782       return;
783     }
784
785   /* if already has a asmop then continue */
786   if (op->aop)
787     return;
788
789   /* if the underlying symbol has a aop */
790   if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
791     {
792       op->aop = OP_SYMBOL (op)->aop;
793       return;
794     }
795
796   /* if this is a true symbol */
797   if (IS_TRUE_SYMOP (op))
798     {
799       op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
800       return;
801     }
802
803   /* this is a temporary : this has
804      only four choices :
805      a) register
806      b) spillocation
807      c) rematerialize
808      d) conditional
809      e) can be a return use only */
810
811   sym = OP_SYMBOL (op);
812
813
814   /* if the type is a conditional */
815   if (sym->regType == REG_CND)
816     {
817       aop = op->aop = sym->aop = newAsmop (AOP_CRY);
818       aop->size = 0;
819       return;
820     }
821
822   /* if it is spilt then two situations
823      a) is rematerialize
824      b) has a spill location */
825   if (sym->isspilt || sym->nRegs == 0)
826     {
827
828       /* rematerialize it NOW */
829       if (sym->remat)
830         {
831           sym->aop = op->aop = aop =
832             aopForRemat (sym);
833           aop->size = getSize (sym->type);
834           return;
835         }
836
837       if (sym->accuse)
838         {
839           int i;
840           aop = op->aop = sym->aop = newAsmop (AOP_ACC);
841           aop->size = getSize (sym->type);
842           for (i = 0; i < 2; i++)
843             aop->aopu.aop_str[i] = accUse[i];
844           return;
845         }
846
847       if (sym->ruonly)
848         {
849           int i;
850
851           if (useDP2)
852             {
853               /* a AOP_STR uses DPTR, but DPTR is already in use;
854                * we're just hosed.
855                */
856               fprintf (stderr, "*** Internal error: AOP_STR with DPTR in use! for operand %s\n",sym->name);
857             }
858
859           aop = op->aop = sym->aop = newAsmop (AOP_STR);
860           aop->size = getSize (sym->type);
861           for (i = 0; i < (int) fReturnSizeDS390; i++)
862             aop->aopu.aop_str[i] = fReturn[i];
863           return;
864         }
865
866       /* else spill location  */
867       if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
868           /* force a new aop if sizes differ */
869           sym->usl.spillLoc->aop = NULL;
870       }
871       sym->aop = op->aop = aop =
872         aopForSym (ic, sym->usl.spillLoc, result, useDP2);
873       aop->size = getSize (sym->type);
874       return;
875     }
876
877   /* must be in a register */
878   sym->aop = op->aop = aop = newAsmop (AOP_REG);
879   aop->size = sym->nRegs;
880   for (i = 0; i < sym->nRegs; i++)
881     aop->aopu.aop_reg[i] = sym->regs[i];
882 }
883
884 /*-----------------------------------------------------------------*/
885 /* freeAsmop - free up the asmop given to an operand               */
886 /*----------------------------------------------------------------*/
887 static void
888 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
889 {
890   asmop *aop;
891
892   if (!op)
893     aop = aaop;
894   else
895     aop = op->aop;
896
897   if (!aop)
898     return;
899
900   if (aop->freed)
901     goto dealloc;
902
903   aop->freed = 1;
904
905   /* depending on the asmop type only three cases need work AOP_RO
906      , AOP_R1 && AOP_STK */
907   switch (aop->type)
908     {
909     case AOP_R0:
910       if (_G.r0Pushed)
911         {
912           if (pop)
913             {
914               emitcode ("pop", "ar0");
915               _G.r0Pushed--;
916             }
917         }
918       bitVectUnSetBit (ic->rUsed, R0_IDX);
919       break;
920
921     case AOP_R1:
922       if (_G.r1Pushed)
923         {
924           if (pop)
925             {
926               emitcode ("pop", "ar1");
927               _G.r1Pushed--;
928             }
929         }
930       bitVectUnSetBit (ic->rUsed, R1_IDX);
931       break;
932
933     case AOP_STK:
934       {
935         int sz = aop->size;
936         int stk = aop->aopu.aop_stk + aop->size;
937         bitVectUnSetBit (ic->rUsed, R0_IDX);
938         bitVectUnSetBit (ic->rUsed, R1_IDX);
939
940         getFreePtr (ic, &aop, FALSE);
941
942         if (options.stack10bit)
943           {
944             /* I'm not sure what to do here yet... */
945             /* #STUB */
946             fprintf (stderr,
947                      "*** Warning: probably generating bad code for "
948                      "10 bit stack mode.\n");
949           }
950
951         if (stk)
952           {
953             emitcode ("mov", "a,_bp");
954             emitcode ("add", "a,#!constbyte", ((char) stk) & 0xff);
955             emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
956           }
957         else
958           {
959             emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
960           }
961
962         while (sz--)
963           {
964             emitcode ("pop", "acc");
965             emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
966             if (!sz)
967               break;
968             emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
969           }
970         op->aop = aop;
971         freeAsmop (op, NULL, ic, TRUE);
972         if (_G.r0Pushed)
973           {
974             emitcode ("pop", "ar0");
975             _G.r0Pushed--;
976           }
977
978         if (_G.r1Pushed)
979           {
980             emitcode ("pop", "ar1");
981             _G.r1Pushed--;
982           }
983       }
984     }
985
986 dealloc:
987   /* all other cases just dealloc */
988   if (op)
989     {
990       op->aop = NULL;
991       if (IS_SYMOP (op))
992         {
993           OP_SYMBOL (op)->aop = NULL;
994           /* if the symbol has a spill */
995           if (SPIL_LOC (op))
996             SPIL_LOC (op)->aop = NULL;
997         }
998     }
999 }
1000
1001 /*------------------------------------------------------------------*/
1002 /* aopGet - for fetching value of the aop                           */
1003 /*                    */
1004 /* Set canClobberACC if you are sure it is OK to clobber the value  */
1005 /* in the accumulator. Set it FALSE otherwise; FALSE is always safe, */
1006 /* just less efficient.               */
1007 /*------------------------------------------------------------------*/
1008
1009 static char *
1010 aopGet (asmop * aop,
1011         int offset,
1012         bool bit16,
1013         bool dname,
1014         bool canClobberACC)
1015 {
1016   char *s = buffer;
1017   char *rs;
1018
1019   /* offset is greater than
1020      size then zero */
1021   if (offset > (aop->size - 1) &&
1022       aop->type != AOP_LIT)
1023     return zero;
1024
1025   /* depending on type */
1026   switch (aop->type)
1027     {
1028
1029     case AOP_R0:
1030     case AOP_R1:
1031       /* if we need to increment it */
1032       while (offset > aop->coff)
1033         {
1034           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1035           aop->coff++;
1036         }
1037
1038       while (offset < aop->coff)
1039         {
1040           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1041           aop->coff--;
1042         }
1043
1044       aop->coff = offset;
1045       if (aop->paged)
1046         {
1047           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1048           return (dname ? "acc" : "a");
1049         }
1050       sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1051       rs = Safe_calloc (1, strlen (s) + 1);
1052       strcpy (rs, s);
1053       return rs;
1054
1055     case AOP_DPTR:
1056     case AOP_DPTR2:
1057
1058       if (aop->type == AOP_DPTR2)
1059         {
1060           genSetDPTR (1);
1061           if (!canClobberACC)
1062             {
1063                     TR_AP("#1");
1064                     emitcode ("xch", "a, %s", DP2_RESULT_REG);
1065             }
1066         }
1067
1068       _flushLazyDPS ();
1069
1070       while (offset > aop->coff)
1071         {
1072           emitcode ("inc", "dptr");
1073           aop->coff++;
1074         }
1075
1076       while (offset < aop->coff)
1077         {
1078           emitcode ("lcall", "__decdptr");
1079           aop->coff--;
1080         }
1081
1082       aop->coff = offset;
1083       if (aop->code)
1084         {
1085           emitcode ("clr", "a");
1086           emitcode ("movc", "a,@a+dptr");
1087         }
1088       else
1089         {
1090           emitcode ("movx", "a,@dptr");
1091         }
1092
1093       if (aop->type == AOP_DPTR2)
1094         {
1095           genSetDPTR (0);
1096           if (!canClobberACC)
1097             {
1098        TR_AP("#2");
1099               emitcode ("xch", "a, %s", DP2_RESULT_REG);
1100               return DP2_RESULT_REG;
1101             }
1102         }
1103       return (dname ? "acc" : "a");
1104
1105     case AOP_IMMD:
1106       if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
1107               sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
1108       } else if (bit16)
1109         sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
1110       else if (offset) {
1111           switch (offset) {
1112           case 1:
1113               tsprintf(s,"#!his",aop->aopu.aop_immd.aop_immd1);
1114               break;
1115           case 2:
1116               tsprintf(s,"#!hihis",aop->aopu.aop_immd.aop_immd1);
1117               break;
1118           case 3:
1119               tsprintf(s,"#!hihihis",aop->aopu.aop_immd.aop_immd1);
1120               break;
1121           default: /* should not need this (just in case) */
1122               sprintf (s, "#(%s >> %d)",
1123                        aop->aopu.aop_immd.aop_immd1,
1124                        offset * 8);
1125           }
1126       }
1127       else
1128         sprintf (s, "#%s",
1129                  aop->aopu.aop_immd.aop_immd1);
1130       rs = Safe_calloc (1, strlen (s) + 1);
1131       strcpy (rs, s);
1132       return rs;
1133
1134     case AOP_DIR:
1135       if (offset)
1136         sprintf (s, "(%s + %d)",
1137                  aop->aopu.aop_dir,
1138                  offset);
1139       else
1140         sprintf (s, "%s", aop->aopu.aop_dir);
1141       rs = Safe_calloc (1, strlen (s) + 1);
1142       strcpy (rs, s);
1143       return rs;
1144
1145     case AOP_REG:
1146       if (dname)
1147         return aop->aopu.aop_reg[offset]->dname;
1148       else
1149         return aop->aopu.aop_reg[offset]->name;
1150
1151     case AOP_CRY:
1152       emitcode ("clr", "a");
1153       emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1154       emitcode ("rlc", "a");
1155       return (dname ? "acc" : "a");
1156
1157     case AOP_ACC:
1158       if (!offset && dname)
1159         return "acc";
1160       return aop->aopu.aop_str[offset];
1161
1162     case AOP_LIT:
1163       return aopLiteral (aop->aopu.aop_lit, offset);
1164
1165     case AOP_STR:
1166       aop->coff = offset;
1167       if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1168           dname)
1169         return "acc";
1170
1171       return aop->aopu.aop_str[offset];
1172
1173     }
1174
1175   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1176           "aopget got unsupported aop->type");
1177   exit (1);
1178 }
1179 /*-----------------------------------------------------------------*/
1180 /* aopPut - puts a string for a aop                                */
1181 /*-----------------------------------------------------------------*/
1182 static void
1183 aopPut (asmop * aop, char *s, int offset)
1184 {
1185   char *d = buffer;
1186
1187   if (aop->size && offset > (aop->size - 1))
1188     {
1189       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1190               "aopPut got offset > aop->size");
1191       exit (1);
1192     }
1193
1194   /* will assign value to value */
1195   /* depending on where it is ofcourse */
1196   switch (aop->type)
1197     {
1198     case AOP_DIR:
1199       if (offset)
1200         sprintf (d, "(%s + %d)",
1201                  aop->aopu.aop_dir, offset);
1202       else
1203         sprintf (d, "%s", aop->aopu.aop_dir);
1204
1205       if (strcmp (d, s))
1206         emitcode ("mov", "%s,%s", d, s);
1207
1208       break;
1209
1210     case AOP_REG:
1211       if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1212           strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1213         {
1214           if (*s == '@' ||
1215               strcmp (s, "r0") == 0 ||
1216               strcmp (s, "r1") == 0 ||
1217               strcmp (s, "r2") == 0 ||
1218               strcmp (s, "r3") == 0 ||
1219               strcmp (s, "r4") == 0 ||
1220               strcmp (s, "r5") == 0 ||
1221               strcmp (s, "r6") == 0 ||
1222               strcmp (s, "r7") == 0)
1223             emitcode ("mov", "%s,%s",
1224                       aop->aopu.aop_reg[offset]->dname, s);
1225           else
1226             emitcode ("mov", "%s,%s",
1227                       aop->aopu.aop_reg[offset]->name, s);
1228         }
1229       break;
1230
1231     case AOP_DPTR:
1232     case AOP_DPTR2:
1233
1234       if (aop->type == AOP_DPTR2)
1235         {
1236           genSetDPTR (1);
1237         }
1238       _flushLazyDPS ();
1239
1240       if (aop->code)
1241         {
1242           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1243                   "aopPut writting to code space");
1244           exit (1);
1245         }
1246
1247       while (offset > aop->coff)
1248         {
1249           aop->coff++;
1250           emitcode ("inc", "dptr");
1251         }
1252
1253       while (offset < aop->coff)
1254         {
1255           aop->coff--;
1256           emitcode ("lcall", "__decdptr");
1257         }
1258
1259       aop->coff = offset;
1260
1261       /* if not in accumulater */
1262       MOVA (s);
1263
1264       emitcode ("movx", "@dptr,a");
1265
1266       if (aop->type == AOP_DPTR2)
1267         {
1268           genSetDPTR (0);
1269         }
1270       break;
1271
1272     case AOP_R0:
1273     case AOP_R1:
1274       while (offset > aop->coff)
1275         {
1276           aop->coff++;
1277           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1278         }
1279       while (offset < aop->coff)
1280         {
1281           aop->coff--;
1282           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1283         }
1284       aop->coff = offset;
1285
1286       if (aop->paged)
1287         {
1288           MOVA (s);
1289           emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1290
1291         }
1292       else if (*s == '@')
1293         {
1294           MOVA (s);
1295           emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1296         }
1297       else if (strcmp (s, "r0") == 0 ||
1298                strcmp (s, "r1") == 0 ||
1299                strcmp (s, "r2") == 0 ||
1300                strcmp (s, "r3") == 0 ||
1301                strcmp (s, "r4") == 0 ||
1302                strcmp (s, "r5") == 0 ||
1303                strcmp (s, "r6") == 0 ||
1304                strcmp (s, "r7") == 0)
1305         {
1306           char buffer[10];
1307           sprintf (buffer, "a%s", s);
1308           emitcode ("mov", "@%s,%s",
1309                     aop->aopu.aop_ptr->name, buffer);
1310         }
1311       else
1312         emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1313
1314       break;
1315
1316     case AOP_STK:
1317       if (strcmp (s, "a") == 0)
1318         emitcode ("push", "acc");
1319       else
1320         if (*s=='@') {
1321           MOVA(s);
1322           emitcode ("push", "acc");
1323         } else {
1324           emitcode ("push", s);
1325         }
1326
1327       break;
1328
1329     case AOP_CRY:
1330       /* if bit variable */
1331       if (!aop->aopu.aop_dir)
1332         {
1333           emitcode ("clr", "a");
1334           emitcode ("rlc", "a");
1335         }
1336       else
1337         {
1338           if (s == zero)
1339             emitcode ("clr", "%s", aop->aopu.aop_dir);
1340           else if (s == one)
1341             emitcode ("setb", "%s", aop->aopu.aop_dir);
1342           else if (!strcmp (s, "c"))
1343             emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1344           else
1345             {
1346               if (strcmp (s, "a"))
1347                 {
1348                   MOVA (s);
1349                 }
1350               {
1351                 symbol *lbl = newiTempLabel (NULL);
1352                 emitcode ("clr", "c");
1353                 emitcode ("jz", "!tlabel", lbl->key + 100);
1354                 emitcode ("cpl", "c");
1355                 emitcode ("", "!tlabeldef", lbl->key + 100);
1356                 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1357               }
1358             }
1359         }
1360       break;
1361
1362     case AOP_STR:
1363       aop->coff = offset;
1364       if (strcmp (aop->aopu.aop_str[offset], s))
1365         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1366       break;
1367
1368     case AOP_ACC:
1369       aop->coff = offset;
1370       if (!offset && (strcmp (s, "acc") == 0))
1371         break;
1372
1373       if (strcmp (aop->aopu.aop_str[offset], s))
1374         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1375       break;
1376
1377     default:
1378       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1379               "aopPut got unsupported aop->type");
1380       exit (1);
1381     }
1382
1383 }
1384
1385
1386 /*--------------------------------------------------------------------*/
1387 /* reAdjustPreg - points a register back to where it should (coff==0) */
1388 /*--------------------------------------------------------------------*/
1389 static void
1390 reAdjustPreg (asmop * aop)
1391 {
1392   if ((aop->coff==0) || (aop->size <= 1)) {
1393     return;
1394   }
1395
1396   switch (aop->type)
1397     {
1398     case AOP_R0:
1399     case AOP_R1:
1400       while (aop->coff--)
1401         emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1402       break;
1403     case AOP_DPTR:
1404     case AOP_DPTR2:
1405       if (aop->type == AOP_DPTR2)
1406         {
1407           genSetDPTR (1);
1408           _flushLazyDPS ();
1409         }
1410       while (aop->coff--)
1411         {
1412           emitcode ("lcall", "__decdptr");
1413         }
1414
1415       if (aop->type == AOP_DPTR2)
1416         {
1417           genSetDPTR (0);
1418         }
1419       break;
1420
1421     }
1422   aop->coff=0;
1423 }
1424
1425 #define AOP(op) op->aop
1426 #define AOP_TYPE(op) AOP(op)->type
1427 #define AOP_SIZE(op) AOP(op)->size
1428 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1429                        AOP_TYPE(x) == AOP_R0))
1430
1431 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
1432                         AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1433                          AOP(x)->paged))
1434
1435 #define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
1436                       (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1437                       x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1438
1439 /* Workaround for DS80C390 bug: div ab may return bogus results
1440  * if A is accessed in instruction immediately before the div.
1441  *
1442  * Will be fixed in B4 rev of processor, Dallas claims.
1443  */
1444
1445 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L)       \
1446     if (!AOP_NEEDSACC(RIGHT))         \
1447     {               \
1448       /* We can load A first, then B, since     \
1449        * B (the RIGHT operand) won't clobber A,   \
1450        * thus avoiding touching A right before the div. \
1451        */             \
1452       D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1453       L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE);     \
1454       MOVA(L);            \
1455       emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1456     }               \
1457     else              \
1458     {               \
1459       /* Just stuff in a nop after loading A. */    \
1460       emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1461       L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE);   \
1462       MOVA(L);            \
1463       emitcode("nop", "; workaround for DS80C390 div bug.");  \
1464     }
1465
1466 /*-----------------------------------------------------------------*/
1467 /* genNotFloat - generates not for float operations              */
1468 /*-----------------------------------------------------------------*/
1469 static void
1470 genNotFloat (operand * op, operand * res)
1471 {
1472   int size, offset;
1473   char *l;
1474   symbol *tlbl;
1475
1476   D (emitcode (";", "genNotFloat ");
1477     );
1478
1479   /* we will put 127 in the first byte of
1480      the result */
1481   aopPut (AOP (res), "#127", 0);
1482   size = AOP_SIZE (op) - 1;
1483   offset = 1;
1484
1485   _startLazyDPSEvaluation ();
1486   l = aopGet (op->aop, offset++, FALSE, FALSE, TRUE);
1487   MOVA (l);
1488
1489   while (size--)
1490     {
1491       emitcode ("orl", "a,%s",
1492                 aopGet (op->aop,
1493                         offset++, FALSE, FALSE, FALSE));
1494     }
1495   _endLazyDPSEvaluation ();
1496
1497   tlbl = newiTempLabel (NULL);
1498   aopPut (res->aop, one, 1);
1499   emitcode ("jz", "!tlabel", (tlbl->key + 100));
1500   aopPut (res->aop, zero, 1);
1501   emitcode ("", "!tlabeldef", (tlbl->key + 100));
1502
1503   size = res->aop->size - 2;
1504   offset = 2;
1505   /* put zeros in the rest */
1506   while (size--)
1507     aopPut (res->aop, zero, offset++);
1508 }
1509
1510 /*-----------------------------------------------------------------*/
1511 /* opIsGptr: returns non-zero if the passed operand is       */
1512 /* a generic pointer type.             */
1513 /*-----------------------------------------------------------------*/
1514 static int
1515 opIsGptr (operand * op)
1516 {
1517   sym_link *type = operandType (op);
1518
1519   if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1520     {
1521       return 1;
1522     }
1523   return 0;
1524 }
1525
1526 /*-----------------------------------------------------------------*/
1527 /* getDataSize - get the operand data size                         */
1528 /*-----------------------------------------------------------------*/
1529 static int
1530 getDataSize (operand * op)
1531 {
1532   int size;
1533   size = AOP_SIZE (op);
1534   if (size == GPTRSIZE)
1535     {
1536       sym_link *type = operandType (op);
1537       if (IS_GENPTR (type))
1538         {
1539           /* generic pointer; arithmetic operations
1540            * should ignore the high byte (pointer type).
1541            */
1542           size--;
1543         }
1544     }
1545   return size;
1546 }
1547
1548 /*-----------------------------------------------------------------*/
1549 /* outAcc - output Acc                                             */
1550 /*-----------------------------------------------------------------*/
1551 static void
1552 outAcc (operand * result)
1553 {
1554   int size, offset;
1555   size = getDataSize (result);
1556   if (size)
1557     {
1558       aopPut (AOP (result), "a", 0);
1559       size--;
1560       offset = 1;
1561       /* unsigned or positive */
1562       while (size--)
1563         {
1564           aopPut (AOP (result), zero, offset++);
1565         }
1566     }
1567 }
1568
1569 /*-----------------------------------------------------------------*/
1570 /* outBitC - output a bit C                                        */
1571 /*-----------------------------------------------------------------*/
1572 static void
1573 outBitC (operand * result)
1574 {
1575   /* if the result is bit */
1576   if (AOP_TYPE (result) == AOP_CRY)
1577     {
1578       aopPut (AOP (result), "c", 0);
1579     }
1580   else
1581     {
1582       emitcode ("clr", "a");
1583       emitcode ("rlc", "a");
1584       outAcc (result);
1585     }
1586 }
1587
1588 /*-----------------------------------------------------------------*/
1589 /* toBoolean - emit code for orl a,operator(sizeop)                */
1590 /*-----------------------------------------------------------------*/
1591 static void
1592 toBoolean (operand * oper)
1593 {
1594   int   size = AOP_SIZE (oper) - 1;
1595   int   offset = 1;
1596   bool usedB = FALSE;
1597
1598   /* The generic part of a generic pointer should
1599    * not participate in it's truth value.
1600    *
1601    * i.e. 0x10000000 is zero.
1602    */
1603   if (opIsGptr (oper))
1604     {
1605       D (emitcode (";", "toBoolean: generic ptr special case.");
1606         );
1607       size--;
1608     }
1609
1610   _startLazyDPSEvaluation ();
1611   if (AOP_NEEDSACC (oper) && size)
1612     {
1613       usedB = TRUE;
1614       emitcode ("push", "b");
1615       emitcode ("mov", "b, %s", aopGet (AOP (oper), 0, FALSE, FALSE, FALSE));
1616     }
1617   else
1618     {
1619       MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, TRUE));
1620     }
1621   while (size--)
1622     {
1623       if (usedB)
1624         {
1625           emitcode ("orl", "b,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1626         }
1627       else
1628         {
1629           emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1630         }
1631     }
1632   _endLazyDPSEvaluation ();
1633
1634   if (usedB)
1635     {
1636       emitcode ("mov", "a,b");
1637       emitcode ("pop", "b");
1638     }
1639 }
1640
1641
1642 /*-----------------------------------------------------------------*/
1643 /* genNot - generate code for ! operation                          */
1644 /*-----------------------------------------------------------------*/
1645 static void
1646 genNot (iCode * ic)
1647 {
1648   symbol *tlbl;
1649   sym_link *optype = operandType (IC_LEFT (ic));
1650
1651   D (emitcode (";", "genNot ");
1652     );
1653
1654   /* assign asmOps to operand & result */
1655   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1656   aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1657
1658   /* if in bit space then a special case */
1659   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1660     {
1661       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1662       emitcode ("cpl", "c");
1663       outBitC (IC_RESULT (ic));
1664       goto release;
1665     }
1666
1667   /* if type float then do float */
1668   if (IS_FLOAT (optype))
1669     {
1670       genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1671       goto release;
1672     }
1673
1674   toBoolean (IC_LEFT (ic));
1675
1676   tlbl = newiTempLabel (NULL);
1677   emitcode ("cjne", "a,#1,!tlabel", tlbl->key + 100);
1678   emitcode ("", "!tlabeldef", tlbl->key + 100);
1679   outBitC (IC_RESULT (ic));
1680
1681 release:
1682   /* release the aops */
1683   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1684   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1685 }
1686
1687
1688 /*-----------------------------------------------------------------*/
1689 /* genCpl - generate code for complement                           */
1690 /*-----------------------------------------------------------------*/
1691 static void
1692 genCpl (iCode * ic)
1693 {
1694   int offset = 0;
1695   int size;
1696   symbol *tlbl;
1697
1698   D (emitcode (";", "genCpl ");
1699     );
1700
1701
1702   /* assign asmOps to operand & result */
1703   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1704   aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1705
1706   /* special case if in bit space */
1707   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
1708     if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
1709       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1710       emitcode ("cpl", "c");
1711       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1712       goto release;
1713     }
1714     tlbl=newiTempLabel(NULL);
1715     emitcode ("cjne", "%s,#0x01,%05d$", 
1716               aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE,TRUE), tlbl->key+100);
1717     emitcode ("", "%05d$:", tlbl->key+100);
1718     outBitC (IC_RESULT(ic));
1719     goto release;
1720   }
1721
1722   size = AOP_SIZE (IC_RESULT (ic));
1723   _startLazyDPSEvaluation ();
1724   while (size--)
1725     {
1726       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1727       MOVA (l);
1728       emitcode ("cpl", "a");
1729       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1730     }
1731   _endLazyDPSEvaluation ();
1732
1733
1734 release:
1735   /* release the aops */
1736   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1737   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1738 }
1739
1740 /*-----------------------------------------------------------------*/
1741 /* genUminusFloat - unary minus for floating points                */
1742 /*-----------------------------------------------------------------*/
1743 static void
1744 genUminusFloat (operand * op, operand * result)
1745 {
1746   int size, offset = 0;
1747   char *l;
1748   /* for this we just need to flip the
1749      first it then copy the rest in place */
1750   D (emitcode (";", "genUminusFloat");
1751     );
1752
1753   _startLazyDPSEvaluation ();
1754   size = AOP_SIZE (op) - 1;
1755   l = aopGet (AOP (op), 3, FALSE, FALSE, TRUE);
1756   MOVA (l);
1757
1758   emitcode ("cpl", "acc.7");
1759   aopPut (AOP (result), "a", 3);
1760
1761   while (size--)
1762     {
1763       aopPut (AOP (result),
1764               aopGet (AOP (op), offset, FALSE, FALSE, FALSE),
1765               offset);
1766       offset++;
1767     }
1768   _endLazyDPSEvaluation ();
1769 }
1770
1771 /*-----------------------------------------------------------------*/
1772 /* genUminus - unary minus code generation                         */
1773 /*-----------------------------------------------------------------*/
1774 static void
1775 genUminus (iCode * ic)
1776 {
1777   int offset, size;
1778   sym_link *optype, *rtype;
1779
1780   D (emitcode (";", "genUminus ");
1781     );
1782
1783
1784   /* assign asmops */
1785   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1786   aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1787
1788   /* if both in bit space then special
1789      case */
1790   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1791       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1792     {
1793
1794       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1795       emitcode ("cpl", "c");
1796       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1797       goto release;
1798     }
1799
1800   optype = operandType (IC_LEFT (ic));
1801   rtype = operandType (IC_RESULT (ic));
1802
1803   /* if float then do float stuff */
1804   if (IS_FLOAT (optype))
1805     {
1806       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1807       goto release;
1808     }
1809
1810   /* otherwise subtract from zero */
1811   size = AOP_SIZE (IC_LEFT (ic));
1812   offset = 0;
1813   _startLazyDPSEvaluation ();
1814   while (size--)
1815     {
1816       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1817       if (!strcmp (l, "a"))
1818         {
1819           if (offset == 0)
1820             SETC;
1821           emitcode ("cpl", "a");
1822           emitcode ("addc", "a,#0");
1823         }
1824       else
1825         {
1826           if (offset == 0)
1827             CLRC;
1828           emitcode ("clr", "a");
1829           emitcode ("subb", "a,%s", l);
1830         }
1831       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1832     }
1833   _endLazyDPSEvaluation ();
1834
1835   /* if any remaining bytes in the result */
1836   /* we just need to propagate the sign   */
1837   if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1838     {
1839       emitcode ("rlc", "a");
1840       emitcode ("subb", "a,acc");
1841       while (size--)
1842         aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1843     }
1844
1845 release:
1846   /* release the aops */
1847   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1848   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1849 }
1850
1851 /*-----------------------------------------------------------------*/
1852 /* savermask - saves registers in the mask                         */
1853 /*-----------------------------------------------------------------*/
1854 static void savermask(bitVect *rs_mask)
1855 {
1856     int i;
1857     if (options.useXstack) {
1858         if (bitVectBitValue (rs_mask, R0_IDX))
1859             emitcode ("mov", "b,r0");
1860         emitcode ("mov", "r0,%s", spname);
1861         for (i = 0; i < ds390_nRegs; i++) {
1862             if (bitVectBitValue (rs_mask, i)) {
1863                 if (i == R0_IDX)
1864                     emitcode ("mov", "a,b");
1865                 else
1866                     emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
1867                 emitcode ("movx", "@r0,a");
1868                 emitcode ("inc", "r0");
1869             }
1870         }
1871         emitcode ("mov", "%s,r0", spname);
1872         if (bitVectBitValue (rs_mask, R0_IDX))
1873             emitcode ("mov", "r0,b");
1874     } else {
1875         for (i = 0; i < ds390_nRegs; i++) {
1876             if (bitVectBitValue (rs_mask, i))
1877                 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
1878         }
1879     }
1880 }
1881
1882 /*-----------------------------------------------------------------*/
1883 /* saveRegisters - will look for a call and save the registers     */
1884 /*-----------------------------------------------------------------*/
1885 static void
1886 saveRegisters (iCode * lic)
1887 {
1888   iCode *ic;
1889   bitVect *rsave;
1890
1891   /* look for call */
1892   for (ic = lic; ic; ic = ic->next)
1893     if (ic->op == CALL || ic->op == PCALL)
1894       break;
1895
1896   if (!ic)
1897     {
1898       fprintf (stderr, "found parameter push with no function call\n");
1899       return;
1900     }
1901
1902   /* if the registers have been saved already then
1903      do nothing */
1904   if (ic->regsSaved || IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic)))) return ;
1905
1906   /* special case if DPTR alive across a function call then must save it 
1907      even though callee saves */
1908   if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
1909       int i =0;
1910       rsave = newBitVect(ic->rMask->size);
1911       for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
1912           if (bitVectBitValue(ic->rMask,i))
1913               rsave = bitVectSetBit(rsave,i);
1914       }
1915       rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
1916   } else {
1917     /* safe the registers in use at this time but skip the
1918        ones for the result */
1919     rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1920                            ds390_rUmaskForOp (IC_RESULT(ic)));
1921   }
1922   ic->regsSaved = 1;
1923   savermask(rsave);
1924 }
1925
1926 /*-----------------------------------------------------------------*/
1927 /* usavermask - restore registers with mask                        */
1928 /*-----------------------------------------------------------------*/
1929 static void unsavermask(bitVect *rs_mask)
1930 {
1931     int i;
1932     if (options.useXstack) {
1933         emitcode ("mov", "r0,%s", spname);
1934         for (i = ds390_nRegs; i >= 0; i--) {
1935             if (bitVectBitValue (rs_mask, i)) {
1936                 emitcode ("dec", "r0");
1937                 emitcode ("movx", "a,@r0");
1938                 if (i == R0_IDX)
1939                     emitcode ("mov", "b,a");
1940                 else
1941                     emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
1942             }       
1943         }
1944         emitcode ("mov", "%s,r0", spname);
1945         if (bitVectBitValue (rs_mask, R0_IDX))
1946             emitcode ("mov", "r0,b");
1947     } else {
1948         for (i = ds390_nRegs; i >= 0; i--) {
1949             if (bitVectBitValue (rs_mask, i))
1950                 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
1951         }
1952     }
1953 }
1954
1955 /*-----------------------------------------------------------------*/
1956 /* unsaveRegisters - pop the pushed registers                      */
1957 /*-----------------------------------------------------------------*/
1958 static void
1959 unsaveRegisters (iCode * ic)
1960 {
1961   bitVect *rsave;
1962
1963   if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
1964       int i =0;
1965       rsave = newBitVect(ic->rMask->size);
1966       for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
1967           if (bitVectBitValue(ic->rMask,i))
1968               rsave = bitVectSetBit(rsave,i);
1969       }
1970       rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
1971   } else {
1972     /* restore the registers in use at this time but skip the
1973        ones for the result */
1974     rsave = bitVectCplAnd (bitVectCopy (ic->rMask), 
1975                            ds390_rUmaskForOp (IC_RESULT(ic)));
1976   }
1977   unsavermask(rsave);
1978 }
1979
1980
1981 /*-----------------------------------------------------------------*/
1982 /* pushSide -                */
1983 /*-----------------------------------------------------------------*/
1984 static void
1985 pushSide (operand * oper, int size)
1986 {
1987   int offset = 0;
1988   _startLazyDPSEvaluation ();
1989   while (size--)
1990     {
1991       char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, FALSE);
1992       if (AOP_TYPE (oper) != AOP_REG &&
1993           AOP_TYPE (oper) != AOP_DIR &&
1994           strcmp (l, "a"))
1995         {
1996           emitcode ("mov", "a,%s", l);
1997           emitcode ("push", "acc");
1998         }
1999       else
2000         emitcode ("push", "%s", l);
2001     }
2002   _endLazyDPSEvaluation ();
2003 }
2004
2005 /*-----------------------------------------------------------------*/
2006 /* assignResultValue -               */
2007 /*-----------------------------------------------------------------*/
2008 static void
2009 assignResultValue (operand * oper)
2010 {
2011   int offset = 0;
2012   int size = AOP_SIZE (oper);
2013
2014   _startLazyDPSEvaluation ();
2015   while (size--)
2016     {
2017       aopPut (AOP (oper), fReturn[offset], offset);
2018       offset++;
2019     }
2020   _endLazyDPSEvaluation ();
2021 }
2022
2023
2024 /*-----------------------------------------------------------------*/
2025 /* genXpush - pushes onto the external stack                       */
2026 /*-----------------------------------------------------------------*/
2027 static void
2028 genXpush (iCode * ic)
2029 {
2030   asmop *aop = newAsmop (0);
2031   regs *r;
2032   int size, offset = 0;
2033
2034   D (emitcode (";", "genXpush ");
2035     );
2036
2037   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2038   r = getFreePtr (ic, &aop, FALSE);
2039
2040
2041   emitcode ("mov", "%s,_spx", r->name);
2042
2043   size = AOP_SIZE (IC_LEFT (ic));
2044   _startLazyDPSEvaluation ();
2045   while (size--)
2046     {
2047
2048       char *l = aopGet (AOP (IC_LEFT (ic)),
2049                         offset++, FALSE, FALSE, TRUE);
2050       MOVA (l);
2051       emitcode ("movx", "@%s,a", r->name);
2052       emitcode ("inc", "%s", r->name);
2053
2054     }
2055   _endLazyDPSEvaluation ();
2056
2057
2058   emitcode ("mov", "_spx,%s", r->name);
2059
2060   freeAsmop (NULL, aop, ic, TRUE);
2061   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2062 }
2063
2064 /*-----------------------------------------------------------------*/
2065 /* genIpush - genrate code for pushing this gets a little complex  */
2066 /*-----------------------------------------------------------------*/
2067 static void
2068 genIpush (iCode * ic)
2069 {
2070   int size, offset = 0;
2071   char *l;
2072
2073   D (emitcode (";", "genIpush ");
2074     );
2075
2076   /* if this is not a parm push : ie. it is spill push
2077      and spill push is always done on the local stack */
2078   if (!ic->parmPush)
2079     {
2080
2081       /* and the item is spilt then do nothing */
2082       if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2083         return;
2084
2085       aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2086       size = AOP_SIZE (IC_LEFT (ic));
2087       /* push it on the stack */
2088       _startLazyDPSEvaluation ();
2089       while (size--)
2090         {
2091           l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, TRUE);
2092           if (*l == '#')
2093             {
2094               MOVA (l);
2095               l = "acc";
2096             }
2097           emitcode ("push", "%s", l);
2098         }
2099       _endLazyDPSEvaluation ();
2100       return;
2101     }
2102
2103   /* this is a paramter push: in this case we call
2104      the routine to find the call and save those
2105      registers that need to be saved */
2106   saveRegisters (ic);
2107
2108   /* if use external stack then call the external
2109      stack pushing routine */
2110   if (options.useXstack)
2111     {
2112       genXpush (ic);
2113       return;
2114     }
2115
2116   /* then do the push */
2117   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2118
2119   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2120   size = AOP_SIZE (IC_LEFT (ic));
2121
2122   _startLazyDPSEvaluation ();
2123   while (size--)
2124     {
2125       l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, FALSE);
2126       if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2127           AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2128           strcmp (l, "a"))
2129         {
2130           emitcode ("mov", "a,%s", l);
2131           emitcode ("push", "acc");
2132         }
2133       else
2134         emitcode ("push", "%s", l);
2135     }
2136   _endLazyDPSEvaluation ();
2137
2138   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2139 }
2140
2141 /*-----------------------------------------------------------------*/
2142 /* genIpop - recover the registers: can happen only for spilling   */
2143 /*-----------------------------------------------------------------*/
2144 static void
2145 genIpop (iCode * ic)
2146 {
2147   int size, offset;
2148
2149   D (emitcode (";", "genIpop ");
2150     );
2151
2152
2153   /* if the temp was not pushed then */
2154   if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2155     return;
2156
2157   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2158   size = AOP_SIZE (IC_LEFT (ic));
2159   offset = (size - 1);
2160   _startLazyDPSEvaluation ();
2161   while (size--)
2162     {
2163       emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2164                                      FALSE, TRUE, TRUE));
2165     }
2166   _endLazyDPSEvaluation ();
2167
2168   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2169 }
2170
2171 /*-----------------------------------------------------------------*/
2172 /* unsaveRBank - restores the resgister bank from stack            */
2173 /*-----------------------------------------------------------------*/
2174 static void
2175 unsaveRBank (int bank, iCode * ic, bool popPsw)
2176 {
2177   int i;
2178   asmop *aop = NULL;
2179   regs *r = NULL;
2180
2181   if (options.useXstack)
2182   {
2183       if (!ic)
2184       {
2185           /* Assume r0 is available for use. */
2186           r = ds390_regWithIdx (R0_IDX);;          
2187       } 
2188       else
2189       {
2190           aop = newAsmop (0);
2191           r = getFreePtr (ic, &aop, FALSE);
2192       }
2193       emitcode ("mov", "%s,_spx", r->name);      
2194   }
2195   
2196   if (popPsw)
2197     {
2198       if (options.useXstack)
2199       {
2200           emitcode ("movx", "a,@%s", r->name);
2201           emitcode ("mov", "psw,a");
2202           emitcode ("dec", "%s", r->name);
2203         }
2204       else
2205       {
2206         emitcode ("pop", "psw");
2207       }
2208     }
2209
2210   for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2211     {
2212       if (options.useXstack)
2213         {
2214           emitcode ("movx", "a,@%s", r->name);
2215           emitcode ("mov", "(%s+%d),a",
2216                     regs390[i].base, 8 * bank + regs390[i].offset);
2217           emitcode ("dec", "%s", r->name);
2218
2219         }
2220       else
2221         emitcode ("pop", "(%s+%d)",
2222                   regs390[i].base, 8 * bank + regs390[i].offset);
2223     }
2224
2225   if (options.useXstack)
2226     {
2227       emitcode ("mov", "_spx,%s", r->name);
2228     }
2229     
2230   if (aop)
2231   {
2232       freeAsmop (NULL, aop, ic, TRUE);  
2233   }    
2234 }
2235
2236 /*-----------------------------------------------------------------*/
2237 /* saveRBank - saves an entire register bank on the stack          */
2238 /*-----------------------------------------------------------------*/
2239 static void
2240 saveRBank (int bank, iCode * ic, bool pushPsw)
2241 {
2242   int i;
2243   asmop *aop = NULL;
2244   regs *r = NULL;
2245
2246   if (options.useXstack)
2247     {
2248         if (!ic)
2249         {
2250           /* Assume r0 is available for use. */
2251                   r = ds390_regWithIdx (R0_IDX);;
2252         }
2253         else
2254         {
2255           aop = newAsmop (0);
2256           r = getFreePtr (ic, &aop, FALSE);
2257         }
2258         emitcode ("mov", "%s,_spx", r->name);    
2259     }
2260
2261   for (i = 0; i < 8 ; i++) /* only R0-R7 needs saving */
2262     {
2263       if (options.useXstack)
2264         {
2265           emitcode ("inc", "%s", r->name);
2266           emitcode ("mov", "a,(%s+%d)",
2267                     regs390[i].base, 8 * bank + regs390[i].offset);
2268           emitcode ("movx", "@%s,a", r->name);
2269         }
2270       else
2271         emitcode ("push", "(%s+%d)",
2272                   regs390[i].base, 8 * bank + regs390[i].offset);
2273     }
2274
2275   if (pushPsw)
2276     {
2277       if (options.useXstack)
2278         {
2279           emitcode ("mov", "a,psw");
2280           emitcode ("movx", "@%s,a", r->name);
2281           emitcode ("inc", "%s", r->name);
2282           emitcode ("mov", "_spx,%s", r->name);
2283         }
2284       else
2285       {
2286         emitcode ("push", "psw");
2287       }
2288
2289       emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2290     }
2291   
2292   if (aop)
2293   {
2294        freeAsmop (NULL, aop, ic, TRUE);
2295   }    
2296     
2297   if (ic)
2298   {  
2299       ic->bankSaved = 1;
2300   }
2301 }
2302
2303 /*-----------------------------------------------------------------*/
2304 /* genCall - generates a call statement                            */
2305 /*-----------------------------------------------------------------*/
2306 static void
2307 genCall (iCode * ic)
2308 {
2309   sym_link *dtype;
2310   bool restoreBank = FALSE;
2311   bool swapBanks = FALSE;
2312
2313   D (emitcode (";", "genCall "););
2314
2315   /* if we are calling a not _naked function that is not using
2316      the same register bank then we need to save the
2317      destination registers on the stack */
2318   dtype = operandType (IC_LEFT (ic));
2319   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2320       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2321       IFFUNC_ISISR (currFunc->type))
2322   {
2323       if (!ic->bankSaved) 
2324       {
2325            /* This is unexpected; the bank should have been saved in
2326             * genFunction.
2327             */
2328            saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2329            restoreBank = TRUE;
2330       }
2331       swapBanks = TRUE;
2332   }
2333   
2334     /* if caller saves & we have not saved then */
2335     if (!ic->regsSaved)
2336       saveRegisters (ic);
2337   
2338   /* if send set is not empty the assign */
2339   /* We've saved all the registers we care about;
2340   * therefore, we may clobber any register not used
2341   * in the calling convention (i.e. anything not in
2342   * fReturn.
2343   */
2344   if (_G.sendSet)
2345     {
2346       iCode *sic;
2347
2348       for (sic = setFirstItem (_G.sendSet); sic;
2349            sic = setNextItem (_G.sendSet))
2350         {
2351           int size, offset = 0;
2352
2353           // we know that dpl(hxb) is the result, so
2354           _startLazyDPSEvaluation ();
2355           size=getSize(operandType(IC_LEFT(sic)));
2356           if (size>1) {
2357             aopOp (IC_LEFT (sic), sic, FALSE, 
2358                    (IS_SYMOP(IC_LEFT(sic)) && OP_SYMBOL(IC_LEFT(sic))->ruonly ? FALSE : TRUE));
2359           } else {
2360             aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2361           }
2362           while (size--)
2363             {
2364               char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2365                                 FALSE, FALSE, TRUE);
2366               if (strcmp (l, fReturn[offset]))
2367                 {
2368                   emitcode ("mov", "%s,%s",
2369                             fReturn[offset],
2370                             l);
2371                 }
2372               offset++;
2373             }
2374           _endLazyDPSEvaluation ();
2375           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2376         }
2377       _G.sendSet = NULL;
2378     }  
2379     
2380   if (swapBanks)
2381   {
2382         emitcode ("mov", "psw,#!constbyte", 
2383            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2384   }
2385
2386   /* make the call */
2387   emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2388                             OP_SYMBOL (IC_LEFT (ic))->rname :
2389                             OP_SYMBOL (IC_LEFT (ic))->name));
2390
2391   if (swapBanks)
2392   {
2393        emitcode ("mov", "psw,#!constbyte", 
2394           ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2395   }
2396
2397   /* if we need assign a result value */
2398   if ((IS_ITEMP (IC_RESULT (ic)) &&
2399        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2400         OP_SYMBOL (IC_RESULT (ic))->accuse ||
2401         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2402       IS_TRUE_SYMOP (IC_RESULT (ic)))
2403     {
2404       if (isOperandInFarSpace (IC_RESULT (ic))
2405           && getSize (operandType (IC_RESULT (ic))) <= 2)
2406         {
2407           int size = getSize (operandType (IC_RESULT (ic)));
2408
2409           /* Special case for 1 or 2 byte return in far space. */
2410           MOVA (fReturn[0]);
2411           if (size > 1)
2412             {
2413               emitcode ("mov", "b,%s", fReturn[1]);
2414             }
2415
2416           aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2417           aopPut (AOP (IC_RESULT (ic)), "a", 0);
2418
2419           if (size > 1)
2420             {
2421               aopPut (AOP (IC_RESULT (ic)), "b", 1);
2422             }
2423           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2424         }
2425       else
2426         {
2427           _G.accInUse++;
2428           aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2429           _G.accInUse--;
2430
2431           assignResultValue (IC_RESULT (ic));
2432
2433           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2434         }
2435     }
2436
2437   /* adjust the stack for parameters if
2438      required */
2439   if (ic->parmBytes) {
2440       int i;
2441       if (options.stack10bit) {
2442           if (ic->parmBytes <= 4) {
2443               emitcode(";","stack adjustment for parms");
2444               for (i=0; i < ic->parmBytes ; i++) {
2445                   emitcode("pop","acc");
2446               }
2447           } else {
2448               emitcode ("clr","c");
2449               emitcode ("mov","a,sp");
2450               emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2451               emitcode ("mov","sp,a");
2452               emitcode ("mov","a,esp");
2453               emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2454               emitcode ("mov","esp,a");   
2455           }
2456       } else {
2457           if (ic->parmBytes > 3) {
2458               emitcode ("mov", "a,%s", spname);
2459               emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2460               emitcode ("mov", "%s,a", spname);
2461           } else
2462               for (i = 0; i < ic->parmBytes; i++)
2463                   emitcode ("dec", "%s", spname);
2464       }
2465   }
2466
2467   /* if we hade saved some registers then unsave them */
2468   if (ic->regsSaved)
2469     unsaveRegisters (ic);
2470
2471   /* if register bank was saved then pop them */
2472   if (restoreBank)
2473     unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2474 }
2475
2476 /*-----------------------------------------------------------------*/
2477 /* genPcall - generates a call by pointer statement                */
2478 /*-----------------------------------------------------------------*/
2479 static void
2480 genPcall (iCode * ic)
2481 {
2482   sym_link *dtype;
2483   symbol *rlbl = newiTempLabel (NULL);
2484   bool restoreBank=FALSE;
2485
2486   D (emitcode (";", "genPcall ");
2487     );
2488
2489
2490   /* if caller saves & we have not saved then */
2491   if (!ic->regsSaved)
2492     saveRegisters (ic);
2493
2494   /* if we are calling a function that is not using
2495      the same register bank then we need to save the
2496      destination registers on the stack */
2497   dtype = operandType (IC_LEFT (ic));
2498   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2499       IFFUNC_ISISR (currFunc->type) &&
2500       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2501     saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2502     restoreBank=TRUE;
2503   }
2504
2505   /* push the return address on to the stack */
2506   emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
2507   emitcode ("push", "acc");
2508   emitcode ("mov", "a,#!hil", (rlbl->key + 100));
2509   emitcode ("push", "acc");
2510
2511   if (options.model == MODEL_FLAT24)
2512     {
2513       emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
2514       emitcode ("push", "acc");
2515     }
2516
2517   /* now push the calling address */
2518   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2519
2520   pushSide (IC_LEFT (ic), FPTRSIZE);
2521
2522   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2523
2524   /* if send set is not empty the assign */
2525   if (_G.sendSet)
2526     {
2527       iCode *sic;
2528
2529       for (sic = setFirstItem (_G.sendSet); sic;
2530            sic = setNextItem (_G.sendSet))
2531         {
2532           int size, offset = 0;
2533
2534           // we know that dpl(hxb) is the result, so
2535           _startLazyDPSEvaluation ();
2536           size=getSize(operandType(IC_LEFT(sic)));
2537           if (size>1) {
2538             aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2539           } else {
2540             aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2541           }
2542           while (size--)
2543             {
2544               char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2545                                 FALSE, FALSE, TRUE);
2546               if (strcmp (l, fReturn[offset]))
2547                 {
2548                   emitcode ("mov", "%s,%s",
2549                             fReturn[offset],
2550                             l);
2551                 }
2552               offset++;
2553             }
2554           _endLazyDPSEvaluation ();
2555           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2556         }
2557       _G.sendSet = NULL;
2558     }
2559
2560   emitcode ("ret", "");
2561   emitcode ("", "!tlabeldef", (rlbl->key + 100));
2562
2563
2564   /* if we need assign a result value */
2565   if ((IS_ITEMP (IC_RESULT (ic)) &&
2566        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2567         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2568       IS_TRUE_SYMOP (IC_RESULT (ic)))
2569     {
2570
2571       _G.accInUse++;
2572       aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2573       _G.accInUse--;
2574
2575       assignResultValue (IC_RESULT (ic));
2576
2577       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2578     }
2579
2580   /* adjust the stack for parameters if
2581      required */
2582   if (ic->parmBytes)
2583     {
2584       int i;
2585       if (ic->parmBytes > 3)
2586         {
2587           emitcode ("mov", "a,%s", spname);
2588           emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2589           emitcode ("mov", "%s,a", spname);
2590         }
2591       else
2592         for (i = 0; i < ic->parmBytes; i++)
2593           emitcode ("dec", "%s", spname);
2594
2595     }
2596
2597   /* if register bank was saved then unsave them */
2598   if (restoreBank)
2599     unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2600   
2601   /* if we hade saved some registers then
2602      unsave them */
2603   if (ic->regsSaved)
2604     unsaveRegisters (ic);
2605
2606 }
2607
2608 /*-----------------------------------------------------------------*/
2609 /* resultRemat - result  is rematerializable                       */
2610 /*-----------------------------------------------------------------*/
2611 static int
2612 resultRemat (iCode * ic)
2613 {
2614   if (SKIP_IC (ic) || ic->op == IFX)
2615     return 0;
2616
2617   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2618     {
2619       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2620       if (sym->remat && !POINTER_SET (ic))
2621         return 1;
2622     }
2623
2624   return 0;
2625 }
2626
2627 #if defined(__BORLANDC__) || defined(_MSC_VER)
2628 #define STRCASECMP stricmp
2629 #else
2630 #define STRCASECMP strcasecmp
2631 #endif
2632
2633 /*-----------------------------------------------------------------*/
2634 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2635 /*-----------------------------------------------------------------*/
2636 static bool
2637 inExcludeList (char *s)
2638 {
2639   int i = 0;
2640
2641   if (options.excludeRegs[i] &&
2642       STRCASECMP (options.excludeRegs[i], "none") == 0)
2643     return FALSE;
2644
2645   for (i = 0; options.excludeRegs[i]; i++)
2646     {
2647       if (options.excludeRegs[i] &&
2648           STRCASECMP (s, options.excludeRegs[i]) == 0)
2649         return TRUE;
2650     }
2651   return FALSE;
2652 }
2653
2654 /*-----------------------------------------------------------------*/
2655 /* genFunction - generated code for function entry                 */
2656 /*-----------------------------------------------------------------*/
2657 static void
2658 genFunction (iCode * ic)
2659 {
2660   symbol *sym;
2661   sym_link *ftype;
2662   bool   switchedPSW = FALSE;
2663
2664   D (emitcode (";", "genFunction "););
2665
2666   _G.nRegsSaved = 0;
2667   /* create the function header */
2668   emitcode (";", "-----------------------------------------");
2669   emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2670   emitcode (";", "-----------------------------------------");
2671
2672   emitcode ("", "%s:", sym->rname);
2673   ftype = operandType (IC_LEFT (ic));
2674
2675   if (IFFUNC_ISNAKED(ftype))
2676   {
2677       emitcode(";", "naked function: no prologue.");
2678       return;
2679   }
2680   
2681   if (options.stack_probe) 
2682       emitcode ("lcall","__stack_probe");
2683   /* if critical function then turn interrupts off */
2684   if (IFFUNC_ISCRITICAL (ftype))
2685     emitcode ("clr", "ea");
2686
2687   /* here we need to generate the equates for the
2688      register bank if required */
2689   if (FUNC_REGBANK (ftype) != rbank)
2690     {
2691       int i;
2692
2693       rbank = FUNC_REGBANK (ftype);
2694       for (i = 0; i < ds390_nRegs; i++)
2695         {
2696           if (regs390[i].print) {
2697               if (strcmp (regs390[i].base, "0") == 0)
2698                   emitcode ("", "%s !equ !constbyte",
2699                             regs390[i].dname,
2700                             8 * rbank + regs390[i].offset);
2701               else
2702                   emitcode ("", "%s !equ %s + !constbyte",
2703                             regs390[i].dname,
2704                             regs390[i].base,
2705                             8 * rbank + regs390[i].offset);
2706           }
2707         }
2708     }
2709
2710   /* if this is an interrupt service routine then
2711      save acc, b, dpl, dph  */
2712   if (IFFUNC_ISISR (sym->type))
2713     {
2714
2715       if (!inExcludeList ("acc"))
2716         emitcode ("push", "acc");
2717       if (!inExcludeList ("b"))
2718         emitcode ("push", "b");
2719       if (!inExcludeList ("dpl"))
2720         emitcode ("push", "dpl");
2721       if (!inExcludeList ("dph"))
2722         emitcode ("push", "dph");
2723       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2724         {
2725           emitcode ("push", "dpx");
2726           /* Make sure we're using standard DPTR */
2727           emitcode ("push", "dps");
2728           emitcode ("mov", "dps,#0");
2729           if (options.stack10bit)
2730             {
2731               /* This ISR could conceivably use DPTR2. Better save it. */
2732               emitcode ("push", "dpl1");
2733               emitcode ("push", "dph1");
2734               emitcode ("push", "dpx1");
2735               emitcode ("push",  DP2_RESULT_REG);
2736             }
2737         }
2738       /* if this isr has no bank i.e. is going to
2739          run with bank 0 , then we need to save more
2740          registers :-) */
2741       if (!FUNC_REGBANK (sym->type))
2742         {
2743
2744           /* if this function does not call any other
2745              function then we can be economical and
2746              save only those registers that are used */
2747           if (!IFFUNC_HASFCALL(sym->type))
2748             {
2749               int i;
2750
2751               /* if any registers used */
2752               if (sym->regsUsed)
2753                 {
2754                   /* save the registers used */
2755                   for (i = 0; i < sym->regsUsed->size; i++)
2756                     {
2757                       if (bitVectBitValue (sym->regsUsed, i) ||
2758                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2759                         emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2760                     }
2761                 }
2762
2763             }
2764           else
2765             {
2766               /* this function has  a function call cannot
2767                  determines register usage so we will have to push the
2768                  entire bank */
2769               saveRBank (0, ic, FALSE);
2770             }
2771         }
2772         else
2773         {
2774             /* This ISR uses a non-zero bank.
2775              *
2776              * We assume that the bank is available for our
2777              * exclusive use.
2778              *
2779              * However, if this ISR calls a function which uses some
2780              * other bank, we must save that bank entirely.
2781              */
2782             unsigned long banksToSave = 0;
2783             
2784             if (IFFUNC_HASFCALL(sym->type))
2785             {
2786
2787 #define MAX_REGISTER_BANKS 4
2788
2789                 iCode *i;
2790                 int ix;
2791
2792                 for (i = ic; i; i = i->next)
2793                 {
2794                     if (i->op == ENDFUNCTION)
2795                     {
2796                         /* we got to the end OK. */
2797                         break;
2798                     }
2799                     
2800                     if (i->op == CALL)
2801                     {
2802                         sym_link *dtype;
2803                         
2804                         dtype = operandType (IC_LEFT(i));
2805                         if (dtype 
2806                          && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2807                         {
2808                              /* Mark this bank for saving. */
2809                              if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2810                              {
2811                                  werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2812                              }
2813                              else
2814                              {
2815                                  banksToSave |= (1 << FUNC_REGBANK(dtype));
2816                              }
2817                              
2818                              /* And note that we don't need to do it in 
2819                               * genCall.
2820                               */
2821                              i->bankSaved = 1;
2822                         }
2823                     }
2824                     if (i->op == PCALL)
2825                     {
2826                         /* This is a mess; we have no idea what
2827                          * register bank the called function might
2828                          * use.
2829                          *
2830                          * The only thing I can think of to do is
2831                          * throw a warning and hope.
2832                          */
2833                         werror(W_FUNCPTR_IN_USING_ISR);   
2834                     }
2835                 }
2836
2837                 if (banksToSave && options.useXstack)
2838                 {
2839                     /* Since we aren't passing it an ic, 
2840                      * saveRBank will assume r0 is available to abuse.
2841                      *
2842                      * So switch to our (trashable) bank now, so
2843                      * the caller's R0 isn't trashed.
2844                      */
2845                     emitcode ("push", "psw");
2846                     emitcode ("mov", "psw,#!constbyte", 
2847                               (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2848                     switchedPSW = TRUE;
2849                 }
2850                 
2851                 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2852                 {
2853                      if (banksToSave & (1 << ix))
2854                      {
2855                          saveRBank(ix, NULL, FALSE);
2856                      }
2857                 }
2858             }
2859             // jwk: this needs a closer look
2860             SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2861         }
2862     }
2863   else
2864     {
2865       /* if callee-save to be used for this function
2866          then save the registers being used in this function */
2867       if (IFFUNC_CALLEESAVES(sym->type))
2868         {
2869           int i;
2870
2871           /* if any registers used */
2872           if (sym->regsUsed)
2873             {
2874               /* save the registers used */
2875               for (i = 0; i < sym->regsUsed->size; i++)
2876                 {
2877                   if (bitVectBitValue (sym->regsUsed, i) ||
2878                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2879                     {
2880                       emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2881                       _G.nRegsSaved++;
2882                     }
2883                 }
2884             }
2885         }
2886     }
2887
2888   /* set the register bank to the desired value */
2889   if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
2890    && !switchedPSW)
2891     {
2892       emitcode ("push", "psw");
2893       emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2894     }
2895
2896   if ( (IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
2897        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
2898       if (options.stack10bit) {
2899           emitcode ("push","_bpx");
2900           emitcode ("push","_bpx+1");
2901           emitcode ("mov","_bpx,%s",spname);
2902           emitcode ("mov","_bpx+1,esp");
2903           emitcode ("anl","_bpx+1,#3");
2904       } else {
2905           if (options.useXstack) {
2906               emitcode ("mov", "r0,%s", spname);
2907               emitcode ("mov", "a,_bp");
2908               emitcode ("movx", "@r0,a");
2909               emitcode ("inc", "%s", spname);
2910           } else {
2911               /* set up the stack */
2912               emitcode ("push", "_bp"); /* save the callers stack  */
2913           }
2914           emitcode ("mov", "_bp,%s", spname);
2915       }
2916   }
2917
2918   /* adjust the stack for the function */
2919   if (sym->stack) {
2920       int i = sym->stack;
2921       if (options.stack10bit) {
2922           if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);
2923           assert (sym->recvSize <= 4);
2924           emitcode ("mov","a,sp");
2925           emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
2926           emitcode ("mov","sp,a");
2927           emitcode ("mov","a,esp");
2928           emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
2929           emitcode ("mov","esp,a");
2930       } else {
2931           if (i > 256)
2932               werror (W_STACK_OVERFLOW, sym->name);
2933           
2934           if (i > 3 && sym->recvSize < 4) {
2935               
2936               emitcode ("mov", "a,sp");
2937               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
2938               emitcode ("mov", "sp,a");
2939               
2940           } else
2941               while (i--)
2942                   emitcode ("inc", "sp");
2943       }
2944   }
2945
2946   if (sym->xstack)
2947     {
2948
2949       emitcode ("mov", "a,_spx");
2950       emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
2951       emitcode ("mov", "_spx,a");
2952     }
2953
2954 }
2955
2956 /*-----------------------------------------------------------------*/
2957 /* genEndFunction - generates epilogue for functions               */
2958 /*-----------------------------------------------------------------*/
2959 static void
2960 genEndFunction (iCode * ic)
2961 {
2962   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2963
2964   D (emitcode (";", "genEndFunction "););
2965
2966   if (IFFUNC_ISNAKED(sym->type))
2967   {
2968       emitcode(";", "naked function: no epilogue.");
2969       return;
2970   }
2971
2972   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
2973        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
2974
2975       if (options.stack10bit) {
2976           emitcode ("mov", "sp,_bpx", spname);
2977           emitcode ("mov", "esp,_bpx+1", spname);
2978       } else {
2979           emitcode ("mov", "%s,_bp", spname);
2980       }
2981   }
2982
2983   /* if use external stack but some variables were
2984      added to the local stack then decrement the
2985      local stack */
2986   if (options.useXstack && sym->stack) {
2987       emitcode ("mov", "a,sp");
2988       emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
2989       emitcode ("mov", "sp,a");
2990   }
2991
2992
2993   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
2994        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
2995
2996       if (options.useXstack) {
2997           emitcode ("mov", "r0,%s", spname);
2998           emitcode ("movx", "a,@r0");
2999           emitcode ("mov", "_bp,a");
3000           emitcode ("dec", "%s", spname);
3001       } else {
3002           if (options.stack10bit) {
3003               emitcode ("pop", "_bpx+1");
3004               emitcode ("pop", "_bpx");
3005           } else {
3006               emitcode ("pop", "_bp");
3007           }
3008       }
3009   }
3010
3011   /* restore the register bank  */
3012   if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3013   {
3014     if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3015      || !options.useXstack)
3016     {
3017         /* Special case of ISR using non-zero bank with useXstack
3018          * is handled below.
3019          */
3020         emitcode ("pop", "psw");
3021     }
3022   }
3023
3024   if (IFFUNC_ISISR (sym->type))
3025     {
3026
3027       /* now we need to restore the registers */
3028       /* if this isr has no bank i.e. is going to
3029          run with bank 0 , then we need to save more
3030          registers :-) */
3031       if (!FUNC_REGBANK (sym->type))
3032         {
3033           /* if this function does not call any other
3034              function then we can be economical and
3035              save only those registers that are used */
3036           if (!IFFUNC_HASFCALL(sym->type))
3037             {
3038               int i;
3039
3040               /* if any registers used */
3041               if (sym->regsUsed)
3042                 {
3043                   /* save the registers used */
3044                   for (i = sym->regsUsed->size; i >= 0; i--)
3045                     {
3046                       if (bitVectBitValue (sym->regsUsed, i) ||
3047                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3048                         emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3049                     }
3050                 }
3051
3052             }
3053           else
3054             {
3055               /* this function has  a function call cannot
3056                  determines register usage so we will have to pop the
3057                  entire bank */
3058               unsaveRBank (0, ic, FALSE);
3059             }
3060         }
3061         else
3062         {
3063             /* This ISR uses a non-zero bank.
3064              *
3065              * Restore any register banks saved by genFunction
3066              * in reverse order.
3067              */
3068           // jwk: this needs a closer look
3069             unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3070             int ix;
3071           
3072             for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3073             {
3074                 if (savedBanks & (1 << ix))
3075                 {
3076                     unsaveRBank(ix, NULL, FALSE);
3077                 }
3078             }
3079             
3080             if (options.useXstack)
3081             {
3082                 /* Restore bank AFTER calling unsaveRBank,
3083                  * since it can trash r0.
3084                  */
3085                 emitcode ("pop", "psw");
3086             }
3087         }
3088
3089       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3090         {
3091           if (options.stack10bit)
3092             {
3093               emitcode ("pop", DP2_RESULT_REG);
3094               emitcode ("pop", "dpx1");
3095               emitcode ("pop", "dph1");
3096               emitcode ("pop", "dpl1");
3097             }
3098           emitcode ("pop", "dps");
3099           emitcode ("pop", "dpx");
3100         }
3101       if (!inExcludeList ("dph"))
3102         emitcode ("pop", "dph");
3103       if (!inExcludeList ("dpl"))
3104         emitcode ("pop", "dpl");
3105       if (!inExcludeList ("b"))
3106         emitcode ("pop", "b");
3107       if (!inExcludeList ("acc"))
3108         emitcode ("pop", "acc");
3109
3110       if (IFFUNC_ISCRITICAL (sym->type))
3111         emitcode ("setb", "ea");
3112
3113       /* if debug then send end of function */
3114       if (options.debug && currFunc) {
3115           _G.debugLine = 1;
3116           emitcode ("", "C$%s$%d$%d$%d ==.",
3117                     FileBaseName (ic->filename), currFunc->lastLine,
3118                     ic->level, ic->block);
3119           if (IS_STATIC (currFunc->etype))
3120             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3121           else
3122             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3123           _G.debugLine = 0;
3124         }
3125
3126       emitcode ("reti", "");
3127     }
3128   else
3129     {
3130       if (IFFUNC_ISCRITICAL (sym->type))
3131         emitcode ("setb", "ea");
3132
3133       if (IFFUNC_CALLEESAVES(sym->type))
3134         {
3135           int i;
3136
3137           /* if any registers used */
3138           if (sym->regsUsed)
3139             {
3140               /* save the registers used */
3141               for (i = sym->regsUsed->size; i >= 0; i--)
3142                 {
3143                   if (bitVectBitValue (sym->regsUsed, i) ||
3144                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3145                     emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3146                 }
3147             }
3148
3149         }
3150
3151       /* if debug then send end of function */
3152       if (options.debug && currFunc)
3153         {
3154           _G.debugLine = 1;
3155           emitcode ("", "C$%s$%d$%d$%d ==.",
3156                     FileBaseName (ic->filename), currFunc->lastLine,
3157                     ic->level, ic->block);
3158           if (IS_STATIC (currFunc->etype))
3159             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3160           else
3161             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3162           _G.debugLine = 0;
3163         }
3164
3165       emitcode ("ret", "");
3166     }
3167
3168 }
3169
3170 /*-----------------------------------------------------------------*/
3171 /* genJavaNativeRet - generate code for return JavaNative          */
3172 /*-----------------------------------------------------------------*/
3173 static void genJavaNativeRet(iCode *ic)
3174 {
3175     int i, size;
3176
3177     aopOp (IC_LEFT (ic), ic, FALSE, 
3178            (IS_SYMOP(IC_LEFT(ic)) && OP_SYMBOL(IC_LEFT(ic))->ruonly ? FALSE :TRUE));
3179     size = AOP_SIZE (IC_LEFT (ic));
3180
3181     assert (size <= 4);
3182
3183     /* it is assigned to GPR0-R3 then push them */
3184     if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3185         aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3186         for (i = 0 ; i < size ; i++ ) {
3187             emitcode ("push","%s",aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,FALSE));     
3188         }
3189         for (i = (size-1) ; i >= 0 ; i--) {
3190             emitcode ("pop","a%s",javaRet[i]);
3191         }
3192     } else {
3193         for (i = 0 ; i < size ; i++) 
3194             emitcode ("mov","%s,%s",javaRet[i],aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,FALSE));
3195     }
3196     for (i = size ; i < 4 ; i++ )
3197             emitcode ("mov","%s,#0",javaRet[i]);
3198     return;
3199 }
3200
3201 /*-----------------------------------------------------------------*/
3202 /* genRet - generate code for return statement                     */
3203 /*-----------------------------------------------------------------*/
3204 static void
3205 genRet (iCode * ic)
3206 {
3207   int size, offset = 0, pushed = 0;
3208
3209   D (emitcode (";", "genRet ");
3210     );
3211
3212   /* if we have no return value then
3213      just generate the "ret" */
3214   if (!IC_LEFT (ic))
3215     goto jumpret;
3216
3217   /* if this is a JavaNative function then return 
3218      value in different register */
3219   if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3220       genJavaNativeRet(ic);
3221       goto jumpret;
3222   }
3223   /* we have something to return then
3224      move the return value into place */
3225   aopOp (IC_LEFT (ic), ic, FALSE, 
3226          (IS_SYMOP(IC_LEFT(ic)) && OP_SYMBOL(IC_LEFT(ic))->ruonly ? FALSE :TRUE));
3227   size = AOP_SIZE (IC_LEFT (ic));
3228
3229   _startLazyDPSEvaluation ();
3230   while (size--)
3231     {
3232       char *l;
3233       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3234         {
3235           l = aopGet (AOP (IC_LEFT (ic)), offset++,
3236                       FALSE, TRUE, FALSE);
3237           emitcode ("push", "%s", l);
3238           pushed++;
3239         }
3240       else
3241         {
3242           /* Since A is the last element of fReturn,
3243            * is is OK to clobber it in the aopGet.
3244            */
3245           l = aopGet (AOP (IC_LEFT (ic)), offset,
3246                       FALSE, FALSE, TRUE);
3247           if (strcmp (fReturn[offset], l))
3248             emitcode ("mov", "%s,%s", fReturn[offset++], l);
3249         }
3250     }
3251   _endLazyDPSEvaluation ();
3252
3253   if (pushed)
3254     {
3255       while (pushed)
3256         {
3257           pushed--;
3258           if (strcmp (fReturn[pushed], "a"))
3259             emitcode ("pop", fReturn[pushed]);
3260           else
3261             emitcode ("pop", "acc");
3262         }
3263     }
3264   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3265
3266 jumpret:
3267   /* generate a jump to the return label
3268      if the next is not the return statement */
3269   if (!(ic->next && ic->next->op == LABEL &&
3270         IC_LABEL (ic->next) == returnLabel))
3271
3272     emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3273
3274 }
3275
3276 /*-----------------------------------------------------------------*/
3277 /* genLabel - generates a label                                    */
3278 /*-----------------------------------------------------------------*/
3279 static void
3280 genLabel (iCode * ic)
3281 {
3282   /* special case never generate */
3283   if (IC_LABEL (ic) == entryLabel)
3284     return;
3285
3286   D (emitcode (";", "genLabel ");
3287     );
3288
3289   emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3290 }
3291
3292 /*-----------------------------------------------------------------*/
3293 /* genGoto - generates a ljmp                                      */
3294 /*-----------------------------------------------------------------*/
3295 static void
3296 genGoto (iCode * ic)
3297 {
3298   D (emitcode (";", "genGoto ");
3299     );
3300   emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3301 }
3302
3303 /*-----------------------------------------------------------------*/
3304 /* findLabelBackwards: walks back through the iCode chain looking  */
3305 /* for the given label. Returns number of iCode instructions     */
3306 /* between that label and given ic.          */
3307 /* Returns zero if label not found.          */
3308 /*-----------------------------------------------------------------*/
3309 static int
3310 findLabelBackwards (iCode * ic, int key)
3311 {
3312   int count = 0;
3313
3314   while (ic->prev)
3315     {
3316       ic = ic->prev;
3317       count++;
3318
3319       /* If we have any pushes or pops, we cannot predict the distance.
3320          I don't like this at all, this should be dealt with in the 
3321          back-end */
3322       if (ic->op == IPUSH || ic->op == IPOP) {
3323         return 0;
3324       }
3325
3326       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3327         {
3328           /* printf("findLabelBackwards = %d\n", count); */
3329           return count;
3330         }
3331     }
3332
3333   return 0;
3334 }
3335
3336 /*-----------------------------------------------------------------*/
3337 /* genPlusIncr :- does addition with increment if possible         */
3338 /*-----------------------------------------------------------------*/
3339 static bool
3340 genPlusIncr (iCode * ic)
3341 {
3342   unsigned int icount;
3343   unsigned int size = getDataSize (IC_RESULT (ic));
3344
3345   /* will try to generate an increment */
3346   /* if the right side is not a literal
3347      we cannot */
3348   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3349     return FALSE;
3350
3351   /* if the literal value of the right hand side
3352      is greater than 4 then it is not worth it */
3353   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3354     return FALSE;
3355
3356   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3357       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3358       while (icount--) {
3359           emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
3360       }
3361       return TRUE;
3362   }
3363   /* if increment 16 bits in register */
3364   if (
3365        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3366        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3367        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3368        (size > 1) &&
3369        (icount == 1))
3370     {
3371       symbol *tlbl;
3372       int emitTlbl;
3373       int labelRange;
3374
3375       /* If the next instruction is a goto and the goto target
3376        * is <= 5 instructions previous to this, we can generate
3377        * jumps straight to that target.
3378        */
3379       if (ic->next && ic->next->op == GOTO
3380           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3381           && labelRange <= 5)
3382         {
3383           emitcode (";", "tail increment optimized (range %d)", labelRange);
3384           tlbl = IC_LABEL (ic->next);
3385           emitTlbl = 0;
3386         }
3387       else
3388         {
3389           tlbl = newiTempLabel (NULL);
3390           emitTlbl = 1;
3391         }
3392       emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3393       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3394           IS_AOP_PREG (IC_RESULT (ic)))
3395         emitcode ("cjne", "%s,#0,!tlabel"
3396                   ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3397                   ,tlbl->key + 100);
3398       else
3399         {
3400           emitcode ("clr", "a");
3401           emitcode ("cjne", "a,%s,!tlabel"
3402                     ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3403                     ,tlbl->key + 100);
3404         }
3405
3406       emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3407       if (size > 2)
3408         {
3409           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3410               IS_AOP_PREG (IC_RESULT (ic)))
3411             emitcode ("cjne", "%s,#0,!tlabel"
3412                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3413                       ,tlbl->key + 100);
3414           else
3415             emitcode ("cjne", "a,%s,!tlabel"
3416                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3417                       ,tlbl->key + 100);
3418
3419           emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3420         }
3421       if (size > 3)
3422         {
3423           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3424               IS_AOP_PREG (IC_RESULT (ic)))
3425             emitcode ("cjne", "%s,#0,!tlabel"
3426                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3427                       ,tlbl->key + 100);
3428           else
3429             {
3430               emitcode ("cjne", "a,%s,!tlabel"
3431                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3432                         ,tlbl->key + 100);
3433             }
3434           emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3435         }
3436
3437       if (emitTlbl)
3438         {
3439           emitcode ("", "!tlabeldef", tlbl->key + 100);
3440         }
3441       return TRUE;
3442     }
3443
3444   /* if the sizes are greater than 1 then we cannot */
3445   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3446       AOP_SIZE (IC_LEFT (ic)) > 1)
3447     return FALSE;
3448
3449   /* we can if the aops of the left & result match or
3450      if they are in registers and the registers are the
3451      same */
3452   if (
3453        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3454        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3455        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3456     {
3457
3458       if (icount > 3)
3459         {
3460           MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3461           emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3462           aopPut (AOP (IC_RESULT (ic)), "a", 0);
3463         }
3464       else
3465         {
3466
3467           _startLazyDPSEvaluation ();
3468           while (icount--)
3469             {
3470               emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3471             }
3472           _endLazyDPSEvaluation ();
3473         }
3474
3475       return TRUE;
3476     }
3477
3478   return FALSE;
3479 }
3480
3481 /*-----------------------------------------------------------------*/
3482 /* outBitAcc - output a bit in acc                                 */
3483 /*-----------------------------------------------------------------*/
3484 static void
3485 outBitAcc (operand * result)
3486 {
3487   symbol *tlbl = newiTempLabel (NULL);
3488   /* if the result is a bit */
3489   if (AOP_TYPE (result) == AOP_CRY)
3490     {
3491       aopPut (AOP (result), "a", 0);
3492     }
3493   else
3494     {
3495       emitcode ("jz", "!tlabel", tlbl->key + 100);
3496       emitcode ("mov", "a,%s", one);
3497       emitcode ("", "!tlabeldef", tlbl->key + 100);
3498       outAcc (result);
3499     }
3500 }
3501
3502 /*-----------------------------------------------------------------*/
3503 /* genPlusBits - generates code for addition of two bits           */
3504 /*-----------------------------------------------------------------*/
3505 static void
3506 genPlusBits (iCode * ic)
3507 {
3508   D (emitcode (";", "genPlusBits ");
3509     );
3510   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3511     {
3512       symbol *lbl = newiTempLabel (NULL);
3513       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3514       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3515       emitcode ("cpl", "c");
3516       emitcode ("", "!tlabeldef", (lbl->key + 100));
3517       outBitC (IC_RESULT (ic));
3518     }
3519   else
3520     {
3521       emitcode ("clr", "a");
3522       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3523       emitcode ("rlc", "a");
3524       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3525       emitcode ("addc", "a,#0");
3526       outAcc (IC_RESULT (ic));
3527     }
3528 }
3529
3530 static void
3531 adjustArithmeticResult (iCode * ic)
3532 {
3533   if (opIsGptr (IC_RESULT (ic)) &&
3534       opIsGptr (IC_LEFT (ic)) &&
3535       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3536     {
3537       aopPut (AOP (IC_RESULT (ic)),
3538               aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3539               GPTRSIZE - 1);
3540     }
3541
3542   if (opIsGptr (IC_RESULT (ic)) &&
3543       opIsGptr (IC_RIGHT (ic)) &&
3544       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3545     {
3546       aopPut (AOP (IC_RESULT (ic)),
3547             aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3548               GPTRSIZE - 1);
3549     }
3550
3551   if (opIsGptr (IC_RESULT (ic)) &&
3552       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3553       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3554       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3555       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3556     {
3557       char buffer[5];
3558       sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3559       aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3560     }
3561 }
3562
3563 #if 0 // AOP_OP_3 is deprecated; nobody likes Ack errors.
3564       // Please don't bring it back without a really good reason.
3565 // Macro to aopOp all three operands of an ic. Will fatal if this cannot be done
3566 // (because all three operands are in far space).
3567 #define AOP_OP_3(ic) \
3568     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3569     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3570     aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3571               (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3572     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3573         AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3574     { \
3575         /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3576         fprintf(stderr,                                  \
3577                "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno);   \
3578     }
3579 #endif
3580
3581 // Macro to aopOp all three operands of an ic. If this cannot be done, 
3582 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3583 // will be set TRUE. The caller must then handle the case specially, noting
3584 // that the IC_RESULT operand is not aopOp'd.
3585 #define AOP_OP_3_NOFATAL(ic, rc) \
3586     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3587     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR) || \
3588                                   ((OP_SYMBOL(IC_RESULT(ic))->ruonly) && !isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)))); \
3589     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3590         (isOperandInFarSpace(IC_RESULT(ic)) || (OP_SYMBOL(IC_RESULT(ic))->ruonly && !isOperandEqual(IC_LEFT(ic),IC_RESULT(ic))))) \
3591     { \
3592        /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3593        rc = TRUE; \
3594     }  \
3595     else \
3596     { \
3597        aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3598                                      (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3599        rc = FALSE; \
3600        if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3601            AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3602        { \
3603             /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3604             fprintf(stderr,                                  \
3605                     "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno);   \
3606        } \
3607     }
3608
3609 // aopOp the left & right operands of an ic.
3610 #define AOP_OP_2(ic) \
3611     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3612     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3613
3614 // convienience macro.
3615 #define AOP_SET_LOCALS(ic) \
3616     left = IC_LEFT(ic); \
3617     right = IC_RIGHT(ic); \
3618     result = IC_RESULT(ic);
3619
3620
3621 // Given an integer value of pushedSize bytes on the stack,
3622 // adjust it to be resultSize bytes, either by discarding
3623 // the most significant bytes or by zero-padding.
3624 //
3625 // On exit from this macro, pushedSize will have been adjusted to
3626 // equal resultSize, and ACC may be trashed.
3627 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize)            \
3628       /* If the pushed data is bigger than the result,          \
3629        * simply discard unused bytes. Icky, but works.          \
3630        */                                                       \
3631       while (pushedSize > resultSize)                           \
3632       {                                                         \
3633           D (emitcode (";", "discarding unused result byte."););\
3634           emitcode ("pop", "acc");                              \
3635           pushedSize--;                                         \
3636       }                                                         \
3637       if (pushedSize < resultSize)                              \
3638       {                                                         \
3639           emitcode ("clr", "a");                                \
3640           /* Conversly, we haven't pushed enough here.          \
3641            * just zero-pad, and all is well.                    \
3642            */                                                   \
3643           while (pushedSize < resultSize)                       \
3644           {                                                     \
3645               emitcode("push", "acc");                          \
3646               pushedSize++;                                     \
3647           }                                                     \
3648       }                                                         \
3649       assert(pushedSize == resultSize);
3650
3651 /*-----------------------------------------------------------------*/
3652 /* genPlus - generates code for addition                           */
3653 /*-----------------------------------------------------------------*/
3654 static void
3655 genPlus (iCode * ic)
3656 {
3657   int size, offset = 0;
3658   bool pushResult = FALSE;
3659   int rSize;
3660
3661   D (emitcode (";", "genPlus "););
3662
3663   /* special cases :- */
3664   if ( IS_SYMOP(IC_LEFT(ic)) && OP_SYMBOL(IC_LEFT(ic))->ruonly &&
3665       isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
3666       aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
3667       size = floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
3668       if (size <= 9) {
3669           while (size--) emitcode ("inc","dptr");
3670       } else {
3671           emitcode ("mov","a,dpl");
3672           emitcode ("add","a,#!constbyte",size & 0xff);
3673           emitcode ("mov","dpl,a");
3674           emitcode ("mov","a,dph");
3675           emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
3676           emitcode ("mov","dph,a");
3677           emitcode ("mov","a,dpx");
3678           emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
3679           emitcode ("mov","dpx,a");
3680       }
3681       freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
3682       return ;
3683   }
3684   if ( IS_SYMOP(IC_LEFT(ic)) && 
3685        OP_SYMBOL(IC_LEFT(ic))->remat &&
3686        isOperandInFarSpace(IC_RIGHT(ic))) {
3687       operand *op = IC_RIGHT(ic);
3688       IC_RIGHT(ic) = IC_LEFT(ic);
3689       IC_LEFT(ic) = op;
3690   }
3691                 
3692   AOP_OP_3_NOFATAL (ic, pushResult);
3693   if (pushResult)
3694     {
3695       D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3696     }
3697
3698   if (!pushResult)
3699     {
3700       /* if literal, literal on the right or
3701          if left requires ACC or right is already
3702          in ACC */
3703       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3704        || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3705           || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3706         {
3707           operand *t = IC_RIGHT (ic);
3708           IC_RIGHT (ic) = IC_LEFT (ic);
3709           IC_LEFT (ic) = t;
3710           emitcode (";", "Swapped plus args.");
3711         }
3712
3713       /* if both left & right are in bit
3714          space */
3715       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3716           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3717         {
3718           genPlusBits (ic);
3719           goto release;
3720         }
3721
3722       /* if left in bit space & right literal */
3723       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3724           AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3725         {
3726           emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3727           /* if result in bit space */
3728           if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3729             {
3730               if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3731                 emitcode ("cpl", "c");
3732               outBitC (IC_RESULT (ic));
3733             }
3734           else
3735             {
3736               size = getDataSize (IC_RESULT (ic));
3737               _startLazyDPSEvaluation ();
3738               while (size--)
3739                 {
3740                   MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3741                   emitcode ("addc", "a,#0");
3742                   aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3743                 }
3744               _endLazyDPSEvaluation ();
3745             }
3746           goto release;
3747         }
3748
3749       /* if I can do an increment instead
3750          of add then GOOD for ME */
3751       if (genPlusIncr (ic) == TRUE)
3752         {
3753           emitcode (";", "did genPlusIncr");
3754           goto release;
3755         }
3756
3757     }
3758   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3759
3760   _startLazyDPSEvaluation ();
3761   while (size--)
3762     {
3763       if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
3764         {
3765           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3766           if (offset == 0)
3767             emitcode ("add", "a,%s",
3768                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3769           else
3770             emitcode ("addc", "a,%s",
3771                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3772         }
3773       else
3774         {
3775           if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
3776           {
3777               /* right is going to use ACC or we would have taken the
3778                * above branch.
3779                */
3780               assert(AOP_NEEDSACC(IC_RIGHT(ic)));
3781        TR_AP("#3");
3782               D(emitcode(";", "+ AOP_ACC special case."););
3783               emitcode("xch", "a, %s", DP2_RESULT_REG);
3784           }
3785           MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3786           if (offset == 0)
3787           {
3788             if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
3789             {
3790          TR_AP("#4");
3791                 emitcode("add", "a, %s", DP2_RESULT_REG); 
3792             }
3793             else
3794             {
3795                 emitcode ("add", "a,%s",
3796                         aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE, FALSE));
3797             }
3798           }
3799           else
3800           {
3801             emitcode ("addc", "a,%s",
3802                   aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3803           }
3804         }
3805       if (!pushResult)
3806         {
3807           aopPut (AOP (IC_RESULT (ic)), "a", offset);
3808         }
3809       else
3810         {
3811           emitcode ("push", "acc");
3812         }
3813       offset++;
3814     }
3815   _endLazyDPSEvaluation ();
3816
3817   if (pushResult)
3818     {
3819       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3820
3821       size = getDataSize (IC_LEFT (ic));
3822       rSize = getDataSize (IC_RESULT (ic));
3823
3824       ADJUST_PUSHED_RESULT(size, rSize);
3825
3826       _startLazyDPSEvaluation ();
3827       while (size--)
3828         {
3829           emitcode ("pop", "acc");
3830           aopPut (AOP (IC_RESULT (ic)), "a", size);
3831         }
3832       _endLazyDPSEvaluation ();
3833     }
3834
3835   adjustArithmeticResult (ic);
3836
3837 release:
3838   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3839   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3840   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3841 }
3842
3843 /*-----------------------------------------------------------------*/
3844 /* genMinusDec :- does subtraction with deccrement if possible     */
3845 /*-----------------------------------------------------------------*/
3846 static bool
3847 genMinusDec (iCode * ic)
3848 {
3849   unsigned int icount;
3850   unsigned int size = getDataSize (IC_RESULT (ic));
3851
3852   /* will try to generate an increment */
3853   /* if the right side is not a literal
3854      we cannot */
3855   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3856     return FALSE;
3857
3858   /* if the literal value of the right hand side
3859      is greater than 4 then it is not worth it */
3860   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3861     return FALSE;
3862
3863   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3864       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3865       while (icount--) {
3866           emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
3867       }
3868       return TRUE;
3869   }
3870   /* if decrement 16 bits in register */
3871   if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3872       AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3873       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3874       (size > 1) &&
3875       (icount == 1))
3876     {
3877       symbol *tlbl;
3878       int emitTlbl;
3879       int labelRange;
3880
3881       /* If the next instruction is a goto and the goto target
3882          * is <= 5 instructions previous to this, we can generate
3883          * jumps straight to that target.
3884        */
3885       if (ic->next && ic->next->op == GOTO
3886           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3887           && labelRange <= 5)
3888         {
3889           emitcode (";", "tail decrement optimized (range %d)", labelRange);
3890           tlbl = IC_LABEL (ic->next);
3891           emitTlbl = 0;
3892         }
3893       else
3894         {
3895           tlbl = newiTempLabel (NULL);
3896           emitTlbl = 1;
3897         }
3898
3899       emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3900       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3901           AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3902           IS_AOP_PREG (IC_RESULT (ic)))
3903         emitcode ("cjne", "%s,#!constbyte,!tlabel"
3904                   ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE), 0xff
3905                   ,tlbl->key + 100);
3906       else
3907         {
3908           emitcode ("mov", "a,#!constbyte",0xff);
3909           emitcode ("cjne", "a,%s,!tlabel"
3910                     ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3911                     ,tlbl->key + 100);
3912         }
3913       emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3914       if (size > 2)
3915         {
3916           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3917               AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3918               IS_AOP_PREG (IC_RESULT (ic)))
3919             emitcode ("cjne", "%s,#!constbyte,!tlabel"
3920                       ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE),0xff
3921                       ,tlbl->key + 100);
3922           else
3923             {
3924               emitcode ("cjne", "a,%s,!tlabel"
3925                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3926                         ,tlbl->key + 100);
3927             }
3928           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3929         }
3930       if (size > 3)
3931         {
3932           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3933               AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3934               IS_AOP_PREG (IC_RESULT (ic)))
3935             emitcode ("cjne", "%s,#!constbyte,!tlabel"
3936                       ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE),0xff
3937                       ,tlbl->key + 100);
3938           else
3939             {
3940               emitcode ("cjne", "a,%s,!tlabel"
3941                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3942                         ,tlbl->key + 100);
3943             }
3944           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3945         }
3946       if (emitTlbl)
3947         {
3948           emitcode ("", "!tlabeldef", tlbl->key + 100);
3949         }
3950       return TRUE;
3951     }
3952
3953   /* if the sizes are greater than 1 then we cannot */
3954   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3955       AOP_SIZE (IC_LEFT (ic)) > 1)
3956     return FALSE;
3957
3958   /* we can if the aops of the left & result match or
3959      if they are in registers and the registers are the
3960      same */
3961   if (
3962        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3963        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3964        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3965     {
3966
3967       _startLazyDPSEvaluation ();
3968       while (icount--)
3969         {
3970           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
3971         }
3972       _endLazyDPSEvaluation ();
3973
3974       return TRUE;
3975     }
3976
3977   return FALSE;
3978 }
3979
3980 /*-----------------------------------------------------------------*/
3981 /* addSign - complete with sign                                    */
3982 /*-----------------------------------------------------------------*/
3983 static void
3984 addSign (operand * result, int offset, int sign)
3985 {
3986   int size = (getDataSize (result) - offset);
3987   if (size > 0)
3988     {
3989       _startLazyDPSEvaluation();
3990       if (sign)
3991         {
3992           emitcode ("rlc", "a");
3993           emitcode ("subb", "a,acc");
3994           while (size--)
3995           {
3996             aopPut (AOP (result), "a", offset++);
3997           }
3998         }
3999       else
4000       {
4001         while (size--)
4002         {
4003           aopPut (AOP (result), zero, offset++);
4004         }
4005       }
4006       _endLazyDPSEvaluation();
4007     }
4008 }
4009
4010 /*-----------------------------------------------------------------*/
4011 /* genMinusBits - generates code for subtraction  of two bits      */
4012 /*-----------------------------------------------------------------*/
4013 static void
4014 genMinusBits (iCode * ic)
4015 {
4016   symbol *lbl = newiTempLabel (NULL);
4017
4018   D (emitcode (";", "genMinusBits "););
4019
4020   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4021     {
4022       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4023       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4024       emitcode ("cpl", "c");
4025       emitcode ("", "!tlabeldef", (lbl->key + 100));
4026       outBitC (IC_RESULT (ic));
4027     }
4028   else
4029     {
4030       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4031       emitcode ("subb", "a,acc");
4032       emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4033       emitcode ("inc", "a");
4034       emitcode ("", "!tlabeldef", (lbl->key + 100));
4035       aopPut (AOP (IC_RESULT (ic)), "a", 0);
4036       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4037     }
4038 }
4039
4040 /*-----------------------------------------------------------------*/
4041 /* genMinus - generates code for subtraction                       */
4042 /*-----------------------------------------------------------------*/
4043 static void
4044 genMinus (iCode * ic)
4045 {
4046   int size, offset = 0;
4047   int rSize;
4048   unsigned long lit = 0L;
4049   bool pushResult = FALSE;
4050
4051   D (emitcode (";", "genMinus "););
4052
4053   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
4054   aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
4055   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
4056       (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
4057     {
4058       pushResult = TRUE;
4059     }
4060   else
4061     {
4062       aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
4063
4064       /* special cases :- */
4065       /* if both left & right are in bit space */
4066       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4067           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4068         {
4069           genMinusBits (ic);
4070           goto release;
4071         }
4072
4073       /* if I can do an decrement instead
4074          of subtract then GOOD for ME */
4075       if (genMinusDec (ic) == TRUE)
4076         goto release;
4077
4078     }
4079
4080   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4081
4082   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4083     {
4084       CLRC;
4085     }
4086   else
4087     {
4088       lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4089       lit = -(long) lit;
4090     }
4091
4092
4093   /* if literal, add a,#-lit, else normal subb */
4094   _startLazyDPSEvaluation ();
4095   while (size--)
4096     {
4097       MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
4098       if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4099         emitcode ("subb", "a,%s",
4100                   aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
4101       else
4102         {
4103           /* first add without previous c */
4104           if (!offset) {
4105             if (!size && lit==-1) {
4106               emitcode ("dec", "a");
4107             } else {
4108               emitcode ("add", "a,#!constbyte",
4109                         (unsigned int) (lit & 0x0FFL));
4110             }
4111           } else {
4112             emitcode ("addc", "a,#!constbyte",
4113                       (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4114           }
4115         }
4116
4117       if (pushResult)
4118         {
4119           emitcode ("push", "acc");
4120         }
4121       else
4122         {
4123           aopPut (AOP (IC_RESULT (ic)), "a", offset);
4124         }
4125       offset++;
4126     }
4127   _endLazyDPSEvaluation ();
4128
4129   if (pushResult)
4130     {
4131       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4132
4133       size = getDataSize (IC_LEFT (ic));
4134       rSize = getDataSize (IC_RESULT (ic));
4135
4136       ADJUST_PUSHED_RESULT(size, rSize);
4137
4138       _startLazyDPSEvaluation ();
4139       while (size--)
4140         {
4141           emitcode ("pop", "acc");
4142           aopPut (AOP (IC_RESULT (ic)), "a", size);
4143         }
4144       _endLazyDPSEvaluation ();
4145     }
4146
4147   adjustArithmeticResult (ic);
4148
4149 release:
4150   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4151   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4152   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4153 }
4154
4155
4156 /*-----------------------------------------------------------------*/
4157 /* genMultbits :- multiplication of bits                           */
4158 /*-----------------------------------------------------------------*/
4159 static void
4160 genMultbits (operand * left,
4161              operand * right,
4162              operand * result,
4163              iCode   * ic)
4164 {
4165   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4166   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4167   aopOp(result, ic, TRUE, FALSE);
4168   outBitC (result);
4169 }
4170
4171
4172 /*-----------------------------------------------------------------*/
4173 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
4174 /*-----------------------------------------------------------------*/
4175 static void
4176 genMultOneByte (operand * left,
4177                 operand * right,
4178                 operand * result,
4179                 iCode   * ic)
4180 {
4181   sym_link *opetype = operandType (result);
4182   symbol *lbl;
4183
4184
4185   /* (if two literals: the value is computed before) */
4186   /* if one literal, literal on the right */
4187   if (AOP_TYPE (left) == AOP_LIT)
4188     {
4189       operand *t = right;
4190       right = left;
4191       left = t;
4192       emitcode (";", "swapped left and right");
4193     }
4194
4195   if (SPEC_USIGN(opetype)
4196       // ignore the sign of left and right, what else can we do?
4197       || (SPEC_USIGN(operandType(left)) && 
4198           SPEC_USIGN(operandType(right)))) {
4199     // just an unsigned 8*8=8/16 multiply
4200     //emitcode (";","unsigned");
4201     emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4202     MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4203     emitcode ("mul", "ab");
4204    
4205     _G.accInUse++; _G.bInUse++;
4206     aopOp(result, ic, TRUE, FALSE);
4207       
4208       if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4209       {
4210           // this should never happen
4211           fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4212                    AOP_SIZE(result), __FILE__, lineno);
4213           exit (1);
4214       }      
4215       
4216     aopPut (AOP (result), "a", 0);
4217     _G.accInUse--; _G.bInUse--;
4218     if (AOP_SIZE(result)==2) 
4219     {
4220       aopPut (AOP (result), "b", 1);
4221     }
4222     return;
4223   }
4224
4225   // we have to do a signed multiply
4226
4227   emitcode (";", "signed");
4228   emitcode ("clr", "F0"); // reset sign flag
4229   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4230
4231   lbl=newiTempLabel(NULL);
4232   emitcode ("jnb", "acc.7,!tlabel",  lbl->key+100);
4233   // left side is negative, 8-bit two's complement, this fails for -128
4234   emitcode ("setb", "F0"); // set sign flag
4235   emitcode ("cpl", "a");
4236   emitcode ("inc", "a");
4237
4238   emitcode ("", "!tlabeldef", lbl->key+100);
4239
4240   /* if literal */
4241   if (AOP_TYPE(right)==AOP_LIT) {
4242     signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
4243     /* AND literal negative */
4244     if ((int) val < 0) {
4245       emitcode ("cpl", "F0"); // complement sign flag
4246       emitcode ("mov", "b,#!constbyte", -val);
4247     } else {
4248       emitcode ("mov", "b,#!constbyte", val);
4249     }
4250   } else {
4251     lbl=newiTempLabel(NULL);
4252     emitcode ("mov", "b,a");
4253     emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4254     emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4255     // right side is negative, 8-bit two's complement
4256     emitcode ("cpl", "F0"); // complement sign flag
4257     emitcode ("cpl", "a");
4258     emitcode ("inc", "a");
4259     emitcode ("", "!tlabeldef", lbl->key+100);
4260   }
4261   emitcode ("mul", "ab");
4262     
4263   _G.accInUse++;_G.bInUse++;
4264   aopOp(result, ic, TRUE, FALSE);
4265     
4266   if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4267   {
4268     // this should never happen
4269       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4270                AOP_SIZE(result), __FILE__, lineno);
4271       exit (1);
4272   }    
4273     
4274   lbl=newiTempLabel(NULL);
4275   emitcode ("jnb", "F0,!tlabel", lbl->key+100);
4276   // only ONE op was negative, we have to do a 8/16-bit two's complement
4277   emitcode ("cpl", "a"); // lsb
4278   if (AOP_SIZE(result)==1) {
4279     emitcode ("inc", "a");
4280   } else {
4281     emitcode ("add", "a,#1");
4282     emitcode ("xch", "a,b");
4283     emitcode ("cpl", "a"); // msb
4284     emitcode ("addc", "a,#0");
4285     emitcode ("xch", "a,b");
4286   }
4287
4288   emitcode ("", "!tlabeldef", lbl->key+100);
4289   aopPut (AOP (result), "a", 0);
4290   _G.accInUse--;_G.bInUse--;
4291   if (AOP_SIZE(result)==2) {
4292     aopPut (AOP (result), "b", 1);
4293   }
4294 }
4295
4296 /*-----------------------------------------------------------------*/
4297 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply    */
4298 /*-----------------------------------------------------------------*/
4299 static void genMultTwoByte (operand *left, operand *right, 
4300                             operand *result, iCode *ic)
4301 {
4302         sym_link *retype = getSpec(operandType(right));
4303         sym_link *letype = getSpec(operandType(left));
4304         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4305         symbol *lbl;
4306
4307         if (AOP_TYPE (left) == AOP_LIT) {
4308                 operand *t = right;
4309                 right = left;
4310                 left = t;
4311         }
4312         /* save EA bit in F1 */
4313         lbl = newiTempLabel(NULL);
4314         emitcode ("setb","F1");
4315         emitcode ("jbc","EA,!tlabel",lbl->key+100);
4316         emitcode ("clr","F1");
4317         emitcode("","!tlabeldef",lbl->key+100);
4318
4319         /* load up MB with right */
4320         if (!umult) {
4321                 emitcode("clr","F0");
4322                 if (AOP_TYPE(right) == AOP_LIT) {
4323                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
4324                         if (val < 0) {
4325                                 emitcode("setb","F0");
4326                                 val = -val;
4327                         }
4328                         emitcode ("mov","mb,#!constbyte",val & 0xff);
4329                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
4330                 } else {
4331                         lbl = newiTempLabel(NULL);
4332                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4333                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4334                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
4335                         emitcode ("xch", "a,b");
4336                         emitcode ("cpl","a");
4337                         emitcode ("add", "a,#1");
4338                         emitcode ("xch", "a,b");
4339                         emitcode ("cpl", "a"); // msb
4340                         emitcode ("addc", "a,#0");
4341                         emitcode ("setb","F0");
4342                         emitcode ("","!tlabeldef",lbl->key+100);
4343                         emitcode ("mov","mb,b");
4344                         emitcode ("mov","mb,a");
4345                 }
4346         } else {
4347                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4348                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4349         }
4350         /* load up MA with left */
4351         if (!umult) {
4352                 lbl = newiTempLabel(NULL);
4353                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4354                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4355                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4356                 emitcode ("xch", "a,b");
4357                 emitcode ("cpl","a");
4358                 emitcode ("add", "a,#1");
4359                 emitcode ("xch", "a,b");
4360                 emitcode ("cpl", "a"); // msb
4361                 emitcode ("addc","a,#0");
4362                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4363                 emitcode ("setb","F0");
4364                 emitcode ("","!tlabeldef",lbl->key+100);
4365                 emitcode ("mov","ma,b");
4366                 emitcode ("mov","ma,a");
4367         } else {
4368                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4369                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4370         }
4371         /* wait for multiplication to finish */
4372         lbl = newiTempLabel(NULL);
4373         emitcode("","!tlabeldef", lbl->key+100);
4374         emitcode("mov","a,mcnt1");
4375         emitcode("anl","a,#!constbyte",0x80);
4376         emitcode("jnz","!tlabel",lbl->key+100);
4377         
4378         freeAsmop (left, NULL, ic, TRUE);
4379         freeAsmop (right, NULL, ic,TRUE);
4380         aopOp(result, ic, TRUE, FALSE);
4381
4382         /* if unsigned then simple */   
4383         if (umult) {
4384                 emitcode ("mov","a,ma");
4385                 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4386                 emitcode ("mov","a,ma");
4387                 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4388                 aopPut(AOP(result),"ma",1);
4389                 aopPut(AOP(result),"ma",0);
4390         } else {
4391                 emitcode("push","ma");
4392                 emitcode("push","ma");
4393                 emitcode("push","ma");
4394                 MOVA("ma");
4395                 /* negate result if needed */
4396                 lbl = newiTempLabel(NULL);      
4397                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4398                 emitcode("cpl","a");
4399                 emitcode("add","a,#1");
4400                 emitcode("","!tlabeldef", lbl->key+100);
4401                 if (AOP_TYPE(result) == AOP_ACC)
4402                 {
4403                     D(emitcode(";", "ACC special case."););
4404                     /* We know result is the only live aop, and 
4405                      * it's obviously not a DPTR2, so AP is available.
4406                      */
4407                     emitcode("mov", "%s,acc", DP2_RESULT_REG);
4408                 }
4409                 else
4410                 {
4411                     aopPut(AOP(result),"a",0);
4412                 }
4413             
4414                 emitcode("pop","acc");
4415                 lbl = newiTempLabel(NULL);      
4416                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4417                 emitcode("cpl","a");
4418                 emitcode("addc","a,#0");
4419                 emitcode("","!tlabeldef", lbl->key+100);
4420                 aopPut(AOP(result),"a",1);
4421                 emitcode("pop","acc");
4422                 if (AOP_SIZE(result) >= 3) {
4423                         lbl = newiTempLabel(NULL);      
4424                         emitcode("jnb","F0,!tlabel",lbl->key+100);
4425                         emitcode("cpl","a");
4426                         emitcode("addc","a,#0");                        
4427                         emitcode("","!tlabeldef", lbl->key+100);
4428                         aopPut(AOP(result),"a",2);
4429                 }
4430                 emitcode("pop","acc");
4431                 if (AOP_SIZE(result) >= 4) {
4432                         lbl = newiTempLabel(NULL);      
4433                         emitcode("jnb","F0,!tlabel",lbl->key+100);
4434                         emitcode("cpl","a");
4435                         emitcode("addc","a,#0");                        
4436                         emitcode("","!tlabeldef", lbl->key+100);
4437                         aopPut(AOP(result),"a",3);
4438                 }
4439                 if (AOP_TYPE(result) == AOP_ACC)
4440                 {
4441                     /* We stashed the result away above. */
4442                     emitcode("mov", "acc,%s", DP2_RESULT_REG);
4443                 }           
4444                 
4445         }
4446         freeAsmop (result, NULL, ic, TRUE);
4447
4448         /* restore EA bit in F1 */
4449         lbl = newiTempLabel(NULL);
4450         emitcode ("jnb","F1,!tlabel",lbl->key+100);
4451         emitcode ("setb","EA");
4452         emitcode("","!tlabeldef",lbl->key+100);
4453         return ;
4454 }
4455
4456 /*-----------------------------------------------------------------*/
4457 /* genMult - generates code for multiplication                     */
4458 /*-----------------------------------------------------------------*/
4459 static void
4460 genMult (iCode * ic)
4461 {
4462   operand *left = IC_LEFT (ic);
4463   operand *right = IC_RIGHT (ic);
4464   operand *result = IC_RESULT (ic);
4465
4466   D (emitcode (";", "genMult "););
4467
4468   /* assign the amsops */
4469   AOP_OP_2 (ic);
4470
4471   /* special cases first */
4472   /* both are bits */
4473   if (AOP_TYPE (left) == AOP_CRY &&
4474       AOP_TYPE (right) == AOP_CRY)
4475     {
4476       genMultbits (left, right, result, ic);
4477       goto release;
4478     }
4479
4480   /* if both are of size == 1 */
4481   if (AOP_SIZE (left) == 1 &&
4482       AOP_SIZE (right) == 1)
4483     {
4484       genMultOneByte (left, right, result, ic);
4485       goto release;
4486     }
4487
4488   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4489           /* use the ds390 ARITHMETIC accel UNIT */
4490           genMultTwoByte (left, right, result, ic);
4491           return ;
4492   }
4493   /* should have been converted to function call */
4494   assert (0);
4495
4496 release:
4497   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4498   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4499   freeAsmop (result, NULL, ic, TRUE);
4500 }
4501
4502 /*-----------------------------------------------------------------*/
4503 /* genDivbits :- division of bits                                  */
4504 /*-----------------------------------------------------------------*/
4505 static void
4506 genDivbits (operand * left,
4507             operand * right,
4508             operand * result,
4509             iCode   * ic)
4510 {
4511
4512   char *l;
4513
4514   /* the result must be bit */
4515   LOAD_AB_FOR_DIV (left, right, l);
4516   emitcode ("div", "ab");
4517   emitcode ("rrc", "a");
4518   aopOp(result, ic, TRUE, FALSE);
4519     
4520   aopPut (AOP (result), "c", 0);
4521 }
4522
4523 /*-----------------------------------------------------------------*/
4524 /* genDivOneByte : 8 bit division                                  */
4525 /*-----------------------------------------------------------------*/
4526 static void
4527 genDivOneByte (operand * left,
4528                operand * right,
4529                operand * result,
4530                iCode   * ic)
4531 {
4532   sym_link *opetype = operandType (result);
4533   char *l;
4534   symbol *lbl;
4535   int size, offset;
4536
4537   offset = 1;
4538   /* signed or unsigned */
4539   if (SPEC_USIGN (opetype))
4540     {
4541         /* unsigned is easy */
4542         LOAD_AB_FOR_DIV (left, right, l);
4543         emitcode ("div", "ab");
4544
4545         _G.accInUse++;
4546         aopOp(result, ic, TRUE, FALSE);
4547         aopPut (AOP (result), "a", 0);
4548         _G.accInUse--;
4549
4550         size = AOP_SIZE (result) - 1;
4551         
4552         while (size--)
4553         {
4554             aopPut (AOP (result), zero, offset++);
4555         }
4556       return;
4557     }
4558
4559   /* signed is a little bit more difficult */
4560
4561   /* save the signs of the operands */
4562   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4563   MOVA (l);
4564   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4565   emitcode ("push", "acc");     /* save it on the stack */
4566
4567   /* now sign adjust for both left & right */
4568   l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4569   MOVA (l);
4570   lbl = newiTempLabel (NULL);
4571   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4572   emitcode ("cpl", "a");
4573   emitcode ("inc", "a");
4574   emitcode ("", "!tlabeldef", (lbl->key + 100));
4575   emitcode ("mov", "b,a");
4576
4577   /* sign adjust left side */
4578   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4579   MOVA (l);
4580
4581   lbl = newiTempLabel (NULL);
4582   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4583   emitcode ("cpl", "a");
4584   emitcode ("inc", "a");
4585   emitcode ("", "!tlabeldef", (lbl->key + 100));
4586
4587   /* now the division */
4588   emitcode ("nop", "; workaround for DS80C390 div bug.");
4589   emitcode ("div", "ab");
4590   /* we are interested in the lower order
4591      only */
4592   emitcode ("mov", "b,a");
4593   lbl = newiTempLabel (NULL);
4594   emitcode ("pop", "acc");
4595   /* if there was an over flow we don't
4596      adjust the sign of the result */
4597   emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4598   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4599   CLRC;
4600   emitcode ("clr", "a");
4601   emitcode ("subb", "a,b");
4602   emitcode ("mov", "b,a");
4603   emitcode ("", "!tlabeldef", (lbl->key + 100));
4604
4605   /* now we are done */
4606   _G.accInUse++;     _G.bInUse++;
4607     aopOp(result, ic, TRUE, FALSE);
4608     
4609     aopPut (AOP (result), "b", 0);
4610     
4611     size = AOP_SIZE (result) - 1;
4612     
4613     if (size > 0)
4614     {
4615       emitcode ("mov", "c,b.7");
4616       emitcode ("subb", "a,acc");
4617     }
4618     while (size--)
4619     {
4620         aopPut (AOP (result), "a", offset++);
4621     }
4622     _G.accInUse--;     _G.bInUse--;
4623
4624 }
4625
4626 /*-----------------------------------------------------------------*/
4627 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide       */
4628 /*-----------------------------------------------------------------*/
4629 static void genDivTwoByte (operand *left, operand *right, 
4630                             operand *result, iCode *ic)
4631 {
4632         sym_link *retype = getSpec(operandType(right));
4633         sym_link *letype = getSpec(operandType(left));
4634         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4635         symbol *lbl;
4636
4637         /* save EA bit in F1 */
4638         lbl = newiTempLabel(NULL);
4639         emitcode ("setb","F1");
4640         emitcode ("jbc","EA,!tlabel",lbl->key+100);
4641         emitcode ("clr","F1");
4642         emitcode("","!tlabeldef",lbl->key+100);
4643
4644         /* load up MA with left */
4645         if (!umult) {
4646                 emitcode("clr","F0");
4647                 lbl = newiTempLabel(NULL);
4648                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4649                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4650                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4651                 emitcode ("xch", "a,b");
4652                 emitcode ("cpl","a");
4653                 emitcode ("add", "a,#1");
4654                 emitcode ("xch", "a,b");
4655                 emitcode ("cpl", "a"); // msb
4656                 emitcode ("addc","a,#0");
4657                 emitcode ("setb","F0");
4658                 emitcode ("","!tlabeldef",lbl->key+100);
4659                 emitcode ("mov","ma,b");
4660                 emitcode ("mov","ma,a");
4661         } else {
4662                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4663                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4664         }
4665
4666         /* load up MB with right */
4667         if (!umult) {
4668                 if (AOP_TYPE(right) == AOP_LIT) {
4669                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
4670                         if (val < 0) {
4671                                 lbl = newiTempLabel(NULL);
4672                                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4673                                 emitcode("setb","F0");
4674                                 emitcode ("","!tlabeldef",lbl->key+100);
4675                                 val = -val;
4676                         } 
4677                         emitcode ("mov","mb,#!constbyte",val & 0xff);               
4678                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4679                 } else {
4680                         lbl = newiTempLabel(NULL);
4681                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4682                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4683                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
4684                         emitcode ("xch", "a,b");
4685                         emitcode ("cpl","a");
4686                         emitcode ("add", "a,#1");
4687                         emitcode ("xch", "a,b");
4688                         emitcode ("cpl", "a"); // msb
4689                         emitcode ("addc", "a,#0");
4690                         emitcode ("jbc","F0,!tlabel",lbl->key+100);
4691                         emitcode ("setb","F0");
4692                         emitcode ("","!tlabeldef",lbl->key+100);
4693                         emitcode ("mov","mb,b");
4694                         emitcode ("mov","mb,a");
4695                 }
4696         } else {
4697                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4698                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4699         }
4700
4701         /* wait for multiplication to finish */
4702         lbl = newiTempLabel(NULL);
4703         emitcode("","!tlabeldef", lbl->key+100);
4704         emitcode("mov","a,mcnt1");
4705         emitcode("anl","a,#!constbyte",0x80);
4706         emitcode("jnz","!tlabel",lbl->key+100);
4707         
4708         freeAsmop (left, NULL, ic, TRUE);
4709         freeAsmop (right, NULL, ic,TRUE);
4710         aopOp(result, ic, TRUE, FALSE);
4711
4712         /* if unsigned then simple */   
4713         if (umult) {
4714                 aopPut(AOP(result),"ma",1);
4715                 aopPut(AOP(result),"ma",0);
4716         } else {
4717                 emitcode("push","ma");
4718                 MOVA("ma");
4719                 /* negate result if needed */
4720                 lbl = newiTempLabel(NULL);      
4721                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4722                 emitcode("cpl","a");
4723                 emitcode("add","a,#1");
4724                 emitcode("","!tlabeldef", lbl->key+100);
4725                 aopPut(AOP(result),"a",0);
4726                 emitcode("pop","acc");
4727                 lbl = newiTempLabel(NULL);      
4728                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4729                 emitcode("cpl","a");
4730                 emitcode("addc","a,#0");
4731                 emitcode("","!tlabeldef", lbl->key+100);
4732                 aopPut(AOP(result),"a",1);
4733         }
4734         freeAsmop (result, NULL, ic, TRUE);
4735         /* restore EA bit in F1 */
4736         lbl = newiTempLabel(NULL);
4737         emitcode ("jnb","F1,!tlabel",lbl->key+100);
4738         emitcode ("setb","EA");
4739         emitcode("","!tlabeldef",lbl->key+100);
4740         return ;
4741 }
4742
4743 /*-----------------------------------------------------------------*/
4744 /* genDiv - generates code for division                            */
4745 /*-----------------------------------------------------------------*/
4746 static void
4747 genDiv (iCode * ic)
4748 {
4749   operand *left = IC_LEFT (ic);
4750   operand *right = IC_RIGHT (ic);
4751   operand *result = IC_RESULT (ic);
4752
4753   D (emitcode (";", "genDiv "););
4754
4755   /* assign the amsops */
4756   AOP_OP_2 (ic);
4757
4758   /* special cases first */
4759   /* both are bits */
4760   if (AOP_TYPE (left) == AOP_CRY &&
4761       AOP_TYPE (right) == AOP_CRY)
4762     {
4763       genDivbits (left, right, result, ic);
4764       goto release;
4765     }
4766
4767   /* if both are of size == 1 */
4768   if (AOP_SIZE (left) == 1 &&
4769       AOP_SIZE (right) == 1)
4770     {
4771       genDivOneByte (left, right, result, ic);
4772       goto release;
4773     }
4774
4775   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4776           /* use the ds390 ARITHMETIC accel UNIT */
4777           genDivTwoByte (left, right, result, ic);
4778           return ;
4779   }
4780   /* should have been converted to function call */
4781   assert (0);
4782 release:
4783   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4784   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4785   freeAsmop (result, NULL, ic, TRUE);
4786 }
4787
4788 /*-----------------------------------------------------------------*/
4789 /* genModbits :- modulus of bits                                   */
4790 /*-----------------------------------------------------------------*/
4791 static void
4792 genModbits (operand * left,
4793             operand * right,
4794             operand * result,
4795             iCode   * ic)
4796 {
4797
4798   char *l;
4799
4800   /* the result must be bit */
4801   LOAD_AB_FOR_DIV (left, right, l);
4802   emitcode ("div", "ab");
4803   emitcode ("mov", "a,b");
4804   emitcode ("rrc", "a");
4805   aopOp(result, ic, TRUE, FALSE);
4806   aopPut (AOP (result), "c", 0);
4807 }
4808
4809 /*-----------------------------------------------------------------*/
4810 /* genModOneByte : 8 bit modulus                                   */
4811 /*-----------------------------------------------------------------*/
4812 static void
4813 genModOneByte (operand * left,
4814                operand * right,
4815                operand * result,
4816                iCode   * ic)
4817 {
4818   sym_link *opetype = operandType (result);
4819   char *l;
4820   symbol *lbl;
4821
4822   /* signed or unsigned */
4823   if (SPEC_USIGN (opetype))
4824     {
4825       /* unsigned is easy */
4826       LOAD_AB_FOR_DIV (left, right, l);
4827       emitcode ("div", "ab");
4828       aopOp(result, ic, TRUE, FALSE);   
4829       aopPut (AOP (result), "b", 0);
4830       return;
4831     }
4832
4833   /* signed is a little bit more difficult */
4834
4835   /* save the signs of the operands */
4836   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4837   MOVA (l);
4838
4839   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4840   emitcode ("push", "acc");     /* save it on the stack */
4841
4842   /* now sign adjust for both left & right */
4843   l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4844   MOVA (l);
4845
4846   lbl = newiTempLabel (NULL);
4847   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4848   emitcode ("cpl", "a");
4849   emitcode ("inc", "a");
4850   emitcode ("", "!tlabeldef", (lbl->key + 100));
4851   emitcode ("mov", "b,a");
4852
4853   /* sign adjust left side */
4854   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4855   MOVA (l);
4856
4857   lbl = newiTempLabel (NULL);
4858   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4859   emitcode ("cpl", "a");
4860   emitcode ("inc", "a");
4861   emitcode ("", "!tlabeldef", (lbl->key + 100));
4862
4863   /* now the multiplication */
4864   emitcode ("nop", "; workaround for DS80C390 div bug.");
4865   emitcode ("div", "ab");
4866   /* we are interested in the lower order
4867      only */
4868   lbl = newiTempLabel (NULL);
4869   emitcode ("pop", "acc");
4870   /* if there was an over flow we don't
4871      adjust the sign of the result */
4872   emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4873   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4874   CLRC;
4875   emitcode ("clr", "a");
4876   emitcode ("subb", "a,b");
4877   emitcode ("mov", "b,a");
4878   emitcode ("", "!tlabeldef", (lbl->key + 100));
4879   
4880   _G.bInUse++;
4881   /* now we are done */
4882   aopOp(result, ic, TRUE, FALSE);    
4883   aopPut (AOP (result), "b", 0);
4884   _G.bInUse--;
4885
4886 }
4887
4888 /*-----------------------------------------------------------------*/
4889 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus      */
4890 /*-----------------------------------------------------------------*/
4891 static void genModTwoByte (operand *left, operand *right, 
4892                             operand *result, iCode *ic)
4893 {
4894         sym_link *retype = getSpec(operandType(right));
4895         sym_link *letype = getSpec(operandType(left));
4896         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4897         symbol *lbl;
4898
4899         /* load up MA with left */
4900         /* save EA bit in F1 */
4901         lbl = newiTempLabel(NULL);
4902         emitcode ("setb","F1");
4903         emitcode ("jbc","EA,!tlabel",lbl->key+100);
4904         emitcode ("clr","F1");
4905         emitcode("","!tlabeldef",lbl->key+100);
4906
4907         if (!umult) {
4908                 lbl = newiTempLabel(NULL);
4909                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4910                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4911                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4912                 emitcode ("xch", "a,b");
4913                 emitcode ("cpl","a");
4914                 emitcode ("add", "a,#1");
4915                 emitcode ("xch", "a,b");
4916                 emitcode ("cpl", "a"); // msb
4917                 emitcode ("addc","a,#0");
4918                 emitcode ("","!tlabeldef",lbl->key+100);
4919                 emitcode ("mov","ma,b");
4920                 emitcode ("mov","ma,a");
4921         } else {
4922                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4923                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4924         }
4925
4926         /* load up MB with right */
4927         if (!umult) {
4928                 if (AOP_TYPE(right) == AOP_LIT) {
4929                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
4930                         if (val < 0) {
4931                                 val = -val;
4932                         } 
4933                         emitcode ("mov","mb,#!constbyte",val & 0xff);
4934                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
4935                 } else {
4936                         lbl = newiTempLabel(NULL);
4937                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4938                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4939                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
4940                         emitcode ("xch", "a,b");
4941                         emitcode ("cpl","a");
4942                         emitcode ("add", "a,#1");
4943                         emitcode ("xch", "a,b");
4944                         emitcode ("cpl", "a"); // msb
4945                         emitcode ("addc", "a,#0");
4946                         emitcode ("","!tlabeldef",lbl->key+100);
4947                         emitcode ("mov","mb,b");
4948                         emitcode ("mov","mb,a");
4949                 }
4950         } else {
4951                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4952                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4953         }
4954
4955         /* wait for multiplication to finish */
4956         lbl = newiTempLabel(NULL);
4957         emitcode("","!tlabeldef", lbl->key+100);
4958         emitcode("mov","a,mcnt1");
4959         emitcode("anl","a,#!constbyte",0x80);
4960         emitcode("jnz","!tlabel",lbl->key+100);
4961         
4962         freeAsmop (left, NULL, ic, TRUE);
4963         freeAsmop (right, NULL, ic,TRUE);
4964         aopOp(result, ic, TRUE, FALSE);
4965
4966         aopPut(AOP(result),"mb",1);
4967         aopPut(AOP(result),"mb",0);
4968         freeAsmop (result, NULL, ic, TRUE);
4969
4970         /* restore EA bit in F1 */
4971         lbl = newiTempLabel(NULL);
4972         emitcode ("jnb","F1,!tlabel",lbl->key+100);
4973         emitcode ("setb","EA");
4974         emitcode("","!tlabeldef",lbl->key+100);
4975         return ;
4976 }
4977
4978 /*-----------------------------------------------------------------*/
4979 /* genMod - generates code for division                            */
4980 /*-----------------------------------------------------------------*/
4981 static void
4982 genMod (iCode * ic)
4983 {
4984   operand *left = IC_LEFT (ic);
4985   operand *right = IC_RIGHT (ic);
4986   operand *result = IC_RESULT (ic);
4987
4988   D (emitcode (";", "genMod "); );
4989
4990   /* assign the amsops */
4991   AOP_OP_2 (ic);
4992
4993   /* special cases first */
4994   /* both are bits */
4995   if (AOP_TYPE (left) == AOP_CRY &&
4996       AOP_TYPE (right) == AOP_CRY)
4997     {
4998       genModbits (left, right, result, ic);
4999       goto release;
5000     }
5001
5002   /* if both are of size == 1 */
5003   if (AOP_SIZE (left) == 1 &&
5004       AOP_SIZE (right) == 1)
5005     {
5006       genModOneByte (left, right, result, ic);
5007       goto release;
5008     }
5009
5010   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5011           /* use the ds390 ARITHMETIC accel UNIT */
5012           genModTwoByte (left, right, result, ic);
5013           return ;
5014   }
5015
5016   /* should have been converted to function call */
5017   assert (0);
5018
5019 release:
5020   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5021   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5022   freeAsmop (result, NULL, ic, TRUE);
5023 }
5024
5025 /*-----------------------------------------------------------------*/
5026 /* genIfxJump :- will create a jump depending on the ifx           */
5027 /*-----------------------------------------------------------------*/
5028 static void
5029 genIfxJump (iCode * ic, char *jval)
5030 {
5031   symbol *jlbl;
5032   symbol *tlbl = newiTempLabel (NULL);
5033   char *inst;
5034
5035   D (emitcode (";", "genIfxJump ");
5036     );
5037
5038   /* if true label then we jump if condition
5039      supplied is true */
5040   if (IC_TRUE (ic))
5041     {
5042       jlbl = IC_TRUE (ic);
5043       inst = ((strcmp (jval, "a") == 0 ? "jz" :
5044                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5045     }
5046   else
5047     {
5048       /* false label is present */
5049       jlbl = IC_FALSE (ic);
5050       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5051                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5052     }
5053   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5054     emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5055   else
5056     emitcode (inst, "!tlabel", tlbl->key + 100);
5057   emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5058   emitcode ("", "!tlabeldef", tlbl->key + 100);
5059
5060   /* mark the icode as generated */
5061   ic->generated = 1;
5062 }
5063
5064 /*-----------------------------------------------------------------*/
5065 /* genCmp :- greater or less than comparison                       */
5066 /*-----------------------------------------------------------------*/
5067 static void
5068 genCmp (operand * left, operand * right,
5069         iCode * ic, iCode * ifx, int sign)
5070 {
5071   int size, offset = 0;
5072   unsigned long lit = 0L;
5073   operand *result;
5074
5075   D (emitcode (";", "genCmp");
5076     );
5077
5078   result = IC_RESULT (ic);
5079
5080   /* if left & right are bit variables */
5081   if (AOP_TYPE (left) == AOP_CRY &&
5082       AOP_TYPE (right) == AOP_CRY)
5083     {
5084       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5085       emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
5086     }
5087   else
5088     {
5089       /* subtract right from left if at the
5090          end the carry flag is set then we know that
5091          left is greater than right */
5092       size = max (AOP_SIZE (left), AOP_SIZE (right));
5093
5094       /* if unsigned char cmp with lit, do cjne left,#right,zz */
5095       if ((size == 1) && !sign &&
5096           (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5097         {
5098           symbol *lbl = newiTempLabel (NULL);
5099           emitcode ("cjne", "%s,%s,!tlabel",
5100                     aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5101                     aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
5102                     lbl->key + 100);
5103           emitcode ("", "!tlabeldef", lbl->key + 100);
5104         }
5105       else
5106         {
5107           if (AOP_TYPE (right) == AOP_LIT)
5108             {
5109               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5110               /* optimize if(x < 0) or if(x >= 0) */
5111               if (lit == 0L)
5112                 {
5113                   if (!sign)
5114                     {
5115                       CLRC;
5116                     }
5117                   else
5118                     {
5119                       MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
5120
5121                       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5122                       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5123
5124                       aopOp (result, ic, FALSE, FALSE);
5125
5126                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5127                         {
5128                           freeAsmop (result, NULL, ic, TRUE);
5129                           genIfxJump (ifx, "acc.7");
5130                           return;
5131                         }
5132                       else
5133                         {
5134                           emitcode ("rlc", "a");
5135                         }
5136                       goto release_freedLR;
5137                     }
5138                   goto release;
5139                 }
5140             }
5141           CLRC;
5142           while (size--)
5143             {
5144               //emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5145               MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5146               //emitcode (";", "genCmp #2");
5147               if (sign && (size == 0))
5148                 {
5149                     //emitcode (";", "genCmp #3");
5150                   emitcode ("xrl", "a,#!constbyte",0x80);
5151                   if (AOP_TYPE (right) == AOP_LIT)
5152                     {
5153                       unsigned long lit = (unsigned long)
5154                       floatFromVal (AOP (right)->aopu.aop_lit);
5155                       //emitcode (";", "genCmp #3.1");
5156                       emitcode ("subb", "a,#!constbyte",
5157                                 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5158                     }
5159                   else
5160                     {
5161                       //emitcode (";", "genCmp #3.2");
5162                       if (AOP_NEEDSACC (right))
5163                         {
5164                           emitcode ("push", "acc");
5165                         }
5166                       emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
5167                                                        FALSE, FALSE, FALSE));
5168                       emitcode ("xrl", "b,#!constbyte",0x80);
5169                       if (AOP_NEEDSACC (right))
5170                         {
5171                           emitcode ("pop", "acc");
5172                         }
5173                       emitcode ("subb", "a,b");
5174                     }
5175                 }
5176               else
5177                 {
5178                   const char *s;
5179
5180                   //emitcode (";", "genCmp #4");
5181                   if (AOP_NEEDSACC (right))
5182                     {
5183                       /* Yuck!! */
5184                       //emitcode (";", "genCmp #4.1");
5185                       emitcode ("xch", "a, b");
5186                       MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
5187                       emitcode ("xch", "a, b");
5188                       s = "b";
5189                     }
5190                   else
5191                     {
5192                       //emitcode (";", "genCmp #4.2");
5193                       s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
5194                     }
5195
5196                   emitcode ("subb", "a,%s", s);
5197                 }
5198             }
5199         }
5200     }
5201
5202 release:
5203 /* Don't need the left & right operands any more; do need the result. */
5204   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5205   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5206
5207   aopOp (result, ic, FALSE, FALSE);
5208
5209 release_freedLR:
5210
5211   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5212     {
5213       outBitC (result);
5214     }
5215   else
5216     {
5217       /* if the result is used in the next
5218          ifx conditional branch then generate
5219          code a little differently */
5220       if (ifx)
5221         {
5222           genIfxJump (ifx, "c");
5223         }
5224       else
5225         {
5226           outBitC (result);
5227         }
5228       /* leave the result in acc */
5229     }
5230   freeAsmop (result, NULL, ic, TRUE);
5231 }
5232
5233 /*-----------------------------------------------------------------*/
5234 /* genCmpGt :- greater than comparison                             */
5235 /*-----------------------------------------------------------------*/
5236 static void
5237 genCmpGt (iCode * ic, iCode * ifx)
5238 {
5239   operand *left, *right;
5240   sym_link *letype, *retype;
5241   int sign;
5242
5243   D (emitcode (";", "genCmpGt ");
5244     );
5245
5246   left = IC_LEFT (ic);
5247   right = IC_RIGHT (ic);
5248
5249   letype = getSpec (operandType (left));
5250   retype = getSpec (operandType (right));
5251   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5252
5253   /* assign the left & right amsops */
5254   AOP_OP_2 (ic);
5255
5256   genCmp (right, left, ic, ifx, sign);
5257 }
5258
5259 /*-----------------------------------------------------------------*/
5260 /* genCmpLt - less than comparisons                                */
5261 /*-----------------------------------------------------------------*/
5262 static void
5263 genCmpLt (iCode * ic, iCode * ifx)
5264 {
5265   operand *left, *right;
5266   sym_link *letype, *retype;
5267   int sign;
5268
5269   D (emitcode (";", "genCmpLt "););
5270
5271   left = IC_LEFT (ic);
5272   right = IC_RIGHT (ic);
5273
5274   letype = getSpec (operandType (left));
5275   retype = getSpec (operandType (right));
5276   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5277
5278   /* assign the left & right amsops */
5279   AOP_OP_2 (ic);
5280
5281   genCmp (left, right, ic, ifx, sign);
5282 }
5283
5284 /*-----------------------------------------------------------------*/
5285 /* gencjneshort - compare and jump if not equal                    */
5286 /*-----------------------------------------------------------------*/
5287 static void
5288 gencjneshort (operand * left, operand * right, symbol * lbl)
5289 {
5290   int size = max (AOP_SIZE (left), AOP_SIZE (right));
5291   int offset = 0;
5292   unsigned long lit = 0L;
5293
5294   D (emitcode (";", "gencjneshort");
5295     );
5296
5297   /* if the left side is a literal or
5298      if the right is in a pointer register and left
5299      is not */
5300   if ((AOP_TYPE (left) == AOP_LIT) ||
5301       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5302     {
5303       operand *t = right;
5304       right = left;
5305       left = t;
5306     }
5307
5308   if (AOP_TYPE (right) == AOP_LIT)
5309     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5310
5311   if (opIsGptr (left) || opIsGptr (right))
5312     {
5313       /* We are comparing a generic pointer to something.
5314        * Exclude the generic type byte from the comparison.
5315        */
5316       size--;
5317       D (emitcode (";", "cjneshort: generic ptr special case.");
5318         )
5319     }
5320
5321
5322   /* if the right side is a literal then anything goes */
5323   if (AOP_TYPE (right) == AOP_LIT &&
5324       AOP_TYPE (left) != AOP_DIR)
5325     {
5326       while (size--)
5327         {
5328           char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5329           MOVA (l);
5330           emitcode ("cjne", "a,%s,!tlabel",
5331                     aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
5332                     lbl->key + 100);
5333           offset++;
5334         }
5335     }
5336
5337   /* if the right side is in a register or in direct space or
5338      if the left is a pointer register & right is not */
5339   else if (AOP_TYPE (right) == AOP_REG ||
5340            AOP_TYPE (right) == AOP_DIR ||
5341            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5342            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5343     {
5344       while (size--)
5345         {
5346           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5347           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5348               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5349             emitcode ("jnz", "!tlabel", lbl->key + 100);
5350           else
5351             emitcode ("cjne", "a,%s,!tlabel",
5352                       aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
5353                       lbl->key + 100);
5354           offset++;
5355         }
5356     }
5357   else
5358     {
5359       /* right is a pointer reg need both a & b */
5360       while (size--)
5361         {
5362           char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5363           if (strcmp (l, "b"))
5364             emitcode ("mov", "b,%s", l);
5365           MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5366           emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
5367           offset++;
5368         }
5369     }
5370 }
5371
5372 /*-----------------------------------------------------------------*/
5373 /* gencjne - compare and jump if not equal                         */
5374 /*-----------------------------------------------------------------*/
5375 static void
5376 gencjne (operand * left, operand * right, symbol * lbl)
5377 {
5378   symbol *tlbl = newiTempLabel (NULL);
5379
5380   D (emitcode (";", "gencjne");
5381     );
5382
5383   gencjneshort (left, right, lbl);
5384
5385   emitcode ("mov", "a,%s", one);
5386   emitcode ("sjmp", "!tlabel", tlbl->key + 100);
5387   emitcode ("", "!tlabeldef", lbl->key + 100);
5388   emitcode ("clr", "a");
5389   emitcode ("", "!tlabeldef", tlbl->key + 100);
5390 }
5391
5392 /*-----------------------------------------------------------------*/
5393 /* genCmpEq - generates code for equal to                          */
5394 /*-----------------------------------------------------------------*/
5395 static void
5396 genCmpEq (iCode * ic, iCode * ifx)
5397 {
5398   operand *left, *right, *result;
5399
5400   D (emitcode (";", "genCmpEq ");
5401     );
5402
5403   AOP_OP_2 (ic);
5404   AOP_SET_LOCALS (ic);
5405
5406   /* if literal, literal on the right or
5407      if the right is in a pointer register and left
5408      is not */
5409   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5410       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5411     {
5412       operand *t = IC_RIGHT (ic);
5413       IC_RIGHT (ic) = IC_LEFT (ic);
5414       IC_LEFT (ic) = t;
5415     }
5416
5417   if (ifx &&                    /* !AOP_SIZE(result) */
5418       OP_SYMBOL (result) &&
5419       OP_SYMBOL (result)->regType == REG_CND)
5420     {
5421       symbol *tlbl;
5422       /* if they are both bit variables */
5423       if (AOP_TYPE (left) == AOP_CRY &&
5424           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5425         {
5426           if (AOP_TYPE (right) == AOP_LIT)
5427             {
5428               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5429               if (lit == 0L)
5430                 {
5431                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5432                   emitcode ("cpl", "c");
5433                 }
5434               else if (lit == 1L)
5435                 {
5436                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5437                 }
5438               else
5439                 {
5440                   emitcode ("clr", "c");
5441                 }
5442               /* AOP_TYPE(right) == AOP_CRY */
5443             }
5444           else
5445             {
5446               symbol *lbl = newiTempLabel (NULL);
5447               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5448               emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5449               emitcode ("cpl", "c");
5450               emitcode ("", "!tlabeldef", (lbl->key + 100));
5451             }
5452           /* if true label then we jump if condition
5453              supplied is true */
5454           tlbl = newiTempLabel (NULL);
5455           if (IC_TRUE (ifx))
5456             {
5457               emitcode ("jnc", "!tlabel", tlbl->key + 100);
5458               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5459             }
5460           else
5461             {
5462               emitcode ("jc", "!tlabel", tlbl->key + 100);
5463               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5464             }
5465           emitcode ("", "!tlabeldef", tlbl->key + 100);
5466         }
5467       else
5468         {
5469           tlbl = newiTempLabel (NULL);
5470           gencjneshort (left, right, tlbl);
5471           if (IC_TRUE (ifx))
5472             {
5473               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5474               emitcode ("", "!tlabeldef", tlbl->key + 100);
5475             }
5476           else
5477             {
5478               symbol *lbl = newiTempLabel (NULL);
5479               emitcode ("sjmp", "!tlabel", lbl->key + 100);
5480               emitcode ("", "!tlabeldef", tlbl->key + 100);
5481               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5482               emitcode ("", "!tlabeldef", lbl->key + 100);
5483             }
5484         }
5485       /* mark the icode as generated */
5486       ifx->generated = 1;
5487
5488       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5489       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5490       return;
5491     }
5492
5493   /* if they are both bit variables */
5494   if (AOP_TYPE (left) == AOP_CRY &&
5495       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5496     {
5497       if (AOP_TYPE (right) == AOP_LIT)
5498         {
5499           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5500           if (lit == 0L)
5501             {
5502               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5503               emitcode ("cpl", "c");
5504             }
5505           else if (lit == 1L)
5506             {
5507               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5508             }
5509           else
5510             {
5511               emitcode ("clr", "c");
5512             }
5513           /* AOP_TYPE(right) == AOP_CRY */
5514         }
5515       else
5516         {
5517           symbol *lbl = newiTempLabel (NULL);
5518           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5519           emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5520           emitcode ("cpl", "c");
5521           emitcode ("", "!tlabeldef", (lbl->key + 100));
5522         }
5523
5524       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5525       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5526
5527       aopOp (result, ic, TRUE, FALSE);
5528
5529       /* c = 1 if egal */
5530       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5531         {
5532           outBitC (result);
5533           goto release;
5534         }
5535       if (ifx)
5536         {
5537           genIfxJump (ifx, "c");
5538           goto release;
5539         }
5540       /* if the result is used in an arithmetic operation
5541          then put the result in place */
5542       outBitC (result);
5543     }
5544   else
5545     {
5546       gencjne (left, right, newiTempLabel (NULL));
5547
5548       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5549       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5550
5551       aopOp (result, ic, TRUE, FALSE);
5552
5553       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5554         {
5555           aopPut (AOP (result), "a", 0);
5556           goto release;
5557         }
5558       if (ifx)
5559         {
5560           genIfxJump (ifx, "a");
5561           goto release;
5562         }
5563       /* if the result is used in an arithmetic operation
5564          then put the result in place */
5565       if (AOP_TYPE (result) != AOP_CRY)
5566         outAcc (result);
5567       /* leave the result in acc */
5568     }
5569
5570 release:
5571   freeAsmop (result, NULL, ic, TRUE);
5572 }
5573
5574 /*-----------------------------------------------------------------*/
5575 /* ifxForOp - returns the icode containing the ifx for operand     */
5576 /*-----------------------------------------------------------------*/
5577 static iCode *
5578 ifxForOp (operand * op, iCode * ic)
5579 {
5580   /* if true symbol then needs to be assigned */
5581   if (IS_TRUE_SYMOP (op))
5582     return NULL;
5583
5584   /* if this has register type condition and
5585      the next instruction is ifx with the same operand
5586      and live to of the operand is upto the ifx only then */
5587   if (ic->next &&
5588       ic->next->op == IFX &&
5589       IC_COND (ic->next)->key == op->key &&
5590       OP_SYMBOL (op)->liveTo <= ic->next->seq)
5591     return ic->next;
5592
5593   return NULL;
5594 }
5595 /*-----------------------------------------------------------------*/
5596 /* hasInc - operand is incremented before any other use            */
5597 /*-----------------------------------------------------------------*/
5598 static iCode *
5599 hasInc (operand *op, iCode *ic, int osize)
5600 {
5601   sym_link *type = operandType(op);
5602   sym_link *retype = getSpec (type);
5603   iCode *lic = ic->next;
5604   int isize ;
5605   
5606   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5607   if (!IS_SYMOP(op)) return NULL;
5608
5609   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5610   if (IS_AGGREGATE(type->next)) return NULL;
5611   if (osize != (isize = getSize(type->next))) return NULL;
5612
5613   while (lic) {
5614       /* if operand of the form op = op + <sizeof *op> */
5615       if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5616           isOperandEqual(IC_RESULT(lic),op) && 
5617           isOperandLiteral(IC_RIGHT(lic)) &&
5618           operandLitValue(IC_RIGHT(lic)) == isize) {
5619           return lic;
5620       }
5621       /* if the operand used or deffed */
5622       if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5623           return NULL;
5624       }
5625       /* if GOTO or IFX */
5626       if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5627       lic = lic->next;
5628   }
5629   return NULL;
5630 }
5631
5632 /*-----------------------------------------------------------------*/
5633 /* genAndOp - for && operation                                     */
5634 /*-----------------------------------------------------------------*/
5635 static void
5636 genAndOp (iCode * ic)
5637 {
5638   operand *left, *right, *result;
5639   symbol *tlbl;
5640
5641   D (emitcode (";", "genAndOp "););
5642
5643   /* note here that && operations that are in an
5644      if statement are taken away by backPatchLabels
5645      only those used in arthmetic operations remain */
5646   AOP_OP_2 (ic);
5647   AOP_SET_LOCALS (ic);
5648
5649   /* if both are bit variables */
5650   if (AOP_TYPE (left) == AOP_CRY &&
5651       AOP_TYPE (right) == AOP_CRY)
5652     {
5653       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5654       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5655       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5656       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5657   
5658       aopOp (result,ic,FALSE, FALSE);
5659       outBitC (result);
5660     }
5661   else
5662     {
5663       tlbl = newiTempLabel (NULL);
5664       toBoolean (left);
5665       emitcode ("jz", "!tlabel", tlbl->key + 100);
5666       toBoolean (right);
5667       emitcode ("", "!tlabeldef", tlbl->key + 100);
5668       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5669       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5670   
5671       aopOp (result,ic,FALSE, FALSE);
5672       outBitAcc (result);
5673     }
5674     freeAsmop (result, NULL, ic, TRUE);
5675 }
5676
5677
5678 /*-----------------------------------------------------------------*/
5679 /* genOrOp - for || operation                                      */
5680 /*-----------------------------------------------------------------*/
5681 static void
5682 genOrOp (iCode * ic)
5683 {
5684   operand *left, *right, *result;
5685   symbol *tlbl;
5686
5687   D (emitcode (";", "genOrOp "););
5688
5689   /* note here that || operations that are in an
5690      if statement are taken away by backPatchLabels
5691      only those used in arthmetic operations remain */
5692   AOP_OP_2 (ic);
5693   AOP_SET_LOCALS (ic);
5694
5695   /* if both are bit variables */
5696   if (AOP_TYPE (left) == AOP_CRY &&
5697       AOP_TYPE (right) == AOP_CRY)
5698     {
5699       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5700       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5701       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5702       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5703   
5704       aopOp (result,ic,FALSE, FALSE);
5705       
5706       outBitC (result);
5707     }
5708   else
5709     {
5710       tlbl = newiTempLabel (NULL);
5711       toBoolean (left);
5712       emitcode ("jnz", "!tlabel", tlbl->key + 100);
5713       toBoolean (right);
5714       emitcode ("", "!tlabeldef", tlbl->key + 100);
5715       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5716       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5717   
5718       aopOp (result,ic,FALSE, FALSE);
5719       
5720       outBitAcc (result);
5721     }
5722
5723   freeAsmop (result, NULL, ic, TRUE);
5724 }
5725
5726 /*-----------------------------------------------------------------*/
5727 /* isLiteralBit - test if lit == 2^n                               */
5728 /*-----------------------------------------------------------------*/
5729 static int
5730 isLiteralBit (unsigned long lit)
5731 {
5732   unsigned long pw[32] =
5733   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5734    0x100L, 0x200L, 0x400L, 0x800L,
5735    0x1000L, 0x2000L, 0x4000L, 0x8000L,
5736    0x10000L, 0x20000L, 0x40000L, 0x80000L,
5737    0x100000L, 0x200000L, 0x400000L, 0x800000L,
5738    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5739    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5740   int idx;
5741
5742   for (idx = 0; idx < 32; idx++)
5743     if (lit == pw[idx])
5744       return idx + 1;
5745   return 0;
5746 }
5747
5748 /*-----------------------------------------------------------------*/
5749 /* continueIfTrue -                                                */
5750 /*-----------------------------------------------------------------*/
5751 static void
5752 continueIfTrue (iCode * ic)
5753 {
5754   if (IC_TRUE (ic))
5755     emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
5756   ic->generated = 1;
5757 }
5758
5759 /*-----------------------------------------------------------------*/
5760 /* jmpIfTrue -                                                     */
5761 /*-----------------------------------------------------------------*/
5762 static void
5763 jumpIfTrue (iCode * ic)
5764 {
5765   if (!IC_TRUE (ic))
5766     emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
5767   ic->generated = 1;
5768 }
5769
5770 /*-----------------------------------------------------------------*/
5771 /* jmpTrueOrFalse -                                                */
5772 /*-----------------------------------------------------------------*/
5773 static void
5774 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
5775 {
5776   // ugly but optimized by peephole
5777   if (IC_TRUE (ic))
5778     {
5779       symbol *nlbl = newiTempLabel (NULL);
5780       emitcode ("sjmp", "!tlabel", nlbl->key + 100);
5781       emitcode ("", "!tlabeldef", tlbl->key + 100);
5782       emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
5783       emitcode ("", "!tlabeldef", nlbl->key + 100);
5784     }
5785   else
5786     {
5787       emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
5788       emitcode ("", "!tlabeldef", tlbl->key + 100);
5789     }
5790   ic->generated = 1;
5791 }
5792
5793 // Generate code to perform a bit-wise logic operation
5794 // on two operands in far space (assumed to already have been 
5795 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
5796 // in far space. This requires pushing the result on the stack
5797 // then popping it into the result.
5798 static void
5799 genFarFarLogicOp(iCode *ic, char *logicOp)
5800 {
5801       int size, resultSize, compSize;
5802       int offset = 0;
5803       
5804       TR_AP("#5");
5805       D(emitcode(";", "%s special case for 3 far operands.", logicOp););
5806       compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ? 
5807                   AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
5808       
5809       _startLazyDPSEvaluation();
5810       for (size = compSize; (size--); offset++)
5811       {
5812           MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
5813           emitcode ("mov", "%s, acc", DP2_RESULT_REG);
5814           MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
5815           
5816           emitcode (logicOp, "a,%s", DP2_RESULT_REG);
5817           emitcode ("push", "acc");
5818       }
5819       _endLazyDPSEvaluation();
5820      
5821       freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5822       freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5823       aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
5824      
5825       resultSize = AOP_SIZE(IC_RESULT(ic));
5826
5827       ADJUST_PUSHED_RESULT(compSize, resultSize);
5828
5829       _startLazyDPSEvaluation();
5830       while (compSize--)
5831       {
5832           emitcode ("pop", "acc");
5833           aopPut (AOP (IC_RESULT (ic)), "a", compSize);
5834       }
5835       _endLazyDPSEvaluation();
5836       freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
5837 }
5838
5839
5840 /*-----------------------------------------------------------------*/
5841 /* genAnd  - code for and                                          */
5842 /*-----------------------------------------------------------------*/
5843 static void
5844 genAnd (iCode * ic, iCode * ifx)
5845 {
5846   operand *left, *right, *result;
5847   int size, offset = 0;
5848   unsigned long lit = 0L;
5849   int bytelit = 0;
5850   char buffer[10];
5851   bool pushResult;
5852
5853   D (emitcode (";", "genAnd "););
5854
5855   AOP_OP_3_NOFATAL (ic, pushResult);
5856   AOP_SET_LOCALS (ic);
5857
5858   if (pushResult)
5859   {
5860       genFarFarLogicOp(ic, "anl");
5861       return;
5862   }  
5863
5864 #ifdef DEBUG_TYPE
5865   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5866             AOP_TYPE (result),
5867             AOP_TYPE (left), AOP_TYPE (right));
5868   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5869             AOP_SIZE (result),
5870             AOP_SIZE (left), AOP_SIZE (right));
5871 #endif
5872
5873   /* if left is a literal & right is not then exchange them */
5874   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5875 #ifdef LOGIC_OPS_BROKEN      
5876     ||  AOP_NEEDSACC (left)
5877 #endif
5878     )
5879     {
5880       operand *tmp = right;
5881       right = left;
5882       left = tmp;
5883     }
5884
5885   /* if result = right then exchange them */
5886   if (sameRegs (AOP (result), AOP (right)))
5887     {
5888       operand *tmp = right;
5889       right = left;
5890       left = tmp;
5891     }
5892
5893   /* if right is bit then exchange them */
5894   if (AOP_TYPE (right) == AOP_CRY &&
5895       AOP_TYPE (left) != AOP_CRY)
5896     {
5897       operand *tmp = right;
5898       right = left;
5899       left = tmp;
5900     }
5901   if (AOP_TYPE (right) == AOP_LIT)
5902     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5903
5904   size = AOP_SIZE (result);
5905
5906   // if(bit & yy)
5907   // result = bit & yy;
5908   if (AOP_TYPE (left) == AOP_CRY)
5909     {
5910       // c = bit & literal;
5911       if (AOP_TYPE (right) == AOP_LIT)
5912         {
5913           if (lit & 1)
5914             {
5915               if (size && sameRegs (AOP (result), AOP (left)))
5916                 // no change
5917                 goto release;
5918               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5919             }
5920           else
5921             {
5922               // bit(result) = 0;
5923               if (size && (AOP_TYPE (result) == AOP_CRY))
5924                 {
5925                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5926                   goto release;
5927                 }
5928               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5929                 {
5930                   jumpIfTrue (ifx);
5931                   goto release;
5932                 }
5933               emitcode ("clr", "c");
5934             }
5935         }
5936       else
5937         {
5938           if (AOP_TYPE (right) == AOP_CRY)
5939             {
5940               // c = bit & bit;
5941               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5942               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5943             }
5944           else
5945             {
5946               // c = bit & val;
5947               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
5948               // c = lsb
5949               emitcode ("rrc", "a");
5950               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5951             }
5952         }
5953       // bit = c
5954       // val = c
5955       if (size)
5956         outBitC (result);
5957       // if(bit & ...)
5958       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5959         genIfxJump (ifx, "c");
5960       goto release;
5961     }
5962
5963   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5964   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5965   if ((AOP_TYPE (right) == AOP_LIT) &&
5966       (AOP_TYPE (result) == AOP_CRY) &&
5967       (AOP_TYPE (left) != AOP_CRY))
5968     {
5969       int posbit = isLiteralBit (lit);
5970       /* left &  2^n */
5971       if (posbit)
5972         {
5973           posbit--;
5974           MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
5975           // bit = left & 2^n
5976           if (size)
5977             emitcode ("mov", "c,acc.%d", posbit & 0x07);
5978           // if(left &  2^n)
5979           else
5980             {
5981               if (ifx)
5982                 {
5983                   sprintf (buffer, "acc.%d", posbit & 0x07);
5984                   genIfxJump (ifx, buffer);
5985                 }
5986               goto release;
5987             }
5988         }
5989       else
5990         {
5991           symbol *tlbl = newiTempLabel (NULL);
5992           int sizel = AOP_SIZE (left);
5993           if (size)
5994             emitcode ("setb", "c");
5995           while (sizel--)
5996             {
5997               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5998                 {
5999                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6000                   // byte ==  2^n ?
6001                   if ((posbit = isLiteralBit (bytelit)) != 0)
6002                     emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
6003                   else
6004                     {
6005                       if (bytelit != 0x0FFL)
6006                         emitcode ("anl", "a,%s",
6007                           aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
6008                       emitcode ("jnz", "!tlabel", tlbl->key + 100);
6009                     }
6010                 }
6011               offset++;
6012             }
6013           // bit = left & literal
6014           if (size)
6015             {
6016               emitcode ("clr", "c");
6017               emitcode ("", "!tlabeldef", tlbl->key + 100);
6018             }
6019           // if(left & literal)
6020           else
6021             {
6022               if (ifx)
6023                 jmpTrueOrFalse (ifx, tlbl);
6024               goto release;
6025             }
6026         }
6027       outBitC (result);
6028       goto release;
6029     }
6030
6031   /* if left is same as result */
6032   if (sameRegs (AOP (result), AOP (left)))
6033     {
6034       for (; size--; offset++)
6035         {
6036           if (AOP_TYPE (right) == AOP_LIT)
6037             {
6038               if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6039                 continue;
6040               else if (bytelit == 0)
6041                 aopPut (AOP (result), zero, offset);
6042               else if (IS_AOP_PREG (result))
6043                 {
6044                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6045                   emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6046                   aopPut (AOP (result), "a", offset);
6047                 }
6048               else
6049                 emitcode ("anl", "%s,%s",
6050                           aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6051                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6052             }
6053           else
6054             {
6055               if (AOP_TYPE (left) == AOP_ACC)
6056                 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6057               else
6058                 {
6059                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6060                   if (IS_AOP_PREG (result))
6061                     {
6062                       emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6063                       aopPut (AOP (result), "a", offset);
6064
6065                     }
6066                   else
6067                     emitcode ("anl", "%s,a",
6068                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6069                 }
6070             }
6071         }
6072     }
6073   else
6074     {
6075       // left & result in different registers
6076       if (AOP_TYPE (result) == AOP_CRY)
6077         {
6078           // result = bit
6079           // if(size), result in bit
6080           // if(!size && ifx), conditional oper: if(left & right)
6081           symbol *tlbl = newiTempLabel (NULL);
6082           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6083           if (size)
6084             emitcode ("setb", "c");
6085           while (sizer--)
6086             {
6087               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6088                 emitcode ("anl", "a,%s",
6089                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6090               } else {
6091                 if (AOP_TYPE(left)==AOP_ACC) {
6092                   emitcode("mov", "b,a");
6093                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6094                   emitcode("anl", "a,b");
6095                 }else {
6096                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6097                   emitcode ("anl", "a,%s",
6098                             aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6099                 }
6100               }
6101               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6102               offset++;
6103             }
6104           if (size)
6105             {
6106               CLRC;
6107               emitcode ("", "!tlabeldef", tlbl->key + 100);
6108               outBitC (result);
6109             }
6110           else if (ifx)
6111             jmpTrueOrFalse (ifx, tlbl);
6112         }
6113       else
6114         {
6115           for (; (size--); offset++)
6116             {
6117               // normal case
6118               // result = left & right
6119               if (AOP_TYPE (right) == AOP_LIT)
6120                 {
6121                   if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6122                     {
6123                       aopPut (AOP (result),
6124                            aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6125                               offset);
6126                       continue;
6127                     }
6128                   else if (bytelit == 0)
6129                     {
6130                       aopPut (AOP (result), zero, offset);
6131                       continue;
6132                     }
6133                   D (emitcode (";", "better literal AND."););
6134                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6135                   emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6136                                                     FALSE, FALSE, FALSE));
6137
6138                 }
6139               else
6140                 {
6141                   // faster than result <- left, anl result,right
6142                   // and better if result is SFR
6143                   if (AOP_TYPE (left) == AOP_ACC)
6144                     {
6145                       emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
6146                                                        FALSE, FALSE, FALSE));
6147                     }
6148                   else
6149                     {
6150                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6151                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6152                       {
6153                           emitcode("mov", "b,a");
6154                           rOp = "b";
6155                       }
6156                         
6157                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6158                       emitcode ("anl", "a,%s", rOp);
6159                     }                   
6160                 }
6161               aopPut (AOP (result), "a", offset);
6162             }
6163         }
6164     }
6165
6166 release:
6167   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6168   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6169   freeAsmop (result, NULL, ic, TRUE);
6170 }
6171
6172
6173 /*-----------------------------------------------------------------*/
6174 /* genOr  - code for or                                            */
6175 /*-----------------------------------------------------------------*/
6176 static void
6177 genOr (iCode * ic, iCode * ifx)
6178 {
6179   operand *left, *right, *result;
6180   int size, offset = 0;
6181   unsigned long lit = 0L;
6182   bool     pushResult;
6183
6184   D (emitcode (";", "genOr "););
6185
6186   AOP_OP_3_NOFATAL (ic, pushResult);
6187   AOP_SET_LOCALS (ic);
6188
6189   if (pushResult)
6190   {
6191       genFarFarLogicOp(ic, "orl");
6192       return;
6193   }
6194
6195
6196 #ifdef DEBUG_TYPE
6197   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6198             AOP_TYPE (result),
6199             AOP_TYPE (left), AOP_TYPE (right));
6200   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6201             AOP_SIZE (result),
6202             AOP_SIZE (left), AOP_SIZE (right));
6203 #endif
6204
6205   /* if left is a literal & right is not then exchange them */
6206   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6207 #ifdef LOGIC_OPS_BROKEN
6208    || AOP_NEEDSACC (left) // I think this is a net loss now.
6209 #endif      
6210       )
6211     {
6212       operand *tmp = right;
6213       right = left;
6214       left = tmp;
6215     }
6216
6217   /* if result = right then exchange them */
6218   if (sameRegs (AOP (result), AOP (right)))
6219     {
6220       operand *tmp = right;
6221       right = left;
6222       left = tmp;
6223     }
6224
6225   /* if right is bit then exchange them */
6226   if (AOP_TYPE (right) == AOP_CRY &&
6227       AOP_TYPE (left) != AOP_CRY)
6228     {
6229       operand *tmp = right;
6230       right = left;
6231       left = tmp;
6232     }
6233   if (AOP_TYPE (right) == AOP_LIT)
6234     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6235
6236   size = AOP_SIZE (result);
6237
6238   // if(bit | yy)
6239   // xx = bit | yy;
6240   if (AOP_TYPE (left) == AOP_CRY)
6241     {
6242       if (AOP_TYPE (right) == AOP_LIT)
6243         {
6244           // c = bit & literal;
6245           if (lit)
6246             {
6247               // lit != 0 => result = 1
6248               if (AOP_TYPE (result) == AOP_CRY)
6249                 {
6250                   if (size)
6251                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6252                   else if (ifx)
6253                     continueIfTrue (ifx);
6254                   goto release;
6255                 }
6256               emitcode ("setb", "c");
6257             }
6258           else
6259             {
6260               // lit == 0 => result = left
6261               if (size && sameRegs (AOP (result), AOP (left)))
6262                 goto release;
6263               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6264             }
6265         }
6266       else
6267         {
6268           if (AOP_TYPE (right) == AOP_CRY)
6269             {
6270               // c = bit | bit;
6271               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6272               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6273             }
6274           else
6275             {
6276               // c = bit | val;
6277               symbol *tlbl = newiTempLabel (NULL);
6278               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6279                 emitcode ("setb", "c");
6280               emitcode ("jb", "%s,!tlabel",
6281                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
6282               toBoolean (right);
6283               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6284               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6285                 {
6286                   jmpTrueOrFalse (ifx, tlbl);
6287                   goto release;
6288                 }
6289               else
6290                 {
6291                   CLRC;
6292                   emitcode ("", "!tlabeldef", tlbl->key + 100);
6293                 }
6294             }
6295         }
6296       // bit = c
6297       // val = c
6298       if (size)
6299         outBitC (result);
6300       // if(bit | ...)
6301       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6302         genIfxJump (ifx, "c");
6303       goto release;
6304     }
6305
6306   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6307   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6308   if ((AOP_TYPE (right) == AOP_LIT) &&
6309       (AOP_TYPE (result) == AOP_CRY) &&
6310       (AOP_TYPE (left) != AOP_CRY))
6311     {
6312       if (lit)
6313         {
6314           // result = 1
6315           if (size)
6316             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6317           else
6318             continueIfTrue (ifx);
6319           goto release;
6320         }
6321       else
6322         {
6323           // lit = 0, result = boolean(left)
6324           if (size)
6325             emitcode ("setb", "c");
6326           toBoolean (right);
6327           if (size)
6328             {
6329               symbol *tlbl = newiTempLabel (NULL);
6330               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6331               CLRC;
6332               emitcode ("", "!tlabeldef", tlbl->key + 100);
6333             }
6334           else
6335             {
6336               genIfxJump (ifx, "a");
6337               goto release;
6338             }
6339         }
6340       outBitC (result);
6341       goto release;
6342     }
6343
6344   /* if left is same as result */
6345   if (sameRegs (AOP (result), AOP (left)))
6346     {
6347       for (; size--; offset++)
6348         {
6349           if (AOP_TYPE (right) == AOP_LIT)
6350             {
6351               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6352                 {
6353                   continue;
6354                 }
6355               else
6356                 {
6357                   if (IS_AOP_PREG (left))
6358                     {
6359                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6360                       emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6361                       aopPut (AOP (result), "a", offset);
6362                     }
6363                   else
6364                     {
6365                       emitcode ("orl", "%s,%s",
6366                             aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6367                          aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6368                     }
6369                 }
6370             }
6371           else
6372             {
6373               if (AOP_TYPE (left) == AOP_ACC)
6374                 {
6375                   emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6376                 }
6377               else
6378                 {
6379                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6380                   if (IS_AOP_PREG (left))
6381                     {
6382                       emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6383                       aopPut (AOP (result), "a", offset);
6384                     }
6385                   else
6386                     {
6387                       emitcode ("orl", "%s,a",
6388                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6389                     }
6390                 }
6391             }
6392         }
6393     }
6394   else
6395     {
6396       // left & result in different registers
6397       if (AOP_TYPE (result) == AOP_CRY)
6398         {
6399           // result = bit
6400           // if(size), result in bit
6401           // if(!size && ifx), conditional oper: if(left | right)
6402           symbol *tlbl = newiTempLabel (NULL);
6403           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6404           if (size)
6405             emitcode ("setb", "c");
6406           while (sizer--)
6407             {
6408               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6409                 emitcode ("orl", "a,%s",
6410                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6411               } else {
6412                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6413                 emitcode ("orl", "a,%s",
6414                           aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6415               }
6416               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6417               offset++;
6418             }
6419           if (size)
6420             {
6421               CLRC;
6422               emitcode ("", "!tlabeldef", tlbl->key + 100);
6423               outBitC (result);
6424             }
6425           else if (ifx)
6426             jmpTrueOrFalse (ifx, tlbl);
6427         }
6428       else
6429         {
6430             _startLazyDPSEvaluation();
6431           for (; (size--); offset++)
6432             {
6433               // normal case
6434               // result = left & right
6435               if (AOP_TYPE (right) == AOP_LIT)
6436                 {
6437                   if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6438                     {
6439                       aopPut (AOP (result),
6440                            aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6441                               offset);
6442                       continue;
6443                     }
6444                   D (emitcode (";", "better literal OR."););
6445                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6446                   emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
6447                                                     FALSE, FALSE, FALSE));
6448
6449                 }
6450               else
6451                 {
6452                   // faster than result <- left, anl result,right
6453                   // and better if result is SFR
6454                   if (AOP_TYPE (left) == AOP_ACC)
6455                     {
6456                       emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
6457                                                        FALSE, FALSE, FALSE));
6458                     }
6459                   else
6460                     {
6461                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6462                         
6463                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6464                       {
6465                           emitcode("mov", "b,a");
6466                           rOp = "b";
6467                       }
6468                         
6469                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6470                       emitcode ("orl", "a,%s", rOp);
6471                     }
6472                 }
6473               aopPut (AOP (result), "a", offset);
6474             }
6475             _endLazyDPSEvaluation();
6476         }
6477     }
6478
6479 release:
6480   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6481   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6482   freeAsmop (result, NULL, ic, TRUE);
6483 }
6484
6485 /*-----------------------------------------------------------------*/
6486 /* genXor - code for xclusive or                                   */
6487 /*-----------------------------------------------------------------*/
6488 static void
6489 genXor (iCode * ic, iCode * ifx)
6490 {
6491   operand *left, *right, *result;
6492   int size, offset = 0;
6493   unsigned long lit = 0L;
6494   bool pushResult;
6495
6496   D (emitcode (";", "genXor "););
6497
6498   AOP_OP_3_NOFATAL (ic, pushResult);
6499   AOP_SET_LOCALS (ic);
6500
6501   if (pushResult)
6502   {
6503       genFarFarLogicOp(ic, "xrl");
6504       return;
6505   }  
6506
6507 #ifdef DEBUG_TYPE
6508   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6509             AOP_TYPE (result),
6510             AOP_TYPE (left), AOP_TYPE (right));
6511   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6512             AOP_SIZE (result),
6513             AOP_SIZE (left), AOP_SIZE (right));
6514 #endif
6515
6516   /* if left is a literal & right is not ||
6517      if left needs acc & right does not */
6518   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) 
6519 #ifdef LOGIC_OPS_BROKEN      
6520       || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6521 #endif
6522      )
6523     {
6524       operand *tmp = right;
6525       right = left;
6526       left = tmp;
6527     }
6528
6529   /* if result = right then exchange them */
6530   if (sameRegs (AOP (result), AOP (right)))
6531     {
6532       operand *tmp = right;
6533       right = left;
6534       left = tmp;
6535     }
6536
6537   /* if right is bit then exchange them */
6538   if (AOP_TYPE (right) == AOP_CRY &&
6539       AOP_TYPE (left) != AOP_CRY)
6540     {
6541       operand *tmp = right;
6542       right = left;
6543       left = tmp;
6544     }
6545   if (AOP_TYPE (right) == AOP_LIT)
6546     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6547
6548   size = AOP_SIZE (result);
6549
6550   // if(bit ^ yy)
6551   // xx = bit ^ yy;
6552   if (AOP_TYPE (left) == AOP_CRY)
6553     {
6554       if (AOP_TYPE (right) == AOP_LIT)
6555         {
6556           // c = bit & literal;
6557           if (lit >> 1)
6558             {
6559               // lit>>1  != 0 => result = 1
6560               if (AOP_TYPE (result) == AOP_CRY)
6561                 {
6562                   if (size)
6563                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6564                   else if (ifx)
6565                     continueIfTrue (ifx);
6566                   goto release;
6567                 }
6568               emitcode ("setb", "c");
6569             }
6570           else
6571             {
6572               // lit == (0 or 1)
6573               if (lit == 0)
6574                 {
6575                   // lit == 0, result = left
6576                   if (size && sameRegs (AOP (result), AOP (left)))
6577                     goto release;
6578                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6579                 }
6580               else
6581                 {
6582                   // lit == 1, result = not(left)
6583                   if (size && sameRegs (AOP (result), AOP (left)))
6584                     {
6585                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6586                       goto release;
6587                     }
6588                   else
6589                     {
6590                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6591                       emitcode ("cpl", "c");
6592                     }
6593                 }
6594             }
6595
6596         }
6597       else
6598         {
6599           // right != literal
6600           symbol *tlbl = newiTempLabel (NULL);
6601           if (AOP_TYPE (right) == AOP_CRY)
6602             {
6603               // c = bit ^ bit;
6604               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6605             }
6606           else
6607             {
6608               int sizer = AOP_SIZE (right);
6609               // c = bit ^ val
6610               // if val>>1 != 0, result = 1
6611               emitcode ("setb", "c");
6612               while (sizer)
6613                 {
6614                   MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
6615                   if (sizer == 1)
6616                     // test the msb of the lsb
6617                     emitcode ("anl", "a,#!constbyte",0xfe);
6618                   emitcode ("jnz", "!tlabel", tlbl->key + 100);
6619                   sizer--;
6620                 }
6621               // val = (0,1)
6622               emitcode ("rrc", "a");
6623             }
6624           emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6625           emitcode ("cpl", "c");
6626           emitcode ("", "!tlabeldef", (tlbl->key + 100));
6627         }
6628       // bit = c
6629       // val = c
6630       if (size)
6631         outBitC (result);
6632       // if(bit | ...)
6633       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6634         genIfxJump (ifx, "c");
6635       goto release;
6636     }
6637
6638   if (sameRegs (AOP (result), AOP (left)))
6639     {
6640       /* if left is same as result */
6641       for (; size--; offset++)
6642         {
6643           if (AOP_TYPE (right) == AOP_LIT)
6644             {
6645               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6646                 continue;
6647               else if (IS_AOP_PREG (left))
6648                 {
6649                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6650                   emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6651                   aopPut (AOP (result), "a", offset);
6652                 }
6653               else
6654                 emitcode ("xrl", "%s,%s",
6655                           aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6656                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6657             }
6658           else
6659             {
6660               if (AOP_TYPE (left) == AOP_ACC)
6661                 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6662               else
6663                 {
6664                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6665                   if (IS_AOP_PREG (left))
6666                     {
6667                       emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6668                       aopPut (AOP (result), "a", offset);
6669                     }
6670                   else
6671                     emitcode ("xrl", "%s,a",
6672                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6673                 }
6674             }
6675         }
6676     }
6677   else
6678     {
6679       // left & result in different registers
6680       if (AOP_TYPE (result) == AOP_CRY)
6681         {
6682           // result = bit
6683           // if(size), result in bit
6684           // if(!size && ifx), conditional oper: if(left ^ right)
6685           symbol *tlbl = newiTempLabel (NULL);
6686           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6687                   
6688           if (size)
6689             emitcode ("setb", "c");
6690           while (sizer--)
6691             {
6692               if ((AOP_TYPE (right) == AOP_LIT) &&
6693                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6694                 {
6695                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6696                 }
6697               else
6698                 {
6699                   if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6700                     emitcode ("xrl", "a,%s",
6701                               aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6702                   } else {
6703                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6704                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6705                       {
6706                           emitcode("mov", "b,a");
6707                           rOp = "b";
6708                       }
6709                         
6710                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6711                       emitcode ("xrl", "a,%s", rOp);                  
6712                   }
6713                 }
6714               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6715               offset++;
6716             }
6717           if (size)
6718             {
6719               CLRC;
6720               emitcode ("", "!tlabeldef", tlbl->key + 100);
6721               outBitC (result);
6722             }
6723           else if (ifx)
6724             jmpTrueOrFalse (ifx, tlbl);
6725         }
6726       else
6727         {
6728         for (; (size--); offset++)
6729           {
6730             // normal case
6731             // result = left & right
6732             if (AOP_TYPE (right) == AOP_LIT)
6733               {
6734                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6735                   {
6736                     aopPut (AOP (result),
6737                             aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6738                             offset);
6739                     continue;
6740                   }
6741                 D (emitcode (";", "better literal XOR."););
6742                 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6743                 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
6744                                                   FALSE, FALSE, FALSE));
6745               }
6746             else
6747               {
6748                 // faster than result <- left, anl result,right
6749                 // and better if result is SFR
6750                 if (AOP_TYPE (left) == AOP_ACC)
6751                   {
6752                     emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
6753                                                      FALSE, FALSE, FALSE));
6754                   }
6755                 else
6756                   {
6757                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6758                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6759                       {
6760                           emitcode("mov", "b,a");
6761                           rOp = "b";
6762                       }
6763                         
6764                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6765                       emitcode ("xrl", "a,%s", rOp);
6766                   }
6767               }
6768             aopPut (AOP (result), "a", offset);
6769           }
6770         }
6771         
6772     }
6773
6774 release:
6775   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6776   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6777   freeAsmop (result, NULL, ic, TRUE);
6778 }
6779
6780 /*-----------------------------------------------------------------*/
6781 /* genInline - write the inline code out                           */
6782 /*-----------------------------------------------------------------*/
6783 static void
6784 genInline (iCode * ic)
6785 {
6786   char *buffer, *bp, *bp1;
6787
6788   D (emitcode (";", "genInline ");
6789     );
6790
6791   _G.inLine += (!options.asmpeep);
6792
6793   buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6794   strcpy (buffer, IC_INLINE (ic));
6795
6796   /* emit each line as a code */
6797   while (*bp)
6798     {
6799       if (*bp == '\n')
6800         {
6801           *bp++ = '\0';
6802           emitcode (bp1, "");
6803           bp1 = bp;
6804         }
6805       else
6806         {
6807           if (*bp == ':')
6808             {
6809               bp++;
6810               *bp = '\0';
6811               bp++;
6812               emitcode (bp1, "");
6813               bp1 = bp;
6814             }
6815           else
6816             bp++;
6817         }
6818     }
6819   if (bp1 != bp)
6820     emitcode (bp1, "");
6821   /*     emitcode("",buffer); */
6822   _G.inLine -= (!options.asmpeep);
6823 }
6824
6825 /*-----------------------------------------------------------------*/
6826 /* genRRC - rotate right with carry                                */
6827 /*-----------------------------------------------------------------*/
6828 static void
6829 genRRC (iCode * ic)
6830 {
6831   operand *left, *result;
6832   int size, offset = 0;
6833   char *l;
6834
6835   D (emitcode (";", "genRRC ");
6836     );
6837
6838   /* rotate right with carry */
6839   left = IC_LEFT (ic);
6840   result = IC_RESULT (ic);
6841   aopOp (left, ic, FALSE, FALSE);
6842   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6843
6844   /* move it to the result */
6845   size = AOP_SIZE (result);
6846   offset = size - 1;
6847   CLRC;
6848
6849   _startLazyDPSEvaluation ();
6850   while (size--)
6851     {
6852       l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6853       MOVA (l);
6854       emitcode ("rrc", "a");
6855       if (AOP_SIZE (result) > 1)
6856         aopPut (AOP (result), "a", offset--);
6857     }
6858   _endLazyDPSEvaluation ();
6859
6860   /* now we need to put the carry into the
6861      highest order byte of the result */
6862   if (AOP_SIZE (result) > 1)
6863     {
6864       l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
6865       MOVA (l);
6866     }
6867   emitcode ("mov", "acc.7,c");
6868   aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
6869   freeAsmop (left, NULL, ic, TRUE);
6870   freeAsmop (result, NULL, ic, TRUE);
6871 }
6872
6873 /*-----------------------------------------------------------------*/
6874 /* genRLC - generate code for rotate left with carry               */
6875 /*-----------------------------------------------------------------*/
6876 static void
6877 genRLC (iCode * ic)
6878 {
6879   operand *left, *result;
6880   int size, offset = 0;
6881   char *l;
6882
6883   D (emitcode (";", "genRLC ");
6884     );
6885
6886   /* rotate right with carry */
6887   left = IC_LEFT (ic);
6888   result = IC_RESULT (ic);
6889   aopOp (left, ic, FALSE, FALSE);
6890   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6891
6892   /* move it to the result */
6893   size = AOP_SIZE (result);
6894   offset = 0;
6895   if (size--)
6896     {
6897       l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6898       MOVA (l);
6899       emitcode ("add", "a,acc");
6900       if (AOP_SIZE (result) > 1)
6901         {
6902           aopPut (AOP (result), "a", offset++);
6903         }
6904
6905       _startLazyDPSEvaluation ();
6906       while (size--)
6907         {
6908           l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6909           MOVA (l);
6910           emitcode ("rlc", "a");
6911           if (AOP_SIZE (result) > 1)
6912             aopPut (AOP (result), "a", offset++);
6913         }
6914       _endLazyDPSEvaluation ();
6915     }
6916   /* now we need to put the carry into the
6917      highest order byte of the result */
6918   if (AOP_SIZE (result) > 1)
6919     {
6920       l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
6921       MOVA (l);
6922     }
6923   emitcode ("mov", "acc.0,c");
6924   aopPut (AOP (result), "a", 0);
6925   freeAsmop (left, NULL, ic, TRUE);
6926   freeAsmop (result, NULL, ic, TRUE);
6927 }
6928
6929 /*-----------------------------------------------------------------*/
6930 /* genGetHbit - generates code get highest order bit               */
6931 /*-----------------------------------------------------------------*/
6932 static void
6933 genGetHbit (iCode * ic)
6934 {
6935   operand *left, *result;
6936   left = IC_LEFT (ic);
6937   result = IC_RESULT (ic);
6938   aopOp (left, ic, FALSE, FALSE);
6939   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6940
6941   D (emitcode (";", "genGetHbit ");
6942     );
6943
6944   /* get the highest order byte into a */
6945   MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
6946   if (AOP_TYPE (result) == AOP_CRY)
6947     {
6948       emitcode ("rlc", "a");
6949       outBitC (result);
6950     }
6951   else
6952     {
6953       emitcode ("rl", "a");
6954       emitcode ("anl", "a,#1");
6955       outAcc (result);
6956     }
6957
6958
6959   freeAsmop (left, NULL, ic, TRUE);
6960   freeAsmop (result, NULL, ic, TRUE);
6961 }
6962
6963 /*-----------------------------------------------------------------*/
6964 /* AccRol - rotate left accumulator by known count                 */
6965 /*-----------------------------------------------------------------*/
6966 static void
6967 AccRol (int shCount)
6968 {
6969   shCount &= 0x0007;            // shCount : 0..7
6970
6971   switch (shCount)
6972     {
6973     case 0:
6974       break;
6975     case 1:
6976       emitcode ("rl", "a");
6977       break;
6978     case 2:
6979       emitcode ("rl", "a");
6980       emitcode ("rl", "a");
6981       break;
6982     case 3:
6983       emitcode ("swap", "a");
6984       emitcode ("rr", "a");
6985       break;
6986     case 4:
6987       emitcode ("swap", "a");
6988       break;
6989     case 5:
6990       emitcode ("swap", "a");
6991       emitcode ("rl", "a");
6992       break;
6993     case 6:
6994       emitcode ("rr", "a");
6995       emitcode ("rr", "a");
6996       break;
6997     case 7:
6998       emitcode ("rr", "a");
6999       break;
7000     }
7001 }
7002
7003 /*-----------------------------------------------------------------*/
7004 /* AccLsh - left shift accumulator by known count                  */
7005 /*-----------------------------------------------------------------*/
7006 static void
7007 AccLsh (int shCount)
7008 {
7009   if (shCount != 0)
7010     {
7011       if (shCount == 1)
7012         emitcode ("add", "a,acc");
7013       else if (shCount == 2)
7014         {
7015           emitcode ("add", "a,acc");
7016           emitcode ("add", "a,acc");
7017         }
7018       else
7019         {
7020           /* rotate left accumulator */
7021           AccRol (shCount);
7022           /* and kill the lower order bits */
7023           emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7024         }
7025     }
7026 }
7027
7028 /*-----------------------------------------------------------------*/
7029 /* AccRsh - right shift accumulator by known count                 */
7030 /*-----------------------------------------------------------------*/
7031 static void
7032 AccRsh (int shCount)
7033 {
7034   if (shCount != 0)
7035     {
7036       if (shCount == 1)
7037         {
7038           CLRC;
7039           emitcode ("rrc", "a");
7040         }
7041       else
7042         {
7043           /* rotate right accumulator */
7044           AccRol (8 - shCount);
7045           /* and kill the higher order bits */
7046           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7047         }
7048     }
7049 }
7050
7051 #ifdef BETTER_LITERAL_SHIFT
7052 /*-----------------------------------------------------------------*/
7053 /* AccSRsh - signed right shift accumulator by known count                 */
7054 /*-----------------------------------------------------------------*/
7055 static void
7056 AccSRsh (int shCount)
7057 {
7058   symbol *tlbl;
7059   if (shCount != 0)
7060     {
7061       if (shCount == 1)
7062         {
7063           emitcode ("mov", "c,acc.7");
7064           emitcode ("rrc", "a");
7065         }
7066       else if (shCount == 2)
7067         {
7068           emitcode ("mov", "c,acc.7");
7069           emitcode ("rrc", "a");
7070           emitcode ("mov", "c,acc.7");
7071           emitcode ("rrc", "a");
7072         }
7073       else
7074         {
7075           tlbl = newiTempLabel (NULL);
7076           /* rotate right accumulator */
7077           AccRol (8 - shCount);
7078           /* and kill the higher order bits */
7079           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7080           emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7081           emitcode ("orl", "a,#!constbyte",
7082                     (unsigned char) ~SRMask[shCount]);
7083           emitcode ("", "!tlabeldef", tlbl->key + 100);
7084         }
7085     }
7086 }
7087 #endif
7088
7089 #ifdef BETTER_LITERAL_SHIFT
7090 /*-----------------------------------------------------------------*/
7091 /* shiftR1Left2Result - shift right one byte from left to result   */
7092 /*-----------------------------------------------------------------*/
7093 static void
7094 shiftR1Left2Result (operand * left, int offl,
7095                     operand * result, int offr,
7096                     int shCount, int sign)
7097 {
7098   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7099   /* shift right accumulator */
7100   if (sign)
7101     AccSRsh (shCount);
7102   else
7103     AccRsh (shCount);
7104   aopPut (AOP (result), "a", offr);
7105 }
7106 #endif
7107
7108 #ifdef BETTER_LITERAL_SHIFT
7109 /*-----------------------------------------------------------------*/
7110 /* shiftL1Left2Result - shift left one byte from left to result    */
7111 /*-----------------------------------------------------------------*/
7112 static void
7113 shiftL1Left2Result (operand * left, int offl,
7114                     operand * result, int offr, int shCount)
7115 {
7116   MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7117   /* shift left accumulator */
7118   AccLsh (shCount);
7119   aopPut (AOP (result), "a", offr);
7120 }
7121 #endif
7122
7123 #ifdef BETTER_LITERAL_SHIFT
7124 /*-----------------------------------------------------------------*/
7125 /* movLeft2Result - move byte from left to result                  */
7126 /*-----------------------------------------------------------------*/
7127 static void
7128 movLeft2Result (operand * left, int offl,
7129                 operand * result, int offr, int sign)
7130 {
7131   char *l;
7132   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7133   {
7134       l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
7135
7136       if (*l == '@' && (IS_AOP_PREG (result)))
7137       {
7138           emitcode ("mov", "a,%s", l);
7139           aopPut (AOP (result), "a", offr);
7140       }
7141       else
7142       {
7143           if (!sign)
7144           {
7145             aopPut (AOP (result), l, offr);
7146           }
7147           else
7148             {
7149               /* MSB sign in acc.7 ! */
7150               if (getDataSize (left) == offl + 1)
7151                 {
7152                   emitcode ("mov", "a,%s", l);
7153                   aopPut (AOP (result), "a", offr);
7154                 }
7155             }
7156       }
7157   }
7158 }
7159 #endif
7160
7161 #ifdef BETTER_LITERAL_SHIFT
7162 /*-----------------------------------------------------------------*/
7163 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
7164 /*-----------------------------------------------------------------*/
7165 static void
7166 AccAXRrl1 (char *x)
7167 {
7168   emitcode ("rrc", "a");
7169   emitcode ("xch", "a,%s", x);
7170   emitcode ("rrc", "a");
7171   emitcode ("xch", "a,%s", x);
7172 }
7173 #endif
7174
7175 #ifdef BETTER_LITERAL_SHIFT
7176 //REMOVE ME!!!
7177 /*-----------------------------------------------------------------*/
7178 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
7179 /*-----------------------------------------------------------------*/
7180 static void
7181 AccAXLrl1 (char *x)
7182 {
7183   emitcode ("xch", "a,%s", x);
7184   emitcode ("rlc", "a");
7185   emitcode ("xch", "a,%s", x);
7186   emitcode ("rlc", "a");
7187 }
7188 #endif
7189
7190 #ifdef BETTER_LITERAL_SHIFT
7191 /*-----------------------------------------------------------------*/
7192 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
7193 /*-----------------------------------------------------------------*/
7194 static void
7195 AccAXLsh1 (char *x)
7196 {
7197   emitcode ("xch", "a,%s", x);
7198   emitcode ("add", "a,acc");
7199   emitcode ("xch", "a,%s", x);
7200   emitcode ("rlc", "a");
7201 }
7202 #endif
7203
7204 #ifdef BETTER_LITERAL_SHIFT
7205 /*-----------------------------------------------------------------*/
7206 /* AccAXLsh - left shift a:x by known count (0..7)                 */
7207 /*-----------------------------------------------------------------*/
7208 static void
7209 AccAXLsh (char *x, int shCount)
7210 {
7211   switch (shCount)
7212     {
7213     case 0:
7214       break;
7215     case 1:
7216       AccAXLsh1 (x);
7217       break;
7218     case 2:
7219       AccAXLsh1 (x);
7220       AccAXLsh1 (x);
7221       break;
7222     case 3:
7223     case 4:
7224     case 5:                     // AAAAABBB:CCCCCDDD
7225
7226       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
7227
7228       emitcode ("anl", "a,#!constbyte",
7229                 SLMask[shCount]);       // BBB00000:CCCCCDDD
7230
7231       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
7232
7233       AccRol (shCount);         // DDDCCCCC:BBB00000
7234
7235       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
7236
7237       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
7238
7239       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
7240
7241       emitcode ("anl", "a,#!constbyte",
7242                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
7243
7244       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
7245
7246       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
7247
7248       break;
7249     case 6:                     // AAAAAABB:CCCCCCDD
7250       emitcode ("anl", "a,#!constbyte",
7251                 SRMask[shCount]);       // 000000BB:CCCCCCDD
7252       emitcode ("mov", "c,acc.0");      // c = B
7253       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
7254 #if 0
7255       AccAXRrl1 (x);            // BCCCCCCD:D000000B
7256       AccAXRrl1 (x);            // BBCCCCCC:DD000000
7257 #else
7258       emitcode("rrc","a"); 
7259       emitcode("xch","a,%s", x); 
7260       emitcode("rrc","a"); 
7261       emitcode("mov","c,acc.0"); //<< get correct bit 
7262       emitcode("xch","a,%s", x); 
7263
7264       emitcode("rrc","a"); 
7265       emitcode("xch","a,%s", x); 
7266       emitcode("rrc","a"); 
7267       emitcode("xch","a,%s", x); 
7268 #endif
7269       break;
7270     case 7:                     // a:x <<= 7
7271
7272       emitcode ("anl", "a,#!constbyte",
7273                 SRMask[shCount]);       // 0000000B:CCCCCCCD
7274
7275       emitcode ("mov", "c,acc.0");      // c = B
7276
7277       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
7278
7279       AccAXRrl1 (x);            // BCCCCCCC:D0000000
7280
7281       break;
7282     default:
7283       break;
7284     }
7285 }
7286 #endif
7287
7288 #ifdef BETTER_LITERAL_SHIFT
7289 //REMOVE ME!!!
7290 /*-----------------------------------------------------------------*/
7291 /* AccAXRsh - right shift a:x known count (0..7)                   */
7292 /*-----------------------------------------------------------------*/
7293 static void
7294 AccAXRsh (char *x, int shCount)
7295 {
7296   switch (shCount)
7297     {
7298     case 0:
7299       break;
7300     case 1:
7301       CLRC;
7302       AccAXRrl1 (x);            // 0->a:x
7303
7304       break;
7305     case 2:
7306       CLRC;
7307       AccAXRrl1 (x);            // 0->a:x
7308
7309       CLRC;
7310       AccAXRrl1 (x);            // 0->a:x
7311
7312       break;
7313     case 3:
7314     case 4:
7315     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7316
7317       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
7318
7319       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7320
7321       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7322
7323       emitcode ("anl", "a,#!constbyte",
7324                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7325
7326       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7327
7328       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7329
7330       emitcode ("anl", "a,#!constbyte",
7331                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7332
7333       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7334
7335       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7336
7337       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
7338
7339       break;
7340     case 6:                     // AABBBBBB:CCDDDDDD
7341
7342       emitcode ("mov", "c,acc.7");
7343       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7344
7345       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7346
7347       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7348
7349       emitcode ("anl", "a,#!constbyte",
7350                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7351
7352       break;
7353     case 7:                     // ABBBBBBB:CDDDDDDD
7354
7355       emitcode ("mov", "c,acc.7");      // c = A
7356
7357       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7358
7359       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7360
7361       emitcode ("anl", "a,#!constbyte",
7362                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7363
7364       break;
7365     default:
7366       break;
7367     }
7368 }
7369 #endif
7370
7371 #ifdef BETTER_LITERAL_SHIFT
7372 /*-----------------------------------------------------------------*/
7373 /* AccAXRshS - right shift signed a:x known count (0..7)           */
7374 /*-----------------------------------------------------------------*/
7375 static void
7376 AccAXRshS (char *x, int shCount)
7377 {
7378   symbol *tlbl;
7379   switch (shCount)
7380     {
7381     case 0:
7382       break;
7383     case 1:
7384       emitcode ("mov", "c,acc.7");
7385       AccAXRrl1 (x);            // s->a:x
7386
7387       break;
7388     case 2:
7389       emitcode ("mov", "c,acc.7");
7390       AccAXRrl1 (x);            // s->a:x
7391
7392       emitcode ("mov", "c,acc.7");
7393       AccAXRrl1 (x);            // s->a:x
7394
7395       break;
7396     case 3:
7397     case 4:
7398     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7399
7400       tlbl = newiTempLabel (NULL);
7401       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
7402
7403       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7404
7405       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7406
7407       emitcode ("anl", "a,#!constbyte",
7408                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7409
7410       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7411
7412       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7413
7414       emitcode ("anl", "a,#!constbyte",
7415                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7416
7417       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7418
7419       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7420
7421       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
7422
7423       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7424       emitcode ("orl", "a,#!constbyte",
7425                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
7426
7427       emitcode ("", "!tlabeldef", tlbl->key + 100);
7428       break;                    // SSSSAAAA:BBBCCCCC
7429
7430     case 6:                     // AABBBBBB:CCDDDDDD
7431
7432       tlbl = newiTempLabel (NULL);
7433       emitcode ("mov", "c,acc.7");
7434       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7435
7436       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7437
7438       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7439
7440       emitcode ("anl", "a,#!constbyte",
7441                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7442
7443       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7444       emitcode ("orl", "a,#!constbyte",
7445                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
7446
7447       emitcode ("", "!tlabeldef", tlbl->key + 100);
7448       break;
7449     case 7:                     // ABBBBBBB:CDDDDDDD
7450
7451       tlbl = newiTempLabel (NULL);
7452       emitcode ("mov", "c,acc.7");      // c = A
7453
7454       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7455
7456       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7457
7458       emitcode ("anl", "a,#!constbyte",
7459                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7460
7461       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7462       emitcode ("orl", "a,#!constbyte",
7463                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
7464
7465       emitcode ("", "!tlabeldef", tlbl->key + 100);
7466       break;
7467     default:
7468       break;
7469     }
7470 }
7471 #endif
7472
7473 #ifdef BETTER_LITERAL_SHIFT
7474 static void
7475 _loadLeftIntoAx(char    **lsb, 
7476                 operand *left, 
7477                 operand *result,
7478                 int     offl,
7479                 int     offr)
7480 {
7481   // Get the initial value from left into a pair of registers.
7482   // MSB must be in A, LSB can be any register.
7483   //
7484   // If the result is held in registers, it is an optimization
7485   // if the LSB can be held in the register which will hold the,
7486   // result LSB since this saves us from having to copy it into
7487   // the result following AccAXLsh.
7488   //
7489   // If the result is addressed indirectly, this is not a gain.
7490   if (AOP_NEEDSACC(result))
7491   {
7492        char *leftByte;
7493        
7494        _startLazyDPSEvaluation();
7495       if (AOP_TYPE(left) == AOP_DPTR2)
7496        {
7497            // Get MSB in A.
7498            MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
7499            // get LSB in DP2_RESULT_REG.
7500            leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
7501            assert(!strcmp(leftByte, DP2_RESULT_REG));
7502        }
7503        else
7504        {
7505            // get LSB into DP2_RESULT_REG
7506            leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
7507            if (strcmp(leftByte, DP2_RESULT_REG))
7508            {
7509                TR_AP("#7");
7510                emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7511            }
7512            // And MSB in A.
7513            leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
7514            assert(strcmp(leftByte, DP2_RESULT_REG));
7515            MOVA(leftByte);
7516        }
7517        _endLazyDPSEvaluation();
7518        *lsb = DP2_RESULT_REG;
7519   }
7520   else
7521   {
7522       if (sameRegs (AOP (result), AOP (left)) &&
7523         ((offl + MSB16) == offr))
7524       {
7525           /* don't crash result[offr] */
7526           MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
7527           emitcode ("xch", "a,%s", 
7528                     aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
7529       }
7530       else
7531       {
7532           movLeft2Result (left, offl, result, offr, 0);
7533           MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
7534       }
7535       *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
7536       assert(strcmp(*lsb,"a"));      
7537   }
7538 }
7539
7540 static void
7541 _storeAxResults(char    *lsb,
7542                 operand *result,
7543                 int     offr)
7544 {
7545   _startLazyDPSEvaluation();
7546   if (AOP_NEEDSACC(result))
7547   {
7548       /* We have to explicitly update the result LSB.
7549        */
7550       emitcode("xch","a,%s", lsb);
7551       aopPut(AOP(result), "a", offr);
7552       emitcode("mov","a,%s", lsb);
7553   }
7554   if (getDataSize (result) > 1)
7555   {
7556       aopPut (AOP (result), "a", offr + MSB16);
7557   }
7558   _endLazyDPSEvaluation();
7559 }
7560
7561 /*-----------------------------------------------------------------*/
7562 /* shiftL2Left2Result - shift left two bytes from left to result   */
7563 /*-----------------------------------------------------------------*/
7564 static void
7565 shiftL2Left2Result (operand * left, int offl,
7566                     operand * result, int offr, int shCount)
7567 {
7568   char *lsb;
7569
7570   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7571   
7572   AccAXLsh (lsb, shCount);
7573   
7574   _storeAxResults(lsb, result, offr);
7575 }
7576 #endif
7577
7578 #ifdef BETTER_LITERAL_SHIFT
7579 /*-----------------------------------------------------------------*/
7580 /* shiftR2Left2Result - shift right two bytes from left to result  */
7581 /*-----------------------------------------------------------------*/
7582 static void
7583 shiftR2Left2Result (operand * left, int offl,
7584                     operand * result, int offr,
7585                     int shCount, int sign)
7586 {
7587   char *lsb;
7588   
7589   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7590   
7591   /* a:x >> shCount (x = lsb(result)) */
7592   if (sign)
7593   {
7594      AccAXRshS(lsb, shCount);
7595   }
7596   else
7597   {
7598     AccAXRsh(lsb, shCount);
7599   }
7600   
7601   _storeAxResults(lsb, result, offr);
7602 }
7603 #endif
7604
7605 #if 0
7606 //REMOVE ME!!!
7607 /*-----------------------------------------------------------------*/
7608 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7609 /*-----------------------------------------------------------------*/
7610 static void
7611 shiftLLeftOrResult (operand * left, int offl,
7612                     operand * result, int offr, int shCount)
7613 {
7614   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7615   /* shift left accumulator */
7616   AccLsh (shCount);
7617   /* or with result */
7618   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7619   /* back to result */
7620   aopPut (AOP (result), "a", offr);
7621 }
7622 #endif
7623
7624 #if 0
7625 //REMOVE ME!!!
7626 /*-----------------------------------------------------------------*/
7627 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7628 /*-----------------------------------------------------------------*/
7629 static void
7630 shiftRLeftOrResult (operand * left, int offl,
7631                     operand * result, int offr, int shCount)
7632 {
7633   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7634   /* shift right accumulator */
7635   AccRsh (shCount);
7636   /* or with result */
7637   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7638   /* back to result */
7639   aopPut (AOP (result), "a", offr);
7640 }
7641 #endif
7642
7643 #ifdef BETTER_LITERAL_SHIFT
7644 /*-----------------------------------------------------------------*/
7645 /* genlshOne - left shift a one byte quantity by known count       */
7646 /*-----------------------------------------------------------------*/
7647 static void
7648 genlshOne (operand * result, operand * left, int shCount)
7649 {
7650   D (emitcode (";", "genlshOne "););
7651   shiftL1Left2Result (left, LSB, result, LSB, shCount);
7652 }
7653 #endif
7654
7655 #ifdef BETTER_LITERAL_SHIFT
7656 /*-----------------------------------------------------------------*/
7657 /* genlshTwo - left shift two bytes by known amount != 0           */
7658 /*-----------------------------------------------------------------*/
7659 static void
7660 genlshTwo (operand * result, operand * left, int shCount)
7661 {
7662   int size;
7663
7664   D (emitcode (";", "genlshTwo "););
7665
7666   size = getDataSize (result);
7667
7668   /* if shCount >= 8 */
7669   if (shCount >= 8)
7670   {
7671       shCount -= 8;
7672
7673       _startLazyDPSEvaluation();
7674
7675       if (size > 1)
7676         {
7677           if (shCount)
7678           {
7679             _endLazyDPSEvaluation();
7680             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7681             aopPut (AOP (result), zero, LSB);       
7682           }
7683           else
7684           {
7685             movLeft2Result (left, LSB, result, MSB16, 0);
7686             aopPut (AOP (result), zero, LSB);
7687             _endLazyDPSEvaluation();
7688           }
7689         }
7690         else
7691         {
7692           aopPut (AOP (result), zero, LSB);
7693           _endLazyDPSEvaluation();
7694         }
7695   }
7696
7697   /*  1 <= shCount <= 7 */
7698   else
7699     {
7700       if (size == 1)
7701       {
7702         shiftL1Left2Result (left, LSB, result, LSB, shCount);
7703       }
7704       else
7705       {
7706         shiftL2Left2Result (left, LSB, result, LSB, shCount);
7707       }
7708     }
7709 }
7710 #endif
7711
7712 #if 0
7713 //REMOVE ME!!!
7714 /*-----------------------------------------------------------------*/
7715 /* shiftLLong - shift left one long from left to result            */
7716 /* offl = LSB or MSB16                                             */
7717 /*-----------------------------------------------------------------*/
7718 static void
7719 shiftLLong (operand * left, operand * result, int offr)
7720 {
7721   char *l;
7722   int size = AOP_SIZE (result);
7723
7724   if (size >= LSB + offr)
7725     {
7726       l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
7727       MOVA (l);
7728       emitcode ("add", "a,acc");
7729       if (sameRegs (AOP (left), AOP (result)) &&
7730           size >= MSB16 + offr && offr != LSB)
7731         emitcode ("xch", "a,%s",
7732                   aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
7733       else
7734         aopPut (AOP (result), "a", LSB + offr);
7735     }
7736
7737   if (size >= MSB16 + offr)
7738     {
7739       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7740         {
7741           l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
7742           MOVA (l);
7743         }
7744       emitcode ("rlc", "a");
7745       if (sameRegs (AOP (left), AOP (result)) &&
7746           size >= MSB24 + offr && offr != LSB)
7747         emitcode ("xch", "a,%s",
7748                   aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
7749       else
7750         aopPut (AOP (result), "a", MSB16 + offr);
7751     }
7752
7753   if (size >= MSB24 + offr)
7754     {
7755       if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7756         {
7757           l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
7758           MOVA (l);
7759         }
7760       emitcode ("rlc", "a");
7761       if (sameRegs (AOP (left), AOP (result)) &&
7762           size >= MSB32 + offr && offr != LSB)
7763         emitcode ("xch", "a,%s",
7764                   aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
7765       else
7766         aopPut (AOP (result), "a", MSB24 + offr);
7767     }
7768
7769   if (size > MSB32 + offr)
7770     {
7771       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7772         {
7773           l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
7774           MOVA (l);
7775         }
7776       emitcode ("rlc", "a");
7777       aopPut (AOP (result), "a", MSB32 + offr);
7778     }
7779   if (offr != LSB)
7780     aopPut (AOP (result), zero, LSB);
7781 }
7782 #endif
7783
7784 #if 0
7785 //REMOVE ME!!!
7786 /*-----------------------------------------------------------------*/
7787 /* genlshFour - shift four byte by a known amount != 0             */
7788 /*-----------------------------------------------------------------*/
7789 static void
7790 genlshFour (operand * result, operand * left, int shCount)
7791 {
7792   int size;
7793
7794   D (emitcode (";", "genlshFour ");
7795     );
7796
7797   size = AOP_SIZE (result);
7798
7799   /* if shifting more that 3 bytes */
7800   if (shCount >= 24)
7801     {
7802       shCount -= 24;
7803       if (shCount)
7804         /* lowest order of left goes to the highest
7805            order of the destination */
7806         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7807       else
7808         movLeft2Result (left, LSB, result, MSB32, 0);
7809       aopPut (AOP (result), zero, LSB);
7810       aopPut (AOP (result), zero, MSB16);
7811       aopPut (AOP (result), zero, MSB24);
7812       return;
7813     }
7814
7815   /* more than two bytes */
7816   else if (shCount >= 16)
7817     {
7818       /* lower order two bytes goes to higher order two bytes */
7819       shCount -= 16;
7820       /* if some more remaining */
7821       if (shCount)
7822         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7823       else
7824         {
7825           movLeft2Result (left, MSB16, result, MSB32, 0);
7826           movLeft2Result (left, LSB, result, MSB24, 0);
7827         }
7828       aopPut (AOP (result), zero, MSB16);
7829       aopPut (AOP (result), zero, LSB);
7830       return;
7831     }
7832
7833   /* if more than 1 byte */
7834   else if (shCount >= 8)
7835     {
7836       /* lower order three bytes goes to higher order  three bytes */
7837       shCount -= 8;
7838       if (size == 2)
7839         {
7840           if (shCount)
7841             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7842           else
7843             movLeft2Result (left, LSB, result, MSB16, 0);
7844         }
7845       else
7846         {                       /* size = 4 */
7847           if (shCount == 0)
7848             {
7849               movLeft2Result (left, MSB24, result, MSB32, 0);
7850               movLeft2Result (left, MSB16, result, MSB24, 0);
7851               movLeft2Result (left, LSB, result, MSB16, 0);
7852               aopPut (AOP (result), zero, LSB);
7853             }
7854           else if (shCount == 1)
7855             shiftLLong (left, result, MSB16);
7856           else
7857             {
7858               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7859               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7860               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7861               aopPut (AOP (result), zero, LSB);
7862             }
7863         }
7864     }
7865
7866   /* 1 <= shCount <= 7 */
7867   else if (shCount <= 2)
7868     {
7869       shiftLLong (left, result, LSB);
7870       if (shCount == 2)
7871         shiftLLong (result, result, LSB);
7872     }
7873   /* 3 <= shCount <= 7, optimize */
7874   else
7875     {
7876       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7877       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7878       shiftL2Left2Result (left, LSB, result, LSB, shCount);
7879     }
7880 }
7881 #endif
7882
7883 #ifdef BETTER_LITERAL_SHIFT
7884 /*-----------------------------------------------------------------*/
7885 /* genLeftShiftLiteral - left shifting by known count              */
7886 /*-----------------------------------------------------------------*/
7887 static bool
7888 genLeftShiftLiteral (operand * left,
7889                      operand * right,
7890                      operand * result,
7891                      iCode * ic)
7892 {
7893   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7894   int size;
7895
7896   size = getSize (operandType (result));
7897
7898   D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
7899
7900   /* We only handle certain easy cases so far. */
7901   if ((shCount != 0)
7902    && (shCount < (size * 8))
7903    && (size != 1)
7904    && (size != 2))
7905   {
7906       D(emitcode (";", "genLeftShiftLiteral wimping out"););    
7907       return FALSE;
7908   }
7909
7910   freeAsmop (right, NULL, ic, TRUE);
7911
7912   aopOp(left, ic, FALSE, FALSE);
7913   aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
7914
7915 #if 0 // debug spew
7916   if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
7917   {
7918         emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
7919         if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
7920         {
7921            emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
7922         }
7923   }
7924   if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
7925   {
7926         emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
7927         if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
7928         {
7929            emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
7930         }       
7931   }  
7932 #endif
7933   
7934 #if VIEW_SIZE
7935   emitcode ("; shift left ", "result %d, left %d", size,
7936             AOP_SIZE (left));
7937 #endif
7938
7939   /* I suppose that the left size >= result size */
7940   if (shCount == 0)
7941   {
7942         _startLazyDPSEvaluation();
7943         while (size--)
7944         {
7945           movLeft2Result (left, size, result, size, 0);
7946         }
7947         _endLazyDPSEvaluation();
7948   }
7949   else if (shCount >= (size * 8))
7950   {
7951     _startLazyDPSEvaluation();
7952     while (size--)
7953     {
7954       aopPut (AOP (result), zero, size);
7955     }
7956     _endLazyDPSEvaluation();
7957   }
7958   else
7959   {
7960       switch (size)
7961         {
7962         case 1:
7963           genlshOne (result, left, shCount);
7964           break;
7965
7966         case 2:
7967           genlshTwo (result, left, shCount);
7968           break;
7969 #if 0
7970         case 4:
7971           genlshFour (result, left, shCount);
7972           break;
7973 #endif
7974         default:
7975           fprintf(stderr, "*** ack! mystery literal shift!\n");   
7976           break;
7977         }
7978     }
7979   freeAsmop (left, NULL, ic, TRUE);
7980   freeAsmop (result, NULL, ic, TRUE);
7981   return TRUE;
7982 }
7983 #endif
7984
7985 /*-----------------------------------------------------------------*/
7986 /* genLeftShift - generates code for left shifting                 */
7987 /*-----------------------------------------------------------------*/
7988 static void
7989 genLeftShift (iCode * ic)
7990 {
7991   operand *left, *right, *result;
7992   int size, offset;
7993   char *l;
7994   symbol *tlbl, *tlbl1;
7995
7996   D (emitcode (";", "genLeftShift "););
7997
7998   right = IC_RIGHT (ic);
7999   left = IC_LEFT (ic);
8000   result = IC_RESULT (ic);
8001
8002   aopOp (right, ic, FALSE, FALSE);
8003
8004
8005 #ifdef BETTER_LITERAL_SHIFT
8006   /* if the shift count is known then do it
8007      as efficiently as possible */
8008   if (AOP_TYPE (right) == AOP_LIT)
8009     {
8010       if (genLeftShiftLiteral (left, right, result, ic))
8011       {
8012         return;
8013       }
8014     }
8015 #endif
8016
8017   /* shift count is unknown then we have to form
8018      a loop get the loop count in B : Note: we take
8019      only the lower order byte since shifting
8020      more that 32 bits make no sense anyway, ( the
8021      largest size of an object can be only 32 bits ) */
8022
8023   if (AOP_TYPE (right) == AOP_LIT)
8024   {
8025       /* Really should be handled by genLeftShiftLiteral,
8026        * but since I'm too lazy to fix that today, at least we can make
8027        * some small improvement.
8028        */
8029        emitcode("mov", "b,#!constbyte",
8030                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8031   }
8032   else
8033   {
8034         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8035         emitcode ("inc", "b");
8036   }
8037   freeAsmop (right, NULL, ic, TRUE);
8038   aopOp (left, ic, FALSE, FALSE);
8039   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8040
8041   /* now move the left to the result if they are not the
8042      same */
8043   if (!sameRegs (AOP (left), AOP (result)) &&
8044       AOP_SIZE (result) > 1)
8045     {
8046
8047       size = AOP_SIZE (result);
8048       offset = 0;
8049       _startLazyDPSEvaluation ();
8050       while (size--)
8051         {
8052           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8053           if (*l == '@' && (IS_AOP_PREG (result)))
8054             {
8055
8056               emitcode ("mov", "a,%s", l);
8057               aopPut (AOP (result), "a", offset);
8058             }
8059           else
8060             aopPut (AOP (result), l, offset);
8061           offset++;
8062         }
8063       _endLazyDPSEvaluation ();
8064     }
8065
8066   tlbl = newiTempLabel (NULL);
8067   size = AOP_SIZE (result);
8068   offset = 0;
8069   tlbl1 = newiTempLabel (NULL);
8070
8071   /* if it is only one byte then */
8072   if (size == 1)
8073     {
8074       symbol *tlbl1 = newiTempLabel (NULL);
8075
8076       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8077       MOVA (l);
8078       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8079       emitcode ("", "!tlabeldef", tlbl->key + 100);
8080       emitcode ("add", "a,acc");
8081       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8082       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8083       aopPut (AOP (result), "a", 0);
8084       goto release;
8085     }
8086
8087   reAdjustPreg (AOP (result));
8088
8089   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8090   emitcode ("", "!tlabeldef", tlbl->key + 100);
8091   l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8092   MOVA (l);
8093   emitcode ("add", "a,acc");
8094   aopPut (AOP (result), "a", offset++);
8095   _startLazyDPSEvaluation ();
8096   while (--size)
8097     {
8098       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8099       MOVA (l);
8100       emitcode ("rlc", "a");
8101       aopPut (AOP (result), "a", offset++);
8102     }
8103   _endLazyDPSEvaluation ();
8104   reAdjustPreg (AOP (result));
8105
8106   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8107   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8108 release:
8109   freeAsmop (left, NULL, ic, TRUE);
8110   freeAsmop (result, NULL, ic, TRUE);
8111 }
8112
8113 #ifdef BETTER_LITERAL_SHIFT
8114 /*-----------------------------------------------------------------*/
8115 /* genrshOne - right shift a one byte quantity by known count      */
8116 /*-----------------------------------------------------------------*/
8117 static void
8118 genrshOne (operand * result, operand * left,
8119            int shCount, int sign)
8120 {
8121   D (emitcode (";", "genrshOne"););
8122   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8123 }
8124 #endif
8125
8126 #ifdef BETTER_LITERAL_SHIFT
8127 /*-----------------------------------------------------------------*/
8128 /* genrshTwo - right shift two bytes by known amount != 0          */
8129 /*-----------------------------------------------------------------*/
8130 static void
8131 genrshTwo (operand * result, operand * left,
8132            int shCount, int sign)
8133 {
8134   D (emitcode (";", "genrshTwo"););
8135
8136   /* if shCount >= 8 */
8137   if (shCount >= 8)
8138     {
8139       shCount -= 8;
8140       _startLazyDPSEvaluation();
8141       if (shCount)
8142       {
8143         shiftR1Left2Result (left, MSB16, result, LSB,
8144                             shCount, sign);
8145       }                     
8146       else
8147       {
8148         movLeft2Result (left, MSB16, result, LSB, sign);
8149       }
8150       addSign (result, MSB16, sign);
8151       _endLazyDPSEvaluation();
8152     }
8153
8154   /*  1 <= shCount <= 7 */
8155   else
8156   {
8157     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8158   }
8159 }
8160 #endif
8161
8162 #if 0
8163 //REMOVE ME!!!
8164 /*-----------------------------------------------------------------*/
8165 /* shiftRLong - shift right one long from left to result           */
8166 /* offl = LSB or MSB16                                             */
8167 /*-----------------------------------------------------------------*/
8168 static void
8169 shiftRLong (operand * left, int offl,
8170             operand * result, int sign)
8171 {
8172   int isSameRegs=sameRegs(AOP(left),AOP(result));
8173
8174   if (isSameRegs && offl>1) {
8175     // we are in big trouble, but this shouldn't happen
8176     werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8177   }
8178
8179   MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
8180   
8181   if (offl==MSB16) {
8182     // shift is > 8
8183     if (sign) {
8184       emitcode ("rlc", "a");
8185       emitcode ("subb", "a,acc");
8186       emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
8187     } else {
8188       aopPut (AOP(result), zero, MSB32);
8189     }
8190   }
8191
8192   if (!sign) {
8193     emitcode ("clr", "c");
8194   } else {
8195     emitcode ("mov", "c,acc.7");
8196   }
8197
8198   emitcode ("rrc", "a");
8199
8200   if (isSameRegs && offl==MSB16) {
8201     emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
8202   } else {
8203     aopPut (AOP (result), "a", MSB32);
8204     MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
8205   }
8206
8207   emitcode ("rrc", "a");
8208   if (isSameRegs && offl==1) {
8209     emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
8210   } else {
8211     aopPut (AOP (result), "a", MSB24);
8212     MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
8213   }
8214   emitcode ("rrc", "a");
8215   aopPut (AOP (result), "a", MSB16 - offl);
8216
8217   if (offl == LSB)
8218     {
8219       MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
8220       emitcode ("rrc", "a");
8221       aopPut (AOP (result), "a", LSB);
8222     }
8223 }
8224 #endif
8225
8226 #if 0
8227 //REMOVE ME!!!
8228 /*-----------------------------------------------------------------*/
8229 /* genrshFour - shift four byte by a known amount != 0             */
8230 /*-----------------------------------------------------------------*/
8231 static void
8232 genrshFour (operand * result, operand * left,
8233             int shCount, int sign)
8234 {
8235   D (emitcode (";", "genrshFour");
8236     );
8237
8238   /* if shifting more that 3 bytes */
8239   if (shCount >= 24)
8240     {
8241       shCount -= 24;
8242       if (shCount)
8243         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8244       else
8245         movLeft2Result (left, MSB32, result, LSB, sign);
8246       addSign (result, MSB16, sign);
8247     }
8248   else if (shCount >= 16)
8249     {
8250       shCount -= 16;
8251       if (shCount)
8252         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8253       else
8254         {
8255           movLeft2Result (left, MSB24, result, LSB, 0);
8256           movLeft2Result (left, MSB32, result, MSB16, sign);
8257         }
8258       addSign (result, MSB24, sign);
8259     }
8260   else if (shCount >= 8)
8261     {
8262       shCount -= 8;
8263       if (shCount == 1)
8264         shiftRLong (left, MSB16, result, sign);
8265       else if (shCount == 0)
8266         {
8267           movLeft2Result (left, MSB16, result, LSB, 0);
8268           movLeft2Result (left, MSB24, result, MSB16, 0);
8269           movLeft2Result (left, MSB32, result, MSB24, sign);
8270           addSign (result, MSB32, sign);
8271         }
8272       else
8273         {
8274           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8275           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8276           /* the last shift is signed */
8277           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8278           addSign (result, MSB32, sign);
8279         }
8280     }
8281   else
8282     {                           /* 1 <= shCount <= 7 */
8283       if (shCount <= 2)
8284         {
8285           shiftRLong (left, LSB, result, sign);
8286           if (shCount == 2)
8287             shiftRLong (result, LSB, result, sign);
8288         }
8289       else
8290         {
8291           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8292           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8293           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8294         }
8295     }
8296 }
8297 #endif
8298
8299 #ifdef BETTER_LITERAL_SHIFT
8300 /*-----------------------------------------------------------------*/
8301 /* genRightShiftLiteral - right shifting by known count            */
8302 /*-----------------------------------------------------------------*/
8303 static bool
8304 genRightShiftLiteral (operand * left,
8305                       operand * right,
8306                       operand * result,
8307                       iCode * ic,
8308                       int sign)
8309 {
8310   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8311   int size;
8312
8313   size = getSize (operandType (result));
8314
8315   D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8316
8317   /* We only handle certain easy cases so far. */
8318   if ((shCount != 0)
8319    && (shCount < (size * 8))
8320    && (size != 1)
8321    && (size != 2))
8322   {
8323       D(emitcode (";", "genRightShiftLiteral wimping out"););   
8324       return FALSE;
8325   }
8326
8327   freeAsmop (right, NULL, ic, TRUE);
8328
8329   aopOp (left, ic, FALSE, FALSE);
8330   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8331
8332 #if VIEW_SIZE
8333   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8334             AOP_SIZE (left));
8335 #endif
8336
8337   /* test the LEFT size !!! */
8338
8339   /* I suppose that the left size >= result size */
8340   if (shCount == 0)
8341   {
8342       size = getDataSize (result);
8343       _startLazyDPSEvaluation();
8344       while (size--)
8345       {
8346         movLeft2Result (left, size, result, size, 0);
8347       }
8348       _endLazyDPSEvaluation();
8349   }
8350   else if (shCount >= (size * 8))
8351     {
8352       if (sign)
8353       {
8354         /* get sign in acc.7 */
8355         MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
8356       }
8357       addSign (result, LSB, sign);
8358     }
8359   else
8360     {
8361       switch (size)
8362         {
8363         case 1:
8364           genrshOne (result, left, shCount, sign);
8365           break;
8366
8367         case 2:
8368           genrshTwo (result, left, shCount, sign);
8369           break;
8370 #if 0
8371         case 4:
8372           genrshFour (result, left, shCount, sign);
8373           break;
8374 #endif    
8375         default:
8376           break;
8377         }
8378
8379       freeAsmop (left, NULL, ic, TRUE);
8380       freeAsmop (result, NULL, ic, TRUE);
8381     }
8382     return TRUE;
8383 }
8384 #endif
8385
8386 /*-----------------------------------------------------------------*/
8387 /* genSignedRightShift - right shift of signed number              */
8388 /*-----------------------------------------------------------------*/
8389 static void
8390 genSignedRightShift (iCode * ic)
8391 {
8392   operand *right, *left, *result;
8393   int size, offset;
8394   char *l;
8395   symbol *tlbl, *tlbl1;
8396
8397   D (emitcode (";", "genSignedRightShift "););
8398
8399   /* we do it the hard way put the shift count in b
8400      and loop thru preserving the sign */
8401
8402   right = IC_RIGHT (ic);
8403   left = IC_LEFT (ic);
8404   result = IC_RESULT (ic);
8405
8406   aopOp (right, ic, FALSE, FALSE);
8407
8408 #ifdef BETTER_LITERAL_SHIFT
8409   if (AOP_TYPE (right) == AOP_LIT)
8410     {
8411       if (genRightShiftLiteral (left, right, result, ic, 1))
8412       {
8413         return;
8414       }
8415     }
8416 #endif
8417   /* shift count is unknown then we have to form
8418      a loop get the loop count in B : Note: we take
8419      only the lower order byte since shifting
8420      more that 32 bits make no sense anyway, ( the
8421      largest size of an object can be only 32 bits ) */
8422
8423   if (AOP_TYPE (right) == AOP_LIT)
8424   {
8425       /* Really should be handled by genRightShiftLiteral,
8426        * but since I'm too lazy to fix that today, at least we can make
8427        * some small improvement.
8428        */
8429        emitcode("mov", "b,#!constbyte",
8430                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8431   }
8432   else
8433   {
8434         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8435         emitcode ("inc", "b");
8436   }
8437   freeAsmop (right, NULL, ic, TRUE);
8438   aopOp (left, ic, FALSE, FALSE);
8439   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8440
8441   /* now move the left to the result if they are not the
8442      same */
8443   if (!sameRegs (AOP (left), AOP (result)) &&
8444       AOP_SIZE (result) > 1)
8445     {
8446
8447       size = AOP_SIZE (result);
8448       offset = 0;
8449       _startLazyDPSEvaluation ();
8450       while (size--)
8451         {
8452           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8453           if (*l == '@' && IS_AOP_PREG (result))
8454             {
8455
8456               emitcode ("mov", "a,%s", l);
8457               aopPut (AOP (result), "a", offset);
8458             }
8459           else
8460             aopPut (AOP (result), l, offset);
8461           offset++;
8462         }
8463       _endLazyDPSEvaluation ();
8464     }
8465
8466   /* mov the highest order bit to OVR */
8467   tlbl = newiTempLabel (NULL);
8468   tlbl1 = newiTempLabel (NULL);
8469
8470   size = AOP_SIZE (result);
8471   offset = size - 1;
8472   emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
8473   emitcode ("rlc", "a");
8474   emitcode ("mov", "ov,c");
8475   /* if it is only one byte then */
8476   if (size == 1)
8477     {
8478       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8479       MOVA (l);
8480       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8481       emitcode ("", "!tlabeldef", tlbl->key + 100);
8482       emitcode ("mov", "c,ov");
8483       emitcode ("rrc", "a");
8484       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8485       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8486       aopPut (AOP (result), "a", 0);
8487       goto release;
8488     }
8489
8490   reAdjustPreg (AOP (result));
8491   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8492   emitcode ("", "!tlabeldef", tlbl->key + 100);
8493   emitcode ("mov", "c,ov");
8494   _startLazyDPSEvaluation ();
8495   while (size--)
8496     {
8497       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8498       MOVA (l);
8499       emitcode ("rrc", "a");
8500       aopPut (AOP (result), "a", offset--);
8501     }
8502   _endLazyDPSEvaluation ();
8503   reAdjustPreg (AOP (result));
8504   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8505   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8506
8507 release:
8508   freeAsmop (left, NULL, ic, TRUE);
8509   freeAsmop (result, NULL, ic, TRUE);
8510 }
8511
8512 /*-----------------------------------------------------------------*/
8513 /* genRightShift - generate code for right shifting                */
8514 /*-----------------------------------------------------------------*/
8515 static void
8516 genRightShift (iCode * ic)
8517 {
8518   operand *right, *left, *result;
8519   sym_link *retype;
8520   int size, offset;
8521   char *l;
8522   symbol *tlbl, *tlbl1;
8523
8524   D (emitcode (";", "genRightShift "););
8525
8526   /* if signed then we do it the hard way preserve the
8527      sign bit moving it inwards */
8528   retype = getSpec (operandType (IC_RESULT (ic)));
8529
8530   if (!SPEC_USIGN (retype))
8531     {
8532       genSignedRightShift (ic);
8533       return;
8534     }
8535
8536   /* signed & unsigned types are treated the same : i.e. the
8537      signed is NOT propagated inwards : quoting from the
8538      ANSI - standard : "for E1 >> E2, is equivalent to division
8539      by 2**E2 if unsigned or if it has a non-negative value,
8540      otherwise the result is implementation defined ", MY definition
8541      is that the sign does not get propagated */
8542
8543   right = IC_RIGHT (ic);
8544   left = IC_LEFT (ic);
8545   result = IC_RESULT (ic);
8546
8547   aopOp (right, ic, FALSE, FALSE);
8548
8549 #ifdef BETTER_LITERAL_SHIFT
8550   /* if the shift count is known then do it
8551      as efficiently as possible */
8552   if (AOP_TYPE (right) == AOP_LIT)
8553     {
8554       if (genRightShiftLiteral (left, right, result, ic, 0))
8555       {
8556         return;
8557       }
8558     }
8559 #endif
8560
8561   /* shift count is unknown then we have to form
8562      a loop get the loop count in B : Note: we take
8563      only the lower order byte since shifting
8564      more that 32 bits make no sense anyway, ( the
8565      largest size of an object can be only 32 bits ) */
8566   
8567   if (AOP_TYPE (right) == AOP_LIT)
8568   {
8569       /* Really should be handled by genRightShiftLiteral,
8570        * but since I'm too lazy to fix that today, at least we can make
8571        * some small improvement.
8572        */
8573        emitcode("mov", "b,#!constbyte",
8574                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8575   }
8576   else
8577   {
8578         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8579         emitcode ("inc", "b");
8580   }
8581   freeAsmop (right, NULL, ic, TRUE);
8582   aopOp (left, ic, FALSE, FALSE);
8583   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8584
8585   /* now move the left to the result if they are not the
8586      same */
8587   if (!sameRegs (AOP (left), AOP (result)) &&
8588       AOP_SIZE (result) > 1)
8589     {
8590
8591       size = AOP_SIZE (result);
8592       offset = 0;
8593       _startLazyDPSEvaluation ();
8594       while (size--)
8595         {
8596           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8597           if (*l == '@' && IS_AOP_PREG (result))
8598             {
8599
8600               emitcode ("mov", "a,%s", l);
8601               aopPut (AOP (result), "a", offset);
8602             }
8603           else
8604             aopPut (AOP (result), l, offset);
8605           offset++;
8606         }
8607       _endLazyDPSEvaluation ();
8608     }
8609
8610   tlbl = newiTempLabel (NULL);
8611   tlbl1 = newiTempLabel (NULL);
8612   size = AOP_SIZE (result);
8613   offset = size - 1;
8614
8615   /* if it is only one byte then */
8616   if (size == 1)
8617     {
8618       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8619       MOVA (l);
8620       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8621       emitcode ("", "!tlabeldef", tlbl->key + 100);
8622       CLRC;
8623       emitcode ("rrc", "a");
8624       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8625       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8626       aopPut (AOP (result), "a", 0);
8627       goto release;
8628     }
8629
8630   reAdjustPreg (AOP (result));
8631   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8632   emitcode ("", "!tlabeldef", tlbl->key + 100);
8633   CLRC;
8634   _startLazyDPSEvaluation ();
8635   while (size--)
8636     {
8637       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8638       MOVA (l);
8639       emitcode ("rrc", "a");
8640       aopPut (AOP (result), "a", offset--);
8641     }
8642   _endLazyDPSEvaluation ();
8643   reAdjustPreg (AOP (result));
8644
8645   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8646   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8647
8648 release:
8649   freeAsmop (left, NULL, ic, TRUE);
8650   freeAsmop (result, NULL, ic, TRUE);
8651 }
8652
8653 /*-----------------------------------------------------------------*/
8654 /* genUnpackBits - generates code for unpacking bits               */
8655 /*-----------------------------------------------------------------*/
8656 static void
8657 genUnpackBits (operand * result, char *rname, int ptype)
8658 {
8659   int shCnt;
8660   int rlen = 0;
8661   sym_link *etype;
8662   int offset = 0;
8663
8664   D (emitcode (";", "genUnpackBits ");
8665     );
8666
8667   etype = getSpec (operandType (result));
8668
8669   /* read the first byte  */
8670   switch (ptype)
8671     {
8672
8673     case POINTER:
8674     case IPOINTER:
8675       emitcode ("mov", "a,@%s", rname);
8676       break;
8677
8678     case PPOINTER:
8679       emitcode ("movx", "a,@%s", rname);
8680       break;
8681
8682     case FPOINTER:
8683       emitcode ("movx", "a,@dptr");
8684       break;
8685
8686     case CPOINTER:
8687       emitcode ("clr", "a");
8688       emitcode ("movc", "a,@a+dptr");
8689       break;
8690
8691     case GPOINTER:
8692       emitcode ("lcall", "__gptrget");
8693       break;
8694     }
8695
8696   /* if we have bitdisplacement then it fits   */
8697   /* into this byte completely or if length is */
8698   /* less than a byte                          */
8699   if ((shCnt = SPEC_BSTR (etype)) ||
8700       (SPEC_BLEN (etype) <= 8))
8701     {
8702
8703       /* shift right acc */
8704       AccRsh (shCnt);
8705
8706       emitcode ("anl", "a,#!constbyte",
8707                 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
8708       aopPut (AOP (result), "a", offset);
8709       return;
8710     }
8711
8712   /* bit field did not fit in a byte  */
8713   rlen = SPEC_BLEN (etype) - 8;
8714   aopPut (AOP (result), "a", offset++);
8715
8716   while (1)
8717     {
8718
8719       switch (ptype)
8720         {
8721         case POINTER:
8722         case IPOINTER:
8723           emitcode ("inc", "%s", rname);
8724           emitcode ("mov", "a,@%s", rname);
8725           break;
8726
8727         case PPOINTER:
8728           emitcode ("inc", "%s", rname);
8729           emitcode ("movx", "a,@%s", rname);
8730           break;
8731
8732         case FPOINTER:
8733           emitcode ("inc", "dptr");
8734           emitcode ("movx", "a,@dptr");
8735           break;
8736
8737         case CPOINTER:
8738           emitcode ("clr", "a");
8739           emitcode ("inc", "dptr");
8740           emitcode ("movc", "a,@a+dptr");
8741           break;
8742
8743         case GPOINTER:
8744           emitcode ("inc", "dptr");
8745           emitcode ("lcall", "__gptrget");
8746           break;
8747         }
8748
8749       rlen -= 8;
8750       /* if we are done */
8751       if (rlen < 8)
8752         break;
8753
8754       aopPut (AOP (result), "a", offset++);
8755
8756     }
8757
8758   if (rlen)
8759     {
8760       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (rlen));
8761       aopPut (AOP (result), "a", offset);
8762     }
8763
8764   return;
8765 }
8766
8767
8768 /*-----------------------------------------------------------------*/
8769 /* genDataPointerGet - generates code when ptr offset is known     */
8770 /*-----------------------------------------------------------------*/
8771 static void
8772 genDataPointerGet (operand * left,
8773                    operand * result,
8774                    iCode * ic)
8775 {
8776   char *l;
8777   char buffer[256];
8778   int size, offset = 0;
8779   aopOp (result, ic, TRUE, FALSE);
8780
8781   /* get the string representation of the name */
8782   l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
8783   size = AOP_SIZE (result);
8784   _startLazyDPSEvaluation ();
8785   while (size--)
8786     {
8787       if (offset)
8788         sprintf (buffer, "(%s + %d)", l + 1, offset);
8789       else
8790         sprintf (buffer, "%s", l + 1);
8791       aopPut (AOP (result), buffer, offset++);
8792     }
8793   _endLazyDPSEvaluation ();
8794
8795   freeAsmop (left, NULL, ic, TRUE);
8796   freeAsmop (result, NULL, ic, TRUE);
8797 }
8798
8799 /*-----------------------------------------------------------------*/
8800 /* genNearPointerGet - emitcode for near pointer fetch             */
8801 /*-----------------------------------------------------------------*/
8802 static void
8803 genNearPointerGet (operand * left,
8804                    operand * result,
8805                    iCode * ic,
8806                    iCode *pi)
8807 {
8808   asmop *aop = NULL;
8809   regs *preg = NULL;
8810   char *rname;
8811   sym_link *rtype, *retype, *letype;
8812   sym_link *ltype = operandType (left);
8813   char buffer[80];
8814
8815   rtype = operandType (result);
8816   retype = getSpec (rtype);
8817   letype = getSpec (ltype);
8818
8819   aopOp (left, ic, FALSE, FALSE);
8820
8821   /* if left is rematerialisable and
8822      result is not bit variable type and
8823      the left is pointer to data space i.e
8824      lower 128 bytes of space */
8825   if (AOP_TYPE (left) == AOP_IMMD &&
8826       !IS_BITVAR (retype) &&
8827       !IS_BITVAR (letype) &&
8828       DCL_TYPE (ltype) == POINTER)
8829     {
8830       genDataPointerGet (left, result, ic);
8831       return;
8832     }
8833
8834   /* if the value is already in a pointer register
8835      then don't need anything more */
8836   if (!AOP_INPREG (AOP (left)))
8837     {
8838       /* otherwise get a free pointer register */
8839       aop = newAsmop (0);
8840       preg = getFreePtr (ic, &aop, FALSE);
8841       emitcode ("mov", "%s,%s",
8842                 preg->name,
8843                 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8844       rname = preg->name;
8845     }
8846   else
8847     rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8848
8849   freeAsmop (left, NULL, ic, TRUE);
8850   aopOp (result, ic, FALSE, FALSE);
8851
8852   /* if bitfield then unpack the bits */
8853   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8854     genUnpackBits (result, rname, POINTER);
8855   else
8856     {
8857       /* we have can just get the values */
8858       int size = AOP_SIZE (result);
8859       int offset = 0;
8860
8861       while (size--)
8862         {
8863           if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8864             {
8865
8866               emitcode ("mov", "a,@%s", rname);
8867               aopPut (AOP (result), "a", offset);
8868             }
8869           else
8870             {
8871               sprintf (buffer, "@%s", rname);
8872               aopPut (AOP (result), buffer, offset);
8873             }
8874           offset++;
8875           if (size || pi)
8876             emitcode ("inc", "%s", rname);
8877         }
8878     }
8879
8880   /* now some housekeeping stuff */
8881   if (aop)
8882     {
8883       /* we had to allocate for this iCode */
8884       if (pi) { /* post increment present */
8885         aopPut(AOP ( left ),rname,0);
8886       }
8887       freeAsmop (NULL, aop, ic, TRUE);
8888     }
8889   else
8890     {
8891       /* we did not allocate which means left
8892          already in a pointer register, then
8893          if size > 0 && this could be used again
8894          we have to point it back to where it
8895          belongs */
8896       if (AOP_SIZE (result) > 1 &&
8897           !OP_SYMBOL (left)->remat &&
8898           (OP_SYMBOL (left)->liveTo > ic->seq ||
8899            ic->depth) &&
8900           !pi)
8901         {
8902           int size = AOP_SIZE (result) - 1;
8903           while (size--)
8904             emitcode ("dec", "%s", rname);
8905         }
8906     }
8907
8908   /* done */
8909   freeAsmop (result, NULL, ic, TRUE);
8910   if (pi) pi->generated = 1;
8911 }
8912
8913 /*-----------------------------------------------------------------*/
8914 /* genPagedPointerGet - emitcode for paged pointer fetch           */
8915 /*-----------------------------------------------------------------*/
8916 static void
8917 genPagedPointerGet (operand * left,
8918                     operand * result,
8919                     iCode * ic,
8920                     iCode * pi)
8921 {
8922   asmop *aop = NULL;
8923   regs *preg = NULL;
8924   char *rname;
8925   sym_link *rtype, *retype, *letype;
8926
8927   rtype = operandType (result);
8928   retype = getSpec (rtype);
8929   letype = getSpec (operandType (left));
8930   aopOp (left, ic, FALSE, FALSE);
8931
8932   /* if the value is already in a pointer register
8933      then don't need anything more */
8934   if (!AOP_INPREG (AOP (left)))
8935     {
8936       /* otherwise get a free pointer register */
8937       aop = newAsmop (0);
8938       preg = getFreePtr (ic, &aop, FALSE);
8939       emitcode ("mov", "%s,%s",
8940                 preg->name,
8941                 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8942       rname = preg->name;
8943     }
8944   else
8945     rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8946
8947   freeAsmop (left, NULL, ic, TRUE);
8948   aopOp (result, ic, FALSE, FALSE);
8949
8950   /* if bitfield then unpack the bits */
8951   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8952     genUnpackBits (result, rname, PPOINTER);
8953   else
8954     {
8955       /* we have can just get the values */
8956       int size = AOP_SIZE (result);
8957       int offset = 0;
8958
8959       while (size--)
8960         {
8961
8962           emitcode ("movx", "a,@%s", rname);
8963           aopPut (AOP (result), "a", offset);
8964
8965           offset++;
8966
8967           if (size || pi)
8968             emitcode ("inc", "%s", rname);
8969         }
8970     }
8971
8972   /* now some housekeeping stuff */
8973   if (aop)
8974     {
8975       /* we had to allocate for this iCode */
8976       if (pi) aopPut ( AOP (left), rname, 0);
8977       freeAsmop (NULL, aop, ic, TRUE);
8978     }
8979   else
8980     {
8981       /* we did not allocate which means left
8982          already in a pointer register, then
8983          if size > 0 && this could be used again
8984          we have to point it back to where it
8985          belongs */
8986       if (AOP_SIZE (result) > 1 &&
8987           !OP_SYMBOL (left)->remat &&
8988           (OP_SYMBOL (left)->liveTo > ic->seq ||
8989            ic->depth) &&
8990           !pi)
8991         {
8992           int size = AOP_SIZE (result) - 1;
8993           while (size--)
8994             emitcode ("dec", "%s", rname);
8995         }
8996     }
8997
8998   /* done */
8999   freeAsmop (result, NULL, ic, TRUE);
9000   if (pi) pi->generated = 1;
9001 }
9002
9003 /*-----------------------------------------------------------------*/
9004 /* genFarPointerGet - gget value from far space                    */
9005 /*-----------------------------------------------------------------*/
9006 static void
9007 genFarPointerGet (operand * left,
9008                   operand * result, iCode * ic, iCode *pi)
9009 {
9010     int size, offset, dopi=1;
9011   sym_link *retype = getSpec (operandType (result));
9012   sym_link *letype = getSpec (operandType (left));
9013   D (emitcode (";", "genFarPointerGet");
9014     );
9015
9016   aopOp (left, ic, FALSE, FALSE);
9017
9018   /* if the operand is already in dptr
9019      then we do nothing else we move the value to dptr */
9020   if (AOP_TYPE (left) != AOP_STR)
9021     {
9022       /* if this is remateriazable */
9023       if (AOP_TYPE (left) == AOP_IMMD)
9024         {
9025           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9026         }
9027       else
9028         {
9029           /* we need to get it byte by byte */
9030           _startLazyDPSEvaluation ();
9031           if (AOP_TYPE (left) != AOP_DPTR)
9032             {
9033               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9034               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9035               if (options.model == MODEL_FLAT24)
9036                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9037             }
9038           else
9039             {
9040               /* We need to generate a load to DPTR indirect through DPTR. */
9041               D (emitcode (";", "genFarPointerGet -- indirection special case.");
9042                 );
9043               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
9044               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
9045               if (options.model == MODEL_FLAT24)
9046                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9047               emitcode ("pop", "dph");
9048               emitcode ("pop", "dpl");
9049               dopi =0;
9050             }
9051           _endLazyDPSEvaluation ();
9052         }
9053     }
9054   /* so dptr know contains the address */
9055   aopOp (result, ic, FALSE, TRUE);
9056
9057   /* if bit then unpack */
9058   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9059     genUnpackBits (result, "dptr", FPOINTER);
9060   else
9061     {
9062       size = AOP_SIZE (result);
9063       offset = 0;
9064
9065       _startLazyDPSEvaluation ();
9066       while (size--)
9067         {
9068
9069           genSetDPTR (0);
9070           _flushLazyDPS ();
9071
9072           emitcode ("movx", "a,@dptr");
9073           if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9074             emitcode ("inc", "dptr");
9075
9076           aopPut (AOP (result), "a", offset++);
9077         }
9078       _endLazyDPSEvaluation ();
9079     }
9080   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9081     aopPut ( AOP (left), "dpl", 0);
9082     aopPut ( AOP (left), "dph", 1);
9083     if (options.model == MODEL_FLAT24)
9084             aopPut ( AOP (left), "dpx", 2);
9085     pi->generated = 1;
9086   } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9087              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9088       
9089       size = AOP_SIZE (result) - 1;
9090       while (size--) emitcode ("lcall","__decdptr");
9091   }
9092
9093   freeAsmop (left, NULL, ic, TRUE);
9094   freeAsmop (result, NULL, ic, TRUE);
9095 }
9096
9097 /*-----------------------------------------------------------------*/
9098 /* emitcodePointerGet - gget value from code space                  */
9099 /*-----------------------------------------------------------------*/
9100 static void
9101 emitcodePointerGet (operand * left,
9102                     operand * result, iCode * ic, iCode *pi)
9103 {
9104   int size, offset, dopi=1;
9105   sym_link *retype = getSpec (operandType (result));
9106
9107   aopOp (left, ic, FALSE, FALSE);
9108
9109   /* if the operand is already in dptr
9110      then we do nothing else we move the value to dptr */
9111   if (AOP_TYPE (left) != AOP_STR)
9112     {
9113       /* if this is remateriazable */
9114       if (AOP_TYPE (left) == AOP_IMMD)
9115         {
9116           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9117         }
9118       else
9119         {                       /* we need to get it byte by byte */
9120           _startLazyDPSEvaluation ();
9121           if (AOP_TYPE (left) != AOP_DPTR)
9122             {
9123               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9124               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9125               if (options.model == MODEL_FLAT24)
9126                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9127             }
9128           else
9129             {
9130               /* We need to generate a load to DPTR indirect through DPTR. */
9131               D (emitcode (";", "gencodePointerGet -- indirection special case.");
9132                 );
9133               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
9134               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
9135               if (options.model == MODEL_FLAT24)
9136                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9137               emitcode ("pop", "dph");
9138               emitcode ("pop", "dpl");
9139               dopi=0;
9140             }
9141           _endLazyDPSEvaluation ();
9142         }
9143     }
9144   /* so dptr know contains the address */
9145   aopOp (result, ic, FALSE, TRUE);
9146
9147   /* if bit then unpack */
9148   if (IS_BITVAR (retype))
9149     genUnpackBits (result, "dptr", CPOINTER);
9150   else
9151     {
9152       size = AOP_SIZE (result);
9153       offset = 0;
9154
9155       _startLazyDPSEvaluation ();
9156       while (size--)
9157         {
9158           genSetDPTR (0);
9159           _flushLazyDPS ();
9160
9161           emitcode ("clr", "a");
9162           emitcode ("movc", "a,@a+dptr");
9163           if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9164             emitcode ("inc", "dptr");
9165           aopPut (AOP (result), "a", offset++);
9166         }
9167       _endLazyDPSEvaluation ();
9168     }
9169   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9170       aopPut ( AOP (left), "dpl", 0);
9171       aopPut ( AOP (left), "dph", 1);
9172       if (options.model == MODEL_FLAT24)
9173           aopPut ( AOP (left), "dpx", 2);
9174       pi->generated = 1;
9175   } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9176              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9177       
9178       size = AOP_SIZE (result) - 1;
9179       while (size--) emitcode ("lcall","__decdptr");
9180   }
9181   
9182   freeAsmop (left, NULL, ic, TRUE);
9183   freeAsmop (result, NULL, ic, TRUE);
9184 }
9185
9186 /*-----------------------------------------------------------------*/
9187 /* genGenPointerGet - gget value from generic pointer space        */
9188 /*-----------------------------------------------------------------*/
9189 static void
9190 genGenPointerGet (operand * left,
9191                   operand * result, iCode * ic, iCode * pi)
9192 {
9193   int size, offset;
9194   sym_link *retype = getSpec (operandType (result));
9195   sym_link *letype = getSpec (operandType (left));
9196
9197   D (emitcode (";", "genGenPointerGet "); );
9198
9199   aopOp (left, ic, FALSE, (OP_SYMBOL(left)->ruonly ? FALSE : TRUE));
9200
9201   /* if the operand is already in dptr
9202      then we do nothing else we move the value to dptr */
9203   if (AOP_TYPE (left) != AOP_STR)
9204     {
9205       /* if this is remateriazable */
9206       if (AOP_TYPE (left) == AOP_IMMD)
9207         {
9208           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9209           if (AOP(left)->aopu.aop_immd.from_cast_remat) 
9210                   emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, FALSE));
9211           else
9212                   emitcode ("mov", "b,#%d", pointerCode (retype));
9213         }
9214       else
9215         {                       /* we need to get it byte by byte */
9216           _startLazyDPSEvaluation ();
9217           if (AOP(left)->type==AOP_DPTR2) {
9218             char *l;
9219             l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
9220             genSetDPTR(0);
9221             _flushLazyDPS();
9222             emitcode ("mov", "dpl,%s", l);
9223             l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
9224             genSetDPTR(0);
9225             _flushLazyDPS();
9226             emitcode ("mov", "dph,%s", l);
9227             if (options.model == MODEL_FLAT24) {
9228               l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
9229               genSetDPTR(0);
9230               _flushLazyDPS();
9231               emitcode ("mov", "dpx,%s", l);
9232               emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
9233             } else {
9234               emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9235             }
9236           } else {
9237             emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
9238             emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
9239             if (options.model == MODEL_FLAT24) {
9240               emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9241               emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
9242             } else {
9243               emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9244             }
9245           }
9246           _endLazyDPSEvaluation ();
9247         }
9248     }
9249   /* so dptr know contains the address */
9250   aopOp (result, ic, FALSE, TRUE);
9251
9252   /* if bit then unpack */
9253   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9254     genUnpackBits (result, "dptr", GPOINTER);
9255   else
9256     {
9257       size = AOP_SIZE (result);
9258       offset = 0;
9259
9260       while (size--)
9261         {
9262           emitcode ("lcall", "__gptrget");
9263           aopPut (AOP (result), "a", offset++);
9264           if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9265             emitcode ("inc", "dptr");
9266         }
9267     }
9268
9269   if (pi && AOP_TYPE (left) != AOP_IMMD) {
9270     aopPut ( AOP (left), "dpl", 0);
9271     aopPut ( AOP (left), "dph", 1);
9272     if (options.model == MODEL_FLAT24) {
9273         aopPut ( AOP (left), "dpx", 2);
9274         aopPut ( AOP (left), "b", 3);   
9275     } else  aopPut ( AOP (left), "b", 2);       
9276     pi->generated = 1;
9277   } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9278              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9279       
9280       size = AOP_SIZE (result) - 1;
9281       while (size--) emitcode ("lcall","__decdptr");
9282   }
9283
9284   freeAsmop (left, NULL, ic, TRUE);
9285   freeAsmop (result, NULL, ic, TRUE);
9286 }
9287
9288 /*-----------------------------------------------------------------*/
9289 /* genPointerGet - generate code for pointer get                   */
9290 /*-----------------------------------------------------------------*/
9291 static void
9292 genPointerGet (iCode * ic, iCode *pi)
9293 {
9294   operand *left, *result;
9295   sym_link *type, *etype;
9296   int p_type;
9297
9298   D (emitcode (";", "genPointerGet ");
9299     );
9300
9301   left = IC_LEFT (ic);
9302   result = IC_RESULT (ic);
9303
9304   /* depending on the type of pointer we need to
9305      move it to the correct pointer register */
9306   type = operandType (left);
9307   etype = getSpec (type);
9308   /* if left is of type of pointer then it is simple */
9309   if (IS_PTR (type) && !IS_FUNC (type->next))
9310     p_type = DCL_TYPE (type);
9311   else
9312     {
9313       /* we have to go by the storage class */
9314       p_type = PTR_TYPE (SPEC_OCLS (etype));
9315     }
9316   /* special case when cast remat */
9317   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9318       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9319           left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9320           type =   type = operandType (left);
9321           p_type = DCL_TYPE (type);
9322   }
9323   /* now that we have the pointer type we assign
9324      the pointer values */
9325   switch (p_type)
9326     {
9327
9328     case POINTER:
9329     case IPOINTER:
9330       genNearPointerGet (left, result, ic, pi);
9331       break;
9332
9333     case PPOINTER:
9334       genPagedPointerGet (left, result, ic, pi);
9335       break;
9336
9337     case FPOINTER:
9338       genFarPointerGet (left, result, ic, pi);
9339       break;
9340
9341     case CPOINTER:
9342       emitcodePointerGet (left, result, ic, pi);
9343       break;
9344
9345     case GPOINTER:
9346       genGenPointerGet (left, result, ic, pi);
9347       break;
9348     }
9349
9350 }
9351
9352 /*-----------------------------------------------------------------*/
9353 /* genPackBits - generates code for packed bit storage             */
9354 /*-----------------------------------------------------------------*/
9355 static void
9356 genPackBits (sym_link * etype,
9357              operand * right,
9358              char *rname, int p_type)
9359 {
9360   int shCount = 0;
9361   int offset = 0;
9362   int rLen = 0;
9363   int blen, bstr;
9364   char *l;
9365
9366   blen = SPEC_BLEN (etype);
9367   bstr = SPEC_BSTR (etype);
9368
9369   l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9370   MOVA (l);
9371
9372   /* if the bit lenth is less than or    */
9373   /* it exactly fits a byte then         */
9374   if (SPEC_BLEN (etype) <= 8)
9375     {
9376       shCount = SPEC_BSTR (etype);
9377
9378       /* shift left acc */
9379       AccLsh (shCount);
9380
9381       if (SPEC_BLEN (etype) < 8)
9382         {                       /* if smaller than a byte */
9383
9384
9385           switch (p_type)
9386             {
9387             case POINTER:
9388               emitcode ("mov", "b,a");
9389               emitcode ("mov", "a,@%s", rname);
9390               break;
9391
9392             case FPOINTER:
9393               emitcode ("mov", "b,a");
9394               emitcode ("movx", "a,@dptr");
9395               break;
9396
9397             case GPOINTER:
9398               emitcode ("push", "b");
9399               emitcode ("push", "acc");
9400               emitcode ("lcall", "__gptrget");
9401               emitcode ("pop", "b");
9402               break;
9403             }
9404
9405           emitcode ("anl", "a,#!constbyte", (unsigned char)
9406                     ((unsigned char) (0xFF << (blen + bstr)) |
9407                      (unsigned char) (0xFF >> (8 - bstr))));
9408           emitcode ("orl", "a,b");
9409           if (p_type == GPOINTER)
9410             emitcode ("pop", "b");
9411         }
9412     }
9413
9414   switch (p_type)
9415     {
9416     case POINTER:
9417       emitcode ("mov", "@%s,a", rname);
9418       break;
9419
9420     case FPOINTER:
9421       emitcode ("movx", "@dptr,a");
9422       break;
9423
9424     case GPOINTER:
9425       emitcode ("lcall", "__gptrput");
9426       break;
9427     }
9428
9429   /* if we r done */
9430   if (SPEC_BLEN (etype) <= 8)
9431     return;
9432
9433   emitcode ("inc", "%s", rname);
9434   rLen = SPEC_BLEN (etype);
9435
9436   /* now generate for lengths greater than one byte */
9437   while (1)
9438     {
9439
9440       l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
9441
9442       rLen -= 8;
9443       if (rLen < 8)
9444         break;
9445
9446       switch (p_type)
9447         {
9448         case POINTER:
9449           if (*l == '@')
9450             {
9451               MOVA (l);
9452               emitcode ("mov", "@%s,a", rname);
9453             }
9454           else
9455             emitcode ("mov", "@%s,%s", rname, l);
9456           break;
9457
9458         case FPOINTER:
9459           MOVA (l);
9460           emitcode ("movx", "@dptr,a");
9461           break;
9462
9463         case GPOINTER:
9464           MOVA (l);
9465           emitcode ("lcall", "__gptrput");
9466           break;
9467         }
9468       emitcode ("inc", "%s", rname);
9469     }
9470
9471   MOVA (l);
9472
9473   /* last last was not complete */
9474   if (rLen)
9475     {
9476       /* save the byte & read byte */
9477       switch (p_type)
9478         {
9479         case POINTER:
9480           emitcode ("mov", "b,a");
9481           emitcode ("mov", "a,@%s", rname);
9482           break;
9483
9484         case FPOINTER:
9485           emitcode ("mov", "b,a");
9486           emitcode ("movx", "a,@dptr");
9487           break;
9488
9489         case GPOINTER:
9490           emitcode ("push", "b");
9491           emitcode ("push", "acc");
9492           emitcode ("lcall", "__gptrget");
9493           emitcode ("pop", "b");
9494           break;
9495         }
9496
9497       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1 << rLen));
9498       emitcode ("orl", "a,b");
9499     }
9500
9501   if (p_type == GPOINTER)
9502     emitcode ("pop", "b");
9503
9504   switch (p_type)
9505     {
9506
9507     case POINTER:
9508       emitcode ("mov", "@%s,a", rname);
9509       break;
9510
9511     case FPOINTER:
9512       emitcode ("movx", "@dptr,a");
9513       break;
9514
9515     case GPOINTER:
9516       emitcode ("lcall", "__gptrput");
9517       break;
9518     }
9519 }
9520 /*-----------------------------------------------------------------*/
9521 /* genDataPointerSet - remat pointer to data space                 */
9522 /*-----------------------------------------------------------------*/
9523 static void
9524 genDataPointerSet (operand * right,
9525                    operand * result,
9526                    iCode * ic)
9527 {
9528   int size, offset = 0;
9529   char *l, buffer[256];
9530
9531   aopOp (right, ic, FALSE, FALSE);
9532
9533   l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
9534   size = AOP_SIZE (right);
9535   while (size--)
9536     {
9537       if (offset)
9538         sprintf (buffer, "(%s + %d)", l + 1, offset);
9539       else
9540         sprintf (buffer, "%s", l + 1);
9541       emitcode ("mov", "%s,%s", buffer,
9542                 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
9543     }
9544
9545   freeAsmop (right, NULL, ic, TRUE);
9546   freeAsmop (result, NULL, ic, TRUE);
9547 }
9548
9549 /*-----------------------------------------------------------------*/
9550 /* genNearPointerSet - emitcode for near pointer put                */
9551 /*-----------------------------------------------------------------*/
9552 static void
9553 genNearPointerSet (operand * right,
9554                    operand * result,
9555                    iCode * ic,
9556                    iCode * pi)
9557 {
9558   asmop *aop = NULL;
9559   regs *preg = NULL;
9560   char *rname, *l;
9561   sym_link *retype, *letype;
9562   sym_link *ptype = operandType (result);
9563
9564   retype = getSpec (operandType (right));
9565   letype = getSpec (ptype);
9566
9567   aopOp (result, ic, FALSE, FALSE);
9568
9569   /* if the result is rematerializable &
9570      in data space & not a bit variable */
9571   if (AOP_TYPE (result) == AOP_IMMD &&
9572       DCL_TYPE (ptype) == POINTER &&
9573       !IS_BITVAR (retype) &&
9574       !IS_BITVAR (letype))
9575     {
9576       genDataPointerSet (right, result, ic);
9577       return;
9578     }
9579
9580   /* if the value is already in a pointer register
9581      then don't need anything more */
9582   if (!AOP_INPREG (AOP (result)))
9583     {
9584       /* otherwise get a free pointer register */
9585       aop = newAsmop (0);
9586       preg = getFreePtr (ic, &aop, FALSE);
9587       emitcode ("mov", "%s,%s",
9588                 preg->name,
9589                 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9590       rname = preg->name;
9591     }
9592   else
9593     rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9594
9595   aopOp (right, ic, FALSE, FALSE);
9596
9597   /* if bitfield then unpack the bits */
9598   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9599     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
9600   else
9601     {
9602       /* we have can just get the values */
9603       int size = AOP_SIZE (right);
9604       int offset = 0;
9605
9606       while (size--)
9607         {
9608           l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
9609           if (*l == '@')
9610             {
9611               MOVA (l);
9612               emitcode ("mov", "@%s,a", rname);
9613             }
9614           else
9615             emitcode ("mov", "@%s,%s", rname, l);
9616           if (size || pi)
9617             emitcode ("inc", "%s", rname);
9618           offset++;
9619         }
9620     }
9621
9622   /* now some housekeeping stuff */
9623   if (aop)
9624     {
9625       /* we had to allocate for this iCode */
9626       if (pi) aopPut (AOP (result),rname,0);
9627       freeAsmop (NULL, aop, ic, TRUE);
9628     }
9629   else
9630     {
9631       /* we did not allocate which means left
9632          already in a pointer register, then
9633          if size > 0 && this could be used again
9634          we have to point it back to where it
9635          belongs */
9636       if (AOP_SIZE (right) > 1 &&
9637           !OP_SYMBOL (result)->remat &&
9638           (OP_SYMBOL (result)->liveTo > ic->seq ||
9639            ic->depth) &&
9640           !pi)
9641         {
9642           int size = AOP_SIZE (right) - 1;
9643           while (size--)
9644             emitcode ("dec", "%s", rname);
9645         }
9646     }
9647
9648   /* done */
9649   if (pi) pi->generated = 1;
9650   freeAsmop (result, NULL, ic, TRUE);
9651   freeAsmop (right, NULL, ic, TRUE);
9652
9653
9654 }
9655
9656 /*-----------------------------------------------------------------*/
9657 /* genPagedPointerSet - emitcode for Paged pointer put             */
9658 /*-----------------------------------------------------------------*/
9659 static void
9660 genPagedPointerSet (operand * right,
9661                     operand * result,
9662                     iCode * ic,
9663                     iCode *pi)
9664 {
9665   asmop *aop = NULL;
9666   regs *preg = NULL;
9667   char *rname, *l;
9668   sym_link *retype, *letype;
9669
9670   retype = getSpec (operandType (right));
9671   letype = getSpec (operandType (result));
9672
9673   aopOp (result, ic, FALSE, FALSE);
9674
9675   /* if the value is already in a pointer register
9676      then don't need anything more */
9677   if (!AOP_INPREG (AOP (result)))
9678     {
9679       /* otherwise get a free pointer register */
9680       aop = newAsmop (0);
9681       preg = getFreePtr (ic, &aop, FALSE);
9682       emitcode ("mov", "%s,%s",
9683                 preg->name,
9684                 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9685       rname = preg->name;
9686     }
9687   else
9688     rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9689
9690   aopOp (right, ic, FALSE, FALSE);
9691
9692   /* if bitfield then unpack the bits */
9693   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9694     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
9695   else
9696     {
9697       /* we have can just get the values */
9698       int size = AOP_SIZE (right);
9699       int offset = 0;
9700
9701       while (size--)
9702         {
9703           l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
9704
9705           MOVA (l);
9706           emitcode ("movx", "@%s,a", rname);
9707
9708           if (size || pi)
9709             emitcode ("inc", "%s", rname);
9710
9711           offset++;
9712         }
9713     }
9714
9715   /* now some housekeeping stuff */
9716   if (aop)
9717     {
9718       if (pi) aopPut (AOP (result),rname,0);
9719       /* we had to allocate for this iCode */
9720       freeAsmop (NULL, aop, ic, TRUE);
9721     }
9722   else
9723     {
9724       /* we did not allocate which means left
9725          already in a pointer register, then
9726          if size > 0 && this could be used again
9727          we have to point it back to where it
9728          belongs */
9729       if (AOP_SIZE (right) > 1 &&
9730           !OP_SYMBOL (result)->remat &&
9731           (OP_SYMBOL (result)->liveTo > ic->seq ||
9732            ic->depth) &&
9733           !pi)
9734         {
9735           int size = AOP_SIZE (right) - 1;
9736           while (size--)
9737             emitcode ("dec", "%s", rname);
9738         }
9739     }
9740
9741   /* done */
9742   if (pi) pi->generated = 1;
9743   freeAsmop (result, NULL, ic, TRUE);
9744   freeAsmop (right, NULL, ic, TRUE);
9745
9746
9747 }
9748
9749 /*-----------------------------------------------------------------*/
9750 /* genFarPointerSet - set value from far space                     */
9751 /*-----------------------------------------------------------------*/
9752 static void
9753 genFarPointerSet (operand * right,
9754                   operand * result, iCode * ic, iCode *pi)
9755 {
9756   int size, offset, dopi=1;
9757   sym_link *retype = getSpec (operandType (right));
9758   sym_link *letype = getSpec (operandType (result));
9759
9760   aopOp (result, ic, FALSE, FALSE);
9761
9762   /* if the operand is already in dptr
9763      then we do nothing else we move the value to dptr */
9764   if (AOP_TYPE (result) != AOP_STR)
9765     {
9766       /* if this is remateriazable */
9767       if (AOP_TYPE (result) == AOP_IMMD)
9768         emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9769       else
9770         {
9771           /* we need to get it byte by byte */
9772           _startLazyDPSEvaluation ();
9773           if (AOP_TYPE (result) != AOP_DPTR)
9774             {
9775               emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9776               emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9777               if (options.model == MODEL_FLAT24)
9778                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9779             }
9780           else
9781             {
9782               /* We need to generate a load to DPTR indirect through DPTR. */
9783               D (emitcode (";", "genFarPointerSet -- indirection special case.");
9784                 );
9785               emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
9786               emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
9787               if (options.model == MODEL_FLAT24)
9788                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9789               emitcode ("pop", "dph");
9790               emitcode ("pop", "dpl");
9791               dopi=0;
9792             }
9793           _endLazyDPSEvaluation ();
9794         }
9795     }
9796   /* so dptr know contains the address */
9797   aopOp (right, ic, FALSE, TRUE);
9798
9799   /* if bit then unpack */
9800   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9801     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
9802   else
9803     {
9804       size = AOP_SIZE (right);
9805       offset = 0;
9806
9807       _startLazyDPSEvaluation ();
9808       while (size--)
9809         {
9810           char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9811           MOVA (l);
9812
9813           genSetDPTR (0);
9814           _flushLazyDPS ();
9815
9816           emitcode ("movx", "@dptr,a");
9817           if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
9818             emitcode ("inc", "dptr");
9819         }
9820       _endLazyDPSEvaluation ();
9821     }
9822
9823   if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
9824       aopPut (AOP(result),"dpl",0);
9825       aopPut (AOP(result),"dph",1);
9826       if (options.model == MODEL_FLAT24)
9827           aopPut (AOP(result),"dpx",2);
9828       pi->generated=1;
9829   } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
9830              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
9831       
9832       size = AOP_SIZE (right) - 1;
9833       while (size--) emitcode ("lcall","__decdptr");
9834   }
9835   freeAsmop (result, NULL, ic, TRUE);
9836   freeAsmop (right, NULL, ic, TRUE);
9837 }
9838
9839 /*-----------------------------------------------------------------*/
9840 /* genGenPointerSet - set value from generic pointer space         */
9841 /*-----------------------------------------------------------------*/
9842 static void
9843 genGenPointerSet (operand * right,
9844                   operand * result, iCode * ic, iCode *pi)
9845 {
9846   int size, offset;
9847   sym_link *retype = getSpec (operandType (right));
9848   sym_link *letype = getSpec (operandType (result));
9849
9850   aopOp (result, ic, FALSE, OP_SYMBOL(result)->ruonly ? FALSE : TRUE);
9851
9852   /* if the operand is already in dptr
9853      then we do nothing else we move the value to dptr */
9854   if (AOP_TYPE (result) != AOP_STR)
9855     {
9856       _startLazyDPSEvaluation ();
9857       /* if this is remateriazable */
9858       if (AOP_TYPE (result) == AOP_IMMD)
9859         {
9860           emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9861           if (AOP(result)->aopu.aop_immd.from_cast_remat) 
9862                   emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, FALSE));
9863           else
9864                   emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9865         }
9866       else
9867         {                       /* we need to get it byte by byte */
9868           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9869           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9870           if (options.model == MODEL_FLAT24) {
9871             emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9872             emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
9873           } else {
9874             emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9875           }
9876         }
9877       _endLazyDPSEvaluation ();
9878     }
9879   /* so dptr know contains the address */
9880   aopOp (right, ic, FALSE, TRUE);
9881
9882   /* if bit then unpack */
9883   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9884     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
9885   else
9886     {
9887       size = AOP_SIZE (right);
9888       offset = 0;
9889
9890       _startLazyDPSEvaluation ();
9891       while (size--)
9892         {
9893           char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9894           MOVA (l);
9895
9896           genSetDPTR (0);
9897           _flushLazyDPS ();
9898
9899           emitcode ("lcall", "__gptrput");
9900           if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
9901             emitcode ("inc", "dptr");
9902         }
9903       _endLazyDPSEvaluation ();
9904     }
9905
9906   if (pi && AOP_TYPE (result) != AOP_IMMD) {
9907       aopPut (AOP(result),"dpl",0);
9908       aopPut (AOP(result),"dph",1);
9909       if (options.model == MODEL_FLAT24) {
9910           aopPut (AOP(result),"dpx",2);
9911           aopPut (AOP(result),"b",3);
9912       } else {
9913           aopPut (AOP(result),"b",2);
9914       }
9915       pi->generated=1;
9916   } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
9917              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
9918       
9919       size = AOP_SIZE (right) - 1;
9920       while (size--) emitcode ("lcall","__decdptr");
9921   }
9922   freeAsmop (result, NULL, ic, TRUE);
9923   freeAsmop (right, NULL, ic, TRUE);
9924 }
9925
9926 /*-----------------------------------------------------------------*/
9927 /* genPointerSet - stores the value into a pointer location        */
9928 /*-----------------------------------------------------------------*/
9929 static void
9930 genPointerSet (iCode * ic, iCode *pi)
9931 {
9932   operand *right, *result;
9933   sym_link *type, *etype;
9934   int p_type;
9935
9936   D (emitcode (";", "genPointerSet ");
9937     );
9938
9939   right = IC_RIGHT (ic);
9940   result = IC_RESULT (ic);
9941
9942   /* depending on the type of pointer we need to
9943      move it to the correct pointer register */
9944   type = operandType (result);
9945   etype = getSpec (type);
9946   /* if left is of type of pointer then it is simple */
9947   if (IS_PTR (type) && !IS_FUNC (type->next))
9948     {
9949       p_type = DCL_TYPE (type);
9950     }
9951   else
9952     {
9953       /* we have to go by the storage class */
9954       p_type = PTR_TYPE (SPEC_OCLS (etype));
9955     }
9956   /* special case when cast remat */
9957   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
9958       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
9959           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
9960           type =   type = operandType (result);
9961           p_type = DCL_TYPE (type);
9962   }
9963
9964   /* now that we have the pointer type we assign
9965      the pointer values */
9966   switch (p_type)
9967     {
9968
9969     case POINTER:
9970     case IPOINTER:
9971       genNearPointerSet (right, result, ic, pi);
9972       break;
9973
9974     case PPOINTER:
9975       genPagedPointerSet (right, result, ic, pi);
9976       break;
9977
9978     case FPOINTER:
9979       genFarPointerSet (right, result, ic, pi);
9980       break;
9981
9982     case GPOINTER:
9983       genGenPointerSet (right, result, ic, pi);
9984       break;
9985     }
9986
9987 }
9988
9989 /*-----------------------------------------------------------------*/
9990 /* genIfx - generate code for Ifx statement                        */
9991 /*-----------------------------------------------------------------*/
9992 static void
9993 genIfx (iCode * ic, iCode * popIc)
9994 {
9995   operand *cond = IC_COND (ic);
9996   int isbit = 0;
9997
9998   D (emitcode (";", "genIfx "););
9999
10000   aopOp (cond, ic, FALSE, FALSE);
10001
10002   /* get the value into acc */
10003   if (AOP_TYPE (cond) != AOP_CRY)
10004     toBoolean (cond);
10005   else
10006     isbit = 1;
10007   /* the result is now in the accumulator */
10008   freeAsmop (cond, NULL, ic, TRUE);
10009
10010   /* if there was something to be popped then do it */
10011   if (popIc)
10012     genIpop (popIc);
10013
10014   /* if the condition is  a bit variable */
10015   if (isbit && IS_ITEMP (cond) &&
10016       SPIL_LOC (cond))
10017     genIfxJump (ic, SPIL_LOC (cond)->rname);
10018   else if (isbit && !IS_ITEMP (cond))
10019     genIfxJump (ic, OP_SYMBOL (cond)->rname);
10020   else
10021     genIfxJump (ic, "a");
10022
10023   ic->generated = 1;
10024 }
10025
10026 /*-----------------------------------------------------------------*/
10027 /* genAddrOf - generates code for address of                       */
10028 /*-----------------------------------------------------------------*/
10029 static void
10030 genAddrOf (iCode * ic)
10031 {
10032   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10033   int size, offset;
10034
10035   D (emitcode (";", "genAddrOf ");
10036     );
10037
10038   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10039
10040   /* if the operand is on the stack then we
10041      need to get the stack offset of this
10042      variable */
10043   if (sym->onStack) {
10044       
10045       /* if 10 bit stack */
10046       if (options.stack10bit) {
10047           char buff[10];
10048           tsprintf(buff,"#!constbyte",(options.stack_loc >> 16) & 0xff);
10049           /* if it has an offset then we need to compute it */
10050           emitcode ("subb", "a,#!constbyte",
10051                     -((sym->stack < 0) ?
10052                       ((short) (sym->stack - _G.nRegsSaved)) :
10053                       ((short) sym->stack)) & 0xff);
10054           emitcode ("mov","b,a");
10055           emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ?
10056                                          ((short) (sym->stack - _G.nRegsSaved)) :
10057                                          ((short) sym->stack)) >> 8) & 0xff);
10058           if (sym->stack) {
10059               emitcode ("mov", "a,_bpx");
10060               emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ? 
10061                                              ((char) (sym->stack - _G.nRegsSaved)) :
10062                                              ((char) sym->stack )) & 0xff);
10063               emitcode ("mov", "b,a");
10064               emitcode ("mov", "a,_bpx+1");
10065               emitcode ("addc","a,#!constbyte", (((sym->stack < 0) ? 
10066                                               ((short) (sym->stack - _G.nRegsSaved)) :
10067                                               ((short) sym->stack )) >> 8) & 0xff);
10068               aopPut (AOP (IC_RESULT (ic)), "b", 0);
10069               aopPut (AOP (IC_RESULT (ic)), "a", 1);
10070               aopPut (AOP (IC_RESULT (ic)), buff, 2);
10071           } else {
10072               /* we can just move _bp */
10073               aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
10074               aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
10075               aopPut (AOP (IC_RESULT (ic)), buff, 2);
10076           }       
10077       } else {
10078           /* if it has an offset then we need to compute it */
10079           if (sym->stack) {
10080               emitcode ("mov", "a,_bp");
10081               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
10082               aopPut (AOP (IC_RESULT (ic)), "a", 0);
10083           } else {
10084               /* we can just move _bp */
10085               aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
10086           }
10087           /* fill the result with zero */
10088           size = AOP_SIZE (IC_RESULT (ic)) - 1;
10089           
10090           
10091           if (options.stack10bit && size < (FPTRSIZE - 1)) {
10092               fprintf (stderr,
10093                        "*** warning: pointer to stack var truncated.\n");
10094           }
10095
10096           offset = 1;
10097           while (size--) {
10098               aopPut (AOP (IC_RESULT (ic)), zero, offset++);
10099           }      
10100       }
10101       goto release;
10102   }
10103
10104   /* object not on stack then we need the name */
10105   size = AOP_SIZE (IC_RESULT (ic));
10106   offset = 0;
10107
10108   while (size--)
10109     {
10110       char s[SDCC_NAME_MAX];
10111       if (offset) {
10112           switch (offset) {
10113           case 1:
10114               tsprintf(s,"!his",sym->rname);
10115               break;
10116           case 2:
10117               tsprintf(s,"!hihis",sym->rname);
10118               break;
10119           case 3:
10120               tsprintf(s,"!hihihis",sym->rname);
10121               break;
10122           default: /* should not need this (just in case) */
10123               sprintf (s, "#(%s >> %d)",
10124                        sym->rname,
10125                        offset * 8);
10126           }
10127       } else
10128           sprintf (s, "#%s", sym->rname);
10129       aopPut (AOP (IC_RESULT (ic)), s, offset++);
10130     }
10131
10132 release:
10133   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10134
10135 }
10136
10137 /*-----------------------------------------------------------------*/
10138 /* genArrayInit - generates code for address of                       */
10139 /*-----------------------------------------------------------------*/
10140 static void
10141 genArrayInit (iCode * ic)
10142 {
10143     literalList *iLoop;
10144     int         ix, count;
10145     int         elementSize = 0, eIndex;
10146     unsigned    val, lastVal;
10147     sym_link    *type;
10148     operand     *left=IC_LEFT(ic);
10149     
10150     D (emitcode (";", "genArrayInit "););
10151
10152     aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10153     
10154     if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10155     {
10156         // Load immediate value into DPTR.
10157         emitcode("mov", "dptr, %s",
10158              aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, TRUE));
10159     }
10160     else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10161     {
10162 #if 0
10163       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10164               "Unexpected operand to genArrayInit.\n");
10165       exit(1);
10166 #else
10167       // a regression because of SDCCcse.c:1.52
10168       emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
10169       emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
10170       if (options.model == MODEL_FLAT24)
10171         emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
10172 #endif
10173     }
10174     
10175     type = operandType(IC_LEFT(ic));
10176     
10177     if (type && type->next)
10178     {
10179         elementSize = getSize(type->next);
10180     }
10181     else
10182     {
10183         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10184                                 "can't determine element size in genArrayInit.\n");
10185         exit(1);
10186     }
10187     
10188     iLoop = IC_ARRAYILIST(ic);
10189     lastVal = 0xffff;
10190     
10191     while (iLoop)
10192     {
10193         bool firstpass = TRUE;
10194         
10195         emitcode(";", "store %d x 0x%x to DPTR (element size %d)", 
10196                  iLoop->count, (int)iLoop->literalValue, elementSize);
10197         
10198         ix = iLoop->count;
10199         
10200         while (ix)
10201         {
10202             symbol *tlbl = NULL;
10203             
10204             count = ix > 256 ? 256 : ix;
10205             
10206             if (count > 1)
10207             {
10208                 tlbl = newiTempLabel (NULL);
10209                 if (firstpass || (count & 0xff))
10210                 {
10211                     emitcode("mov", "b, #!constbyte", count & 0xff);
10212                 }
10213                 
10214                 emitcode ("", "!tlabeldef", tlbl->key + 100);
10215             }
10216             
10217             firstpass = FALSE;
10218                 
10219             for (eIndex = 0; eIndex < elementSize; eIndex++)
10220             {
10221                 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10222                 if (val != lastVal)
10223                 {
10224                     emitcode("mov", "a, #!constbyte", val);
10225                     lastVal = val;
10226                 }
10227                 
10228                 emitcode("movx", "@dptr, a");
10229                 emitcode("inc", "dptr");
10230             }
10231             
10232             if (count > 1)
10233             {
10234                 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
10235             }
10236             
10237             ix -= count;
10238         }
10239         
10240         iLoop = iLoop->next;
10241     }
10242     
10243     freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10244 }
10245
10246 /*-----------------------------------------------------------------*/
10247 /* genFarFarAssign - assignment when both are in far space         */
10248 /*-----------------------------------------------------------------*/
10249 static void
10250 genFarFarAssign (operand * result, operand * right, iCode * ic)
10251 {
10252   int size = AOP_SIZE (right);
10253   int offset = 0;
10254   symbol *rSym = NULL;
10255
10256   if (size == 1)
10257   {
10258       /* quick & easy case. */
10259       D(emitcode(";","genFarFarAssign (1 byte case)"););      
10260       MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
10261       freeAsmop (right, NULL, ic, FALSE);
10262       /* now assign DPTR to result */
10263       _G.accInUse++;
10264       aopOp(result, ic, FALSE, FALSE);
10265       _G.accInUse--;
10266       aopPut(AOP(result), "a", 0);
10267       freeAsmop(result, NULL, ic, FALSE);
10268       return;
10269   }
10270   
10271   /* See if we've got an underlying symbol to abuse. */
10272   if (IS_SYMOP(result) && OP_SYMBOL(result))
10273   {
10274       if (IS_TRUE_SYMOP(result))
10275       {
10276           rSym = OP_SYMBOL(result);
10277       }
10278       else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10279       {
10280           rSym = OP_SYMBOL(result)->usl.spillLoc;
10281       }
10282   }
10283              
10284   if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10285   {
10286       /* We can use the '390 auto-toggle feature to good effect here. */
10287       
10288       D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10289       emitcode("mov", "dps,#!constbyte",0x21);  /* Select DPTR2 & auto-toggle. */
10290       emitcode ("mov", "dptr,#%s", rSym->rname); 
10291       /* DP2 = result, DP1 = right, DP1 is current. */
10292       while (size)
10293       {
10294           emitcode("movx", "a,@dptr");
10295           emitcode("movx", "@dptr,a");
10296           if (--size)
10297           {
10298                emitcode("inc", "dptr");
10299                emitcode("inc", "dptr");
10300           }
10301       }
10302       emitcode("mov", "dps,#0");
10303       freeAsmop (right, NULL, ic, FALSE);
10304 #if 0
10305 some alternative code for processors without auto-toggle
10306 no time to test now, so later well put in...kpb
10307         D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10308         emitcode("mov", "dps,#1");      /* Select DPTR2. */
10309         emitcode ("mov", "dptr,#%s", rSym->rname); 
10310         /* DP2 = result, DP1 = right, DP1 is current. */
10311         while (size)
10312         {
10313           --size;
10314           emitcode("movx", "a,@dptr");
10315           if (size)
10316             emitcode("inc", "dptr");
10317           emitcode("inc", "dps");
10318           emitcode("movx", "@dptr,a");
10319           if (size)
10320             emitcode("inc", "dptr");
10321           emitcode("inc", "dps");
10322         }
10323         emitcode("mov", "dps,#0");
10324         freeAsmop (right, NULL, ic, FALSE);
10325 #endif
10326   }
10327   else
10328   {
10329       D (emitcode (";", "genFarFarAssign"););
10330       aopOp (result, ic, TRUE, TRUE);
10331
10332       _startLazyDPSEvaluation ();
10333       
10334       while (size--)
10335         {
10336           aopPut (AOP (result),
10337                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
10338           offset++;
10339         }
10340       _endLazyDPSEvaluation ();
10341       freeAsmop (result, NULL, ic, FALSE);
10342       freeAsmop (right, NULL, ic, FALSE);
10343   }
10344 }
10345
10346 /*-----------------------------------------------------------------*/
10347 /* genAssign - generate code for assignment                        */
10348 /*-----------------------------------------------------------------*/
10349 static void
10350 genAssign (iCode * ic)
10351 {
10352   operand *result, *right;
10353   int size, offset;
10354   unsigned long lit = 0L;
10355
10356   D (emitcode (";", "genAssign ");
10357     );
10358
10359   result = IC_RESULT (ic);
10360   right = IC_RIGHT (ic);
10361
10362   /* if they are the same */
10363   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10364     return;
10365
10366   aopOp (right, ic, FALSE, FALSE);
10367
10368   emitcode (";", "genAssign: resultIsFar = %s",
10369             isOperandInFarSpace (result) ?
10370             "TRUE" : "FALSE");
10371
10372   /* special case both in far space */
10373   if ((AOP_TYPE (right) == AOP_DPTR ||
10374        AOP_TYPE (right) == AOP_DPTR2) &&
10375   /* IS_TRUE_SYMOP(result)       && */
10376       isOperandInFarSpace (result))
10377     {
10378       genFarFarAssign (result, right, ic);
10379       return;
10380     }
10381
10382   aopOp (result, ic, TRUE, FALSE);
10383
10384   /* if they are the same registers */
10385   if (sameRegs (AOP (right), AOP (result)))
10386     goto release;
10387
10388   /* if the result is a bit */
10389   if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10390     {
10391       /* if the right size is a literal then
10392          we know what the value is */
10393       if (AOP_TYPE (right) == AOP_LIT)
10394         {
10395           if (((int) operandLitValue (right)))
10396             aopPut (AOP (result), one, 0);
10397           else
10398             aopPut (AOP (result), zero, 0);
10399           goto release;
10400         }
10401
10402       /* the right is also a bit variable */
10403       if (AOP_TYPE (right) == AOP_CRY)
10404         {
10405           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10406           aopPut (AOP (result), "c", 0);
10407           goto release;
10408         }
10409
10410       /* we need to or */
10411       toBoolean (right);
10412       aopPut (AOP (result), "a", 0);
10413       goto release;
10414     }
10415
10416   /* bit variables done */
10417   /* general case */
10418   size = AOP_SIZE (result);
10419   offset = 0;
10420   if (AOP_TYPE (right) == AOP_LIT)
10421     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10422
10423   if ((size > 1) &&
10424       (AOP_TYPE (result) != AOP_REG) &&
10425       (AOP_TYPE (right) == AOP_LIT) &&
10426       !IS_FLOAT (operandType (right)))
10427     {
10428       _startLazyDPSEvaluation ();
10429       while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10430         {
10431           aopPut (AOP (result),
10432                   aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
10433                   offset);
10434           offset++;
10435           size--;
10436         }
10437       /* And now fill the rest with zeros. */
10438       if (size)
10439         {
10440           emitcode ("clr", "a");
10441         }
10442       while (size--)
10443         {
10444           aopPut (AOP (result), "a", offset++);
10445         }
10446       _endLazyDPSEvaluation ();
10447     }
10448   else
10449     {
10450       _startLazyDPSEvaluation ();
10451       while (size--)
10452         {
10453           aopPut (AOP (result),
10454                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10455                   offset);
10456           offset++;
10457         }
10458       _endLazyDPSEvaluation ();
10459     }
10460
10461 release:
10462   freeAsmop (right, NULL, ic, FALSE);
10463   freeAsmop (result, NULL, ic, TRUE);
10464 }
10465
10466 /*-----------------------------------------------------------------*/
10467 /* genJumpTab - generates code for jump table                      */
10468 /*-----------------------------------------------------------------*/
10469 static void
10470 genJumpTab (iCode * ic)
10471 {
10472   symbol *jtab;
10473   char *l;
10474
10475   D (emitcode (";", "genJumpTab ");
10476     );
10477
10478   aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10479   /* get the condition into accumulator */
10480   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
10481   MOVA (l);
10482   /* multiply by four! */
10483   emitcode ("add", "a,acc");
10484   emitcode ("add", "a,acc");
10485   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10486
10487   jtab = newiTempLabel (NULL);
10488   emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
10489   emitcode ("jmp", "@a+dptr");
10490   emitcode ("", "!tlabeldef", jtab->key + 100);
10491   /* now generate the jump labels */
10492   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10493        jtab = setNextItem (IC_JTLABELS (ic)))
10494     emitcode ("ljmp", "!tlabel", jtab->key + 100);
10495
10496 }
10497
10498 /*-----------------------------------------------------------------*/
10499 /* genCast - gen code for casting                                  */
10500 /*-----------------------------------------------------------------*/
10501 static void
10502 genCast (iCode * ic)
10503 {
10504   operand *result = IC_RESULT (ic);
10505   sym_link *ctype = operandType (IC_LEFT (ic));
10506   sym_link *rtype = operandType (IC_RIGHT (ic));
10507   operand *right = IC_RIGHT (ic);
10508   int size, offset;
10509
10510   D (emitcode (";", "genCast ");
10511     );
10512
10513   /* if they are equivalent then do nothing */
10514   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10515     return;
10516
10517   aopOp (right, ic, FALSE, FALSE);
10518   aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
10519
10520   /* if the result is a bit */
10521   // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10522   if (IS_BITVAR(OP_SYMBOL(result)->type))
10523     {
10524       /* if the right size is a literal then
10525          we know what the value is */
10526       if (AOP_TYPE (right) == AOP_LIT)
10527         {
10528           if (((int) operandLitValue (right)))
10529             aopPut (AOP (result), one, 0);
10530           else
10531             aopPut (AOP (result), zero, 0);
10532
10533           goto release;
10534         }
10535
10536       /* the right is also a bit variable */
10537       if (AOP_TYPE (right) == AOP_CRY)
10538         {
10539           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10540           aopPut (AOP (result), "c", 0);
10541           goto release;
10542         }
10543
10544       /* we need to or */
10545       toBoolean (right);
10546       aopPut (AOP (result), "a", 0);
10547       goto release;
10548     }
10549
10550   /* if they are the same size : or less */
10551   if (AOP_SIZE (result) <= AOP_SIZE (right))
10552     {
10553
10554       /* if they are in the same place */
10555       if (sameRegs (AOP (right), AOP (result)))
10556         goto release;
10557
10558       /* if they in different places then copy */
10559       size = AOP_SIZE (result);
10560       offset = 0;
10561       _startLazyDPSEvaluation ();
10562       while (size--)
10563         {
10564           aopPut (AOP (result),
10565                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10566                   offset);
10567           offset++;
10568         }
10569       _endLazyDPSEvaluation ();
10570       goto release;
10571     }
10572
10573
10574   /* if the result is of type pointer */
10575   if (IS_PTR (ctype))
10576     {
10577
10578       int p_type;
10579       sym_link *type = operandType (right);
10580
10581       /* pointer to generic pointer */
10582       if (IS_GENPTR (ctype))
10583         {
10584           char *l = zero;
10585
10586           if (IS_PTR (type))
10587             {
10588               p_type = DCL_TYPE (type);
10589             }
10590           else
10591             {
10592 #if OLD_CAST_BEHAVIOR
10593               /* KV: we are converting a non-pointer type to
10594                * a generic pointer. This (ifdef'd out) code
10595                * says that the resulting generic pointer
10596                * should have the same class as the storage
10597                * location of the non-pointer variable.
10598                *
10599                * For example, converting an int (which happens
10600                * to be stored in DATA space) to a pointer results
10601                * in a DATA generic pointer; if the original int
10602                * in XDATA space, so will be the resulting pointer.
10603                *
10604                * I don't like that behavior, and thus this change:
10605                * all such conversions will be forced to XDATA and
10606                * throw a warning. If you want some non-XDATA
10607                * type, or you want to suppress the warning, you
10608                * must go through an intermediate cast, like so:
10609                *
10610                * char _generic *gp = (char _xdata *)(intVar);
10611                */
10612               sym_link *etype = getSpec (type);
10613
10614               /* we have to go by the storage class */
10615               if (SPEC_OCLS (etype) != generic)
10616                 {
10617                   p_type = PTR_TYPE (SPEC_OCLS (etype));
10618                 }
10619               else
10620 #endif
10621                 {
10622                   /* Converting unknown class (i.e. register variable)
10623                    * to generic pointer. This is not good, but
10624                    * we'll make a guess (and throw a warning).
10625                    */
10626                   p_type = FPOINTER;
10627                   werror (W_INT_TO_GEN_PTR_CAST);
10628                 }
10629             }
10630
10631           /* the first two bytes are known */
10632           size = GPTRSIZE - 1;
10633           offset = 0;
10634           _startLazyDPSEvaluation ();
10635           while (size--)
10636             {
10637               aopPut (AOP (result),
10638                       aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10639                       offset);
10640               offset++;
10641             }
10642           _endLazyDPSEvaluation ();
10643
10644           /* the last byte depending on type */
10645           switch (p_type)
10646             {
10647             case IPOINTER:
10648             case POINTER:
10649               l = zero;
10650               break;
10651             case FPOINTER:
10652               l = one;
10653               break;
10654             case CPOINTER:
10655               l = "#0x02";
10656               break;
10657             case PPOINTER:
10658               l = "#0x03";
10659               break;
10660
10661             default:
10662               /* this should never happen */
10663               werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10664                       "got unknown pointer type");
10665               exit (1);
10666             }
10667           aopPut (AOP (result), l, GPTRSIZE - 1);
10668           goto release;
10669         }
10670
10671       /* just copy the pointers */
10672       size = AOP_SIZE (result);
10673       offset = 0;
10674       _startLazyDPSEvaluation ();
10675       while (size--)
10676         {
10677           aopPut (AOP (result),
10678                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10679                   offset);
10680           offset++;
10681         }
10682       _endLazyDPSEvaluation ();
10683       goto release;
10684     }
10685
10686   /* so we now know that the size of destination is greater
10687      than the size of the source */
10688   /* we move to result for the size of source */
10689   size = AOP_SIZE (right);
10690   offset = 0;
10691   _startLazyDPSEvaluation ();
10692   while (size--)
10693     {
10694       aopPut (AOP (result),
10695               aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10696               offset);
10697       offset++;
10698     }
10699   _endLazyDPSEvaluation ();
10700
10701   /* now depending on the sign of the source && destination */
10702   size = AOP_SIZE (result) - AOP_SIZE (right);
10703   /* if unsigned or not an integral type */
10704   /* also, if the source is a bit, we don't need to sign extend, because
10705    * it can't possibly have set the sign bit.
10706    */
10707   if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
10708     {
10709       while (size--)
10710         {
10711           aopPut (AOP (result), zero, offset++);
10712         }
10713     }
10714   else
10715     {
10716       /* we need to extend the sign :{ */
10717       char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
10718                         FALSE, FALSE, TRUE);
10719       MOVA (l);
10720       emitcode ("rlc", "a");
10721       emitcode ("subb", "a,acc");
10722       while (size--)
10723         aopPut (AOP (result), "a", offset++);
10724     }
10725
10726   /* we are done hurray !!!! */
10727
10728 release:
10729   freeAsmop (right, NULL, ic, TRUE);
10730   freeAsmop (result, NULL, ic, TRUE);
10731
10732 }
10733
10734 /*-----------------------------------------------------------------*/
10735 /* genDjnz - generate decrement & jump if not zero instrucion      */
10736 /*-----------------------------------------------------------------*/
10737 static int
10738 genDjnz (iCode * ic, iCode * ifx)
10739 {
10740   symbol *lbl, *lbl1;
10741   if (!ifx)
10742     return 0;
10743
10744   /* if the if condition has a false label
10745      then we cannot save */
10746   if (IC_FALSE (ifx))
10747     return 0;
10748
10749   /* if the minus is not of the form
10750      a = a - 1 */
10751   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
10752       !IS_OP_LITERAL (IC_RIGHT (ic)))
10753     return 0;
10754
10755   if (operandLitValue (IC_RIGHT (ic)) != 1)
10756     return 0;
10757
10758   /* if the size of this greater than one then no
10759      saving */
10760   if (getSize (operandType (IC_RESULT (ic))) > 1)
10761     return 0;
10762
10763   /* otherwise we can save BIG */
10764   D(emitcode(";", "genDjnz"););
10765
10766   lbl = newiTempLabel (NULL);
10767   lbl1 = newiTempLabel (NULL);
10768
10769   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10770
10771   if (AOP_NEEDSACC(IC_RESULT(ic)))
10772   {
10773       /* If the result is accessed indirectly via
10774        * the accumulator, we must explicitly write
10775        * it back after the decrement.
10776        */
10777       char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
10778       
10779       if (strcmp(rByte, "a"))
10780       {
10781            /* Something is hopelessly wrong */
10782            fprintf(stderr, "*** warning: internal error at %s:%d\n",
10783                    __FILE__, __LINE__);
10784            /* We can just give up; the generated code will be inefficient,
10785             * but what the hey.
10786             */
10787            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10788            return 0;
10789       }
10790       emitcode ("dec", "%s", rByte);
10791       aopPut(AOP(IC_RESULT(ic)), rByte, 0);
10792       emitcode ("jnz", "!tlabel", lbl->key + 100);
10793   }
10794   else if (IS_AOP_PREG (IC_RESULT (ic)))
10795     {
10796       emitcode ("dec", "%s",
10797                 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10798       emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10799       emitcode ("jnz", "!tlabel", lbl->key + 100);
10800     }
10801   else
10802     {
10803       emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
10804                 lbl->key + 100);
10805     }
10806   emitcode ("sjmp", "!tlabel", lbl1->key + 100);
10807   emitcode ("", "!tlabeldef", lbl->key + 100);
10808   emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
10809   emitcode ("", "!tlabeldef", lbl1->key + 100);
10810
10811   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10812   ifx->generated = 1;
10813   return 1;
10814 }
10815
10816 /*-----------------------------------------------------------------*/
10817 /* genReceive - generate code for a receive iCode                  */
10818 /*-----------------------------------------------------------------*/
10819 static void
10820 genReceive (iCode * ic)
10821 {
10822
10823   D (emitcode (";", "genReceive ");
10824     );
10825
10826   if (isOperandInFarSpace (IC_RESULT (ic)) &&
10827       (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
10828        IS_TRUE_SYMOP (IC_RESULT (ic))))
10829     {
10830       int size = getSize (operandType (IC_RESULT (ic)));
10831       int offset = fReturnSizeDS390 - size;
10832       while (size--)
10833         {
10834           emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
10835                             fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
10836           offset++;
10837         }
10838       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10839       size = AOP_SIZE (IC_RESULT (ic));
10840       offset = 0;
10841       while (size--)
10842         {
10843           emitcode ("pop", "acc");
10844           aopPut (AOP (IC_RESULT (ic)), "a", offset++);
10845         }
10846
10847     }
10848   else
10849     {
10850       _G.accInUse++;
10851       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10852       _G.accInUse--;
10853       assignResultValue (IC_RESULT (ic));
10854     }
10855
10856   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10857 }
10858
10859 /*-----------------------------------------------------------------*/
10860 /* genMemcpyX2X - gen code for memcpy xdata to xdata               */
10861 /*-----------------------------------------------------------------*/
10862 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
10863 {
10864     operand *from , *to , *count;
10865     symbol *lbl;
10866     bitVect *rsave;
10867     int i;
10868
10869     /* we know it has to be 3 parameters */
10870     assert (nparms == 3);
10871     
10872     rsave = newBitVect(16);
10873     /* save DPTR if it needs to be saved */
10874     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
10875             if (bitVectBitValue(ic->rMask,i))
10876                     rsave = bitVectSetBit(rsave,i);
10877     }
10878     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
10879                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
10880     savermask(rsave);
10881     
10882     to = parms[0];
10883     from = parms[1];
10884     count = parms[2];
10885
10886     aopOp (from, ic->next, FALSE, FALSE);
10887
10888     /* get from into DPTR1 */
10889     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, TRUE));
10890     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, TRUE));
10891     if (options.model == MODEL_FLAT24) {
10892         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, TRUE));
10893     }
10894
10895     freeAsmop (from, NULL, ic, FALSE);
10896     aopOp (to, ic, FALSE, FALSE);
10897     /* get "to" into DPTR */
10898     /* if the operand is already in dptr
10899        then we do nothing else we move the value to dptr */
10900     if (AOP_TYPE (to) != AOP_STR) {
10901         /* if already in DPTR then we need to push */
10902         if (AOP_TYPE(to) == AOP_DPTR) {
10903             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
10904             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
10905             if (options.model == MODEL_FLAT24)
10906                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
10907             emitcode ("pop", "dph");
10908             emitcode ("pop", "dpl");        
10909         } else {
10910             _startLazyDPSEvaluation ();
10911             /* if this is remateriazable */
10912             if (AOP_TYPE (to) == AOP_IMMD) {
10913                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
10914             } else {                    /* we need to get it byte by byte */
10915                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
10916                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
10917                 if (options.model == MODEL_FLAT24) {
10918                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
10919                 }
10920             }
10921             _endLazyDPSEvaluation ();
10922         }
10923     }
10924     freeAsmop (to, NULL, ic, FALSE);
10925
10926     aopOp (count, ic->next->next, FALSE,FALSE);
10927     lbl =newiTempLabel(NULL);
10928
10929     /* now for the actual copy */
10930     if (AOP_TYPE(count) == AOP_LIT && 
10931         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
10932         emitcode (";","OH  JOY auto increment with djnz (very fast)");
10933         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
10934         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
10935         emitcode ("","!tlabeldef",lbl->key+100);
10936         if (fromc) {
10937             emitcode ("clr","a");
10938             emitcode ("movc", "a,@a+dptr");
10939         } else 
10940             emitcode ("movx", "a,@dptr");
10941         emitcode ("movx", "@dptr,a");
10942         emitcode ("inc", "dptr");
10943         emitcode ("inc", "dptr");
10944         emitcode ("djnz","b,!tlabel",lbl->key+100);
10945     } else {
10946         symbol *lbl1 = newiTempLabel(NULL);
10947         
10948         emitcode (";"," Auto increment but no djnz");
10949         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
10950         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
10951         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
10952         emitcode ("","!tlabeldef",lbl->key+100);
10953         if (fromc) {
10954             emitcode ("clr","a");
10955             emitcode ("movc", "a,@a+dptr");
10956         } else 
10957             emitcode ("movx", "a,@dptr");
10958         emitcode ("movx", "@dptr,a");
10959         emitcode ("inc", "dptr");
10960         emitcode ("inc", "dptr");
10961         emitcode ("mov","a,b");
10962         emitcode ("orl","a,_ap");
10963         emitcode ("jz","!tlabel",lbl1->key+100);
10964         emitcode ("mov","a,_ap");
10965         emitcode ("add","a,#!constbyte",0xFF);
10966         emitcode ("mov","_ap,a");
10967         emitcode ("mov","a,b");
10968         emitcode ("addc","a,#!constbyte",0xFF);
10969         emitcode ("mov","b,a");
10970         emitcode ("sjmp","!tlabel",lbl->key+100);
10971         emitcode ("","!tlabeldef",lbl1->key+100);
10972     }
10973     emitcode ("mov", "dps,#0"); 
10974     freeAsmop (count, NULL, ic, FALSE);
10975     unsavermask(rsave);
10976
10977 }
10978
10979 /*-----------------------------------------------------------------*/
10980 /* genMemsetX - gencode for memSetX data                           */
10981 /*-----------------------------------------------------------------*/
10982 static void genMemsetX(iCode *ic, int nparms, operand **parms)
10983 {
10984     operand *to , *val , *count;
10985     symbol *lbl;
10986     char *l;
10987     int i;
10988     bitVect *rsave = NULL;
10989
10990     /* we know it has to be 3 parameters */
10991     assert (nparms == 3);
10992     
10993     to = parms[0];
10994     val = parms[1];
10995     count = parms[2];
10996         
10997     /* save DPTR if it needs to be saved */
10998     rsave = newBitVect(16);
10999     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11000             if (bitVectBitValue(ic->rMask,i))
11001                     rsave = bitVectSetBit(rsave,i);
11002     }
11003     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11004                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11005     savermask(rsave);
11006
11007     aopOp (to, ic, FALSE, FALSE);
11008     /* get "to" into DPTR */
11009     /* if the operand is already in dptr
11010        then we do nothing else we move the value to dptr */
11011     if (AOP_TYPE (to) != AOP_STR) {
11012         /* if already in DPTR then we need to push */
11013         if (AOP_TYPE(to) == AOP_DPTR) {
11014             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
11015             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
11016             if (options.model == MODEL_FLAT24)
11017                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11018             emitcode ("pop", "dph");
11019             emitcode ("pop", "dpl");        
11020         } else {
11021             _startLazyDPSEvaluation ();
11022             /* if this is remateriazable */
11023             if (AOP_TYPE (to) == AOP_IMMD) {
11024                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
11025             } else {                    /* we need to get it byte by byte */
11026                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
11027                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
11028                 if (options.model == MODEL_FLAT24) {
11029                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11030                 }
11031             }
11032             _endLazyDPSEvaluation ();
11033         }
11034     }
11035     freeAsmop (to, NULL, ic, FALSE);
11036
11037     aopOp (val, ic->next->next, FALSE,FALSE);
11038     aopOp (count, ic->next->next, FALSE,FALSE);    
11039     lbl =newiTempLabel(NULL);
11040     /* now for the actual copy */
11041     if (AOP_TYPE(count) == AOP_LIT && 
11042         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11043         l = aopGet(AOP (val), 0, FALSE, FALSE, TRUE);
11044         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
11045         MOVA(l);
11046         emitcode ("","!tlabeldef",lbl->key+100);
11047         emitcode ("movx", "@dptr,a");
11048         emitcode ("inc", "dptr");
11049         emitcode ("djnz","b,!tlabel",lbl->key+100);
11050     } else {
11051         symbol *lbl1 = newiTempLabel(NULL);
11052         
11053         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
11054         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
11055         emitcode ("","!tlabeldef",lbl->key+100);
11056         l = aopGet(AOP (val), 0, FALSE, FALSE, TRUE);
11057         MOVA(l);
11058         emitcode ("movx", "a,@dptr");
11059         emitcode ("inc", "dptr");
11060         emitcode ("mov","a,b");
11061         emitcode ("orl","a,_ap");
11062         emitcode ("jz","!tlabel",lbl1->key+100);
11063         emitcode ("mov","a,_ap");
11064         emitcode ("add","a,#!constbyte",0xFF);
11065         emitcode ("mov","_ap,a");
11066         emitcode ("mov","a,b");
11067         emitcode ("addc","a,#!constbyte",0xFF);
11068         emitcode ("mov","b,a");
11069         emitcode ("sjmp","!tlabel",lbl->key+100);
11070         emitcode ("","!tlabeldef",lbl1->key+100);
11071     }
11072     freeAsmop (count, NULL, ic, FALSE);
11073     unsavermask(rsave);
11074 }
11075
11076 /*-----------------------------------------------------------------*/
11077 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
11078 /*-----------------------------------------------------------------*/
11079 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
11080 {
11081         bitVect *rsave ;
11082         operand *pnum, *result;
11083         int i;
11084     
11085         assert (nparms==1);
11086         /* save registers that need to be saved */
11087         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11088                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11089     
11090         pnum = parms[0]; 
11091         aopOp (pnum, ic, FALSE, FALSE);
11092         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,FALSE));
11093         freeAsmop (pnum, NULL, ic, FALSE);
11094         emitcode ("lcall","NatLib_LoadPrimitive");
11095         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11096         if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) || 
11097             aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
11098                 for (i = (size-1) ; i >= 0 ; i-- ) {
11099                         emitcode ("push","a%s",javaRet[i]);
11100                 }
11101                 for (i=0; i < size ; i++ ) {
11102                         emitcode ("pop","a%s",aopGet(AOP(result),i,FALSE,FALSE,FALSE));
11103                 }
11104         } else {
11105                 for (i = 0 ; i < size ; i++ ) {
11106                         aopPut(AOP(result),javaRet[i],i);
11107                 }
11108         }    
11109         freeAsmop (result, NULL, ic, FALSE);
11110         unsavermask(rsave);
11111 }
11112
11113 /*-----------------------------------------------------------------*/
11114 /* genNatLibLoadPointer - calls TINI api function to load pointer  */
11115 /*-----------------------------------------------------------------*/
11116 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
11117 {
11118         bitVect *rsave ;
11119         operand *pnum, *result;
11120         int size = 3;
11121         int i;
11122     
11123         assert (nparms==1);
11124         /* save registers that need to be saved */
11125         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11126                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11127     
11128         pnum = parms[0]; 
11129         aopOp (pnum, ic, FALSE, FALSE);
11130         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,FALSE));
11131         freeAsmop (pnum, NULL, ic, FALSE);
11132         emitcode ("lcall","NatLib_LoadPointer");
11133         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11134         if (AOP_TYPE(result)!=AOP_STR) {
11135                 for (i = 0 ; i < size ; i++ ) {
11136                         aopPut(AOP(result),fReturn[i],i);
11137                 }
11138         }    
11139         freeAsmop (result, NULL, ic, FALSE);
11140         unsavermask(rsave);
11141 }
11142
11143 /*-----------------------------------------------------------------*/
11144 /* genNatLibInstallStateBlock -                                    */
11145 /*-----------------------------------------------------------------*/
11146 static void genNatLibInstallStateBlock(iCode *ic, int nparms, 
11147                                        operand **parms, const char *name)
11148 {
11149         bitVect *rsave ;
11150         operand *psb, *handle;
11151         assert (nparms==2);
11152
11153         /* save registers that need to be saved */
11154         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11155                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11156         psb = parms[0];
11157         handle = parms[1];
11158
11159         /* put pointer to state block into DPTR1 */
11160         aopOp (psb, ic, FALSE, FALSE);
11161         if (AOP_TYPE (psb) == AOP_IMMD) {
11162                 emitcode ("mov","dps,#1");
11163                 emitcode ("mov", "dptr,%s", aopGet (AOP (psb), 0, TRUE, FALSE, FALSE));
11164                 emitcode ("mov","dps,#0");
11165         } else {
11166                 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,FALSE));
11167                 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,FALSE));
11168                 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,FALSE));
11169         }
11170         freeAsmop (psb, NULL, ic, FALSE);
11171
11172         /* put libraryID into DPTR */
11173         emitcode ("mov","dptr,#LibraryID");
11174
11175         /* put handle into r3:r2 */
11176         aopOp (handle, ic, FALSE, FALSE);
11177         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11178                 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));  
11179                 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11180                 emitcode ("pop","ar3");
11181                 emitcode ("pop","ar2");
11182         } else {        
11183                 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));        
11184                 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11185         }
11186         freeAsmop (psb, NULL, ic, FALSE);
11187
11188         /* make the call */
11189         emitcode ("lcall","NatLib_Install%sStateBlock",name);
11190
11191         /* put return value into place*/
11192         _G.accInUse++;
11193         aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
11194         _G.accInUse--;
11195         aopPut(AOP(IC_RESULT(ic)),"a",0);
11196         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11197         unsavermask(rsave);
11198 }
11199
11200 /*-----------------------------------------------------------------*/
11201 /* genNatLibRemoveStateBlock -                                     */
11202 /*-----------------------------------------------------------------*/
11203 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
11204 {
11205         bitVect *rsave ;
11206
11207         assert(nparms==0);
11208
11209         /* save registers that need to be saved */
11210         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11211                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11212
11213         /* put libraryID into DPTR */
11214         emitcode ("mov","dptr,#LibraryID");
11215         /* make the call */
11216         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
11217         unsavermask(rsave);
11218 }
11219
11220 /*-----------------------------------------------------------------*/
11221 /* genNatLibGetStateBlock -                                        */
11222 /*-----------------------------------------------------------------*/
11223 static void genNatLibGetStateBlock(iCode *ic,int nparms,
11224                                    operand **parms,const char *name)
11225 {
11226         bitVect *rsave ;
11227         symbol *lbl = newiTempLabel(NULL);
11228         
11229         assert(nparms==0);
11230         /* save registers that need to be saved */
11231         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11232                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11233
11234         /* put libraryID into DPTR */
11235         emitcode ("mov","dptr,#LibraryID");
11236         /* make the call */
11237         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
11238         emitcode ("jnz","!tlabel",lbl->key+100);
11239
11240         /* put return value into place */
11241         aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
11242         if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
11243                 emitcode ("push","ar3");
11244                 emitcode ("push","ar2");
11245                 emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,FALSE));
11246                 emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,FALSE));
11247         } else {
11248                 aopPut(AOP(IC_RESULT(ic)),"r2",0);
11249                 aopPut(AOP(IC_RESULT(ic)),"r3",1);
11250         }
11251         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11252         emitcode ("","!tlabeldef",lbl->key+100);
11253         unsavermask(rsave);
11254 }
11255
11256 /*-----------------------------------------------------------------*/
11257 /* genMMMalloc -                                                   */
11258 /*-----------------------------------------------------------------*/
11259 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
11260                          int size, const char *name)
11261 {
11262         bitVect *rsave ;
11263         operand *bsize;
11264         symbol *rsym;
11265         symbol *lbl = newiTempLabel(NULL);
11266
11267         assert (nparms == 1);
11268         /* save registers that need to be saved */
11269         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11270                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
11271         
11272         bsize=parms[0];
11273         aopOp (bsize,ic,FALSE,FALSE);
11274
11275         /* put the size in R4-R2 */
11276         if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
11277                 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,FALSE));
11278                 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,FALSE));
11279                 if (size==3) {
11280                         emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,FALSE));
11281                         emitcode("pop","ar4");
11282                 }
11283                 emitcode("pop","ar3");
11284                 emitcode("pop","ar2");          
11285         } else {
11286                 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,FALSE));
11287                 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,FALSE));
11288                 if (size==3) {
11289                         emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,FALSE));
11290                 }
11291         }
11292         freeAsmop (bsize, NULL, ic, FALSE);
11293
11294         /* make the call */
11295         emitcode ("lcall","MM_%s",name);
11296         emitcode ("jz","!tlabel",lbl->key+100);
11297         emitcode ("mov","r2,#!constbyte",0xff);
11298         emitcode ("mov","r3,#!constbyte",0xff);
11299         emitcode ("","!tlabeldef",lbl->key+100);
11300         /* we don't care about the pointer : we just save the handle */
11301         rsym = OP_SYMBOL(IC_RESULT(ic));
11302         if (rsym->liveFrom != rsym->liveTo) {
11303                 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
11304                 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
11305                         emitcode ("push","ar3");
11306                         emitcode ("push","ar2");
11307                         emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,FALSE));
11308                         emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,FALSE));
11309                 } else {
11310                         aopPut(AOP(IC_RESULT(ic)),"r2",0);
11311                         aopPut(AOP(IC_RESULT(ic)),"r3",1);
11312                 }
11313                 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11314         }
11315         unsavermask(rsave);
11316 }
11317
11318 /*-----------------------------------------------------------------*/
11319 /* genMMDeref -                                                    */
11320 /*-----------------------------------------------------------------*/
11321 static void genMMDeref (iCode *ic,int nparms, operand **parms)
11322 {
11323         bitVect *rsave ;
11324         operand *handle;
11325
11326         assert (nparms == 1);
11327         /* save registers that need to be saved */
11328         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11329                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
11330         
11331         handle=parms[0];
11332         aopOp (handle,ic,FALSE,FALSE);
11333
11334         /* put the size in R4-R2 */
11335         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11336                 emitcode("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11337                 emitcode("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11338                 emitcode("pop","ar3");
11339                 emitcode("pop","ar2");          
11340         } else {
11341                 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11342                 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11343         }
11344         freeAsmop (handle, NULL, ic, FALSE);
11345
11346         /* make the call */
11347         emitcode ("lcall","MM_Deref");
11348         
11349         {
11350                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11351                 if (rsym->liveFrom != rsym->liveTo) {                   
11352                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11353                         if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
11354                                 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
11355                                 aopPut(AOP(IC_RESULT(ic)),"dph",1);
11356                                 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
11357                         }
11358                 }
11359         }
11360         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11361         unsavermask(rsave);
11362 }
11363
11364 /*-----------------------------------------------------------------*/
11365 /* genMMUnrestrictedPersist -                                      */
11366 /*-----------------------------------------------------------------*/
11367 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
11368 {
11369         bitVect *rsave ;
11370         operand *handle;
11371
11372         assert (nparms == 1);
11373         /* save registers that need to be saved */
11374         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11375                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
11376         
11377         handle=parms[0];
11378         aopOp (handle,ic,FALSE,FALSE);
11379
11380         /* put the size in R3-R2 */
11381         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11382                 emitcode("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11383                 emitcode("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11384                 emitcode("pop","ar3");
11385                 emitcode("pop","ar2");          
11386         } else {
11387                 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11388                 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11389         }
11390         freeAsmop (handle, NULL, ic, FALSE);
11391
11392         /* make the call */
11393         emitcode ("lcall","MM_UnrestrictedPersist");
11394
11395         {
11396                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11397                 if (rsym->liveFrom != rsym->liveTo) {   
11398                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11399                         aopPut(AOP(IC_RESULT(ic)),"a",0);
11400                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11401                 }
11402         }
11403         unsavermask(rsave);
11404 }
11405
11406 /*-----------------------------------------------------------------*/
11407 /* genSystemExecJavaProcess -                                      */
11408 /*-----------------------------------------------------------------*/
11409 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
11410 {
11411         bitVect *rsave ;
11412         operand *handle, *pp;
11413
11414         assert (nparms==2);
11415         /* save registers that need to be saved */
11416         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11417                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
11418         
11419         pp = parms[0];
11420         handle = parms[1];
11421         
11422         /* put the handle in R3-R2 */
11423         aopOp (handle,ic,FALSE,FALSE);
11424         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11425                 emitcode("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11426                 emitcode("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11427                 emitcode("pop","ar3");
11428                 emitcode("pop","ar2");          
11429         } else {
11430                 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11431                 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11432         }
11433         freeAsmop (handle, NULL, ic, FALSE);
11434         
11435         /* put pointer in DPTR */
11436         aopOp (pp,ic,FALSE,FALSE);
11437         if (AOP_TYPE(pp) == AOP_IMMD) {
11438                 emitcode ("mov", "dptr,%s", aopGet (AOP (pp), 0, TRUE, FALSE, FALSE));          
11439         } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
11440                 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,FALSE));
11441                 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,FALSE));
11442                 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,FALSE));
11443         }
11444         freeAsmop (handle, NULL, ic, FALSE);
11445
11446         /* make the call */
11447         emitcode ("lcall","System_ExecJavaProcess");
11448         
11449         /* put result in place */
11450         {
11451                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11452                 if (rsym->liveFrom != rsym->liveTo) {   
11453                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11454                         aopPut(AOP(IC_RESULT(ic)),"a",0);
11455                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11456                 }
11457         }
11458         
11459         unsavermask(rsave);
11460 }
11461
11462 /*-----------------------------------------------------------------*/
11463 /* genSystemRTCRegisters -                                         */
11464 /*-----------------------------------------------------------------*/
11465 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
11466                                   char *name)
11467 {
11468         bitVect *rsave ;
11469         operand *pp;
11470
11471         assert (nparms==1);
11472         /* save registers that need to be saved */
11473         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11474                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
11475         
11476         pp=parms[0];
11477         /* put pointer in DPTR */
11478         aopOp (pp,ic,FALSE,FALSE);
11479         if (AOP_TYPE (pp) == AOP_IMMD) {
11480                 emitcode ("mov","dps,#1");
11481                 emitcode ("mov", "dptr,%s", aopGet (AOP (pp), 0, TRUE, FALSE, FALSE));
11482                 emitcode ("mov","dps,#0");
11483         } else {
11484                 emitcode ("mov","dpl1,%s",aopGet(AOP(pp),0,FALSE,FALSE,FALSE));
11485                 emitcode ("mov","dph1,%s",aopGet(AOP(pp),1,FALSE,FALSE,FALSE));
11486                 emitcode ("mov","dpx1,%s",aopGet(AOP(pp),2,FALSE,FALSE,FALSE));
11487         }
11488         freeAsmop (pp, NULL, ic, FALSE);
11489
11490         /* make the call */
11491         emitcode ("lcall","System_%sRTCRegisters",name);
11492
11493         unsavermask(rsave);
11494 }
11495
11496 /*-----------------------------------------------------------------*/
11497 /* genSystemThreadSleep -                                          */
11498 /*-----------------------------------------------------------------*/
11499 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
11500 {
11501         bitVect *rsave ;
11502         operand *to, *s;
11503
11504         assert (nparms==1);
11505         /* save registers that need to be saved */
11506         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11507                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
11508
11509         to = parms[0];
11510         aopOp(to,ic,FALSE,FALSE);
11511         if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
11512             aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
11513                 emitcode ("push","%s",aopGet(AOP(to),0,FALSE,TRUE,FALSE));
11514                 emitcode ("push","%s",aopGet(AOP(to),1,FALSE,TRUE,FALSE));
11515                 emitcode ("push","%s",aopGet(AOP(to),2,FALSE,TRUE,FALSE));
11516                 emitcode ("push","%s",aopGet(AOP(to),3,FALSE,TRUE,FALSE));
11517                 emitcode ("pop","ar3");
11518                 emitcode ("pop","ar2");
11519                 emitcode ("pop","ar1");
11520                 emitcode ("pop","ar0");
11521         } else {
11522                 emitcode ("mov","r0,%s",aopGet(AOP(to),0,FALSE,TRUE,FALSE));
11523                 emitcode ("mov","r1,%s",aopGet(AOP(to),1,FALSE,TRUE,FALSE));
11524                 emitcode ("mov","r2,%s",aopGet(AOP(to),2,FALSE,TRUE,FALSE));
11525                 emitcode ("mov","r3,%s",aopGet(AOP(to),3,FALSE,TRUE,FALSE));
11526         }
11527         freeAsmop (to, NULL, ic, FALSE);
11528
11529         /* suspend in acc */
11530         s = parms[1];
11531         aopOp(s,ic,FALSE,FALSE);
11532         emitcode ("mov","a,%s",aopGet(AOP(s),0,FALSE,TRUE,FALSE));
11533         freeAsmop (s, NULL, ic, FALSE);
11534
11535         /* make the call */
11536         emitcode ("lcall","System_%s",name);
11537
11538         unsavermask(rsave);
11539 }
11540
11541 /*-----------------------------------------------------------------*/
11542 /* genSystemThreadResume -                                         */
11543 /*-----------------------------------------------------------------*/
11544 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
11545 {
11546         bitVect *rsave ;
11547         operand *tid,*pid;
11548
11549         assert (nparms==2);
11550         /* save registers that need to be saved */
11551         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11552                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11553         
11554         tid = parms[0];
11555         pid = parms[1];
11556         
11557         /* PID in R0 */
11558         aopOp(pid,ic,FALSE,FALSE);
11559         emitcode ("mov","r0,%s",aopGet(AOP(pid),0,FALSE,TRUE,FALSE));
11560         freeAsmop (pid, NULL, ic, FALSE);
11561         
11562         /* tid into ACC */
11563         aopOp(tid,ic,FALSE,FALSE);
11564         emitcode ("mov","a,%s",aopGet(AOP(tid),0,FALSE,TRUE,FALSE));
11565         freeAsmop (tid, NULL, ic, FALSE);
11566         
11567         emitcode ("lcall","System_ThreadResume");
11568
11569         /* put result into place */
11570         {
11571                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11572                 if (rsym->liveFrom != rsym->liveTo) {   
11573                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11574                         aopPut(AOP(IC_RESULT(ic)),"a",0);
11575                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11576                 }
11577         }
11578         unsavermask(rsave);
11579 }
11580
11581 /*-----------------------------------------------------------------*/
11582 /* genSystemProcessResume -                                        */
11583 /*-----------------------------------------------------------------*/
11584 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
11585 {
11586         bitVect *rsave ;
11587         operand *pid;
11588
11589         assert (nparms==1);
11590         /* save registers that need to be saved */
11591         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11592                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11593         
11594         pid = parms[0];
11595         
11596         /* pid into ACC */
11597         aopOp(pid,ic,FALSE,FALSE);
11598         emitcode ("mov","a,%s",aopGet(AOP(pid),0,FALSE,TRUE,FALSE));
11599         freeAsmop (pid, NULL, ic, FALSE);
11600         
11601         emitcode ("lcall","System_ProcessResume");
11602
11603         unsavermask(rsave);
11604 }
11605
11606 /*-----------------------------------------------------------------*/
11607 /* genSystem -                                                     */
11608 /*-----------------------------------------------------------------*/
11609 static void genSystem (iCode *ic,int nparms,char *name)
11610 {
11611         assert(nparms == 0);
11612
11613         emitcode ("lcall","System_%s",name);
11614 }
11615
11616 /*-----------------------------------------------------------------*/
11617 /* genSystemPoll -                                                  */
11618 /*-----------------------------------------------------------------*/
11619 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
11620 {
11621         bitVect *rsave ;
11622         operand *fp;
11623
11624         assert (nparms==1);
11625         /* save registers that need to be saved */
11626         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11627                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11628
11629         fp = parms[0];
11630         aopOp (fp,ic,FALSE,FALSE);
11631         if (AOP_TYPE (fp) == AOP_IMMD) {
11632                 emitcode ("mov", "dptr,%s", aopGet (AOP (fp), 0, TRUE, FALSE, FALSE));
11633         } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
11634                 emitcode ("mov","dpl,%s",aopGet(AOP(fp),0,FALSE,FALSE,FALSE));
11635                 emitcode ("mov","dph,%s",aopGet(AOP(fp),1,FALSE,FALSE,FALSE));
11636                 emitcode ("mov","dpx,%s",aopGet(AOP(fp),2,FALSE,FALSE,FALSE));
11637         }
11638         freeAsmop (fp, NULL, ic, FALSE);
11639
11640         emitcode ("lcall","System_%sPoll",name);
11641
11642         /* put result into place */
11643         {
11644                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11645                 if (rsym->liveFrom != rsym->liveTo) {   
11646                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11647                         aopPut(AOP(IC_RESULT(ic)),"a",0);
11648                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11649                 }
11650         }
11651         unsavermask(rsave);
11652 }
11653
11654 /*-----------------------------------------------------------------*/
11655 /* genSystemGetCurrentID -                                         */
11656 /*-----------------------------------------------------------------*/
11657 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
11658 {
11659         assert (nparms==0);
11660
11661         emitcode ("lcall","System_GetCurrent%sId",name);
11662         /* put result into place */
11663         {
11664                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11665                 if (rsym->liveFrom != rsym->liveTo) {   
11666                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11667                         aopPut(AOP(IC_RESULT(ic)),"a",0);
11668                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11669                 }
11670         }
11671 }
11672
11673 /*-----------------------------------------------------------------*/
11674 /* genBuiltIn - calls the appropriate function to  generating code */
11675 /* for a built in function                                         */
11676 /*-----------------------------------------------------------------*/
11677 static void genBuiltIn (iCode *ic)
11678 {
11679         operand *bi_parms[MAX_BUILTIN_ARGS];
11680         int nbi_parms;
11681         iCode *bi_iCode;
11682         symbol *bif;
11683
11684         /* get all the arguments for a built in function */
11685         bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
11686
11687         /* which function is it */
11688         bif = OP_SYMBOL(IC_LEFT(bi_iCode));
11689         if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
11690                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
11691         } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
11692                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
11693         } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
11694                 genMemsetX(bi_iCode,nbi_parms,bi_parms);
11695         } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
11696                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
11697         } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
11698                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
11699         } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
11700                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
11701         } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
11702                 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
11703         } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
11704                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
11705         } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
11706                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
11707         } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
11708                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
11709         } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
11710                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
11711         } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
11712                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
11713         } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
11714                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
11715         } else if (strcmp(bif->name,"MM_XMalloc")==0) {
11716                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
11717         } else if (strcmp(bif->name,"MM_Malloc")==0) {
11718                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
11719         } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
11720                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
11721         } else if (strcmp(bif->name,"MM_Free")==0) {
11722                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
11723         } else if (strcmp(bif->name,"MM_Deref")==0) {
11724                 genMMDeref(bi_iCode,nbi_parms,bi_parms);
11725         } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
11726                 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
11727         } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
11728                 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
11729         } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
11730                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
11731         } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
11732                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
11733         } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
11734                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
11735         } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
11736                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
11737         } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
11738                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
11739         } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
11740                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
11741         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
11742                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
11743         } else if (strcmp(bif->name,"System_SaveThread")==0) {
11744                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
11745         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
11746                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
11747         } else if (strcmp(bif->name,"System_ProcessResume")==0) {
11748                 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
11749         } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
11750                 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
11751         } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
11752                 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
11753         } else if (strcmp(bif->name,"System_ProcessYield")==0) {
11754                 genSystem(bi_iCode,nbi_parms,"ProcessYield");
11755         } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
11756                 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
11757         } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
11758                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
11759         } else if (strcmp(bif->name,"System_RemovePoll")==0) {
11760                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
11761         } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
11762                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
11763         } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
11764                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
11765         } else {
11766                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
11767                 return ;
11768         }
11769         return ;    
11770 }
11771
11772 /*-----------------------------------------------------------------*/
11773 /* gen390Code - generate code for Dallas 390 based controllers     */
11774 /*-----------------------------------------------------------------*/
11775 void
11776 gen390Code (iCode * lic)
11777 {
11778   iCode *ic;
11779   int cln = 0;
11780
11781   lineHead = lineCurr = NULL;
11782
11783   if (options.model == MODEL_FLAT24) {
11784     fReturnSizeDS390 = 5;
11785     fReturn = fReturn24;
11786   } else {
11787     fReturnSizeDS390 = 4;
11788     fReturn = fReturn16;
11789     options.stack10bit=0;
11790   }
11791 #if 1
11792   /* print the allocation information */
11793   if (allocInfo)
11794     printAllocInfo (currFunc, codeOutFile);
11795 #endif
11796   /* if debug information required */
11797   if (options.debug && currFunc)
11798     {
11799       cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
11800       _G.debugLine = 1;
11801       if (IS_STATIC (currFunc->etype))
11802         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
11803       else
11804         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
11805       _G.debugLine = 0;
11806     }
11807   /* stack pointer name */
11808   if (options.useXstack)
11809     spname = "_spx";
11810   else
11811     spname = "sp";
11812
11813
11814   for (ic = lic; ic; ic = ic->next)
11815     {
11816
11817       if (cln != ic->lineno)
11818         {
11819           if (options.debug)
11820             {
11821               _G.debugLine = 1;
11822               emitcode ("", "C$%s$%d$%d$%d ==.",
11823                         FileBaseName (ic->filename), ic->lineno,
11824                         ic->level, ic->block);
11825               _G.debugLine = 0;
11826             }
11827           emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno, 
11828                     printCLine(ic->filename, ic->lineno));
11829           cln = ic->lineno;
11830         }
11831       /* if the result is marked as
11832          spilt and rematerializable or code for
11833          this has already been generated then
11834          do nothing */
11835       if (resultRemat (ic) || ic->generated)
11836         continue;
11837
11838       /* depending on the operation */
11839       switch (ic->op)
11840         {
11841         case '!':
11842           genNot (ic);
11843           break;
11844
11845         case '~':
11846           genCpl (ic);
11847           break;
11848
11849         case UNARYMINUS:
11850           genUminus (ic);
11851           break;
11852
11853         case IPUSH:
11854           genIpush (ic);
11855           break;
11856
11857         case IPOP:
11858           /* IPOP happens only when trying to restore a
11859              spilt live range, if there is an ifx statement
11860              following this pop then the if statement might
11861              be using some of the registers being popped which
11862              would destory the contents of the register so
11863              we need to check for this condition and handle it */
11864           if (ic->next &&
11865               ic->next->op == IFX &&
11866               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11867             genIfx (ic->next, ic);
11868           else
11869             genIpop (ic);
11870           break;
11871
11872         case CALL:
11873           genCall (ic);
11874           break;
11875
11876         case PCALL:
11877           genPcall (ic);
11878           break;
11879
11880         case FUNCTION:
11881           genFunction (ic);
11882           break;
11883
11884         case ENDFUNCTION:
11885           genEndFunction (ic);
11886           break;
11887
11888         case RETURN:
11889           genRet (ic);
11890           break;
11891
11892         case LABEL:
11893           genLabel (ic);
11894           break;
11895
11896         case GOTO:
11897           genGoto (ic);
11898           break;
11899
11900         case '+':
11901           genPlus (ic);
11902           break;
11903
11904         case '-':
11905           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11906             genMinus (ic);
11907           break;
11908
11909         case '*':
11910           genMult (ic);
11911           break;
11912
11913         case '/':
11914           genDiv (ic);
11915           break;
11916
11917         case '%':
11918           genMod (ic);
11919           break;
11920
11921         case '>':
11922           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11923           break;
11924
11925         case '<':
11926           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11927           break;
11928
11929         case LE_OP:
11930         case GE_OP:
11931         case NE_OP:
11932
11933           /* note these two are xlated by algebraic equivalence
11934              during parsing SDCC.y */
11935           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11936                   "got '>=' or '<=' shouldn't have come here");
11937           break;
11938
11939         case EQ_OP:
11940           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11941           break;
11942
11943         case AND_OP:
11944           genAndOp (ic);
11945           break;
11946
11947         case OR_OP:
11948           genOrOp (ic);
11949           break;
11950
11951         case '^':
11952           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11953           break;
11954
11955         case '|':
11956           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11957           break;
11958
11959         case BITWISEAND:
11960           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
11961           break;
11962
11963         case INLINEASM:
11964           genInline (ic);
11965           break;
11966
11967         case RRC:
11968           genRRC (ic);
11969           break;
11970
11971         case RLC:
11972           genRLC (ic);
11973           break;
11974
11975         case GETHBIT:
11976           genGetHbit (ic);
11977           break;
11978
11979         case LEFT_OP:
11980           genLeftShift (ic);
11981           break;
11982
11983         case RIGHT_OP:
11984           genRightShift (ic);
11985           break;
11986
11987         case GET_VALUE_AT_ADDRESS:
11988           genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_LEFT(ic)))));
11989           break;
11990
11991         case '=':
11992           if (POINTER_SET (ic))
11993             genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
11994           else
11995             genAssign (ic);
11996           break;
11997
11998         case IFX:
11999           genIfx (ic, NULL);
12000           break;
12001
12002         case ADDRESS_OF:
12003           genAddrOf (ic);
12004           break;
12005
12006         case JUMPTABLE:
12007           genJumpTab (ic);
12008           break;
12009
12010         case CAST:
12011           genCast (ic);
12012           break;
12013
12014         case RECEIVE:
12015           genReceive (ic);
12016           break;
12017
12018         case SEND:
12019           if (ic->builtinSEND) genBuiltIn(ic);
12020           else addSet (&_G.sendSet, ic);
12021           break;
12022
12023         case ARRAYINIT:
12024             genArrayInit(ic);
12025             break;
12026             
12027         default:
12028           ic = ic;
12029         }
12030     }
12031
12032
12033   /* now we are ready to call the
12034      peep hole optimizer */
12035   if (!options.nopeep)
12036     peepHole (&lineHead);
12037
12038   /* now do the actual printing */
12039   printLine (lineHead, codeOutFile);
12040   return;
12041 }