first pass at including c-code as asm comments
[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 (ic->op == LABEL && IC_LABEL (ic)->key == key)
3320         {
3321           /* printf("findLabelBackwards = %d\n", count); */
3322           return count;
3323         }
3324     }
3325
3326   return 0;
3327 }
3328
3329 /*-----------------------------------------------------------------*/
3330 /* genPlusIncr :- does addition with increment if possible         */
3331 /*-----------------------------------------------------------------*/
3332 static bool
3333 genPlusIncr (iCode * ic)
3334 {
3335   unsigned int icount;
3336   unsigned int size = getDataSize (IC_RESULT (ic));
3337
3338   /* will try to generate an increment */
3339   /* if the right side is not a literal
3340      we cannot */
3341   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3342     return FALSE;
3343
3344   /* if the literal value of the right hand side
3345      is greater than 4 then it is not worth it */
3346   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3347     return FALSE;
3348
3349   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3350       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3351       while (icount--) {
3352           emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
3353       }
3354       return TRUE;
3355   }
3356   /* if increment 16 bits in register */
3357   if (
3358        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3359        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3360        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3361        (size > 1) &&
3362        (icount == 1))
3363     {
3364       symbol *tlbl;
3365       int emitTlbl;
3366       int labelRange;
3367
3368       /* If the next instruction is a goto and the goto target
3369        * is <= 5 instructions previous to this, we can generate
3370        * jumps straight to that target.
3371        */
3372       if (ic->next && ic->next->op == GOTO
3373           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3374           && labelRange <= 5)
3375         {
3376           emitcode (";", "tail increment optimized (range %d)", labelRange);
3377           tlbl = IC_LABEL (ic->next);
3378           emitTlbl = 0;
3379         }
3380       else
3381         {
3382           tlbl = newiTempLabel (NULL);
3383           emitTlbl = 1;
3384         }
3385       emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3386       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3387           IS_AOP_PREG (IC_RESULT (ic)))
3388         emitcode ("cjne", "%s,#0,!tlabel"
3389                   ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3390                   ,tlbl->key + 100);
3391       else
3392         {
3393           emitcode ("clr", "a");
3394           emitcode ("cjne", "a,%s,!tlabel"
3395                     ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3396                     ,tlbl->key + 100);
3397         }
3398
3399       emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3400       if (size > 2)
3401         {
3402           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3403               IS_AOP_PREG (IC_RESULT (ic)))
3404             emitcode ("cjne", "%s,#0,!tlabel"
3405                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3406                       ,tlbl->key + 100);
3407           else
3408             emitcode ("cjne", "a,%s,!tlabel"
3409                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3410                       ,tlbl->key + 100);
3411
3412           emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3413         }
3414       if (size > 3)
3415         {
3416           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3417               IS_AOP_PREG (IC_RESULT (ic)))
3418             emitcode ("cjne", "%s,#0,!tlabel"
3419                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3420                       ,tlbl->key + 100);
3421           else
3422             {
3423               emitcode ("cjne", "a,%s,!tlabel"
3424                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3425                         ,tlbl->key + 100);
3426             }
3427           emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3428         }
3429
3430       if (emitTlbl)
3431         {
3432           emitcode ("", "!tlabeldef", tlbl->key + 100);
3433         }
3434       return TRUE;
3435     }
3436
3437   /* if the sizes are greater than 1 then we cannot */
3438   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3439       AOP_SIZE (IC_LEFT (ic)) > 1)
3440     return FALSE;
3441
3442   /* we can if the aops of the left & result match or
3443      if they are in registers and the registers are the
3444      same */
3445   if (
3446        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3447        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3448        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3449     {
3450
3451       if (icount > 3)
3452         {
3453           MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3454           emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3455           aopPut (AOP (IC_RESULT (ic)), "a", 0);
3456         }
3457       else
3458         {
3459
3460           _startLazyDPSEvaluation ();
3461           while (icount--)
3462             {
3463               emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3464             }
3465           _endLazyDPSEvaluation ();
3466         }
3467
3468       return TRUE;
3469     }
3470
3471   return FALSE;
3472 }
3473
3474 /*-----------------------------------------------------------------*/
3475 /* outBitAcc - output a bit in acc                                 */
3476 /*-----------------------------------------------------------------*/
3477 static void
3478 outBitAcc (operand * result)
3479 {
3480   symbol *tlbl = newiTempLabel (NULL);
3481   /* if the result is a bit */
3482   if (AOP_TYPE (result) == AOP_CRY)
3483     {
3484       aopPut (AOP (result), "a", 0);
3485     }
3486   else
3487     {
3488       emitcode ("jz", "!tlabel", tlbl->key + 100);
3489       emitcode ("mov", "a,%s", one);
3490       emitcode ("", "!tlabeldef", tlbl->key + 100);
3491       outAcc (result);
3492     }
3493 }
3494
3495 /*-----------------------------------------------------------------*/
3496 /* genPlusBits - generates code for addition of two bits           */
3497 /*-----------------------------------------------------------------*/
3498 static void
3499 genPlusBits (iCode * ic)
3500 {
3501   D (emitcode (";", "genPlusBits ");
3502     );
3503   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3504     {
3505       symbol *lbl = newiTempLabel (NULL);
3506       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3507       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3508       emitcode ("cpl", "c");
3509       emitcode ("", "!tlabeldef", (lbl->key + 100));
3510       outBitC (IC_RESULT (ic));
3511     }
3512   else
3513     {
3514       emitcode ("clr", "a");
3515       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3516       emitcode ("rlc", "a");
3517       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3518       emitcode ("addc", "a,#0");
3519       outAcc (IC_RESULT (ic));
3520     }
3521 }
3522
3523 static void
3524 adjustArithmeticResult (iCode * ic)
3525 {
3526   if (opIsGptr (IC_RESULT (ic)) &&
3527       opIsGptr (IC_LEFT (ic)) &&
3528       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3529     {
3530       aopPut (AOP (IC_RESULT (ic)),
3531               aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3532               GPTRSIZE - 1);
3533     }
3534
3535   if (opIsGptr (IC_RESULT (ic)) &&
3536       opIsGptr (IC_RIGHT (ic)) &&
3537       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3538     {
3539       aopPut (AOP (IC_RESULT (ic)),
3540             aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3541               GPTRSIZE - 1);
3542     }
3543
3544   if (opIsGptr (IC_RESULT (ic)) &&
3545       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3546       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3547       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3548       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3549     {
3550       char buffer[5];
3551       sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3552       aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3553     }
3554 }
3555
3556 #if 0 // AOP_OP_3 is deprecated; nobody likes Ack errors.
3557       // Please don't bring it back without a really good reason.
3558 // Macro to aopOp all three operands of an ic. Will fatal if this cannot be done
3559 // (because all three operands are in far space).
3560 #define AOP_OP_3(ic) \
3561     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3562     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3563     aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3564               (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3565     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3566         AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3567     { \
3568         /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3569         fprintf(stderr,                                  \
3570                "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno);   \
3571     }
3572 #endif
3573
3574 // Macro to aopOp all three operands of an ic. If this cannot be done, 
3575 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3576 // will be set TRUE. The caller must then handle the case specially, noting
3577 // that the IC_RESULT operand is not aopOp'd.
3578 #define AOP_OP_3_NOFATAL(ic, rc) \
3579     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3580     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR) || \
3581                                   ((OP_SYMBOL(IC_RESULT(ic))->ruonly) && !isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)))); \
3582     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3583         (isOperandInFarSpace(IC_RESULT(ic)) || (OP_SYMBOL(IC_RESULT(ic))->ruonly && !isOperandEqual(IC_LEFT(ic),IC_RESULT(ic))))) \
3584     { \
3585        /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3586        rc = TRUE; \
3587     }  \
3588     else \
3589     { \
3590        aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3591                                      (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3592        rc = FALSE; \
3593        if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3594            AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3595        { \
3596             /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3597             fprintf(stderr,                                  \
3598                     "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno);   \
3599        } \
3600     }
3601
3602 // aopOp the left & right operands of an ic.
3603 #define AOP_OP_2(ic) \
3604     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3605     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3606
3607 // convienience macro.
3608 #define AOP_SET_LOCALS(ic) \
3609     left = IC_LEFT(ic); \
3610     right = IC_RIGHT(ic); \
3611     result = IC_RESULT(ic);
3612
3613
3614 // Given an integer value of pushedSize bytes on the stack,
3615 // adjust it to be resultSize bytes, either by discarding
3616 // the most significant bytes or by zero-padding.
3617 //
3618 // On exit from this macro, pushedSize will have been adjusted to
3619 // equal resultSize, and ACC may be trashed.
3620 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize)            \
3621       /* If the pushed data is bigger than the result,          \
3622        * simply discard unused bytes. Icky, but works.          \
3623        */                                                       \
3624       while (pushedSize > resultSize)                           \
3625       {                                                         \
3626           D (emitcode (";", "discarding unused result byte."););\
3627           emitcode ("pop", "acc");                              \
3628           pushedSize--;                                         \
3629       }                                                         \
3630       if (pushedSize < resultSize)                              \
3631       {                                                         \
3632           emitcode ("clr", "a");                                \
3633           /* Conversly, we haven't pushed enough here.          \
3634            * just zero-pad, and all is well.                    \
3635            */                                                   \
3636           while (pushedSize < resultSize)                       \
3637           {                                                     \
3638               emitcode("push", "acc");                          \
3639               pushedSize++;                                     \
3640           }                                                     \
3641       }                                                         \
3642       assert(pushedSize == resultSize);
3643
3644 /*-----------------------------------------------------------------*/
3645 /* genPlus - generates code for addition                           */
3646 /*-----------------------------------------------------------------*/
3647 static void
3648 genPlus (iCode * ic)
3649 {
3650   int size, offset = 0;
3651   bool pushResult = FALSE;
3652   int rSize;
3653
3654   D (emitcode (";", "genPlus "););
3655
3656   /* special cases :- */
3657   if ( IS_SYMOP(IC_LEFT(ic)) && OP_SYMBOL(IC_LEFT(ic))->ruonly &&
3658       isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
3659       aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
3660       size = floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
3661       if (size <= 9) {
3662           while (size--) emitcode ("inc","dptr");
3663       } else {
3664           emitcode ("mov","a,dpl");
3665           emitcode ("add","a,#!constbyte",size & 0xff);
3666           emitcode ("mov","dpl,a");
3667           emitcode ("mov","a,dph");
3668           emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
3669           emitcode ("mov","dph,a");
3670           emitcode ("mov","a,dpx");
3671           emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
3672           emitcode ("mov","dpx,a");
3673       }
3674       freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
3675       return ;
3676   }
3677   if ( IS_SYMOP(IC_LEFT(ic)) && 
3678        OP_SYMBOL(IC_LEFT(ic))->remat &&
3679        isOperandInFarSpace(IC_RIGHT(ic))) {
3680       operand *op = IC_RIGHT(ic);
3681       IC_RIGHT(ic) = IC_LEFT(ic);
3682       IC_LEFT(ic) = op;
3683   }
3684                 
3685   AOP_OP_3_NOFATAL (ic, pushResult);
3686   if (pushResult)
3687     {
3688       D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3689     }
3690
3691   if (!pushResult)
3692     {
3693       /* if literal, literal on the right or
3694          if left requires ACC or right is already
3695          in ACC */
3696       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3697        || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3698           || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3699         {
3700           operand *t = IC_RIGHT (ic);
3701           IC_RIGHT (ic) = IC_LEFT (ic);
3702           IC_LEFT (ic) = t;
3703           emitcode (";", "Swapped plus args.");
3704         }
3705
3706       /* if both left & right are in bit
3707          space */
3708       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3709           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3710         {
3711           genPlusBits (ic);
3712           goto release;
3713         }
3714
3715       /* if left in bit space & right literal */
3716       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3717           AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3718         {
3719           emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3720           /* if result in bit space */
3721           if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3722             {
3723               if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3724                 emitcode ("cpl", "c");
3725               outBitC (IC_RESULT (ic));
3726             }
3727           else
3728             {
3729               size = getDataSize (IC_RESULT (ic));
3730               _startLazyDPSEvaluation ();
3731               while (size--)
3732                 {
3733                   MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3734                   emitcode ("addc", "a,#0");
3735                   aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3736                 }
3737               _endLazyDPSEvaluation ();
3738             }
3739           goto release;
3740         }
3741
3742       /* if I can do an increment instead
3743          of add then GOOD for ME */
3744       if (genPlusIncr (ic) == TRUE)
3745         {
3746           emitcode (";", "did genPlusIncr");
3747           goto release;
3748         }
3749
3750     }
3751   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3752
3753   _startLazyDPSEvaluation ();
3754   while (size--)
3755     {
3756       if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
3757         {
3758           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3759           if (offset == 0)
3760             emitcode ("add", "a,%s",
3761                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3762           else
3763             emitcode ("addc", "a,%s",
3764                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3765         }
3766       else
3767         {
3768           if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
3769           {
3770               /* right is going to use ACC or we would have taken the
3771                * above branch.
3772                */
3773               assert(AOP_NEEDSACC(IC_RIGHT(ic)));
3774        TR_AP("#3");
3775               D(emitcode(";", "+ AOP_ACC special case."););
3776               emitcode("xch", "a, %s", DP2_RESULT_REG);
3777           }
3778           MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3779           if (offset == 0)
3780           {
3781             if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
3782             {
3783          TR_AP("#4");
3784                 emitcode("add", "a, %s", DP2_RESULT_REG); 
3785             }
3786             else
3787             {
3788                 emitcode ("add", "a,%s",
3789                         aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE, FALSE));
3790             }
3791           }
3792           else
3793           {
3794             emitcode ("addc", "a,%s",
3795                   aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3796           }
3797         }
3798       if (!pushResult)
3799         {
3800           aopPut (AOP (IC_RESULT (ic)), "a", offset);
3801         }
3802       else
3803         {
3804           emitcode ("push", "acc");
3805         }
3806       offset++;
3807     }
3808   _endLazyDPSEvaluation ();
3809
3810   if (pushResult)
3811     {
3812       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3813
3814       size = getDataSize (IC_LEFT (ic));
3815       rSize = getDataSize (IC_RESULT (ic));
3816
3817       ADJUST_PUSHED_RESULT(size, rSize);
3818
3819       _startLazyDPSEvaluation ();
3820       while (size--)
3821         {
3822           emitcode ("pop", "acc");
3823           aopPut (AOP (IC_RESULT (ic)), "a", size);
3824         }
3825       _endLazyDPSEvaluation ();
3826     }
3827
3828   adjustArithmeticResult (ic);
3829
3830 release:
3831   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3832   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3833   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3834 }
3835
3836 /*-----------------------------------------------------------------*/
3837 /* genMinusDec :- does subtraction with deccrement if possible     */
3838 /*-----------------------------------------------------------------*/
3839 static bool
3840 genMinusDec (iCode * ic)
3841 {
3842   unsigned int icount;
3843   unsigned int size = getDataSize (IC_RESULT (ic));
3844
3845   /* will try to generate an increment */
3846   /* if the right side is not a literal
3847      we cannot */
3848   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3849     return FALSE;
3850
3851   /* if the literal value of the right hand side
3852      is greater than 4 then it is not worth it */
3853   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3854     return FALSE;
3855
3856   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3857       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3858       while (icount--) {
3859           emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
3860       }
3861       return TRUE;
3862   }
3863   /* if decrement 16 bits in register */
3864   if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3865       AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3866       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3867       (size > 1) &&
3868       (icount == 1))
3869     {
3870       symbol *tlbl;
3871       int emitTlbl;
3872       int labelRange;
3873
3874       /* If the next instruction is a goto and the goto target
3875          * is <= 5 instructions previous to this, we can generate
3876          * jumps straight to that target.
3877        */
3878       if (ic->next && ic->next->op == GOTO
3879           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3880           && labelRange <= 5)
3881         {
3882           emitcode (";", "tail decrement optimized (range %d)", labelRange);
3883           tlbl = IC_LABEL (ic->next);
3884           emitTlbl = 0;
3885         }
3886       else
3887         {
3888           tlbl = newiTempLabel (NULL);
3889           emitTlbl = 1;
3890         }
3891
3892       emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3893       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3894           AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3895           IS_AOP_PREG (IC_RESULT (ic)))
3896         emitcode ("cjne", "%s,#!constbyte,!tlabel"
3897                   ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE), 0xff
3898                   ,tlbl->key + 100);
3899       else
3900         {
3901           emitcode ("mov", "a,#!constbyte",0xff);
3902           emitcode ("cjne", "a,%s,!tlabel"
3903                     ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3904                     ,tlbl->key + 100);
3905         }
3906       emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3907       if (size > 2)
3908         {
3909           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3910               AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3911               IS_AOP_PREG (IC_RESULT (ic)))
3912             emitcode ("cjne", "%s,#!constbyte,!tlabel"
3913                       ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE),0xff
3914                       ,tlbl->key + 100);
3915           else
3916             {
3917               emitcode ("cjne", "a,%s,!tlabel"
3918                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3919                         ,tlbl->key + 100);
3920             }
3921           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3922         }
3923       if (size > 3)
3924         {
3925           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3926               AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3927               IS_AOP_PREG (IC_RESULT (ic)))
3928             emitcode ("cjne", "%s,#!constbyte,!tlabel"
3929                       ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE),0xff
3930                       ,tlbl->key + 100);
3931           else
3932             {
3933               emitcode ("cjne", "a,%s,!tlabel"
3934                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3935                         ,tlbl->key + 100);
3936             }
3937           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3938         }
3939       if (emitTlbl)
3940         {
3941           emitcode ("", "!tlabeldef", tlbl->key + 100);
3942         }
3943       return TRUE;
3944     }
3945
3946   /* if the sizes are greater than 1 then we cannot */
3947   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3948       AOP_SIZE (IC_LEFT (ic)) > 1)
3949     return FALSE;
3950
3951   /* we can if the aops of the left & result match or
3952      if they are in registers and the registers are the
3953      same */
3954   if (
3955        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3956        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3957        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3958     {
3959
3960       _startLazyDPSEvaluation ();
3961       while (icount--)
3962         {
3963           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
3964         }
3965       _endLazyDPSEvaluation ();
3966
3967       return TRUE;
3968     }
3969
3970   return FALSE;
3971 }
3972
3973 /*-----------------------------------------------------------------*/
3974 /* addSign - complete with sign                                    */
3975 /*-----------------------------------------------------------------*/
3976 static void
3977 addSign (operand * result, int offset, int sign)
3978 {
3979   int size = (getDataSize (result) - offset);
3980   if (size > 0)
3981     {
3982       _startLazyDPSEvaluation();
3983       if (sign)
3984         {
3985           emitcode ("rlc", "a");
3986           emitcode ("subb", "a,acc");
3987           while (size--)
3988           {
3989             aopPut (AOP (result), "a", offset++);
3990           }
3991         }
3992       else
3993       {
3994         while (size--)
3995         {
3996           aopPut (AOP (result), zero, offset++);
3997         }
3998       }
3999       _endLazyDPSEvaluation();
4000     }
4001 }
4002
4003 /*-----------------------------------------------------------------*/
4004 /* genMinusBits - generates code for subtraction  of two bits      */
4005 /*-----------------------------------------------------------------*/
4006 static void
4007 genMinusBits (iCode * ic)
4008 {
4009   symbol *lbl = newiTempLabel (NULL);
4010
4011   D (emitcode (";", "genMinusBits "););
4012
4013   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4014     {
4015       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4016       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4017       emitcode ("cpl", "c");
4018       emitcode ("", "!tlabeldef", (lbl->key + 100));
4019       outBitC (IC_RESULT (ic));
4020     }
4021   else
4022     {
4023       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4024       emitcode ("subb", "a,acc");
4025       emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4026       emitcode ("inc", "a");
4027       emitcode ("", "!tlabeldef", (lbl->key + 100));
4028       aopPut (AOP (IC_RESULT (ic)), "a", 0);
4029       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4030     }
4031 }
4032
4033 /*-----------------------------------------------------------------*/
4034 /* genMinus - generates code for subtraction                       */
4035 /*-----------------------------------------------------------------*/
4036 static void
4037 genMinus (iCode * ic)
4038 {
4039   int size, offset = 0;
4040   int rSize;
4041   unsigned long lit = 0L;
4042   bool pushResult = FALSE;
4043
4044   D (emitcode (";", "genMinus "););
4045
4046   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
4047   aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
4048   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
4049       (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
4050     {
4051       pushResult = TRUE;
4052     }
4053   else
4054     {
4055       aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
4056
4057       /* special cases :- */
4058       /* if both left & right are in bit space */
4059       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4060           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4061         {
4062           genMinusBits (ic);
4063           goto release;
4064         }
4065
4066       /* if I can do an decrement instead
4067          of subtract then GOOD for ME */
4068       if (genMinusDec (ic) == TRUE)
4069         goto release;
4070
4071     }
4072
4073   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4074
4075   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4076     {
4077       CLRC;
4078     }
4079   else
4080     {
4081       lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4082       lit = -(long) lit;
4083     }
4084
4085
4086   /* if literal, add a,#-lit, else normal subb */
4087   _startLazyDPSEvaluation ();
4088   while (size--)
4089     {
4090       MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
4091       if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4092         emitcode ("subb", "a,%s",
4093                   aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
4094       else
4095         {
4096           /* first add without previous c */
4097           if (!offset) {
4098             if (!size && lit==-1) {
4099               emitcode ("dec", "a");
4100             } else {
4101               emitcode ("add", "a,#!constbyte",
4102                         (unsigned int) (lit & 0x0FFL));
4103             }
4104           } else {
4105             emitcode ("addc", "a,#!constbyte",
4106                       (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4107           }
4108         }
4109
4110       if (pushResult)
4111         {
4112           emitcode ("push", "acc");
4113         }
4114       else
4115         {
4116           aopPut (AOP (IC_RESULT (ic)), "a", offset);
4117         }
4118       offset++;
4119     }
4120   _endLazyDPSEvaluation ();
4121
4122   if (pushResult)
4123     {
4124       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4125
4126       size = getDataSize (IC_LEFT (ic));
4127       rSize = getDataSize (IC_RESULT (ic));
4128
4129       ADJUST_PUSHED_RESULT(size, rSize);
4130
4131       _startLazyDPSEvaluation ();
4132       while (size--)
4133         {
4134           emitcode ("pop", "acc");
4135           aopPut (AOP (IC_RESULT (ic)), "a", size);
4136         }
4137       _endLazyDPSEvaluation ();
4138     }
4139
4140   adjustArithmeticResult (ic);
4141
4142 release:
4143   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4144   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4145   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4146 }
4147
4148
4149 /*-----------------------------------------------------------------*/
4150 /* genMultbits :- multiplication of bits                           */
4151 /*-----------------------------------------------------------------*/
4152 static void
4153 genMultbits (operand * left,
4154              operand * right,
4155              operand * result,
4156              iCode   * ic)
4157 {
4158   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4159   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4160   aopOp(result, ic, TRUE, FALSE);
4161   outBitC (result);
4162 }
4163
4164
4165 /*-----------------------------------------------------------------*/
4166 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
4167 /*-----------------------------------------------------------------*/
4168 static void
4169 genMultOneByte (operand * left,
4170                 operand * right,
4171                 operand * result,
4172                 iCode   * ic)
4173 {
4174   sym_link *opetype = operandType (result);
4175   symbol *lbl;
4176
4177
4178   /* (if two literals: the value is computed before) */
4179   /* if one literal, literal on the right */
4180   if (AOP_TYPE (left) == AOP_LIT)
4181     {
4182       operand *t = right;
4183       right = left;
4184       left = t;
4185       emitcode (";", "swapped left and right");
4186     }
4187
4188   if (SPEC_USIGN(opetype)
4189       // ignore the sign of left and right, what else can we do?
4190       || (SPEC_USIGN(operandType(left)) && 
4191           SPEC_USIGN(operandType(right)))) {
4192     // just an unsigned 8*8=8/16 multiply
4193     //emitcode (";","unsigned");
4194     emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4195     MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4196     emitcode ("mul", "ab");
4197    
4198     _G.accInUse++; _G.bInUse++;
4199     aopOp(result, ic, TRUE, FALSE);
4200       
4201       if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4202       {
4203           // this should never happen
4204           fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4205                    AOP_SIZE(result), __FILE__, lineno);
4206           exit (1);
4207       }      
4208       
4209     aopPut (AOP (result), "a", 0);
4210     _G.accInUse--; _G.bInUse--;
4211     if (AOP_SIZE(result)==2) 
4212     {
4213       aopPut (AOP (result), "b", 1);
4214     }
4215     return;
4216   }
4217
4218   // we have to do a signed multiply
4219
4220   emitcode (";", "signed");
4221   emitcode ("clr", "F0"); // reset sign flag
4222   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4223
4224   lbl=newiTempLabel(NULL);
4225   emitcode ("jnb", "acc.7,!tlabel",  lbl->key+100);
4226   // left side is negative, 8-bit two's complement, this fails for -128
4227   emitcode ("setb", "F0"); // set sign flag
4228   emitcode ("cpl", "a");
4229   emitcode ("inc", "a");
4230
4231   emitcode ("", "!tlabeldef", lbl->key+100);
4232
4233   /* if literal */
4234   if (AOP_TYPE(right)==AOP_LIT) {
4235     signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
4236     /* AND literal negative */
4237     if ((int) val < 0) {
4238       emitcode ("cpl", "F0"); // complement sign flag
4239       emitcode ("mov", "b,#!constbyte", -val);
4240     } else {
4241       emitcode ("mov", "b,#!constbyte", val);
4242     }
4243   } else {
4244     lbl=newiTempLabel(NULL);
4245     emitcode ("mov", "b,a");
4246     emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4247     emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4248     // right side is negative, 8-bit two's complement
4249     emitcode ("cpl", "F0"); // complement sign flag
4250     emitcode ("cpl", "a");
4251     emitcode ("inc", "a");
4252     emitcode ("", "!tlabeldef", lbl->key+100);
4253   }
4254   emitcode ("mul", "ab");
4255     
4256   _G.accInUse++;_G.bInUse++;
4257   aopOp(result, ic, TRUE, FALSE);
4258     
4259   if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4260   {
4261     // this should never happen
4262       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4263                AOP_SIZE(result), __FILE__, lineno);
4264       exit (1);
4265   }    
4266     
4267   lbl=newiTempLabel(NULL);
4268   emitcode ("jnb", "F0,!tlabel", lbl->key+100);
4269   // only ONE op was negative, we have to do a 8/16-bit two's complement
4270   emitcode ("cpl", "a"); // lsb
4271   if (AOP_SIZE(result)==1) {
4272     emitcode ("inc", "a");
4273   } else {
4274     emitcode ("add", "a,#1");
4275     emitcode ("xch", "a,b");
4276     emitcode ("cpl", "a"); // msb
4277     emitcode ("addc", "a,#0");
4278     emitcode ("xch", "a,b");
4279   }
4280
4281   emitcode ("", "!tlabeldef", lbl->key+100);
4282   aopPut (AOP (result), "a", 0);
4283   _G.accInUse--;_G.bInUse--;
4284   if (AOP_SIZE(result)==2) {
4285     aopPut (AOP (result), "b", 1);
4286   }
4287 }
4288
4289 /*-----------------------------------------------------------------*/
4290 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply    */
4291 /*-----------------------------------------------------------------*/
4292 static void genMultTwoByte (operand *left, operand *right, 
4293                             operand *result, iCode *ic)
4294 {
4295         sym_link *retype = getSpec(operandType(right));
4296         sym_link *letype = getSpec(operandType(left));
4297         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4298         symbol *lbl;
4299
4300         if (AOP_TYPE (left) == AOP_LIT) {
4301                 operand *t = right;
4302                 right = left;
4303                 left = t;
4304         }
4305         /* save EA bit in F1 */
4306         lbl = newiTempLabel(NULL);
4307         emitcode ("setb","F1");
4308         emitcode ("jbc","EA,!tlabel",lbl->key+100);
4309         emitcode ("clr","F1");
4310         emitcode("","!tlabeldef",lbl->key+100);
4311
4312         /* load up MB with right */
4313         if (!umult) {
4314                 emitcode("clr","F0");
4315                 if (AOP_TYPE(right) == AOP_LIT) {
4316                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
4317                         if (val < 0) {
4318                                 emitcode("setb","F0");
4319                                 val = -val;
4320                         }
4321                         emitcode ("mov","mb,#!constbyte",val & 0xff);
4322                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
4323                 } else {
4324                         lbl = newiTempLabel(NULL);
4325                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4326                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4327                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
4328                         emitcode ("xch", "a,b");
4329                         emitcode ("cpl","a");
4330                         emitcode ("add", "a,#1");
4331                         emitcode ("xch", "a,b");
4332                         emitcode ("cpl", "a"); // msb
4333                         emitcode ("addc", "a,#0");
4334                         emitcode ("setb","F0");
4335                         emitcode ("","!tlabeldef",lbl->key+100);
4336                         emitcode ("mov","mb,b");
4337                         emitcode ("mov","mb,a");
4338                 }
4339         } else {
4340                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4341                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4342         }
4343         /* load up MA with left */
4344         if (!umult) {
4345                 lbl = newiTempLabel(NULL);
4346                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4347                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4348                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4349                 emitcode ("xch", "a,b");
4350                 emitcode ("cpl","a");
4351                 emitcode ("add", "a,#1");
4352                 emitcode ("xch", "a,b");
4353                 emitcode ("cpl", "a"); // msb
4354                 emitcode ("addc","a,#0");
4355                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4356                 emitcode ("setb","F0");
4357                 emitcode ("","!tlabeldef",lbl->key+100);
4358                 emitcode ("mov","ma,b");
4359                 emitcode ("mov","ma,a");
4360         } else {
4361                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4362                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4363         }
4364         /* wait for multiplication to finish */
4365         lbl = newiTempLabel(NULL);
4366         emitcode("","!tlabeldef", lbl->key+100);
4367         emitcode("mov","a,mcnt1");
4368         emitcode("anl","a,#!constbyte",0x80);
4369         emitcode("jnz","!tlabel",lbl->key+100);
4370         
4371         freeAsmop (left, NULL, ic, TRUE);
4372         freeAsmop (right, NULL, ic,TRUE);
4373         aopOp(result, ic, TRUE, FALSE);
4374
4375         /* if unsigned then simple */   
4376         if (umult) {
4377                 emitcode ("mov","a,ma");
4378                 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4379                 emitcode ("mov","a,ma");
4380                 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4381                 aopPut(AOP(result),"ma",1);
4382                 aopPut(AOP(result),"ma",0);
4383         } else {
4384                 emitcode("push","ma");
4385                 emitcode("push","ma");
4386                 emitcode("push","ma");
4387                 MOVA("ma");
4388                 /* negate result if needed */
4389                 lbl = newiTempLabel(NULL);      
4390                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4391                 emitcode("cpl","a");
4392                 emitcode("add","a,#1");
4393                 emitcode("","!tlabeldef", lbl->key+100);
4394                 if (AOP_TYPE(result) == AOP_ACC)
4395                 {
4396                     D(emitcode(";", "ACC special case."););
4397                     /* We know result is the only live aop, and 
4398                      * it's obviously not a DPTR2, so AP is available.
4399                      */
4400                     emitcode("mov", "%s,acc", DP2_RESULT_REG);
4401                 }
4402                 else
4403                 {
4404                     aopPut(AOP(result),"a",0);
4405                 }
4406             
4407                 emitcode("pop","acc");
4408                 lbl = newiTempLabel(NULL);      
4409                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4410                 emitcode("cpl","a");
4411                 emitcode("addc","a,#0");
4412                 emitcode("","!tlabeldef", lbl->key+100);
4413                 aopPut(AOP(result),"a",1);
4414                 emitcode("pop","acc");
4415                 if (AOP_SIZE(result) >= 3) {
4416                         lbl = newiTempLabel(NULL);      
4417                         emitcode("jnb","F0,!tlabel",lbl->key+100);
4418                         emitcode("cpl","a");
4419                         emitcode("addc","a,#0");                        
4420                         emitcode("","!tlabeldef", lbl->key+100);
4421                         aopPut(AOP(result),"a",2);
4422                 }
4423                 emitcode("pop","acc");
4424                 if (AOP_SIZE(result) >= 4) {
4425                         lbl = newiTempLabel(NULL);      
4426                         emitcode("jnb","F0,!tlabel",lbl->key+100);
4427                         emitcode("cpl","a");
4428                         emitcode("addc","a,#0");                        
4429                         emitcode("","!tlabeldef", lbl->key+100);
4430                         aopPut(AOP(result),"a",3);
4431                 }
4432                 if (AOP_TYPE(result) == AOP_ACC)
4433                 {
4434                     /* We stashed the result away above. */
4435                     emitcode("mov", "acc,%s", DP2_RESULT_REG);
4436                 }           
4437                 
4438         }
4439         freeAsmop (result, NULL, ic, TRUE);
4440
4441         /* restore EA bit in F1 */
4442         lbl = newiTempLabel(NULL);
4443         emitcode ("jnb","F1,!tlabel",lbl->key+100);
4444         emitcode ("setb","EA");
4445         emitcode("","!tlabeldef",lbl->key+100);
4446         return ;
4447 }
4448
4449 /*-----------------------------------------------------------------*/
4450 /* genMult - generates code for multiplication                     */
4451 /*-----------------------------------------------------------------*/
4452 static void
4453 genMult (iCode * ic)
4454 {
4455   operand *left = IC_LEFT (ic);
4456   operand *right = IC_RIGHT (ic);
4457   operand *result = IC_RESULT (ic);
4458
4459   D (emitcode (";", "genMult "););
4460
4461   /* assign the amsops */
4462   AOP_OP_2 (ic);
4463
4464   /* special cases first */
4465   /* both are bits */
4466   if (AOP_TYPE (left) == AOP_CRY &&
4467       AOP_TYPE (right) == AOP_CRY)
4468     {
4469       genMultbits (left, right, result, ic);
4470       goto release;
4471     }
4472
4473   /* if both are of size == 1 */
4474   if (AOP_SIZE (left) == 1 &&
4475       AOP_SIZE (right) == 1)
4476     {
4477       genMultOneByte (left, right, result, ic);
4478       goto release;
4479     }
4480
4481   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4482           /* use the ds390 ARITHMETIC accel UNIT */
4483           genMultTwoByte (left, right, result, ic);
4484           return ;
4485   }
4486   /* should have been converted to function call */
4487   assert (0);
4488
4489 release:
4490   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4491   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4492   freeAsmop (result, NULL, ic, TRUE);
4493 }
4494
4495 /*-----------------------------------------------------------------*/
4496 /* genDivbits :- division of bits                                  */
4497 /*-----------------------------------------------------------------*/
4498 static void
4499 genDivbits (operand * left,
4500             operand * right,
4501             operand * result,
4502             iCode   * ic)
4503 {
4504
4505   char *l;
4506
4507   /* the result must be bit */
4508   LOAD_AB_FOR_DIV (left, right, l);
4509   emitcode ("div", "ab");
4510   emitcode ("rrc", "a");
4511   aopOp(result, ic, TRUE, FALSE);
4512     
4513   aopPut (AOP (result), "c", 0);
4514 }
4515
4516 /*-----------------------------------------------------------------*/
4517 /* genDivOneByte : 8 bit division                                  */
4518 /*-----------------------------------------------------------------*/
4519 static void
4520 genDivOneByte (operand * left,
4521                operand * right,
4522                operand * result,
4523                iCode   * ic)
4524 {
4525   sym_link *opetype = operandType (result);
4526   char *l;
4527   symbol *lbl;
4528   int size, offset;
4529
4530   offset = 1;
4531   /* signed or unsigned */
4532   if (SPEC_USIGN (opetype))
4533     {
4534         /* unsigned is easy */
4535         LOAD_AB_FOR_DIV (left, right, l);
4536         emitcode ("div", "ab");
4537
4538         _G.accInUse++;
4539         aopOp(result, ic, TRUE, FALSE);
4540         aopPut (AOP (result), "a", 0);
4541         _G.accInUse--;
4542
4543         size = AOP_SIZE (result) - 1;
4544         
4545         while (size--)
4546         {
4547             aopPut (AOP (result), zero, offset++);
4548         }
4549       return;
4550     }
4551
4552   /* signed is a little bit more difficult */
4553
4554   /* save the signs of the operands */
4555   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4556   MOVA (l);
4557   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4558   emitcode ("push", "acc");     /* save it on the stack */
4559
4560   /* now sign adjust for both left & right */
4561   l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4562   MOVA (l);
4563   lbl = newiTempLabel (NULL);
4564   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4565   emitcode ("cpl", "a");
4566   emitcode ("inc", "a");
4567   emitcode ("", "!tlabeldef", (lbl->key + 100));
4568   emitcode ("mov", "b,a");
4569
4570   /* sign adjust left side */
4571   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4572   MOVA (l);
4573
4574   lbl = newiTempLabel (NULL);
4575   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4576   emitcode ("cpl", "a");
4577   emitcode ("inc", "a");
4578   emitcode ("", "!tlabeldef", (lbl->key + 100));
4579
4580   /* now the division */
4581   emitcode ("nop", "; workaround for DS80C390 div bug.");
4582   emitcode ("div", "ab");
4583   /* we are interested in the lower order
4584      only */
4585   emitcode ("mov", "b,a");
4586   lbl = newiTempLabel (NULL);
4587   emitcode ("pop", "acc");
4588   /* if there was an over flow we don't
4589      adjust the sign of the result */
4590   emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4591   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4592   CLRC;
4593   emitcode ("clr", "a");
4594   emitcode ("subb", "a,b");
4595   emitcode ("mov", "b,a");
4596   emitcode ("", "!tlabeldef", (lbl->key + 100));
4597
4598   /* now we are done */
4599   _G.accInUse++;     _G.bInUse++;
4600     aopOp(result, ic, TRUE, FALSE);
4601     
4602     aopPut (AOP (result), "b", 0);
4603     
4604     size = AOP_SIZE (result) - 1;
4605     
4606     if (size > 0)
4607     {
4608       emitcode ("mov", "c,b.7");
4609       emitcode ("subb", "a,acc");
4610     }
4611     while (size--)
4612     {
4613         aopPut (AOP (result), "a", offset++);
4614     }
4615     _G.accInUse--;     _G.bInUse--;
4616
4617 }
4618
4619 /*-----------------------------------------------------------------*/
4620 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide       */
4621 /*-----------------------------------------------------------------*/
4622 static void genDivTwoByte (operand *left, operand *right, 
4623                             operand *result, iCode *ic)
4624 {
4625         sym_link *retype = getSpec(operandType(right));
4626         sym_link *letype = getSpec(operandType(left));
4627         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4628         symbol *lbl;
4629
4630         /* save EA bit in F1 */
4631         lbl = newiTempLabel(NULL);
4632         emitcode ("setb","F1");
4633         emitcode ("jbc","EA,!tlabel",lbl->key+100);
4634         emitcode ("clr","F1");
4635         emitcode("","!tlabeldef",lbl->key+100);
4636
4637         /* load up MA with left */
4638         if (!umult) {
4639                 emitcode("clr","F0");
4640                 lbl = newiTempLabel(NULL);
4641                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4642                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4643                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4644                 emitcode ("xch", "a,b");
4645                 emitcode ("cpl","a");
4646                 emitcode ("add", "a,#1");
4647                 emitcode ("xch", "a,b");
4648                 emitcode ("cpl", "a"); // msb
4649                 emitcode ("addc","a,#0");
4650                 emitcode ("setb","F0");
4651                 emitcode ("","!tlabeldef",lbl->key+100);
4652                 emitcode ("mov","ma,b");
4653                 emitcode ("mov","ma,a");
4654         } else {
4655                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4656                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4657         }
4658
4659         /* load up MB with right */
4660         if (!umult) {
4661                 if (AOP_TYPE(right) == AOP_LIT) {
4662                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
4663                         if (val < 0) {
4664                                 lbl = newiTempLabel(NULL);
4665                                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4666                                 emitcode("setb","F0");
4667                                 emitcode ("","!tlabeldef",lbl->key+100);
4668                                 val = -val;
4669                         } 
4670                         emitcode ("mov","mb,#!constbyte",val & 0xff);               
4671                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4672                 } else {
4673                         lbl = newiTempLabel(NULL);
4674                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4675                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4676                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
4677                         emitcode ("xch", "a,b");
4678                         emitcode ("cpl","a");
4679                         emitcode ("add", "a,#1");
4680                         emitcode ("xch", "a,b");
4681                         emitcode ("cpl", "a"); // msb
4682                         emitcode ("addc", "a,#0");
4683                         emitcode ("jbc","F0,!tlabel",lbl->key+100);
4684                         emitcode ("setb","F0");
4685                         emitcode ("","!tlabeldef",lbl->key+100);
4686                         emitcode ("mov","mb,b");
4687                         emitcode ("mov","mb,a");
4688                 }
4689         } else {
4690                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4691                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4692         }
4693
4694         /* wait for multiplication to finish */
4695         lbl = newiTempLabel(NULL);
4696         emitcode("","!tlabeldef", lbl->key+100);
4697         emitcode("mov","a,mcnt1");
4698         emitcode("anl","a,#!constbyte",0x80);
4699         emitcode("jnz","!tlabel",lbl->key+100);
4700         
4701         freeAsmop (left, NULL, ic, TRUE);
4702         freeAsmop (right, NULL, ic,TRUE);
4703         aopOp(result, ic, TRUE, FALSE);
4704
4705         /* if unsigned then simple */   
4706         if (umult) {
4707                 aopPut(AOP(result),"ma",1);
4708                 aopPut(AOP(result),"ma",0);
4709         } else {
4710                 emitcode("push","ma");
4711                 MOVA("ma");
4712                 /* negate result if needed */
4713                 lbl = newiTempLabel(NULL);      
4714                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4715                 emitcode("cpl","a");
4716                 emitcode("add","a,#1");
4717                 emitcode("","!tlabeldef", lbl->key+100);
4718                 aopPut(AOP(result),"a",0);
4719                 emitcode("pop","acc");
4720                 lbl = newiTempLabel(NULL);      
4721                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4722                 emitcode("cpl","a");
4723                 emitcode("addc","a,#0");
4724                 emitcode("","!tlabeldef", lbl->key+100);
4725                 aopPut(AOP(result),"a",1);
4726         }
4727         freeAsmop (result, NULL, ic, TRUE);
4728         /* restore EA bit in F1 */
4729         lbl = newiTempLabel(NULL);
4730         emitcode ("jnb","F1,!tlabel",lbl->key+100);
4731         emitcode ("setb","EA");
4732         emitcode("","!tlabeldef",lbl->key+100);
4733         return ;
4734 }
4735
4736 /*-----------------------------------------------------------------*/
4737 /* genDiv - generates code for division                            */
4738 /*-----------------------------------------------------------------*/
4739 static void
4740 genDiv (iCode * ic)
4741 {
4742   operand *left = IC_LEFT (ic);
4743   operand *right = IC_RIGHT (ic);
4744   operand *result = IC_RESULT (ic);
4745
4746   D (emitcode (";", "genDiv "););
4747
4748   /* assign the amsops */
4749   AOP_OP_2 (ic);
4750
4751   /* special cases first */
4752   /* both are bits */
4753   if (AOP_TYPE (left) == AOP_CRY &&
4754       AOP_TYPE (right) == AOP_CRY)
4755     {
4756       genDivbits (left, right, result, ic);
4757       goto release;
4758     }
4759
4760   /* if both are of size == 1 */
4761   if (AOP_SIZE (left) == 1 &&
4762       AOP_SIZE (right) == 1)
4763     {
4764       genDivOneByte (left, right, result, ic);
4765       goto release;
4766     }
4767
4768   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4769           /* use the ds390 ARITHMETIC accel UNIT */
4770           genDivTwoByte (left, right, result, ic);
4771           return ;
4772   }
4773   /* should have been converted to function call */
4774   assert (0);
4775 release:
4776   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4777   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4778   freeAsmop (result, NULL, ic, TRUE);
4779 }
4780
4781 /*-----------------------------------------------------------------*/
4782 /* genModbits :- modulus of bits                                   */
4783 /*-----------------------------------------------------------------*/
4784 static void
4785 genModbits (operand * left,
4786             operand * right,
4787             operand * result,
4788             iCode   * ic)
4789 {
4790
4791   char *l;
4792
4793   /* the result must be bit */
4794   LOAD_AB_FOR_DIV (left, right, l);
4795   emitcode ("div", "ab");
4796   emitcode ("mov", "a,b");
4797   emitcode ("rrc", "a");
4798   aopOp(result, ic, TRUE, FALSE);
4799   aopPut (AOP (result), "c", 0);
4800 }
4801
4802 /*-----------------------------------------------------------------*/
4803 /* genModOneByte : 8 bit modulus                                   */
4804 /*-----------------------------------------------------------------*/
4805 static void
4806 genModOneByte (operand * left,
4807                operand * right,
4808                operand * result,
4809                iCode   * ic)
4810 {
4811   sym_link *opetype = operandType (result);
4812   char *l;
4813   symbol *lbl;
4814
4815   /* signed or unsigned */
4816   if (SPEC_USIGN (opetype))
4817     {
4818       /* unsigned is easy */
4819       LOAD_AB_FOR_DIV (left, right, l);
4820       emitcode ("div", "ab");
4821       aopOp(result, ic, TRUE, FALSE);   
4822       aopPut (AOP (result), "b", 0);
4823       return;
4824     }
4825
4826   /* signed is a little bit more difficult */
4827
4828   /* save the signs of the operands */
4829   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4830   MOVA (l);
4831
4832   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4833   emitcode ("push", "acc");     /* save it on the stack */
4834
4835   /* now sign adjust for both left & right */
4836   l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4837   MOVA (l);
4838
4839   lbl = newiTempLabel (NULL);
4840   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4841   emitcode ("cpl", "a");
4842   emitcode ("inc", "a");
4843   emitcode ("", "!tlabeldef", (lbl->key + 100));
4844   emitcode ("mov", "b,a");
4845
4846   /* sign adjust left side */
4847   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4848   MOVA (l);
4849
4850   lbl = newiTempLabel (NULL);
4851   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4852   emitcode ("cpl", "a");
4853   emitcode ("inc", "a");
4854   emitcode ("", "!tlabeldef", (lbl->key + 100));
4855
4856   /* now the multiplication */
4857   emitcode ("nop", "; workaround for DS80C390 div bug.");
4858   emitcode ("div", "ab");
4859   /* we are interested in the lower order
4860      only */
4861   lbl = newiTempLabel (NULL);
4862   emitcode ("pop", "acc");
4863   /* if there was an over flow we don't
4864      adjust the sign of the result */
4865   emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4866   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4867   CLRC;
4868   emitcode ("clr", "a");
4869   emitcode ("subb", "a,b");
4870   emitcode ("mov", "b,a");
4871   emitcode ("", "!tlabeldef", (lbl->key + 100));
4872   
4873   _G.bInUse++;
4874   /* now we are done */
4875   aopOp(result, ic, TRUE, FALSE);    
4876   aopPut (AOP (result), "b", 0);
4877   _G.bInUse--;
4878
4879 }
4880
4881 /*-----------------------------------------------------------------*/
4882 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus      */
4883 /*-----------------------------------------------------------------*/
4884 static void genModTwoByte (operand *left, operand *right, 
4885                             operand *result, iCode *ic)
4886 {
4887         sym_link *retype = getSpec(operandType(right));
4888         sym_link *letype = getSpec(operandType(left));
4889         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4890         symbol *lbl;
4891
4892         /* load up MA with left */
4893         /* save EA bit in F1 */
4894         lbl = newiTempLabel(NULL);
4895         emitcode ("setb","F1");
4896         emitcode ("jbc","EA,!tlabel",lbl->key+100);
4897         emitcode ("clr","F1");
4898         emitcode("","!tlabeldef",lbl->key+100);
4899
4900         if (!umult) {
4901                 lbl = newiTempLabel(NULL);
4902                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4903                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4904                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4905                 emitcode ("xch", "a,b");
4906                 emitcode ("cpl","a");
4907                 emitcode ("add", "a,#1");
4908                 emitcode ("xch", "a,b");
4909                 emitcode ("cpl", "a"); // msb
4910                 emitcode ("addc","a,#0");
4911                 emitcode ("","!tlabeldef",lbl->key+100);
4912                 emitcode ("mov","ma,b");
4913                 emitcode ("mov","ma,a");
4914         } else {
4915                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4916                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4917         }
4918
4919         /* load up MB with right */
4920         if (!umult) {
4921                 if (AOP_TYPE(right) == AOP_LIT) {
4922                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
4923                         if (val < 0) {
4924                                 val = -val;
4925                         } 
4926                         emitcode ("mov","mb,#!constbyte",val & 0xff);
4927                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
4928                 } else {
4929                         lbl = newiTempLabel(NULL);
4930                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4931                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4932                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
4933                         emitcode ("xch", "a,b");
4934                         emitcode ("cpl","a");
4935                         emitcode ("add", "a,#1");
4936                         emitcode ("xch", "a,b");
4937                         emitcode ("cpl", "a"); // msb
4938                         emitcode ("addc", "a,#0");
4939                         emitcode ("","!tlabeldef",lbl->key+100);
4940                         emitcode ("mov","mb,b");
4941                         emitcode ("mov","mb,a");
4942                 }
4943         } else {
4944                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4945                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4946         }
4947
4948         /* wait for multiplication to finish */
4949         lbl = newiTempLabel(NULL);
4950         emitcode("","!tlabeldef", lbl->key+100);
4951         emitcode("mov","a,mcnt1");
4952         emitcode("anl","a,#!constbyte",0x80);
4953         emitcode("jnz","!tlabel",lbl->key+100);
4954         
4955         freeAsmop (left, NULL, ic, TRUE);
4956         freeAsmop (right, NULL, ic,TRUE);
4957         aopOp(result, ic, TRUE, FALSE);
4958
4959         aopPut(AOP(result),"mb",1);
4960         aopPut(AOP(result),"mb",0);
4961         freeAsmop (result, NULL, ic, TRUE);
4962
4963         /* restore EA bit in F1 */
4964         lbl = newiTempLabel(NULL);
4965         emitcode ("jnb","F1,!tlabel",lbl->key+100);
4966         emitcode ("setb","EA");
4967         emitcode("","!tlabeldef",lbl->key+100);
4968         return ;
4969 }
4970
4971 /*-----------------------------------------------------------------*/
4972 /* genMod - generates code for division                            */
4973 /*-----------------------------------------------------------------*/
4974 static void
4975 genMod (iCode * ic)
4976 {
4977   operand *left = IC_LEFT (ic);
4978   operand *right = IC_RIGHT (ic);
4979   operand *result = IC_RESULT (ic);
4980
4981   D (emitcode (";", "genMod "); );
4982
4983   /* assign the amsops */
4984   AOP_OP_2 (ic);
4985
4986   /* special cases first */
4987   /* both are bits */
4988   if (AOP_TYPE (left) == AOP_CRY &&
4989       AOP_TYPE (right) == AOP_CRY)
4990     {
4991       genModbits (left, right, result, ic);
4992       goto release;
4993     }
4994
4995   /* if both are of size == 1 */
4996   if (AOP_SIZE (left) == 1 &&
4997       AOP_SIZE (right) == 1)
4998     {
4999       genModOneByte (left, right, result, ic);
5000       goto release;
5001     }
5002
5003   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5004           /* use the ds390 ARITHMETIC accel UNIT */
5005           genModTwoByte (left, right, result, ic);
5006           return ;
5007   }
5008
5009   /* should have been converted to function call */
5010   assert (0);
5011
5012 release:
5013   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5014   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5015   freeAsmop (result, NULL, ic, TRUE);
5016 }
5017
5018 /*-----------------------------------------------------------------*/
5019 /* genIfxJump :- will create a jump depending on the ifx           */
5020 /*-----------------------------------------------------------------*/
5021 static void
5022 genIfxJump (iCode * ic, char *jval)
5023 {
5024   symbol *jlbl;
5025   symbol *tlbl = newiTempLabel (NULL);
5026   char *inst;
5027
5028   D (emitcode (";", "genIfxJump ");
5029     );
5030
5031   /* if true label then we jump if condition
5032      supplied is true */
5033   if (IC_TRUE (ic))
5034     {
5035       jlbl = IC_TRUE (ic);
5036       inst = ((strcmp (jval, "a") == 0 ? "jz" :
5037                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5038     }
5039   else
5040     {
5041       /* false label is present */
5042       jlbl = IC_FALSE (ic);
5043       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5044                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5045     }
5046   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5047     emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5048   else
5049     emitcode (inst, "!tlabel", tlbl->key + 100);
5050   emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5051   emitcode ("", "!tlabeldef", tlbl->key + 100);
5052
5053   /* mark the icode as generated */
5054   ic->generated = 1;
5055 }
5056
5057 /*-----------------------------------------------------------------*/
5058 /* genCmp :- greater or less than comparison                       */
5059 /*-----------------------------------------------------------------*/
5060 static void
5061 genCmp (operand * left, operand * right,
5062         iCode * ic, iCode * ifx, int sign)
5063 {
5064   int size, offset = 0;
5065   unsigned long lit = 0L;
5066   operand *result;
5067
5068   D (emitcode (";", "genCmp");
5069     );
5070
5071   result = IC_RESULT (ic);
5072
5073   /* if left & right are bit variables */
5074   if (AOP_TYPE (left) == AOP_CRY &&
5075       AOP_TYPE (right) == AOP_CRY)
5076     {
5077       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5078       emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
5079     }
5080   else
5081     {
5082       /* subtract right from left if at the
5083          end the carry flag is set then we know that
5084          left is greater than right */
5085       size = max (AOP_SIZE (left), AOP_SIZE (right));
5086
5087       /* if unsigned char cmp with lit, do cjne left,#right,zz */
5088       if ((size == 1) && !sign &&
5089           (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5090         {
5091           symbol *lbl = newiTempLabel (NULL);
5092           emitcode ("cjne", "%s,%s,!tlabel",
5093                     aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5094                     aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
5095                     lbl->key + 100);
5096           emitcode ("", "!tlabeldef", lbl->key + 100);
5097         }
5098       else
5099         {
5100           if (AOP_TYPE (right) == AOP_LIT)
5101             {
5102               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5103               /* optimize if(x < 0) or if(x >= 0) */
5104               if (lit == 0L)
5105                 {
5106                   if (!sign)
5107                     {
5108                       CLRC;
5109                     }
5110                   else
5111                     {
5112                       MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
5113
5114                       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5115                       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5116
5117                       aopOp (result, ic, FALSE, FALSE);
5118
5119                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5120                         {
5121                           freeAsmop (result, NULL, ic, TRUE);
5122                           genIfxJump (ifx, "acc.7");
5123                           return;
5124                         }
5125                       else
5126                         {
5127                           emitcode ("rlc", "a");
5128                         }
5129                       goto release_freedLR;
5130                     }
5131                   goto release;
5132                 }
5133             }
5134           CLRC;
5135           while (size--)
5136             {
5137               //emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5138               MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5139               //emitcode (";", "genCmp #2");
5140               if (sign && (size == 0))
5141                 {
5142                     //emitcode (";", "genCmp #3");
5143                   emitcode ("xrl", "a,#!constbyte",0x80);
5144                   if (AOP_TYPE (right) == AOP_LIT)
5145                     {
5146                       unsigned long lit = (unsigned long)
5147                       floatFromVal (AOP (right)->aopu.aop_lit);
5148                       //emitcode (";", "genCmp #3.1");
5149                       emitcode ("subb", "a,#!constbyte",
5150                                 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5151                     }
5152                   else
5153                     {
5154                       //emitcode (";", "genCmp #3.2");
5155                       if (AOP_NEEDSACC (right))
5156                         {
5157                           emitcode ("push", "acc");
5158                         }
5159                       emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
5160                                                        FALSE, FALSE, FALSE));
5161                       emitcode ("xrl", "b,#!constbyte",0x80);
5162                       if (AOP_NEEDSACC (right))
5163                         {
5164                           emitcode ("pop", "acc");
5165                         }
5166                       emitcode ("subb", "a,b");
5167                     }
5168                 }
5169               else
5170                 {
5171                   const char *s;
5172
5173                   //emitcode (";", "genCmp #4");
5174                   if (AOP_NEEDSACC (right))
5175                     {
5176                       /* Yuck!! */
5177                       //emitcode (";", "genCmp #4.1");
5178                       emitcode ("xch", "a, b");
5179                       MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
5180                       emitcode ("xch", "a, b");
5181                       s = "b";
5182                     }
5183                   else
5184                     {
5185                       //emitcode (";", "genCmp #4.2");
5186                       s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
5187                     }
5188
5189                   emitcode ("subb", "a,%s", s);
5190                 }
5191             }
5192         }
5193     }
5194
5195 release:
5196 /* Don't need the left & right operands any more; do need the result. */
5197   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5198   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5199
5200   aopOp (result, ic, FALSE, FALSE);
5201
5202 release_freedLR:
5203
5204   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5205     {
5206       outBitC (result);
5207     }
5208   else
5209     {
5210       /* if the result is used in the next
5211          ifx conditional branch then generate
5212          code a little differently */
5213       if (ifx)
5214         {
5215           genIfxJump (ifx, "c");
5216         }
5217       else
5218         {
5219           outBitC (result);
5220         }
5221       /* leave the result in acc */
5222     }
5223   freeAsmop (result, NULL, ic, TRUE);
5224 }
5225
5226 /*-----------------------------------------------------------------*/
5227 /* genCmpGt :- greater than comparison                             */
5228 /*-----------------------------------------------------------------*/
5229 static void
5230 genCmpGt (iCode * ic, iCode * ifx)
5231 {
5232   operand *left, *right;
5233   sym_link *letype, *retype;
5234   int sign;
5235
5236   D (emitcode (";", "genCmpGt ");
5237     );
5238
5239   left = IC_LEFT (ic);
5240   right = IC_RIGHT (ic);
5241
5242   letype = getSpec (operandType (left));
5243   retype = getSpec (operandType (right));
5244   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5245
5246   /* assign the left & right amsops */
5247   AOP_OP_2 (ic);
5248
5249   genCmp (right, left, ic, ifx, sign);
5250 }
5251
5252 /*-----------------------------------------------------------------*/
5253 /* genCmpLt - less than comparisons                                */
5254 /*-----------------------------------------------------------------*/
5255 static void
5256 genCmpLt (iCode * ic, iCode * ifx)
5257 {
5258   operand *left, *right;
5259   sym_link *letype, *retype;
5260   int sign;
5261
5262   D (emitcode (";", "genCmpLt "););
5263
5264   left = IC_LEFT (ic);
5265   right = IC_RIGHT (ic);
5266
5267   letype = getSpec (operandType (left));
5268   retype = getSpec (operandType (right));
5269   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5270
5271   /* assign the left & right amsops */
5272   AOP_OP_2 (ic);
5273
5274   genCmp (left, right, ic, ifx, sign);
5275 }
5276
5277 /*-----------------------------------------------------------------*/
5278 /* gencjneshort - compare and jump if not equal                    */
5279 /*-----------------------------------------------------------------*/
5280 static void
5281 gencjneshort (operand * left, operand * right, symbol * lbl)
5282 {
5283   int size = max (AOP_SIZE (left), AOP_SIZE (right));
5284   int offset = 0;
5285   unsigned long lit = 0L;
5286
5287   D (emitcode (";", "gencjneshort");
5288     );
5289
5290   /* if the left side is a literal or
5291      if the right is in a pointer register and left
5292      is not */
5293   if ((AOP_TYPE (left) == AOP_LIT) ||
5294       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5295     {
5296       operand *t = right;
5297       right = left;
5298       left = t;
5299     }
5300
5301   if (AOP_TYPE (right) == AOP_LIT)
5302     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5303
5304   if (opIsGptr (left) || opIsGptr (right))
5305     {
5306       /* We are comparing a generic pointer to something.
5307        * Exclude the generic type byte from the comparison.
5308        */
5309       size--;
5310       D (emitcode (";", "cjneshort: generic ptr special case.");
5311         )
5312     }
5313
5314
5315   /* if the right side is a literal then anything goes */
5316   if (AOP_TYPE (right) == AOP_LIT &&
5317       AOP_TYPE (left) != AOP_DIR)
5318     {
5319       while (size--)
5320         {
5321           char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5322           MOVA (l);
5323           emitcode ("cjne", "a,%s,!tlabel",
5324                     aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
5325                     lbl->key + 100);
5326           offset++;
5327         }
5328     }
5329
5330   /* if the right side is in a register or in direct space or
5331      if the left is a pointer register & right is not */
5332   else if (AOP_TYPE (right) == AOP_REG ||
5333            AOP_TYPE (right) == AOP_DIR ||
5334            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5335            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5336     {
5337       while (size--)
5338         {
5339           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5340           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5341               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5342             emitcode ("jnz", "!tlabel", lbl->key + 100);
5343           else
5344             emitcode ("cjne", "a,%s,!tlabel",
5345                       aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
5346                       lbl->key + 100);
5347           offset++;
5348         }
5349     }
5350   else
5351     {
5352       /* right is a pointer reg need both a & b */
5353       while (size--)
5354         {
5355           char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5356           if (strcmp (l, "b"))
5357             emitcode ("mov", "b,%s", l);
5358           MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5359           emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
5360           offset++;
5361         }
5362     }
5363 }
5364
5365 /*-----------------------------------------------------------------*/
5366 /* gencjne - compare and jump if not equal                         */
5367 /*-----------------------------------------------------------------*/
5368 static void
5369 gencjne (operand * left, operand * right, symbol * lbl)
5370 {
5371   symbol *tlbl = newiTempLabel (NULL);
5372
5373   D (emitcode (";", "gencjne");
5374     );
5375
5376   gencjneshort (left, right, lbl);
5377
5378   emitcode ("mov", "a,%s", one);
5379   emitcode ("sjmp", "!tlabel", tlbl->key + 100);
5380   emitcode ("", "!tlabeldef", lbl->key + 100);
5381   emitcode ("clr", "a");
5382   emitcode ("", "!tlabeldef", tlbl->key + 100);
5383 }
5384
5385 /*-----------------------------------------------------------------*/
5386 /* genCmpEq - generates code for equal to                          */
5387 /*-----------------------------------------------------------------*/
5388 static void
5389 genCmpEq (iCode * ic, iCode * ifx)
5390 {
5391   operand *left, *right, *result;
5392
5393   D (emitcode (";", "genCmpEq ");
5394     );
5395
5396   AOP_OP_2 (ic);
5397   AOP_SET_LOCALS (ic);
5398
5399   /* if literal, literal on the right or
5400      if the right is in a pointer register and left
5401      is not */
5402   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5403       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5404     {
5405       operand *t = IC_RIGHT (ic);
5406       IC_RIGHT (ic) = IC_LEFT (ic);
5407       IC_LEFT (ic) = t;
5408     }
5409
5410   if (ifx &&                    /* !AOP_SIZE(result) */
5411       OP_SYMBOL (result) &&
5412       OP_SYMBOL (result)->regType == REG_CND)
5413     {
5414       symbol *tlbl;
5415       /* if they are both bit variables */
5416       if (AOP_TYPE (left) == AOP_CRY &&
5417           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5418         {
5419           if (AOP_TYPE (right) == AOP_LIT)
5420             {
5421               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5422               if (lit == 0L)
5423                 {
5424                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5425                   emitcode ("cpl", "c");
5426                 }
5427               else if (lit == 1L)
5428                 {
5429                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5430                 }
5431               else
5432                 {
5433                   emitcode ("clr", "c");
5434                 }
5435               /* AOP_TYPE(right) == AOP_CRY */
5436             }
5437           else
5438             {
5439               symbol *lbl = newiTempLabel (NULL);
5440               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5441               emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5442               emitcode ("cpl", "c");
5443               emitcode ("", "!tlabeldef", (lbl->key + 100));
5444             }
5445           /* if true label then we jump if condition
5446              supplied is true */
5447           tlbl = newiTempLabel (NULL);
5448           if (IC_TRUE (ifx))
5449             {
5450               emitcode ("jnc", "!tlabel", tlbl->key + 100);
5451               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5452             }
5453           else
5454             {
5455               emitcode ("jc", "!tlabel", tlbl->key + 100);
5456               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5457             }
5458           emitcode ("", "!tlabeldef", tlbl->key + 100);
5459         }
5460       else
5461         {
5462           tlbl = newiTempLabel (NULL);
5463           gencjneshort (left, right, tlbl);
5464           if (IC_TRUE (ifx))
5465             {
5466               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5467               emitcode ("", "!tlabeldef", tlbl->key + 100);
5468             }
5469           else
5470             {
5471               symbol *lbl = newiTempLabel (NULL);
5472               emitcode ("sjmp", "!tlabel", lbl->key + 100);
5473               emitcode ("", "!tlabeldef", tlbl->key + 100);
5474               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5475               emitcode ("", "!tlabeldef", lbl->key + 100);
5476             }
5477         }
5478       /* mark the icode as generated */
5479       ifx->generated = 1;
5480
5481       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5482       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5483       return;
5484     }
5485
5486   /* if they are both bit variables */
5487   if (AOP_TYPE (left) == AOP_CRY &&
5488       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5489     {
5490       if (AOP_TYPE (right) == AOP_LIT)
5491         {
5492           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5493           if (lit == 0L)
5494             {
5495               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5496               emitcode ("cpl", "c");
5497             }
5498           else if (lit == 1L)
5499             {
5500               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5501             }
5502           else
5503             {
5504               emitcode ("clr", "c");
5505             }
5506           /* AOP_TYPE(right) == AOP_CRY */
5507         }
5508       else
5509         {
5510           symbol *lbl = newiTempLabel (NULL);
5511           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5512           emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5513           emitcode ("cpl", "c");
5514           emitcode ("", "!tlabeldef", (lbl->key + 100));
5515         }
5516
5517       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5518       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5519
5520       aopOp (result, ic, TRUE, FALSE);
5521
5522       /* c = 1 if egal */
5523       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5524         {
5525           outBitC (result);
5526           goto release;
5527         }
5528       if (ifx)
5529         {
5530           genIfxJump (ifx, "c");
5531           goto release;
5532         }
5533       /* if the result is used in an arithmetic operation
5534          then put the result in place */
5535       outBitC (result);
5536     }
5537   else
5538     {
5539       gencjne (left, right, newiTempLabel (NULL));
5540
5541       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5542       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5543
5544       aopOp (result, ic, TRUE, FALSE);
5545
5546       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5547         {
5548           aopPut (AOP (result), "a", 0);
5549           goto release;
5550         }
5551       if (ifx)
5552         {
5553           genIfxJump (ifx, "a");
5554           goto release;
5555         }
5556       /* if the result is used in an arithmetic operation
5557          then put the result in place */
5558       if (AOP_TYPE (result) != AOP_CRY)
5559         outAcc (result);
5560       /* leave the result in acc */
5561     }
5562
5563 release:
5564   freeAsmop (result, NULL, ic, TRUE);
5565 }
5566
5567 /*-----------------------------------------------------------------*/
5568 /* ifxForOp - returns the icode containing the ifx for operand     */
5569 /*-----------------------------------------------------------------*/
5570 static iCode *
5571 ifxForOp (operand * op, iCode * ic)
5572 {
5573   /* if true symbol then needs to be assigned */
5574   if (IS_TRUE_SYMOP (op))
5575     return NULL;
5576
5577   /* if this has register type condition and
5578      the next instruction is ifx with the same operand
5579      and live to of the operand is upto the ifx only then */
5580   if (ic->next &&
5581       ic->next->op == IFX &&
5582       IC_COND (ic->next)->key == op->key &&
5583       OP_SYMBOL (op)->liveTo <= ic->next->seq)
5584     return ic->next;
5585
5586   return NULL;
5587 }
5588 /*-----------------------------------------------------------------*/
5589 /* hasInc - operand is incremented before any other use            */
5590 /*-----------------------------------------------------------------*/
5591 static iCode *
5592 hasInc (operand *op, iCode *ic, int osize)
5593 {
5594   sym_link *type = operandType(op);
5595   sym_link *retype = getSpec (type);
5596   iCode *lic = ic->next;
5597   int isize ;
5598   
5599   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5600   if (!IS_SYMOP(op)) return NULL;
5601
5602   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5603   if (IS_AGGREGATE(type->next)) return NULL;
5604   if (osize != (isize = getSize(type->next))) return NULL;
5605
5606   while (lic) {
5607       /* if operand of the form op = op + <sizeof *op> */
5608       if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5609           isOperandEqual(IC_RESULT(lic),op) && 
5610           isOperandLiteral(IC_RIGHT(lic)) &&
5611           operandLitValue(IC_RIGHT(lic)) == isize) {
5612           return lic;
5613       }
5614       /* if the operand used or deffed */
5615       if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5616           return NULL;
5617       }
5618       /* if GOTO or IFX */
5619       if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5620       lic = lic->next;
5621   }
5622   return NULL;
5623 }
5624
5625 /*-----------------------------------------------------------------*/
5626 /* genAndOp - for && operation                                     */
5627 /*-----------------------------------------------------------------*/
5628 static void
5629 genAndOp (iCode * ic)
5630 {
5631   operand *left, *right, *result;
5632   symbol *tlbl;
5633
5634   D (emitcode (";", "genAndOp "););
5635
5636   /* note here that && operations that are in an
5637      if statement are taken away by backPatchLabels
5638      only those used in arthmetic operations remain */
5639   AOP_OP_2 (ic);
5640   AOP_SET_LOCALS (ic);
5641
5642   /* if both are bit variables */
5643   if (AOP_TYPE (left) == AOP_CRY &&
5644       AOP_TYPE (right) == AOP_CRY)
5645     {
5646       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5647       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5648       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5649       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5650   
5651       aopOp (result,ic,FALSE, FALSE);
5652       outBitC (result);
5653     }
5654   else
5655     {
5656       tlbl = newiTempLabel (NULL);
5657       toBoolean (left);
5658       emitcode ("jz", "!tlabel", tlbl->key + 100);
5659       toBoolean (right);
5660       emitcode ("", "!tlabeldef", tlbl->key + 100);
5661       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5662       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5663   
5664       aopOp (result,ic,FALSE, FALSE);
5665       outBitAcc (result);
5666     }
5667     freeAsmop (result, NULL, ic, TRUE);
5668 }
5669
5670
5671 /*-----------------------------------------------------------------*/
5672 /* genOrOp - for || operation                                      */
5673 /*-----------------------------------------------------------------*/
5674 static void
5675 genOrOp (iCode * ic)
5676 {
5677   operand *left, *right, *result;
5678   symbol *tlbl;
5679
5680   D (emitcode (";", "genOrOp "););
5681
5682   /* note here that || operations that are in an
5683      if statement are taken away by backPatchLabels
5684      only those used in arthmetic operations remain */
5685   AOP_OP_2 (ic);
5686   AOP_SET_LOCALS (ic);
5687
5688   /* if both are bit variables */
5689   if (AOP_TYPE (left) == AOP_CRY &&
5690       AOP_TYPE (right) == AOP_CRY)
5691     {
5692       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5693       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5694       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5695       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5696   
5697       aopOp (result,ic,FALSE, FALSE);
5698       
5699       outBitC (result);
5700     }
5701   else
5702     {
5703       tlbl = newiTempLabel (NULL);
5704       toBoolean (left);
5705       emitcode ("jnz", "!tlabel", tlbl->key + 100);
5706       toBoolean (right);
5707       emitcode ("", "!tlabeldef", tlbl->key + 100);
5708       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5709       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5710   
5711       aopOp (result,ic,FALSE, FALSE);
5712       
5713       outBitAcc (result);
5714     }
5715
5716   freeAsmop (result, NULL, ic, TRUE);
5717 }
5718
5719 /*-----------------------------------------------------------------*/
5720 /* isLiteralBit - test if lit == 2^n                               */
5721 /*-----------------------------------------------------------------*/
5722 static int
5723 isLiteralBit (unsigned long lit)
5724 {
5725   unsigned long pw[32] =
5726   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5727    0x100L, 0x200L, 0x400L, 0x800L,
5728    0x1000L, 0x2000L, 0x4000L, 0x8000L,
5729    0x10000L, 0x20000L, 0x40000L, 0x80000L,
5730    0x100000L, 0x200000L, 0x400000L, 0x800000L,
5731    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5732    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5733   int idx;
5734
5735   for (idx = 0; idx < 32; idx++)
5736     if (lit == pw[idx])
5737       return idx + 1;
5738   return 0;
5739 }
5740
5741 /*-----------------------------------------------------------------*/
5742 /* continueIfTrue -                                                */
5743 /*-----------------------------------------------------------------*/
5744 static void
5745 continueIfTrue (iCode * ic)
5746 {
5747   if (IC_TRUE (ic))
5748     emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
5749   ic->generated = 1;
5750 }
5751
5752 /*-----------------------------------------------------------------*/
5753 /* jmpIfTrue -                                                     */
5754 /*-----------------------------------------------------------------*/
5755 static void
5756 jumpIfTrue (iCode * ic)
5757 {
5758   if (!IC_TRUE (ic))
5759     emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
5760   ic->generated = 1;
5761 }
5762
5763 /*-----------------------------------------------------------------*/
5764 /* jmpTrueOrFalse -                                                */
5765 /*-----------------------------------------------------------------*/
5766 static void
5767 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
5768 {
5769   // ugly but optimized by peephole
5770   if (IC_TRUE (ic))
5771     {
5772       symbol *nlbl = newiTempLabel (NULL);
5773       emitcode ("sjmp", "!tlabel", nlbl->key + 100);
5774       emitcode ("", "!tlabeldef", tlbl->key + 100);
5775       emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
5776       emitcode ("", "!tlabeldef", nlbl->key + 100);
5777     }
5778   else
5779     {
5780       emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
5781       emitcode ("", "!tlabeldef", tlbl->key + 100);
5782     }
5783   ic->generated = 1;
5784 }
5785
5786 // Generate code to perform a bit-wise logic operation
5787 // on two operands in far space (assumed to already have been 
5788 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
5789 // in far space. This requires pushing the result on the stack
5790 // then popping it into the result.
5791 static void
5792 genFarFarLogicOp(iCode *ic, char *logicOp)
5793 {
5794       int size, resultSize, compSize;
5795       int offset = 0;
5796       
5797       TR_AP("#5");
5798       D(emitcode(";", "%s special case for 3 far operands.", logicOp););
5799       compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ? 
5800                   AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
5801       
5802       _startLazyDPSEvaluation();
5803       for (size = compSize; (size--); offset++)
5804       {
5805           MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
5806           emitcode ("mov", "%s, acc", DP2_RESULT_REG);
5807           MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
5808           
5809           emitcode (logicOp, "a,%s", DP2_RESULT_REG);
5810           emitcode ("push", "acc");
5811       }
5812       _endLazyDPSEvaluation();
5813      
5814       freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5815       freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5816       aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
5817      
5818       resultSize = AOP_SIZE(IC_RESULT(ic));
5819
5820       ADJUST_PUSHED_RESULT(compSize, resultSize);
5821
5822       _startLazyDPSEvaluation();
5823       while (compSize--)
5824       {
5825           emitcode ("pop", "acc");
5826           aopPut (AOP (IC_RESULT (ic)), "a", compSize);
5827       }
5828       _endLazyDPSEvaluation();
5829       freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
5830 }
5831
5832
5833 /*-----------------------------------------------------------------*/
5834 /* genAnd  - code for and                                          */
5835 /*-----------------------------------------------------------------*/
5836 static void
5837 genAnd (iCode * ic, iCode * ifx)
5838 {
5839   operand *left, *right, *result;
5840   int size, offset = 0;
5841   unsigned long lit = 0L;
5842   int bytelit = 0;
5843   char buffer[10];
5844   bool pushResult;
5845
5846   D (emitcode (";", "genAnd "););
5847
5848   AOP_OP_3_NOFATAL (ic, pushResult);
5849   AOP_SET_LOCALS (ic);
5850
5851   if (pushResult)
5852   {
5853       genFarFarLogicOp(ic, "anl");
5854       return;
5855   }  
5856
5857 #ifdef DEBUG_TYPE
5858   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5859             AOP_TYPE (result),
5860             AOP_TYPE (left), AOP_TYPE (right));
5861   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5862             AOP_SIZE (result),
5863             AOP_SIZE (left), AOP_SIZE (right));
5864 #endif
5865
5866   /* if left is a literal & right is not then exchange them */
5867   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5868 #ifdef LOGIC_OPS_BROKEN      
5869     ||  AOP_NEEDSACC (left)
5870 #endif
5871     )
5872     {
5873       operand *tmp = right;
5874       right = left;
5875       left = tmp;
5876     }
5877
5878   /* if result = right then exchange them */
5879   if (sameRegs (AOP (result), AOP (right)))
5880     {
5881       operand *tmp = right;
5882       right = left;
5883       left = tmp;
5884     }
5885
5886   /* if right is bit then exchange them */
5887   if (AOP_TYPE (right) == AOP_CRY &&
5888       AOP_TYPE (left) != AOP_CRY)
5889     {
5890       operand *tmp = right;
5891       right = left;
5892       left = tmp;
5893     }
5894   if (AOP_TYPE (right) == AOP_LIT)
5895     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5896
5897   size = AOP_SIZE (result);
5898
5899   // if(bit & yy)
5900   // result = bit & yy;
5901   if (AOP_TYPE (left) == AOP_CRY)
5902     {
5903       // c = bit & literal;
5904       if (AOP_TYPE (right) == AOP_LIT)
5905         {
5906           if (lit & 1)
5907             {
5908               if (size && sameRegs (AOP (result), AOP (left)))
5909                 // no change
5910                 goto release;
5911               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5912             }
5913           else
5914             {
5915               // bit(result) = 0;
5916               if (size && (AOP_TYPE (result) == AOP_CRY))
5917                 {
5918                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5919                   goto release;
5920                 }
5921               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5922                 {
5923                   jumpIfTrue (ifx);
5924                   goto release;
5925                 }
5926               emitcode ("clr", "c");
5927             }
5928         }
5929       else
5930         {
5931           if (AOP_TYPE (right) == AOP_CRY)
5932             {
5933               // c = bit & bit;
5934               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5935               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5936             }
5937           else
5938             {
5939               // c = bit & val;
5940               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
5941               // c = lsb
5942               emitcode ("rrc", "a");
5943               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5944             }
5945         }
5946       // bit = c
5947       // val = c
5948       if (size)
5949         outBitC (result);
5950       // if(bit & ...)
5951       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5952         genIfxJump (ifx, "c");
5953       goto release;
5954     }
5955
5956   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5957   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5958   if ((AOP_TYPE (right) == AOP_LIT) &&
5959       (AOP_TYPE (result) == AOP_CRY) &&
5960       (AOP_TYPE (left) != AOP_CRY))
5961     {
5962       int posbit = isLiteralBit (lit);
5963       /* left &  2^n */
5964       if (posbit)
5965         {
5966           posbit--;
5967           MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
5968           // bit = left & 2^n
5969           if (size)
5970             emitcode ("mov", "c,acc.%d", posbit & 0x07);
5971           // if(left &  2^n)
5972           else
5973             {
5974               if (ifx)
5975                 {
5976                   sprintf (buffer, "acc.%d", posbit & 0x07);
5977                   genIfxJump (ifx, buffer);
5978                 }
5979               goto release;
5980             }
5981         }
5982       else
5983         {
5984           symbol *tlbl = newiTempLabel (NULL);
5985           int sizel = AOP_SIZE (left);
5986           if (size)
5987             emitcode ("setb", "c");
5988           while (sizel--)
5989             {
5990               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5991                 {
5992                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5993                   // byte ==  2^n ?
5994                   if ((posbit = isLiteralBit (bytelit)) != 0)
5995                     emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
5996                   else
5997                     {
5998                       if (bytelit != 0x0FFL)
5999                         emitcode ("anl", "a,%s",
6000                           aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
6001                       emitcode ("jnz", "!tlabel", tlbl->key + 100);
6002                     }
6003                 }
6004               offset++;
6005             }
6006           // bit = left & literal
6007           if (size)
6008             {
6009               emitcode ("clr", "c");
6010               emitcode ("", "!tlabeldef", tlbl->key + 100);
6011             }
6012           // if(left & literal)
6013           else
6014             {
6015               if (ifx)
6016                 jmpTrueOrFalse (ifx, tlbl);
6017               goto release;
6018             }
6019         }
6020       outBitC (result);
6021       goto release;
6022     }
6023
6024   /* if left is same as result */
6025   if (sameRegs (AOP (result), AOP (left)))
6026     {
6027       for (; size--; offset++)
6028         {
6029           if (AOP_TYPE (right) == AOP_LIT)
6030             {
6031               if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6032                 continue;
6033               else if (bytelit == 0)
6034                 aopPut (AOP (result), zero, offset);
6035               else if (IS_AOP_PREG (result))
6036                 {
6037                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6038                   emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6039                   aopPut (AOP (result), "a", offset);
6040                 }
6041               else
6042                 emitcode ("anl", "%s,%s",
6043                           aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6044                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6045             }
6046           else
6047             {
6048               if (AOP_TYPE (left) == AOP_ACC)
6049                 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6050               else
6051                 {
6052                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6053                   if (IS_AOP_PREG (result))
6054                     {
6055                       emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6056                       aopPut (AOP (result), "a", offset);
6057
6058                     }
6059                   else
6060                     emitcode ("anl", "%s,a",
6061                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6062                 }
6063             }
6064         }
6065     }
6066   else
6067     {
6068       // left & result in different registers
6069       if (AOP_TYPE (result) == AOP_CRY)
6070         {
6071           // result = bit
6072           // if(size), result in bit
6073           // if(!size && ifx), conditional oper: if(left & right)
6074           symbol *tlbl = newiTempLabel (NULL);
6075           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6076           if (size)
6077             emitcode ("setb", "c");
6078           while (sizer--)
6079             {
6080               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6081                 emitcode ("anl", "a,%s",
6082                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6083               } else {
6084                 if (AOP_TYPE(left)==AOP_ACC) {
6085                   emitcode("mov", "b,a");
6086                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6087                   emitcode("anl", "a,b");
6088                 }else {
6089                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6090                   emitcode ("anl", "a,%s",
6091                             aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6092                 }
6093               }
6094               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6095               offset++;
6096             }
6097           if (size)
6098             {
6099               CLRC;
6100               emitcode ("", "!tlabeldef", tlbl->key + 100);
6101               outBitC (result);
6102             }
6103           else if (ifx)
6104             jmpTrueOrFalse (ifx, tlbl);
6105         }
6106       else
6107         {
6108           for (; (size--); offset++)
6109             {
6110               // normal case
6111               // result = left & right
6112               if (AOP_TYPE (right) == AOP_LIT)
6113                 {
6114                   if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6115                     {
6116                       aopPut (AOP (result),
6117                            aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6118                               offset);
6119                       continue;
6120                     }
6121                   else if (bytelit == 0)
6122                     {
6123                       aopPut (AOP (result), zero, offset);
6124                       continue;
6125                     }
6126                   D (emitcode (";", "better literal AND."););
6127                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6128                   emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6129                                                     FALSE, FALSE, FALSE));
6130
6131                 }
6132               else
6133                 {
6134                   // faster than result <- left, anl result,right
6135                   // and better if result is SFR
6136                   if (AOP_TYPE (left) == AOP_ACC)
6137                     {
6138                       emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
6139                                                        FALSE, FALSE, FALSE));
6140                     }
6141                   else
6142                     {
6143                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6144                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6145                       {
6146                           emitcode("mov", "b,a");
6147                           rOp = "b";
6148                       }
6149                         
6150                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6151                       emitcode ("anl", "a,%s", rOp);
6152                     }                   
6153                 }
6154               aopPut (AOP (result), "a", offset);
6155             }
6156         }
6157     }
6158
6159 release:
6160   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6161   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6162   freeAsmop (result, NULL, ic, TRUE);
6163 }
6164
6165
6166 /*-----------------------------------------------------------------*/
6167 /* genOr  - code for or                                            */
6168 /*-----------------------------------------------------------------*/
6169 static void
6170 genOr (iCode * ic, iCode * ifx)
6171 {
6172   operand *left, *right, *result;
6173   int size, offset = 0;
6174   unsigned long lit = 0L;
6175   bool     pushResult;
6176
6177   D (emitcode (";", "genOr "););
6178
6179   AOP_OP_3_NOFATAL (ic, pushResult);
6180   AOP_SET_LOCALS (ic);
6181
6182   if (pushResult)
6183   {
6184       genFarFarLogicOp(ic, "orl");
6185       return;
6186   }
6187
6188
6189 #ifdef DEBUG_TYPE
6190   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6191             AOP_TYPE (result),
6192             AOP_TYPE (left), AOP_TYPE (right));
6193   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6194             AOP_SIZE (result),
6195             AOP_SIZE (left), AOP_SIZE (right));
6196 #endif
6197
6198   /* if left is a literal & right is not then exchange them */
6199   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6200 #ifdef LOGIC_OPS_BROKEN
6201    || AOP_NEEDSACC (left) // I think this is a net loss now.
6202 #endif      
6203       )
6204     {
6205       operand *tmp = right;
6206       right = left;
6207       left = tmp;
6208     }
6209
6210   /* if result = right then exchange them */
6211   if (sameRegs (AOP (result), AOP (right)))
6212     {
6213       operand *tmp = right;
6214       right = left;
6215       left = tmp;
6216     }
6217
6218   /* if right is bit then exchange them */
6219   if (AOP_TYPE (right) == AOP_CRY &&
6220       AOP_TYPE (left) != AOP_CRY)
6221     {
6222       operand *tmp = right;
6223       right = left;
6224       left = tmp;
6225     }
6226   if (AOP_TYPE (right) == AOP_LIT)
6227     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6228
6229   size = AOP_SIZE (result);
6230
6231   // if(bit | yy)
6232   // xx = bit | yy;
6233   if (AOP_TYPE (left) == AOP_CRY)
6234     {
6235       if (AOP_TYPE (right) == AOP_LIT)
6236         {
6237           // c = bit & literal;
6238           if (lit)
6239             {
6240               // lit != 0 => result = 1
6241               if (AOP_TYPE (result) == AOP_CRY)
6242                 {
6243                   if (size)
6244                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6245                   else if (ifx)
6246                     continueIfTrue (ifx);
6247                   goto release;
6248                 }
6249               emitcode ("setb", "c");
6250             }
6251           else
6252             {
6253               // lit == 0 => result = left
6254               if (size && sameRegs (AOP (result), AOP (left)))
6255                 goto release;
6256               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6257             }
6258         }
6259       else
6260         {
6261           if (AOP_TYPE (right) == AOP_CRY)
6262             {
6263               // c = bit | bit;
6264               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6265               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6266             }
6267           else
6268             {
6269               // c = bit | val;
6270               symbol *tlbl = newiTempLabel (NULL);
6271               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6272                 emitcode ("setb", "c");
6273               emitcode ("jb", "%s,!tlabel",
6274                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
6275               toBoolean (right);
6276               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6277               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6278                 {
6279                   jmpTrueOrFalse (ifx, tlbl);
6280                   goto release;
6281                 }
6282               else
6283                 {
6284                   CLRC;
6285                   emitcode ("", "!tlabeldef", tlbl->key + 100);
6286                 }
6287             }
6288         }
6289       // bit = c
6290       // val = c
6291       if (size)
6292         outBitC (result);
6293       // if(bit | ...)
6294       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6295         genIfxJump (ifx, "c");
6296       goto release;
6297     }
6298
6299   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6300   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6301   if ((AOP_TYPE (right) == AOP_LIT) &&
6302       (AOP_TYPE (result) == AOP_CRY) &&
6303       (AOP_TYPE (left) != AOP_CRY))
6304     {
6305       if (lit)
6306         {
6307           // result = 1
6308           if (size)
6309             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6310           else
6311             continueIfTrue (ifx);
6312           goto release;
6313         }
6314       else
6315         {
6316           // lit = 0, result = boolean(left)
6317           if (size)
6318             emitcode ("setb", "c");
6319           toBoolean (right);
6320           if (size)
6321             {
6322               symbol *tlbl = newiTempLabel (NULL);
6323               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6324               CLRC;
6325               emitcode ("", "!tlabeldef", tlbl->key + 100);
6326             }
6327           else
6328             {
6329               genIfxJump (ifx, "a");
6330               goto release;
6331             }
6332         }
6333       outBitC (result);
6334       goto release;
6335     }
6336
6337   /* if left is same as result */
6338   if (sameRegs (AOP (result), AOP (left)))
6339     {
6340       for (; size--; offset++)
6341         {
6342           if (AOP_TYPE (right) == AOP_LIT)
6343             {
6344               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6345                 {
6346                   continue;
6347                 }
6348               else
6349                 {
6350                   if (IS_AOP_PREG (left))
6351                     {
6352                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6353                       emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6354                       aopPut (AOP (result), "a", offset);
6355                     }
6356                   else
6357                     {
6358                       emitcode ("orl", "%s,%s",
6359                             aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6360                          aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6361                     }
6362                 }
6363             }
6364           else
6365             {
6366               if (AOP_TYPE (left) == AOP_ACC)
6367                 {
6368                   emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6369                 }
6370               else
6371                 {
6372                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6373                   if (IS_AOP_PREG (left))
6374                     {
6375                       emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6376                       aopPut (AOP (result), "a", offset);
6377                     }
6378                   else
6379                     {
6380                       emitcode ("orl", "%s,a",
6381                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6382                     }
6383                 }
6384             }
6385         }
6386     }
6387   else
6388     {
6389       // left & result in different registers
6390       if (AOP_TYPE (result) == AOP_CRY)
6391         {
6392           // result = bit
6393           // if(size), result in bit
6394           // if(!size && ifx), conditional oper: if(left | right)
6395           symbol *tlbl = newiTempLabel (NULL);
6396           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6397           if (size)
6398             emitcode ("setb", "c");
6399           while (sizer--)
6400             {
6401               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6402                 emitcode ("orl", "a,%s",
6403                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6404               } else {
6405                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6406                 emitcode ("orl", "a,%s",
6407                           aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6408               }
6409               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6410               offset++;
6411             }
6412           if (size)
6413             {
6414               CLRC;
6415               emitcode ("", "!tlabeldef", tlbl->key + 100);
6416               outBitC (result);
6417             }
6418           else if (ifx)
6419             jmpTrueOrFalse (ifx, tlbl);
6420         }
6421       else
6422         {
6423             _startLazyDPSEvaluation();
6424           for (; (size--); offset++)
6425             {
6426               // normal case
6427               // result = left & right
6428               if (AOP_TYPE (right) == AOP_LIT)
6429                 {
6430                   if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6431                     {
6432                       aopPut (AOP (result),
6433                            aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6434                               offset);
6435                       continue;
6436                     }
6437                   D (emitcode (";", "better literal OR."););
6438                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6439                   emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
6440                                                     FALSE, FALSE, FALSE));
6441
6442                 }
6443               else
6444                 {
6445                   // faster than result <- left, anl result,right
6446                   // and better if result is SFR
6447                   if (AOP_TYPE (left) == AOP_ACC)
6448                     {
6449                       emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
6450                                                        FALSE, FALSE, FALSE));
6451                     }
6452                   else
6453                     {
6454                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6455                         
6456                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6457                       {
6458                           emitcode("mov", "b,a");
6459                           rOp = "b";
6460                       }
6461                         
6462                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6463                       emitcode ("orl", "a,%s", rOp);
6464                     }
6465                 }
6466               aopPut (AOP (result), "a", offset);
6467             }
6468             _endLazyDPSEvaluation();
6469         }
6470     }
6471
6472 release:
6473   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6474   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6475   freeAsmop (result, NULL, ic, TRUE);
6476 }
6477
6478 /*-----------------------------------------------------------------*/
6479 /* genXor - code for xclusive or                                   */
6480 /*-----------------------------------------------------------------*/
6481 static void
6482 genXor (iCode * ic, iCode * ifx)
6483 {
6484   operand *left, *right, *result;
6485   int size, offset = 0;
6486   unsigned long lit = 0L;
6487   bool pushResult;
6488
6489   D (emitcode (";", "genXor "););
6490
6491   AOP_OP_3_NOFATAL (ic, pushResult);
6492   AOP_SET_LOCALS (ic);
6493
6494   if (pushResult)
6495   {
6496       genFarFarLogicOp(ic, "xrl");
6497       return;
6498   }  
6499
6500 #ifdef DEBUG_TYPE
6501   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6502             AOP_TYPE (result),
6503             AOP_TYPE (left), AOP_TYPE (right));
6504   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6505             AOP_SIZE (result),
6506             AOP_SIZE (left), AOP_SIZE (right));
6507 #endif
6508
6509   /* if left is a literal & right is not ||
6510      if left needs acc & right does not */
6511   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) 
6512 #ifdef LOGIC_OPS_BROKEN      
6513       || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6514 #endif
6515      )
6516     {
6517       operand *tmp = right;
6518       right = left;
6519       left = tmp;
6520     }
6521
6522   /* if result = right then exchange them */
6523   if (sameRegs (AOP (result), AOP (right)))
6524     {
6525       operand *tmp = right;
6526       right = left;
6527       left = tmp;
6528     }
6529
6530   /* if right is bit then exchange them */
6531   if (AOP_TYPE (right) == AOP_CRY &&
6532       AOP_TYPE (left) != AOP_CRY)
6533     {
6534       operand *tmp = right;
6535       right = left;
6536       left = tmp;
6537     }
6538   if (AOP_TYPE (right) == AOP_LIT)
6539     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6540
6541   size = AOP_SIZE (result);
6542
6543   // if(bit ^ yy)
6544   // xx = bit ^ yy;
6545   if (AOP_TYPE (left) == AOP_CRY)
6546     {
6547       if (AOP_TYPE (right) == AOP_LIT)
6548         {
6549           // c = bit & literal;
6550           if (lit >> 1)
6551             {
6552               // lit>>1  != 0 => result = 1
6553               if (AOP_TYPE (result) == AOP_CRY)
6554                 {
6555                   if (size)
6556                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6557                   else if (ifx)
6558                     continueIfTrue (ifx);
6559                   goto release;
6560                 }
6561               emitcode ("setb", "c");
6562             }
6563           else
6564             {
6565               // lit == (0 or 1)
6566               if (lit == 0)
6567                 {
6568                   // lit == 0, result = left
6569                   if (size && sameRegs (AOP (result), AOP (left)))
6570                     goto release;
6571                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6572                 }
6573               else
6574                 {
6575                   // lit == 1, result = not(left)
6576                   if (size && sameRegs (AOP (result), AOP (left)))
6577                     {
6578                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6579                       goto release;
6580                     }
6581                   else
6582                     {
6583                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6584                       emitcode ("cpl", "c");
6585                     }
6586                 }
6587             }
6588
6589         }
6590       else
6591         {
6592           // right != literal
6593           symbol *tlbl = newiTempLabel (NULL);
6594           if (AOP_TYPE (right) == AOP_CRY)
6595             {
6596               // c = bit ^ bit;
6597               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6598             }
6599           else
6600             {
6601               int sizer = AOP_SIZE (right);
6602               // c = bit ^ val
6603               // if val>>1 != 0, result = 1
6604               emitcode ("setb", "c");
6605               while (sizer)
6606                 {
6607                   MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
6608                   if (sizer == 1)
6609                     // test the msb of the lsb
6610                     emitcode ("anl", "a,#!constbyte",0xfe);
6611                   emitcode ("jnz", "!tlabel", tlbl->key + 100);
6612                   sizer--;
6613                 }
6614               // val = (0,1)
6615               emitcode ("rrc", "a");
6616             }
6617           emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6618           emitcode ("cpl", "c");
6619           emitcode ("", "!tlabeldef", (tlbl->key + 100));
6620         }
6621       // bit = c
6622       // val = c
6623       if (size)
6624         outBitC (result);
6625       // if(bit | ...)
6626       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6627         genIfxJump (ifx, "c");
6628       goto release;
6629     }
6630
6631   if (sameRegs (AOP (result), AOP (left)))
6632     {
6633       /* if left is same as result */
6634       for (; size--; offset++)
6635         {
6636           if (AOP_TYPE (right) == AOP_LIT)
6637             {
6638               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6639                 continue;
6640               else if (IS_AOP_PREG (left))
6641                 {
6642                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6643                   emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6644                   aopPut (AOP (result), "a", offset);
6645                 }
6646               else
6647                 emitcode ("xrl", "%s,%s",
6648                           aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6649                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6650             }
6651           else
6652             {
6653               if (AOP_TYPE (left) == AOP_ACC)
6654                 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6655               else
6656                 {
6657                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6658                   if (IS_AOP_PREG (left))
6659                     {
6660                       emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6661                       aopPut (AOP (result), "a", offset);
6662                     }
6663                   else
6664                     emitcode ("xrl", "%s,a",
6665                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6666                 }
6667             }
6668         }
6669     }
6670   else
6671     {
6672       // left & result in different registers
6673       if (AOP_TYPE (result) == AOP_CRY)
6674         {
6675           // result = bit
6676           // if(size), result in bit
6677           // if(!size && ifx), conditional oper: if(left ^ right)
6678           symbol *tlbl = newiTempLabel (NULL);
6679           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6680                   
6681           if (size)
6682             emitcode ("setb", "c");
6683           while (sizer--)
6684             {
6685               if ((AOP_TYPE (right) == AOP_LIT) &&
6686                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6687                 {
6688                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6689                 }
6690               else
6691                 {
6692                   if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6693                     emitcode ("xrl", "a,%s",
6694                               aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6695                   } else {
6696                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6697                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6698                       {
6699                           emitcode("mov", "b,a");
6700                           rOp = "b";
6701                       }
6702                         
6703                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6704                       emitcode ("xrl", "a,%s", rOp);                  
6705                   }
6706                 }
6707               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6708               offset++;
6709             }
6710           if (size)
6711             {
6712               CLRC;
6713               emitcode ("", "!tlabeldef", tlbl->key + 100);
6714               outBitC (result);
6715             }
6716           else if (ifx)
6717             jmpTrueOrFalse (ifx, tlbl);
6718         }
6719       else
6720         {
6721         for (; (size--); offset++)
6722           {
6723             // normal case
6724             // result = left & right
6725             if (AOP_TYPE (right) == AOP_LIT)
6726               {
6727                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6728                   {
6729                     aopPut (AOP (result),
6730                             aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6731                             offset);
6732                     continue;
6733                   }
6734                 D (emitcode (";", "better literal XOR."););
6735                 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6736                 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
6737                                                   FALSE, FALSE, FALSE));
6738               }
6739             else
6740               {
6741                 // faster than result <- left, anl result,right
6742                 // and better if result is SFR
6743                 if (AOP_TYPE (left) == AOP_ACC)
6744                   {
6745                     emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
6746                                                      FALSE, FALSE, FALSE));
6747                   }
6748                 else
6749                   {
6750                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6751                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6752                       {
6753                           emitcode("mov", "b,a");
6754                           rOp = "b";
6755                       }
6756                         
6757                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6758                       emitcode ("xrl", "a,%s", rOp);
6759                   }
6760               }
6761             aopPut (AOP (result), "a", offset);
6762           }
6763         }
6764         
6765     }
6766
6767 release:
6768   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6769   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6770   freeAsmop (result, NULL, ic, TRUE);
6771 }
6772
6773 /*-----------------------------------------------------------------*/
6774 /* genInline - write the inline code out                           */
6775 /*-----------------------------------------------------------------*/
6776 static void
6777 genInline (iCode * ic)
6778 {
6779   char *buffer, *bp, *bp1;
6780
6781   D (emitcode (";", "genInline ");
6782     );
6783
6784   _G.inLine += (!options.asmpeep);
6785
6786   buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6787   strcpy (buffer, IC_INLINE (ic));
6788
6789   /* emit each line as a code */
6790   while (*bp)
6791     {
6792       if (*bp == '\n')
6793         {
6794           *bp++ = '\0';
6795           emitcode (bp1, "");
6796           bp1 = bp;
6797         }
6798       else
6799         {
6800           if (*bp == ':')
6801             {
6802               bp++;
6803               *bp = '\0';
6804               bp++;
6805               emitcode (bp1, "");
6806               bp1 = bp;
6807             }
6808           else
6809             bp++;
6810         }
6811     }
6812   if (bp1 != bp)
6813     emitcode (bp1, "");
6814   /*     emitcode("",buffer); */
6815   _G.inLine -= (!options.asmpeep);
6816 }
6817
6818 /*-----------------------------------------------------------------*/
6819 /* genRRC - rotate right with carry                                */
6820 /*-----------------------------------------------------------------*/
6821 static void
6822 genRRC (iCode * ic)
6823 {
6824   operand *left, *result;
6825   int size, offset = 0;
6826   char *l;
6827
6828   D (emitcode (";", "genRRC ");
6829     );
6830
6831   /* rotate right with carry */
6832   left = IC_LEFT (ic);
6833   result = IC_RESULT (ic);
6834   aopOp (left, ic, FALSE, FALSE);
6835   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6836
6837   /* move it to the result */
6838   size = AOP_SIZE (result);
6839   offset = size - 1;
6840   CLRC;
6841
6842   _startLazyDPSEvaluation ();
6843   while (size--)
6844     {
6845       l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6846       MOVA (l);
6847       emitcode ("rrc", "a");
6848       if (AOP_SIZE (result) > 1)
6849         aopPut (AOP (result), "a", offset--);
6850     }
6851   _endLazyDPSEvaluation ();
6852
6853   /* now we need to put the carry into the
6854      highest order byte of the result */
6855   if (AOP_SIZE (result) > 1)
6856     {
6857       l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
6858       MOVA (l);
6859     }
6860   emitcode ("mov", "acc.7,c");
6861   aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
6862   freeAsmop (left, NULL, ic, TRUE);
6863   freeAsmop (result, NULL, ic, TRUE);
6864 }
6865
6866 /*-----------------------------------------------------------------*/
6867 /* genRLC - generate code for rotate left with carry               */
6868 /*-----------------------------------------------------------------*/
6869 static void
6870 genRLC (iCode * ic)
6871 {
6872   operand *left, *result;
6873   int size, offset = 0;
6874   char *l;
6875
6876   D (emitcode (";", "genRLC ");
6877     );
6878
6879   /* rotate right with carry */
6880   left = IC_LEFT (ic);
6881   result = IC_RESULT (ic);
6882   aopOp (left, ic, FALSE, FALSE);
6883   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6884
6885   /* move it to the result */
6886   size = AOP_SIZE (result);
6887   offset = 0;
6888   if (size--)
6889     {
6890       l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6891       MOVA (l);
6892       emitcode ("add", "a,acc");
6893       if (AOP_SIZE (result) > 1)
6894         {
6895           aopPut (AOP (result), "a", offset++);
6896         }
6897
6898       _startLazyDPSEvaluation ();
6899       while (size--)
6900         {
6901           l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6902           MOVA (l);
6903           emitcode ("rlc", "a");
6904           if (AOP_SIZE (result) > 1)
6905             aopPut (AOP (result), "a", offset++);
6906         }
6907       _endLazyDPSEvaluation ();
6908     }
6909   /* now we need to put the carry into the
6910      highest order byte of the result */
6911   if (AOP_SIZE (result) > 1)
6912     {
6913       l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
6914       MOVA (l);
6915     }
6916   emitcode ("mov", "acc.0,c");
6917   aopPut (AOP (result), "a", 0);
6918   freeAsmop (left, NULL, ic, TRUE);
6919   freeAsmop (result, NULL, ic, TRUE);
6920 }
6921
6922 /*-----------------------------------------------------------------*/
6923 /* genGetHbit - generates code get highest order bit               */
6924 /*-----------------------------------------------------------------*/
6925 static void
6926 genGetHbit (iCode * ic)
6927 {
6928   operand *left, *result;
6929   left = IC_LEFT (ic);
6930   result = IC_RESULT (ic);
6931   aopOp (left, ic, FALSE, FALSE);
6932   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6933
6934   D (emitcode (";", "genGetHbit ");
6935     );
6936
6937   /* get the highest order byte into a */
6938   MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
6939   if (AOP_TYPE (result) == AOP_CRY)
6940     {
6941       emitcode ("rlc", "a");
6942       outBitC (result);
6943     }
6944   else
6945     {
6946       emitcode ("rl", "a");
6947       emitcode ("anl", "a,#1");
6948       outAcc (result);
6949     }
6950
6951
6952   freeAsmop (left, NULL, ic, TRUE);
6953   freeAsmop (result, NULL, ic, TRUE);
6954 }
6955
6956 /*-----------------------------------------------------------------*/
6957 /* AccRol - rotate left accumulator by known count                 */
6958 /*-----------------------------------------------------------------*/
6959 static void
6960 AccRol (int shCount)
6961 {
6962   shCount &= 0x0007;            // shCount : 0..7
6963
6964   switch (shCount)
6965     {
6966     case 0:
6967       break;
6968     case 1:
6969       emitcode ("rl", "a");
6970       break;
6971     case 2:
6972       emitcode ("rl", "a");
6973       emitcode ("rl", "a");
6974       break;
6975     case 3:
6976       emitcode ("swap", "a");
6977       emitcode ("rr", "a");
6978       break;
6979     case 4:
6980       emitcode ("swap", "a");
6981       break;
6982     case 5:
6983       emitcode ("swap", "a");
6984       emitcode ("rl", "a");
6985       break;
6986     case 6:
6987       emitcode ("rr", "a");
6988       emitcode ("rr", "a");
6989       break;
6990     case 7:
6991       emitcode ("rr", "a");
6992       break;
6993     }
6994 }
6995
6996 /*-----------------------------------------------------------------*/
6997 /* AccLsh - left shift accumulator by known count                  */
6998 /*-----------------------------------------------------------------*/
6999 static void
7000 AccLsh (int shCount)
7001 {
7002   if (shCount != 0)
7003     {
7004       if (shCount == 1)
7005         emitcode ("add", "a,acc");
7006       else if (shCount == 2)
7007         {
7008           emitcode ("add", "a,acc");
7009           emitcode ("add", "a,acc");
7010         }
7011       else
7012         {
7013           /* rotate left accumulator */
7014           AccRol (shCount);
7015           /* and kill the lower order bits */
7016           emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7017         }
7018     }
7019 }
7020
7021 /*-----------------------------------------------------------------*/
7022 /* AccRsh - right shift accumulator by known count                 */
7023 /*-----------------------------------------------------------------*/
7024 static void
7025 AccRsh (int shCount)
7026 {
7027   if (shCount != 0)
7028     {
7029       if (shCount == 1)
7030         {
7031           CLRC;
7032           emitcode ("rrc", "a");
7033         }
7034       else
7035         {
7036           /* rotate right accumulator */
7037           AccRol (8 - shCount);
7038           /* and kill the higher order bits */
7039           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7040         }
7041     }
7042 }
7043
7044 #ifdef BETTER_LITERAL_SHIFT
7045 /*-----------------------------------------------------------------*/
7046 /* AccSRsh - signed right shift accumulator by known count                 */
7047 /*-----------------------------------------------------------------*/
7048 static void
7049 AccSRsh (int shCount)
7050 {
7051   symbol *tlbl;
7052   if (shCount != 0)
7053     {
7054       if (shCount == 1)
7055         {
7056           emitcode ("mov", "c,acc.7");
7057           emitcode ("rrc", "a");
7058         }
7059       else if (shCount == 2)
7060         {
7061           emitcode ("mov", "c,acc.7");
7062           emitcode ("rrc", "a");
7063           emitcode ("mov", "c,acc.7");
7064           emitcode ("rrc", "a");
7065         }
7066       else
7067         {
7068           tlbl = newiTempLabel (NULL);
7069           /* rotate right accumulator */
7070           AccRol (8 - shCount);
7071           /* and kill the higher order bits */
7072           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7073           emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7074           emitcode ("orl", "a,#!constbyte",
7075                     (unsigned char) ~SRMask[shCount]);
7076           emitcode ("", "!tlabeldef", tlbl->key + 100);
7077         }
7078     }
7079 }
7080 #endif
7081
7082 #ifdef BETTER_LITERAL_SHIFT
7083 /*-----------------------------------------------------------------*/
7084 /* shiftR1Left2Result - shift right one byte from left to result   */
7085 /*-----------------------------------------------------------------*/
7086 static void
7087 shiftR1Left2Result (operand * left, int offl,
7088                     operand * result, int offr,
7089                     int shCount, int sign)
7090 {
7091   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7092   /* shift right accumulator */
7093   if (sign)
7094     AccSRsh (shCount);
7095   else
7096     AccRsh (shCount);
7097   aopPut (AOP (result), "a", offr);
7098 }
7099 #endif
7100
7101 #ifdef BETTER_LITERAL_SHIFT
7102 /*-----------------------------------------------------------------*/
7103 /* shiftL1Left2Result - shift left one byte from left to result    */
7104 /*-----------------------------------------------------------------*/
7105 static void
7106 shiftL1Left2Result (operand * left, int offl,
7107                     operand * result, int offr, int shCount)
7108 {
7109   MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7110   /* shift left accumulator */
7111   AccLsh (shCount);
7112   aopPut (AOP (result), "a", offr);
7113 }
7114 #endif
7115
7116 #ifdef BETTER_LITERAL_SHIFT
7117 /*-----------------------------------------------------------------*/
7118 /* movLeft2Result - move byte from left to result                  */
7119 /*-----------------------------------------------------------------*/
7120 static void
7121 movLeft2Result (operand * left, int offl,
7122                 operand * result, int offr, int sign)
7123 {
7124   char *l;
7125   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7126   {
7127       l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
7128
7129       if (*l == '@' && (IS_AOP_PREG (result)))
7130       {
7131           emitcode ("mov", "a,%s", l);
7132           aopPut (AOP (result), "a", offr);
7133       }
7134       else
7135       {
7136           if (!sign)
7137           {
7138             aopPut (AOP (result), l, offr);
7139           }
7140           else
7141             {
7142               /* MSB sign in acc.7 ! */
7143               if (getDataSize (left) == offl + 1)
7144                 {
7145                   emitcode ("mov", "a,%s", l);
7146                   aopPut (AOP (result), "a", offr);
7147                 }
7148             }
7149       }
7150   }
7151 }
7152 #endif
7153
7154 #ifdef BETTER_LITERAL_SHIFT
7155 /*-----------------------------------------------------------------*/
7156 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
7157 /*-----------------------------------------------------------------*/
7158 static void
7159 AccAXRrl1 (char *x)
7160 {
7161   emitcode ("rrc", "a");
7162   emitcode ("xch", "a,%s", x);
7163   emitcode ("rrc", "a");
7164   emitcode ("xch", "a,%s", x);
7165 }
7166 #endif
7167
7168 #ifdef BETTER_LITERAL_SHIFT
7169 //REMOVE ME!!!
7170 /*-----------------------------------------------------------------*/
7171 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
7172 /*-----------------------------------------------------------------*/
7173 static void
7174 AccAXLrl1 (char *x)
7175 {
7176   emitcode ("xch", "a,%s", x);
7177   emitcode ("rlc", "a");
7178   emitcode ("xch", "a,%s", x);
7179   emitcode ("rlc", "a");
7180 }
7181 #endif
7182
7183 #ifdef BETTER_LITERAL_SHIFT
7184 /*-----------------------------------------------------------------*/
7185 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
7186 /*-----------------------------------------------------------------*/
7187 static void
7188 AccAXLsh1 (char *x)
7189 {
7190   emitcode ("xch", "a,%s", x);
7191   emitcode ("add", "a,acc");
7192   emitcode ("xch", "a,%s", x);
7193   emitcode ("rlc", "a");
7194 }
7195 #endif
7196
7197 #ifdef BETTER_LITERAL_SHIFT
7198 /*-----------------------------------------------------------------*/
7199 /* AccAXLsh - left shift a:x by known count (0..7)                 */
7200 /*-----------------------------------------------------------------*/
7201 static void
7202 AccAXLsh (char *x, int shCount)
7203 {
7204   switch (shCount)
7205     {
7206     case 0:
7207       break;
7208     case 1:
7209       AccAXLsh1 (x);
7210       break;
7211     case 2:
7212       AccAXLsh1 (x);
7213       AccAXLsh1 (x);
7214       break;
7215     case 3:
7216     case 4:
7217     case 5:                     // AAAAABBB:CCCCCDDD
7218
7219       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
7220
7221       emitcode ("anl", "a,#!constbyte",
7222                 SLMask[shCount]);       // BBB00000:CCCCCDDD
7223
7224       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
7225
7226       AccRol (shCount);         // DDDCCCCC:BBB00000
7227
7228       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
7229
7230       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
7231
7232       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
7233
7234       emitcode ("anl", "a,#!constbyte",
7235                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
7236
7237       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
7238
7239       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
7240
7241       break;
7242     case 6:                     // AAAAAABB:CCCCCCDD
7243       emitcode ("anl", "a,#!constbyte",
7244                 SRMask[shCount]);       // 000000BB:CCCCCCDD
7245       emitcode ("mov", "c,acc.0");      // c = B
7246       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
7247 #if 0
7248       AccAXRrl1 (x);            // BCCCCCCD:D000000B
7249       AccAXRrl1 (x);            // BBCCCCCC:DD000000
7250 #else
7251       emitcode("rrc","a"); 
7252       emitcode("xch","a,%s", x); 
7253       emitcode("rrc","a"); 
7254       emitcode("mov","c,acc.0"); //<< get correct bit 
7255       emitcode("xch","a,%s", x); 
7256
7257       emitcode("rrc","a"); 
7258       emitcode("xch","a,%s", x); 
7259       emitcode("rrc","a"); 
7260       emitcode("xch","a,%s", x); 
7261 #endif
7262       break;
7263     case 7:                     // a:x <<= 7
7264
7265       emitcode ("anl", "a,#!constbyte",
7266                 SRMask[shCount]);       // 0000000B:CCCCCCCD
7267
7268       emitcode ("mov", "c,acc.0");      // c = B
7269
7270       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
7271
7272       AccAXRrl1 (x);            // BCCCCCCC:D0000000
7273
7274       break;
7275     default:
7276       break;
7277     }
7278 }
7279 #endif
7280
7281 #ifdef BETTER_LITERAL_SHIFT
7282 //REMOVE ME!!!
7283 /*-----------------------------------------------------------------*/
7284 /* AccAXRsh - right shift a:x known count (0..7)                   */
7285 /*-----------------------------------------------------------------*/
7286 static void
7287 AccAXRsh (char *x, int shCount)
7288 {
7289   switch (shCount)
7290     {
7291     case 0:
7292       break;
7293     case 1:
7294       CLRC;
7295       AccAXRrl1 (x);            // 0->a:x
7296
7297       break;
7298     case 2:
7299       CLRC;
7300       AccAXRrl1 (x);            // 0->a:x
7301
7302       CLRC;
7303       AccAXRrl1 (x);            // 0->a:x
7304
7305       break;
7306     case 3:
7307     case 4:
7308     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7309
7310       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
7311
7312       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7313
7314       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7315
7316       emitcode ("anl", "a,#!constbyte",
7317                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7318
7319       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7320
7321       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7322
7323       emitcode ("anl", "a,#!constbyte",
7324                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7325
7326       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7327
7328       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7329
7330       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
7331
7332       break;
7333     case 6:                     // AABBBBBB:CCDDDDDD
7334
7335       emitcode ("mov", "c,acc.7");
7336       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7337
7338       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7339
7340       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7341
7342       emitcode ("anl", "a,#!constbyte",
7343                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7344
7345       break;
7346     case 7:                     // ABBBBBBB:CDDDDDDD
7347
7348       emitcode ("mov", "c,acc.7");      // c = A
7349
7350       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7351
7352       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7353
7354       emitcode ("anl", "a,#!constbyte",
7355                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7356
7357       break;
7358     default:
7359       break;
7360     }
7361 }
7362 #endif
7363
7364 #ifdef BETTER_LITERAL_SHIFT
7365 /*-----------------------------------------------------------------*/
7366 /* AccAXRshS - right shift signed a:x known count (0..7)           */
7367 /*-----------------------------------------------------------------*/
7368 static void
7369 AccAXRshS (char *x, int shCount)
7370 {
7371   symbol *tlbl;
7372   switch (shCount)
7373     {
7374     case 0:
7375       break;
7376     case 1:
7377       emitcode ("mov", "c,acc.7");
7378       AccAXRrl1 (x);            // s->a:x
7379
7380       break;
7381     case 2:
7382       emitcode ("mov", "c,acc.7");
7383       AccAXRrl1 (x);            // s->a:x
7384
7385       emitcode ("mov", "c,acc.7");
7386       AccAXRrl1 (x);            // s->a:x
7387
7388       break;
7389     case 3:
7390     case 4:
7391     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7392
7393       tlbl = newiTempLabel (NULL);
7394       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
7395
7396       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7397
7398       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7399
7400       emitcode ("anl", "a,#!constbyte",
7401                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7402
7403       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7404
7405       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7406
7407       emitcode ("anl", "a,#!constbyte",
7408                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7409
7410       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7411
7412       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7413
7414       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
7415
7416       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7417       emitcode ("orl", "a,#!constbyte",
7418                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
7419
7420       emitcode ("", "!tlabeldef", tlbl->key + 100);
7421       break;                    // SSSSAAAA:BBBCCCCC
7422
7423     case 6:                     // AABBBBBB:CCDDDDDD
7424
7425       tlbl = newiTempLabel (NULL);
7426       emitcode ("mov", "c,acc.7");
7427       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7428
7429       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7430
7431       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7432
7433       emitcode ("anl", "a,#!constbyte",
7434                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7435
7436       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7437       emitcode ("orl", "a,#!constbyte",
7438                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
7439
7440       emitcode ("", "!tlabeldef", tlbl->key + 100);
7441       break;
7442     case 7:                     // ABBBBBBB:CDDDDDDD
7443
7444       tlbl = newiTempLabel (NULL);
7445       emitcode ("mov", "c,acc.7");      // c = A
7446
7447       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7448
7449       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7450
7451       emitcode ("anl", "a,#!constbyte",
7452                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7453
7454       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7455       emitcode ("orl", "a,#!constbyte",
7456                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
7457
7458       emitcode ("", "!tlabeldef", tlbl->key + 100);
7459       break;
7460     default:
7461       break;
7462     }
7463 }
7464 #endif
7465
7466 #ifdef BETTER_LITERAL_SHIFT
7467 static void
7468 _loadLeftIntoAx(char    **lsb, 
7469                 operand *left, 
7470                 operand *result,
7471                 int     offl,
7472                 int     offr)
7473 {
7474   // Get the initial value from left into a pair of registers.
7475   // MSB must be in A, LSB can be any register.
7476   //
7477   // If the result is held in registers, it is an optimization
7478   // if the LSB can be held in the register which will hold the,
7479   // result LSB since this saves us from having to copy it into
7480   // the result following AccAXLsh.
7481   //
7482   // If the result is addressed indirectly, this is not a gain.
7483   if (AOP_NEEDSACC(result))
7484   {
7485        char *leftByte;
7486        
7487        _startLazyDPSEvaluation();
7488       if (AOP_TYPE(left) == AOP_DPTR2)
7489        {
7490            // Get MSB in A.
7491            MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
7492            // get LSB in DP2_RESULT_REG.
7493            leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
7494            assert(!strcmp(leftByte, DP2_RESULT_REG));
7495        }
7496        else
7497        {
7498            // get LSB into DP2_RESULT_REG
7499            leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
7500            if (strcmp(leftByte, DP2_RESULT_REG))
7501            {
7502                TR_AP("#7");
7503                emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7504            }
7505            // And MSB in A.
7506            leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
7507            assert(strcmp(leftByte, DP2_RESULT_REG));
7508            MOVA(leftByte);
7509        }
7510        _endLazyDPSEvaluation();
7511        *lsb = DP2_RESULT_REG;
7512   }
7513   else
7514   {
7515       if (sameRegs (AOP (result), AOP (left)) &&
7516         ((offl + MSB16) == offr))
7517       {
7518           /* don't crash result[offr] */
7519           MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
7520           emitcode ("xch", "a,%s", 
7521                     aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
7522       }
7523       else
7524       {
7525           movLeft2Result (left, offl, result, offr, 0);
7526           MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
7527       }
7528       *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
7529       assert(strcmp(*lsb,"a"));      
7530   }
7531 }
7532
7533 static void
7534 _storeAxResults(char    *lsb,
7535                 operand *result,
7536                 int     offr)
7537 {
7538   _startLazyDPSEvaluation();
7539   if (AOP_NEEDSACC(result))
7540   {
7541       /* We have to explicitly update the result LSB.
7542        */
7543       emitcode("xch","a,%s", lsb);
7544       aopPut(AOP(result), "a", offr);
7545       emitcode("mov","a,%s", lsb);
7546   }
7547   if (getDataSize (result) > 1)
7548   {
7549       aopPut (AOP (result), "a", offr + MSB16);
7550   }
7551   _endLazyDPSEvaluation();
7552 }
7553
7554 /*-----------------------------------------------------------------*/
7555 /* shiftL2Left2Result - shift left two bytes from left to result   */
7556 /*-----------------------------------------------------------------*/
7557 static void
7558 shiftL2Left2Result (operand * left, int offl,
7559                     operand * result, int offr, int shCount)
7560 {
7561   char *lsb;
7562
7563   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7564   
7565   AccAXLsh (lsb, shCount);
7566   
7567   _storeAxResults(lsb, result, offr);
7568 }
7569 #endif
7570
7571 #ifdef BETTER_LITERAL_SHIFT
7572 /*-----------------------------------------------------------------*/
7573 /* shiftR2Left2Result - shift right two bytes from left to result  */
7574 /*-----------------------------------------------------------------*/
7575 static void
7576 shiftR2Left2Result (operand * left, int offl,
7577                     operand * result, int offr,
7578                     int shCount, int sign)
7579 {
7580   char *lsb;
7581   
7582   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7583   
7584   /* a:x >> shCount (x = lsb(result)) */
7585   if (sign)
7586   {
7587      AccAXRshS(lsb, shCount);
7588   }
7589   else
7590   {
7591     AccAXRsh(lsb, shCount);
7592   }
7593   
7594   _storeAxResults(lsb, result, offr);
7595 }
7596 #endif
7597
7598 #if 0
7599 //REMOVE ME!!!
7600 /*-----------------------------------------------------------------*/
7601 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7602 /*-----------------------------------------------------------------*/
7603 static void
7604 shiftLLeftOrResult (operand * left, int offl,
7605                     operand * result, int offr, int shCount)
7606 {
7607   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7608   /* shift left accumulator */
7609   AccLsh (shCount);
7610   /* or with result */
7611   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7612   /* back to result */
7613   aopPut (AOP (result), "a", offr);
7614 }
7615 #endif
7616
7617 #if 0
7618 //REMOVE ME!!!
7619 /*-----------------------------------------------------------------*/
7620 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7621 /*-----------------------------------------------------------------*/
7622 static void
7623 shiftRLeftOrResult (operand * left, int offl,
7624                     operand * result, int offr, int shCount)
7625 {
7626   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7627   /* shift right accumulator */
7628   AccRsh (shCount);
7629   /* or with result */
7630   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7631   /* back to result */
7632   aopPut (AOP (result), "a", offr);
7633 }
7634 #endif
7635
7636 #ifdef BETTER_LITERAL_SHIFT
7637 /*-----------------------------------------------------------------*/
7638 /* genlshOne - left shift a one byte quantity by known count       */
7639 /*-----------------------------------------------------------------*/
7640 static void
7641 genlshOne (operand * result, operand * left, int shCount)
7642 {
7643   D (emitcode (";", "genlshOne "););
7644   shiftL1Left2Result (left, LSB, result, LSB, shCount);
7645 }
7646 #endif
7647
7648 #ifdef BETTER_LITERAL_SHIFT
7649 /*-----------------------------------------------------------------*/
7650 /* genlshTwo - left shift two bytes by known amount != 0           */
7651 /*-----------------------------------------------------------------*/
7652 static void
7653 genlshTwo (operand * result, operand * left, int shCount)
7654 {
7655   int size;
7656
7657   D (emitcode (";", "genlshTwo "););
7658
7659   size = getDataSize (result);
7660
7661   /* if shCount >= 8 */
7662   if (shCount >= 8)
7663   {
7664       shCount -= 8;
7665
7666       _startLazyDPSEvaluation();
7667
7668       if (size > 1)
7669         {
7670           if (shCount)
7671           {
7672             _endLazyDPSEvaluation();
7673             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7674             aopPut (AOP (result), zero, LSB);       
7675           }
7676           else
7677           {
7678             movLeft2Result (left, LSB, result, MSB16, 0);
7679             aopPut (AOP (result), zero, LSB);
7680             _endLazyDPSEvaluation();
7681           }
7682         }
7683         else
7684         {
7685           aopPut (AOP (result), zero, LSB);
7686           _endLazyDPSEvaluation();
7687         }
7688   }
7689
7690   /*  1 <= shCount <= 7 */
7691   else
7692     {
7693       if (size == 1)
7694       {
7695         shiftL1Left2Result (left, LSB, result, LSB, shCount);
7696       }
7697       else
7698       {
7699         shiftL2Left2Result (left, LSB, result, LSB, shCount);
7700       }
7701     }
7702 }
7703 #endif
7704
7705 #if 0
7706 //REMOVE ME!!!
7707 /*-----------------------------------------------------------------*/
7708 /* shiftLLong - shift left one long from left to result            */
7709 /* offl = LSB or MSB16                                             */
7710 /*-----------------------------------------------------------------*/
7711 static void
7712 shiftLLong (operand * left, operand * result, int offr)
7713 {
7714   char *l;
7715   int size = AOP_SIZE (result);
7716
7717   if (size >= LSB + offr)
7718     {
7719       l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
7720       MOVA (l);
7721       emitcode ("add", "a,acc");
7722       if (sameRegs (AOP (left), AOP (result)) &&
7723           size >= MSB16 + offr && offr != LSB)
7724         emitcode ("xch", "a,%s",
7725                   aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
7726       else
7727         aopPut (AOP (result), "a", LSB + offr);
7728     }
7729
7730   if (size >= MSB16 + offr)
7731     {
7732       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7733         {
7734           l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
7735           MOVA (l);
7736         }
7737       emitcode ("rlc", "a");
7738       if (sameRegs (AOP (left), AOP (result)) &&
7739           size >= MSB24 + offr && offr != LSB)
7740         emitcode ("xch", "a,%s",
7741                   aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
7742       else
7743         aopPut (AOP (result), "a", MSB16 + offr);
7744     }
7745
7746   if (size >= MSB24 + offr)
7747     {
7748       if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7749         {
7750           l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
7751           MOVA (l);
7752         }
7753       emitcode ("rlc", "a");
7754       if (sameRegs (AOP (left), AOP (result)) &&
7755           size >= MSB32 + offr && offr != LSB)
7756         emitcode ("xch", "a,%s",
7757                   aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
7758       else
7759         aopPut (AOP (result), "a", MSB24 + offr);
7760     }
7761
7762   if (size > MSB32 + offr)
7763     {
7764       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7765         {
7766           l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
7767           MOVA (l);
7768         }
7769       emitcode ("rlc", "a");
7770       aopPut (AOP (result), "a", MSB32 + offr);
7771     }
7772   if (offr != LSB)
7773     aopPut (AOP (result), zero, LSB);
7774 }
7775 #endif
7776
7777 #if 0
7778 //REMOVE ME!!!
7779 /*-----------------------------------------------------------------*/
7780 /* genlshFour - shift four byte by a known amount != 0             */
7781 /*-----------------------------------------------------------------*/
7782 static void
7783 genlshFour (operand * result, operand * left, int shCount)
7784 {
7785   int size;
7786
7787   D (emitcode (";", "genlshFour ");
7788     );
7789
7790   size = AOP_SIZE (result);
7791
7792   /* if shifting more that 3 bytes */
7793   if (shCount >= 24)
7794     {
7795       shCount -= 24;
7796       if (shCount)
7797         /* lowest order of left goes to the highest
7798            order of the destination */
7799         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7800       else
7801         movLeft2Result (left, LSB, result, MSB32, 0);
7802       aopPut (AOP (result), zero, LSB);
7803       aopPut (AOP (result), zero, MSB16);
7804       aopPut (AOP (result), zero, MSB24);
7805       return;
7806     }
7807
7808   /* more than two bytes */
7809   else if (shCount >= 16)
7810     {
7811       /* lower order two bytes goes to higher order two bytes */
7812       shCount -= 16;
7813       /* if some more remaining */
7814       if (shCount)
7815         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7816       else
7817         {
7818           movLeft2Result (left, MSB16, result, MSB32, 0);
7819           movLeft2Result (left, LSB, result, MSB24, 0);
7820         }
7821       aopPut (AOP (result), zero, MSB16);
7822       aopPut (AOP (result), zero, LSB);
7823       return;
7824     }
7825
7826   /* if more than 1 byte */
7827   else if (shCount >= 8)
7828     {
7829       /* lower order three bytes goes to higher order  three bytes */
7830       shCount -= 8;
7831       if (size == 2)
7832         {
7833           if (shCount)
7834             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7835           else
7836             movLeft2Result (left, LSB, result, MSB16, 0);
7837         }
7838       else
7839         {                       /* size = 4 */
7840           if (shCount == 0)
7841             {
7842               movLeft2Result (left, MSB24, result, MSB32, 0);
7843               movLeft2Result (left, MSB16, result, MSB24, 0);
7844               movLeft2Result (left, LSB, result, MSB16, 0);
7845               aopPut (AOP (result), zero, LSB);
7846             }
7847           else if (shCount == 1)
7848             shiftLLong (left, result, MSB16);
7849           else
7850             {
7851               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7852               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7853               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7854               aopPut (AOP (result), zero, LSB);
7855             }
7856         }
7857     }
7858
7859   /* 1 <= shCount <= 7 */
7860   else if (shCount <= 2)
7861     {
7862       shiftLLong (left, result, LSB);
7863       if (shCount == 2)
7864         shiftLLong (result, result, LSB);
7865     }
7866   /* 3 <= shCount <= 7, optimize */
7867   else
7868     {
7869       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7870       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7871       shiftL2Left2Result (left, LSB, result, LSB, shCount);
7872     }
7873 }
7874 #endif
7875
7876 #ifdef BETTER_LITERAL_SHIFT
7877 /*-----------------------------------------------------------------*/
7878 /* genLeftShiftLiteral - left shifting by known count              */
7879 /*-----------------------------------------------------------------*/
7880 static bool
7881 genLeftShiftLiteral (operand * left,
7882                      operand * right,
7883                      operand * result,
7884                      iCode * ic)
7885 {
7886   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7887   int size;
7888
7889   size = getSize (operandType (result));
7890
7891   D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
7892
7893   /* We only handle certain easy cases so far. */
7894   if ((shCount != 0)
7895    && (shCount < (size * 8))
7896    && (size != 1)
7897    && (size != 2))
7898   {
7899       D(emitcode (";", "genLeftShiftLiteral wimping out"););    
7900       return FALSE;
7901   }
7902
7903   freeAsmop (right, NULL, ic, TRUE);
7904
7905   aopOp(left, ic, FALSE, FALSE);
7906   aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
7907
7908 #if 0 // debug spew
7909   if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
7910   {
7911         emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
7912         if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
7913         {
7914            emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
7915         }
7916   }
7917   if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
7918   {
7919         emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
7920         if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
7921         {
7922            emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
7923         }       
7924   }  
7925 #endif
7926   
7927 #if VIEW_SIZE
7928   emitcode ("; shift left ", "result %d, left %d", size,
7929             AOP_SIZE (left));
7930 #endif
7931
7932   /* I suppose that the left size >= result size */
7933   if (shCount == 0)
7934   {
7935         _startLazyDPSEvaluation();
7936         while (size--)
7937         {
7938           movLeft2Result (left, size, result, size, 0);
7939         }
7940         _endLazyDPSEvaluation();
7941   }
7942   else if (shCount >= (size * 8))
7943   {
7944     _startLazyDPSEvaluation();
7945     while (size--)
7946     {
7947       aopPut (AOP (result), zero, size);
7948     }
7949     _endLazyDPSEvaluation();
7950   }
7951   else
7952   {
7953       switch (size)
7954         {
7955         case 1:
7956           genlshOne (result, left, shCount);
7957           break;
7958
7959         case 2:
7960           genlshTwo (result, left, shCount);
7961           break;
7962 #if 0
7963         case 4:
7964           genlshFour (result, left, shCount);
7965           break;
7966 #endif
7967         default:
7968           fprintf(stderr, "*** ack! mystery literal shift!\n");   
7969           break;
7970         }
7971     }
7972   freeAsmop (left, NULL, ic, TRUE);
7973   freeAsmop (result, NULL, ic, TRUE);
7974   return TRUE;
7975 }
7976 #endif
7977
7978 /*-----------------------------------------------------------------*/
7979 /* genLeftShift - generates code for left shifting                 */
7980 /*-----------------------------------------------------------------*/
7981 static void
7982 genLeftShift (iCode * ic)
7983 {
7984   operand *left, *right, *result;
7985   int size, offset;
7986   char *l;
7987   symbol *tlbl, *tlbl1;
7988
7989   D (emitcode (";", "genLeftShift "););
7990
7991   right = IC_RIGHT (ic);
7992   left = IC_LEFT (ic);
7993   result = IC_RESULT (ic);
7994
7995   aopOp (right, ic, FALSE, FALSE);
7996
7997
7998 #ifdef BETTER_LITERAL_SHIFT
7999   /* if the shift count is known then do it
8000      as efficiently as possible */
8001   if (AOP_TYPE (right) == AOP_LIT)
8002     {
8003       if (genLeftShiftLiteral (left, right, result, ic))
8004       {
8005         return;
8006       }
8007     }
8008 #endif
8009
8010   /* shift count is unknown then we have to form
8011      a loop get the loop count in B : Note: we take
8012      only the lower order byte since shifting
8013      more that 32 bits make no sense anyway, ( the
8014      largest size of an object can be only 32 bits ) */
8015
8016   if (AOP_TYPE (right) == AOP_LIT)
8017   {
8018       /* Really should be handled by genLeftShiftLiteral,
8019        * but since I'm too lazy to fix that today, at least we can make
8020        * some small improvement.
8021        */
8022        emitcode("mov", "b,#!constbyte",
8023                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8024   }
8025   else
8026   {
8027         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8028         emitcode ("inc", "b");
8029   }
8030   freeAsmop (right, NULL, ic, TRUE);
8031   aopOp (left, ic, FALSE, FALSE);
8032   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8033
8034   /* now move the left to the result if they are not the
8035      same */
8036   if (!sameRegs (AOP (left), AOP (result)) &&
8037       AOP_SIZE (result) > 1)
8038     {
8039
8040       size = AOP_SIZE (result);
8041       offset = 0;
8042       _startLazyDPSEvaluation ();
8043       while (size--)
8044         {
8045           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8046           if (*l == '@' && (IS_AOP_PREG (result)))
8047             {
8048
8049               emitcode ("mov", "a,%s", l);
8050               aopPut (AOP (result), "a", offset);
8051             }
8052           else
8053             aopPut (AOP (result), l, offset);
8054           offset++;
8055         }
8056       _endLazyDPSEvaluation ();
8057     }
8058
8059   tlbl = newiTempLabel (NULL);
8060   size = AOP_SIZE (result);
8061   offset = 0;
8062   tlbl1 = newiTempLabel (NULL);
8063
8064   /* if it is only one byte then */
8065   if (size == 1)
8066     {
8067       symbol *tlbl1 = newiTempLabel (NULL);
8068
8069       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8070       MOVA (l);
8071       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8072       emitcode ("", "!tlabeldef", tlbl->key + 100);
8073       emitcode ("add", "a,acc");
8074       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8075       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8076       aopPut (AOP (result), "a", 0);
8077       goto release;
8078     }
8079
8080   reAdjustPreg (AOP (result));
8081
8082   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8083   emitcode ("", "!tlabeldef", tlbl->key + 100);
8084   l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8085   MOVA (l);
8086   emitcode ("add", "a,acc");
8087   aopPut (AOP (result), "a", offset++);
8088   _startLazyDPSEvaluation ();
8089   while (--size)
8090     {
8091       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8092       MOVA (l);
8093       emitcode ("rlc", "a");
8094       aopPut (AOP (result), "a", offset++);
8095     }
8096   _endLazyDPSEvaluation ();
8097   reAdjustPreg (AOP (result));
8098
8099   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8100   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8101 release:
8102   freeAsmop (left, NULL, ic, TRUE);
8103   freeAsmop (result, NULL, ic, TRUE);
8104 }
8105
8106 #ifdef BETTER_LITERAL_SHIFT
8107 /*-----------------------------------------------------------------*/
8108 /* genrshOne - right shift a one byte quantity by known count      */
8109 /*-----------------------------------------------------------------*/
8110 static void
8111 genrshOne (operand * result, operand * left,
8112            int shCount, int sign)
8113 {
8114   D (emitcode (";", "genrshOne"););
8115   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8116 }
8117 #endif
8118
8119 #ifdef BETTER_LITERAL_SHIFT
8120 /*-----------------------------------------------------------------*/
8121 /* genrshTwo - right shift two bytes by known amount != 0          */
8122 /*-----------------------------------------------------------------*/
8123 static void
8124 genrshTwo (operand * result, operand * left,
8125            int shCount, int sign)
8126 {
8127   D (emitcode (";", "genrshTwo"););
8128
8129   /* if shCount >= 8 */
8130   if (shCount >= 8)
8131     {
8132       shCount -= 8;
8133       _startLazyDPSEvaluation();
8134       if (shCount)
8135       {
8136         shiftR1Left2Result (left, MSB16, result, LSB,
8137                             shCount, sign);
8138       }                     
8139       else
8140       {
8141         movLeft2Result (left, MSB16, result, LSB, sign);
8142       }
8143       addSign (result, MSB16, sign);
8144       _endLazyDPSEvaluation();
8145     }
8146
8147   /*  1 <= shCount <= 7 */
8148   else
8149   {
8150     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8151   }
8152 }
8153 #endif
8154
8155 #if 0
8156 //REMOVE ME!!!
8157 /*-----------------------------------------------------------------*/
8158 /* shiftRLong - shift right one long from left to result           */
8159 /* offl = LSB or MSB16                                             */
8160 /*-----------------------------------------------------------------*/
8161 static void
8162 shiftRLong (operand * left, int offl,
8163             operand * result, int sign)
8164 {
8165   int isSameRegs=sameRegs(AOP(left),AOP(result));
8166
8167   if (isSameRegs && offl>1) {
8168     // we are in big trouble, but this shouldn't happen
8169     werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8170   }
8171
8172   MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
8173   
8174   if (offl==MSB16) {
8175     // shift is > 8
8176     if (sign) {
8177       emitcode ("rlc", "a");
8178       emitcode ("subb", "a,acc");
8179       emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
8180     } else {
8181       aopPut (AOP(result), zero, MSB32);
8182     }
8183   }
8184
8185   if (!sign) {
8186     emitcode ("clr", "c");
8187   } else {
8188     emitcode ("mov", "c,acc.7");
8189   }
8190
8191   emitcode ("rrc", "a");
8192
8193   if (isSameRegs && offl==MSB16) {
8194     emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
8195   } else {
8196     aopPut (AOP (result), "a", MSB32);
8197     MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
8198   }
8199
8200   emitcode ("rrc", "a");
8201   if (isSameRegs && offl==1) {
8202     emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
8203   } else {
8204     aopPut (AOP (result), "a", MSB24);
8205     MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
8206   }
8207   emitcode ("rrc", "a");
8208   aopPut (AOP (result), "a", MSB16 - offl);
8209
8210   if (offl == LSB)
8211     {
8212       MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
8213       emitcode ("rrc", "a");
8214       aopPut (AOP (result), "a", LSB);
8215     }
8216 }
8217 #endif
8218
8219 #if 0
8220 //REMOVE ME!!!
8221 /*-----------------------------------------------------------------*/
8222 /* genrshFour - shift four byte by a known amount != 0             */
8223 /*-----------------------------------------------------------------*/
8224 static void
8225 genrshFour (operand * result, operand * left,
8226             int shCount, int sign)
8227 {
8228   D (emitcode (";", "genrshFour");
8229     );
8230
8231   /* if shifting more that 3 bytes */
8232   if (shCount >= 24)
8233     {
8234       shCount -= 24;
8235       if (shCount)
8236         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8237       else
8238         movLeft2Result (left, MSB32, result, LSB, sign);
8239       addSign (result, MSB16, sign);
8240     }
8241   else if (shCount >= 16)
8242     {
8243       shCount -= 16;
8244       if (shCount)
8245         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8246       else
8247         {
8248           movLeft2Result (left, MSB24, result, LSB, 0);
8249           movLeft2Result (left, MSB32, result, MSB16, sign);
8250         }
8251       addSign (result, MSB24, sign);
8252     }
8253   else if (shCount >= 8)
8254     {
8255       shCount -= 8;
8256       if (shCount == 1)
8257         shiftRLong (left, MSB16, result, sign);
8258       else if (shCount == 0)
8259         {
8260           movLeft2Result (left, MSB16, result, LSB, 0);
8261           movLeft2Result (left, MSB24, result, MSB16, 0);
8262           movLeft2Result (left, MSB32, result, MSB24, sign);
8263           addSign (result, MSB32, sign);
8264         }
8265       else
8266         {
8267           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8268           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8269           /* the last shift is signed */
8270           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8271           addSign (result, MSB32, sign);
8272         }
8273     }
8274   else
8275     {                           /* 1 <= shCount <= 7 */
8276       if (shCount <= 2)
8277         {
8278           shiftRLong (left, LSB, result, sign);
8279           if (shCount == 2)
8280             shiftRLong (result, LSB, result, sign);
8281         }
8282       else
8283         {
8284           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8285           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8286           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8287         }
8288     }
8289 }
8290 #endif
8291
8292 #ifdef BETTER_LITERAL_SHIFT
8293 /*-----------------------------------------------------------------*/
8294 /* genRightShiftLiteral - right shifting by known count            */
8295 /*-----------------------------------------------------------------*/
8296 static bool
8297 genRightShiftLiteral (operand * left,
8298                       operand * right,
8299                       operand * result,
8300                       iCode * ic,
8301                       int sign)
8302 {
8303   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8304   int size;
8305
8306   size = getSize (operandType (result));
8307
8308   D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8309
8310   /* We only handle certain easy cases so far. */
8311   if ((shCount != 0)
8312    && (shCount < (size * 8))
8313    && (size != 1)
8314    && (size != 2))
8315   {
8316       D(emitcode (";", "genRightShiftLiteral wimping out"););   
8317       return FALSE;
8318   }
8319
8320   freeAsmop (right, NULL, ic, TRUE);
8321
8322   aopOp (left, ic, FALSE, FALSE);
8323   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8324
8325 #if VIEW_SIZE
8326   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8327             AOP_SIZE (left));
8328 #endif
8329
8330   /* test the LEFT size !!! */
8331
8332   /* I suppose that the left size >= result size */
8333   if (shCount == 0)
8334   {
8335       size = getDataSize (result);
8336       _startLazyDPSEvaluation();
8337       while (size--)
8338       {
8339         movLeft2Result (left, size, result, size, 0);
8340       }
8341       _endLazyDPSEvaluation();
8342   }
8343   else if (shCount >= (size * 8))
8344     {
8345       if (sign)
8346       {
8347         /* get sign in acc.7 */
8348         MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
8349       }
8350       addSign (result, LSB, sign);
8351     }
8352   else
8353     {
8354       switch (size)
8355         {
8356         case 1:
8357           genrshOne (result, left, shCount, sign);
8358           break;
8359
8360         case 2:
8361           genrshTwo (result, left, shCount, sign);
8362           break;
8363 #if 0
8364         case 4:
8365           genrshFour (result, left, shCount, sign);
8366           break;
8367 #endif    
8368         default:
8369           break;
8370         }
8371
8372       freeAsmop (left, NULL, ic, TRUE);
8373       freeAsmop (result, NULL, ic, TRUE);
8374     }
8375     return TRUE;
8376 }
8377 #endif
8378
8379 /*-----------------------------------------------------------------*/
8380 /* genSignedRightShift - right shift of signed number              */
8381 /*-----------------------------------------------------------------*/
8382 static void
8383 genSignedRightShift (iCode * ic)
8384 {
8385   operand *right, *left, *result;
8386   int size, offset;
8387   char *l;
8388   symbol *tlbl, *tlbl1;
8389
8390   D (emitcode (";", "genSignedRightShift "););
8391
8392   /* we do it the hard way put the shift count in b
8393      and loop thru preserving the sign */
8394
8395   right = IC_RIGHT (ic);
8396   left = IC_LEFT (ic);
8397   result = IC_RESULT (ic);
8398
8399   aopOp (right, ic, FALSE, FALSE);
8400
8401 #ifdef BETTER_LITERAL_SHIFT
8402   if (AOP_TYPE (right) == AOP_LIT)
8403     {
8404       if (genRightShiftLiteral (left, right, result, ic, 1))
8405       {
8406         return;
8407       }
8408     }
8409 #endif
8410   /* shift count is unknown then we have to form
8411      a loop get the loop count in B : Note: we take
8412      only the lower order byte since shifting
8413      more that 32 bits make no sense anyway, ( the
8414      largest size of an object can be only 32 bits ) */
8415
8416   if (AOP_TYPE (right) == AOP_LIT)
8417   {
8418       /* Really should be handled by genRightShiftLiteral,
8419        * but since I'm too lazy to fix that today, at least we can make
8420        * some small improvement.
8421        */
8422        emitcode("mov", "b,#!constbyte",
8423                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8424   }
8425   else
8426   {
8427         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8428         emitcode ("inc", "b");
8429   }
8430   freeAsmop (right, NULL, ic, TRUE);
8431   aopOp (left, ic, FALSE, FALSE);
8432   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8433
8434   /* now move the left to the result if they are not the
8435      same */
8436   if (!sameRegs (AOP (left), AOP (result)) &&
8437       AOP_SIZE (result) > 1)
8438     {
8439
8440       size = AOP_SIZE (result);
8441       offset = 0;
8442       _startLazyDPSEvaluation ();
8443       while (size--)
8444         {
8445           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8446           if (*l == '@' && IS_AOP_PREG (result))
8447             {
8448
8449               emitcode ("mov", "a,%s", l);
8450               aopPut (AOP (result), "a", offset);
8451             }
8452           else
8453             aopPut (AOP (result), l, offset);
8454           offset++;
8455         }
8456       _endLazyDPSEvaluation ();
8457     }
8458
8459   /* mov the highest order bit to OVR */
8460   tlbl = newiTempLabel (NULL);
8461   tlbl1 = newiTempLabel (NULL);
8462
8463   size = AOP_SIZE (result);
8464   offset = size - 1;
8465   emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
8466   emitcode ("rlc", "a");
8467   emitcode ("mov", "ov,c");
8468   /* if it is only one byte then */
8469   if (size == 1)
8470     {
8471       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8472       MOVA (l);
8473       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8474       emitcode ("", "!tlabeldef", tlbl->key + 100);
8475       emitcode ("mov", "c,ov");
8476       emitcode ("rrc", "a");
8477       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8478       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8479       aopPut (AOP (result), "a", 0);
8480       goto release;
8481     }
8482
8483   reAdjustPreg (AOP (result));
8484   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8485   emitcode ("", "!tlabeldef", tlbl->key + 100);
8486   emitcode ("mov", "c,ov");
8487   _startLazyDPSEvaluation ();
8488   while (size--)
8489     {
8490       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8491       MOVA (l);
8492       emitcode ("rrc", "a");
8493       aopPut (AOP (result), "a", offset--);
8494     }
8495   _endLazyDPSEvaluation ();
8496   reAdjustPreg (AOP (result));
8497   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8498   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8499
8500 release:
8501   freeAsmop (left, NULL, ic, TRUE);
8502   freeAsmop (result, NULL, ic, TRUE);
8503 }
8504
8505 /*-----------------------------------------------------------------*/
8506 /* genRightShift - generate code for right shifting                */
8507 /*-----------------------------------------------------------------*/
8508 static void
8509 genRightShift (iCode * ic)
8510 {
8511   operand *right, *left, *result;
8512   sym_link *retype;
8513   int size, offset;
8514   char *l;
8515   symbol *tlbl, *tlbl1;
8516
8517   D (emitcode (";", "genRightShift "););
8518
8519   /* if signed then we do it the hard way preserve the
8520      sign bit moving it inwards */
8521   retype = getSpec (operandType (IC_RESULT (ic)));
8522
8523   if (!SPEC_USIGN (retype))
8524     {
8525       genSignedRightShift (ic);
8526       return;
8527     }
8528
8529   /* signed & unsigned types are treated the same : i.e. the
8530      signed is NOT propagated inwards : quoting from the
8531      ANSI - standard : "for E1 >> E2, is equivalent to division
8532      by 2**E2 if unsigned or if it has a non-negative value,
8533      otherwise the result is implementation defined ", MY definition
8534      is that the sign does not get propagated */
8535
8536   right = IC_RIGHT (ic);
8537   left = IC_LEFT (ic);
8538   result = IC_RESULT (ic);
8539
8540   aopOp (right, ic, FALSE, FALSE);
8541
8542 #ifdef BETTER_LITERAL_SHIFT
8543   /* if the shift count is known then do it
8544      as efficiently as possible */
8545   if (AOP_TYPE (right) == AOP_LIT)
8546     {
8547       if (genRightShiftLiteral (left, right, result, ic, 0))
8548       {
8549         return;
8550       }
8551     }
8552 #endif
8553
8554   /* shift count is unknown then we have to form
8555      a loop get the loop count in B : Note: we take
8556      only the lower order byte since shifting
8557      more that 32 bits make no sense anyway, ( the
8558      largest size of an object can be only 32 bits ) */
8559   
8560   if (AOP_TYPE (right) == AOP_LIT)
8561   {
8562       /* Really should be handled by genRightShiftLiteral,
8563        * but since I'm too lazy to fix that today, at least we can make
8564        * some small improvement.
8565        */
8566        emitcode("mov", "b,#!constbyte",
8567                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8568   }
8569   else
8570   {
8571         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8572         emitcode ("inc", "b");
8573   }
8574   freeAsmop (right, NULL, ic, TRUE);
8575   aopOp (left, ic, FALSE, FALSE);
8576   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8577
8578   /* now move the left to the result if they are not the
8579      same */
8580   if (!sameRegs (AOP (left), AOP (result)) &&
8581       AOP_SIZE (result) > 1)
8582     {
8583
8584       size = AOP_SIZE (result);
8585       offset = 0;
8586       _startLazyDPSEvaluation ();
8587       while (size--)
8588         {
8589           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8590           if (*l == '@' && IS_AOP_PREG (result))
8591             {
8592
8593               emitcode ("mov", "a,%s", l);
8594               aopPut (AOP (result), "a", offset);
8595             }
8596           else
8597             aopPut (AOP (result), l, offset);
8598           offset++;
8599         }
8600       _endLazyDPSEvaluation ();
8601     }
8602
8603   tlbl = newiTempLabel (NULL);
8604   tlbl1 = newiTempLabel (NULL);
8605   size = AOP_SIZE (result);
8606   offset = size - 1;
8607
8608   /* if it is only one byte then */
8609   if (size == 1)
8610     {
8611       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8612       MOVA (l);
8613       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8614       emitcode ("", "!tlabeldef", tlbl->key + 100);
8615       CLRC;
8616       emitcode ("rrc", "a");
8617       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8618       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8619       aopPut (AOP (result), "a", 0);
8620       goto release;
8621     }
8622
8623   reAdjustPreg (AOP (result));
8624   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8625   emitcode ("", "!tlabeldef", tlbl->key + 100);
8626   CLRC;
8627   _startLazyDPSEvaluation ();
8628   while (size--)
8629     {
8630       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8631       MOVA (l);
8632       emitcode ("rrc", "a");
8633       aopPut (AOP (result), "a", offset--);
8634     }
8635   _endLazyDPSEvaluation ();
8636   reAdjustPreg (AOP (result));
8637
8638   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8639   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8640
8641 release:
8642   freeAsmop (left, NULL, ic, TRUE);
8643   freeAsmop (result, NULL, ic, TRUE);
8644 }
8645
8646 /*-----------------------------------------------------------------*/
8647 /* genUnpackBits - generates code for unpacking bits               */
8648 /*-----------------------------------------------------------------*/
8649 static void
8650 genUnpackBits (operand * result, char *rname, int ptype)
8651 {
8652   int shCnt;
8653   int rlen = 0;
8654   sym_link *etype;
8655   int offset = 0;
8656
8657   D (emitcode (";", "genUnpackBits ");
8658     );
8659
8660   etype = getSpec (operandType (result));
8661
8662   /* read the first byte  */
8663   switch (ptype)
8664     {
8665
8666     case POINTER:
8667     case IPOINTER:
8668       emitcode ("mov", "a,@%s", rname);
8669       break;
8670
8671     case PPOINTER:
8672       emitcode ("movx", "a,@%s", rname);
8673       break;
8674
8675     case FPOINTER:
8676       emitcode ("movx", "a,@dptr");
8677       break;
8678
8679     case CPOINTER:
8680       emitcode ("clr", "a");
8681       emitcode ("movc", "a,@a+dptr");
8682       break;
8683
8684     case GPOINTER:
8685       emitcode ("lcall", "__gptrget");
8686       break;
8687     }
8688
8689   /* if we have bitdisplacement then it fits   */
8690   /* into this byte completely or if length is */
8691   /* less than a byte                          */
8692   if ((shCnt = SPEC_BSTR (etype)) ||
8693       (SPEC_BLEN (etype) <= 8))
8694     {
8695
8696       /* shift right acc */
8697       AccRsh (shCnt);
8698
8699       emitcode ("anl", "a,#!constbyte",
8700                 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
8701       aopPut (AOP (result), "a", offset);
8702       return;
8703     }
8704
8705   /* bit field did not fit in a byte  */
8706   rlen = SPEC_BLEN (etype) - 8;
8707   aopPut (AOP (result), "a", offset++);
8708
8709   while (1)
8710     {
8711
8712       switch (ptype)
8713         {
8714         case POINTER:
8715         case IPOINTER:
8716           emitcode ("inc", "%s", rname);
8717           emitcode ("mov", "a,@%s", rname);
8718           break;
8719
8720         case PPOINTER:
8721           emitcode ("inc", "%s", rname);
8722           emitcode ("movx", "a,@%s", rname);
8723           break;
8724
8725         case FPOINTER:
8726           emitcode ("inc", "dptr");
8727           emitcode ("movx", "a,@dptr");
8728           break;
8729
8730         case CPOINTER:
8731           emitcode ("clr", "a");
8732           emitcode ("inc", "dptr");
8733           emitcode ("movc", "a,@a+dptr");
8734           break;
8735
8736         case GPOINTER:
8737           emitcode ("inc", "dptr");
8738           emitcode ("lcall", "__gptrget");
8739           break;
8740         }
8741
8742       rlen -= 8;
8743       /* if we are done */
8744       if (rlen < 8)
8745         break;
8746
8747       aopPut (AOP (result), "a", offset++);
8748
8749     }
8750
8751   if (rlen)
8752     {
8753       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (rlen));
8754       aopPut (AOP (result), "a", offset);
8755     }
8756
8757   return;
8758 }
8759
8760
8761 /*-----------------------------------------------------------------*/
8762 /* genDataPointerGet - generates code when ptr offset is known     */
8763 /*-----------------------------------------------------------------*/
8764 static void
8765 genDataPointerGet (operand * left,
8766                    operand * result,
8767                    iCode * ic)
8768 {
8769   char *l;
8770   char buffer[256];
8771   int size, offset = 0;
8772   aopOp (result, ic, TRUE, FALSE);
8773
8774   /* get the string representation of the name */
8775   l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
8776   size = AOP_SIZE (result);
8777   _startLazyDPSEvaluation ();
8778   while (size--)
8779     {
8780       if (offset)
8781         sprintf (buffer, "(%s + %d)", l + 1, offset);
8782       else
8783         sprintf (buffer, "%s", l + 1);
8784       aopPut (AOP (result), buffer, offset++);
8785     }
8786   _endLazyDPSEvaluation ();
8787
8788   freeAsmop (left, NULL, ic, TRUE);
8789   freeAsmop (result, NULL, ic, TRUE);
8790 }
8791
8792 /*-----------------------------------------------------------------*/
8793 /* genNearPointerGet - emitcode for near pointer fetch             */
8794 /*-----------------------------------------------------------------*/
8795 static void
8796 genNearPointerGet (operand * left,
8797                    operand * result,
8798                    iCode * ic,
8799                    iCode *pi)
8800 {
8801   asmop *aop = NULL;
8802   regs *preg = NULL;
8803   char *rname;
8804   sym_link *rtype, *retype, *letype;
8805   sym_link *ltype = operandType (left);
8806   char buffer[80];
8807
8808   rtype = operandType (result);
8809   retype = getSpec (rtype);
8810   letype = getSpec (ltype);
8811
8812   aopOp (left, ic, FALSE, FALSE);
8813
8814   /* if left is rematerialisable and
8815      result is not bit variable type and
8816      the left is pointer to data space i.e
8817      lower 128 bytes of space */
8818   if (AOP_TYPE (left) == AOP_IMMD &&
8819       !IS_BITVAR (retype) &&
8820       !IS_BITVAR (letype) &&
8821       DCL_TYPE (ltype) == POINTER)
8822     {
8823       genDataPointerGet (left, result, ic);
8824       return;
8825     }
8826
8827   /* if the value is already in a pointer register
8828      then don't need anything more */
8829   if (!AOP_INPREG (AOP (left)))
8830     {
8831       /* otherwise get a free pointer register */
8832       aop = newAsmop (0);
8833       preg = getFreePtr (ic, &aop, FALSE);
8834       emitcode ("mov", "%s,%s",
8835                 preg->name,
8836                 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8837       rname = preg->name;
8838     }
8839   else
8840     rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8841
8842   freeAsmop (left, NULL, ic, TRUE);
8843   aopOp (result, ic, FALSE, FALSE);
8844
8845   /* if bitfield then unpack the bits */
8846   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8847     genUnpackBits (result, rname, POINTER);
8848   else
8849     {
8850       /* we have can just get the values */
8851       int size = AOP_SIZE (result);
8852       int offset = 0;
8853
8854       while (size--)
8855         {
8856           if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8857             {
8858
8859               emitcode ("mov", "a,@%s", rname);
8860               aopPut (AOP (result), "a", offset);
8861             }
8862           else
8863             {
8864               sprintf (buffer, "@%s", rname);
8865               aopPut (AOP (result), buffer, offset);
8866             }
8867           offset++;
8868           if (size || pi)
8869             emitcode ("inc", "%s", rname);
8870         }
8871     }
8872
8873   /* now some housekeeping stuff */
8874   if (aop)
8875     {
8876       /* we had to allocate for this iCode */
8877       if (pi) { /* post increment present */
8878         aopPut(AOP ( left ),rname,0);
8879       }
8880       freeAsmop (NULL, aop, ic, TRUE);
8881     }
8882   else
8883     {
8884       /* we did not allocate which means left
8885          already in a pointer register, then
8886          if size > 0 && this could be used again
8887          we have to point it back to where it
8888          belongs */
8889       if (AOP_SIZE (result) > 1 &&
8890           !OP_SYMBOL (left)->remat &&
8891           (OP_SYMBOL (left)->liveTo > ic->seq ||
8892            ic->depth) &&
8893           !pi)
8894         {
8895           int size = AOP_SIZE (result) - 1;
8896           while (size--)
8897             emitcode ("dec", "%s", rname);
8898         }
8899     }
8900
8901   /* done */
8902   freeAsmop (result, NULL, ic, TRUE);
8903   if (pi) pi->generated = 1;
8904 }
8905
8906 /*-----------------------------------------------------------------*/
8907 /* genPagedPointerGet - emitcode for paged pointer fetch           */
8908 /*-----------------------------------------------------------------*/
8909 static void
8910 genPagedPointerGet (operand * left,
8911                     operand * result,
8912                     iCode * ic,
8913                     iCode * pi)
8914 {
8915   asmop *aop = NULL;
8916   regs *preg = NULL;
8917   char *rname;
8918   sym_link *rtype, *retype, *letype;
8919
8920   rtype = operandType (result);
8921   retype = getSpec (rtype);
8922   letype = getSpec (operandType (left));
8923   aopOp (left, ic, FALSE, FALSE);
8924
8925   /* if the value is already in a pointer register
8926      then don't need anything more */
8927   if (!AOP_INPREG (AOP (left)))
8928     {
8929       /* otherwise get a free pointer register */
8930       aop = newAsmop (0);
8931       preg = getFreePtr (ic, &aop, FALSE);
8932       emitcode ("mov", "%s,%s",
8933                 preg->name,
8934                 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8935       rname = preg->name;
8936     }
8937   else
8938     rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8939
8940   freeAsmop (left, NULL, ic, TRUE);
8941   aopOp (result, ic, FALSE, FALSE);
8942
8943   /* if bitfield then unpack the bits */
8944   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8945     genUnpackBits (result, rname, PPOINTER);
8946   else
8947     {
8948       /* we have can just get the values */
8949       int size = AOP_SIZE (result);
8950       int offset = 0;
8951
8952       while (size--)
8953         {
8954
8955           emitcode ("movx", "a,@%s", rname);
8956           aopPut (AOP (result), "a", offset);
8957
8958           offset++;
8959
8960           if (size || pi)
8961             emitcode ("inc", "%s", rname);
8962         }
8963     }
8964
8965   /* now some housekeeping stuff */
8966   if (aop)
8967     {
8968       /* we had to allocate for this iCode */
8969       if (pi) aopPut ( AOP (left), rname, 0);
8970       freeAsmop (NULL, aop, ic, TRUE);
8971     }
8972   else
8973     {
8974       /* we did not allocate which means left
8975          already in a pointer register, then
8976          if size > 0 && this could be used again
8977          we have to point it back to where it
8978          belongs */
8979       if (AOP_SIZE (result) > 1 &&
8980           !OP_SYMBOL (left)->remat &&
8981           (OP_SYMBOL (left)->liveTo > ic->seq ||
8982            ic->depth) &&
8983           !pi)
8984         {
8985           int size = AOP_SIZE (result) - 1;
8986           while (size--)
8987             emitcode ("dec", "%s", rname);
8988         }
8989     }
8990
8991   /* done */
8992   freeAsmop (result, NULL, ic, TRUE);
8993   if (pi) pi->generated = 1;
8994 }
8995
8996 /*-----------------------------------------------------------------*/
8997 /* genFarPointerGet - gget value from far space                    */
8998 /*-----------------------------------------------------------------*/
8999 static void
9000 genFarPointerGet (operand * left,
9001                   operand * result, iCode * ic, iCode *pi)
9002 {
9003     int size, offset, dopi=1;
9004   sym_link *retype = getSpec (operandType (result));
9005   sym_link *letype = getSpec (operandType (left));
9006   D (emitcode (";", "genFarPointerGet");
9007     );
9008
9009   aopOp (left, ic, FALSE, FALSE);
9010
9011   /* if the operand is already in dptr
9012      then we do nothing else we move the value to dptr */
9013   if (AOP_TYPE (left) != AOP_STR)
9014     {
9015       /* if this is remateriazable */
9016       if (AOP_TYPE (left) == AOP_IMMD)
9017         {
9018           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9019         }
9020       else
9021         {
9022           /* we need to get it byte by byte */
9023           _startLazyDPSEvaluation ();
9024           if (AOP_TYPE (left) != AOP_DPTR)
9025             {
9026               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9027               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9028               if (options.model == MODEL_FLAT24)
9029                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9030             }
9031           else
9032             {
9033               /* We need to generate a load to DPTR indirect through DPTR. */
9034               D (emitcode (";", "genFarPointerGet -- indirection special case.");
9035                 );
9036               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
9037               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
9038               if (options.model == MODEL_FLAT24)
9039                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9040               emitcode ("pop", "dph");
9041               emitcode ("pop", "dpl");
9042               dopi =0;
9043             }
9044           _endLazyDPSEvaluation ();
9045         }
9046     }
9047   /* so dptr know contains the address */
9048   aopOp (result, ic, FALSE, TRUE);
9049
9050   /* if bit then unpack */
9051   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9052     genUnpackBits (result, "dptr", FPOINTER);
9053   else
9054     {
9055       size = AOP_SIZE (result);
9056       offset = 0;
9057
9058       _startLazyDPSEvaluation ();
9059       while (size--)
9060         {
9061
9062           genSetDPTR (0);
9063           _flushLazyDPS ();
9064
9065           emitcode ("movx", "a,@dptr");
9066           if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9067             emitcode ("inc", "dptr");
9068
9069           aopPut (AOP (result), "a", offset++);
9070         }
9071       _endLazyDPSEvaluation ();
9072     }
9073   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9074     aopPut ( AOP (left), "dpl", 0);
9075     aopPut ( AOP (left), "dph", 1);
9076     if (options.model == MODEL_FLAT24)
9077             aopPut ( AOP (left), "dpx", 2);
9078     pi->generated = 1;
9079   } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9080              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9081       
9082       size = AOP_SIZE (result) - 1;
9083       while (size--) emitcode ("lcall","__decdptr");
9084   }
9085
9086   freeAsmop (left, NULL, ic, TRUE);
9087   freeAsmop (result, NULL, ic, TRUE);
9088 }
9089
9090 /*-----------------------------------------------------------------*/
9091 /* emitcodePointerGet - gget value from code space                  */
9092 /*-----------------------------------------------------------------*/
9093 static void
9094 emitcodePointerGet (operand * left,
9095                     operand * result, iCode * ic, iCode *pi)
9096 {
9097   int size, offset, dopi=1;
9098   sym_link *retype = getSpec (operandType (result));
9099
9100   aopOp (left, ic, FALSE, FALSE);
9101
9102   /* if the operand is already in dptr
9103      then we do nothing else we move the value to dptr */
9104   if (AOP_TYPE (left) != AOP_STR)
9105     {
9106       /* if this is remateriazable */
9107       if (AOP_TYPE (left) == AOP_IMMD)
9108         {
9109           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9110         }
9111       else
9112         {                       /* we need to get it byte by byte */
9113           _startLazyDPSEvaluation ();
9114           if (AOP_TYPE (left) != AOP_DPTR)
9115             {
9116               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9117               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9118               if (options.model == MODEL_FLAT24)
9119                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9120             }
9121           else
9122             {
9123               /* We need to generate a load to DPTR indirect through DPTR. */
9124               D (emitcode (";", "gencodePointerGet -- indirection special case.");
9125                 );
9126               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
9127               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
9128               if (options.model == MODEL_FLAT24)
9129                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9130               emitcode ("pop", "dph");
9131               emitcode ("pop", "dpl");
9132               dopi=0;
9133             }
9134           _endLazyDPSEvaluation ();
9135         }
9136     }
9137   /* so dptr know contains the address */
9138   aopOp (result, ic, FALSE, TRUE);
9139
9140   /* if bit then unpack */
9141   if (IS_BITVAR (retype))
9142     genUnpackBits (result, "dptr", CPOINTER);
9143   else
9144     {
9145       size = AOP_SIZE (result);
9146       offset = 0;
9147
9148       _startLazyDPSEvaluation ();
9149       while (size--)
9150         {
9151           genSetDPTR (0);
9152           _flushLazyDPS ();
9153
9154           emitcode ("clr", "a");
9155           emitcode ("movc", "a,@a+dptr");
9156           if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9157             emitcode ("inc", "dptr");
9158           aopPut (AOP (result), "a", offset++);
9159         }
9160       _endLazyDPSEvaluation ();
9161     }
9162   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9163       aopPut ( AOP (left), "dpl", 0);
9164       aopPut ( AOP (left), "dph", 1);
9165       if (options.model == MODEL_FLAT24)
9166           aopPut ( AOP (left), "dpx", 2);
9167       pi->generated = 1;
9168   } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9169              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9170       
9171       size = AOP_SIZE (result) - 1;
9172       while (size--) emitcode ("lcall","__decdptr");
9173   }
9174   
9175   freeAsmop (left, NULL, ic, TRUE);
9176   freeAsmop (result, NULL, ic, TRUE);
9177 }
9178
9179 /*-----------------------------------------------------------------*/
9180 /* genGenPointerGet - gget value from generic pointer space        */
9181 /*-----------------------------------------------------------------*/
9182 static void
9183 genGenPointerGet (operand * left,
9184                   operand * result, iCode * ic, iCode * pi)
9185 {
9186   int size, offset;
9187   sym_link *retype = getSpec (operandType (result));
9188   sym_link *letype = getSpec (operandType (left));
9189
9190   D (emitcode (";", "genGenPointerGet "); );
9191
9192   aopOp (left, ic, FALSE, (OP_SYMBOL(left)->ruonly ? FALSE : TRUE));
9193
9194   /* if the operand is already in dptr
9195      then we do nothing else we move the value to dptr */
9196   if (AOP_TYPE (left) != AOP_STR)
9197     {
9198       /* if this is remateriazable */
9199       if (AOP_TYPE (left) == AOP_IMMD)
9200         {
9201           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9202           if (AOP(left)->aopu.aop_immd.from_cast_remat) 
9203                   emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, FALSE));
9204           else
9205                   emitcode ("mov", "b,#%d", pointerCode (retype));
9206         }
9207       else
9208         {                       /* we need to get it byte by byte */
9209           _startLazyDPSEvaluation ();
9210           if (AOP(left)->type==AOP_DPTR2) {
9211             char *l;
9212             l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
9213             genSetDPTR(0);
9214             _flushLazyDPS();
9215             emitcode ("mov", "dpl,%s", l);
9216             l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
9217             genSetDPTR(0);
9218             _flushLazyDPS();
9219             emitcode ("mov", "dph,%s", l);
9220             if (options.model == MODEL_FLAT24) {
9221               l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
9222               genSetDPTR(0);
9223               _flushLazyDPS();
9224               emitcode ("mov", "dpx,%s", l);
9225               emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
9226             } else {
9227               emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9228             }
9229           } else {
9230             emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
9231             emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
9232             if (options.model == MODEL_FLAT24) {
9233               emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9234               emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
9235             } else {
9236               emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9237             }
9238           }
9239           _endLazyDPSEvaluation ();
9240         }
9241     }
9242   /* so dptr know contains the address */
9243   aopOp (result, ic, FALSE, TRUE);
9244
9245   /* if bit then unpack */
9246   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9247     genUnpackBits (result, "dptr", GPOINTER);
9248   else
9249     {
9250       size = AOP_SIZE (result);
9251       offset = 0;
9252
9253       while (size--)
9254         {
9255           emitcode ("lcall", "__gptrget");
9256           aopPut (AOP (result), "a", offset++);
9257           if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9258             emitcode ("inc", "dptr");
9259         }
9260     }
9261
9262   if (pi && AOP_TYPE (left) != AOP_IMMD) {
9263     aopPut ( AOP (left), "dpl", 0);
9264     aopPut ( AOP (left), "dph", 1);
9265     if (options.model == MODEL_FLAT24) {
9266         aopPut ( AOP (left), "dpx", 2);
9267         aopPut ( AOP (left), "b", 3);   
9268     } else  aopPut ( AOP (left), "b", 2);       
9269     pi->generated = 1;
9270   } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9271              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9272       
9273       size = AOP_SIZE (result) - 1;
9274       while (size--) emitcode ("lcall","__decdptr");
9275   }
9276
9277   freeAsmop (left, NULL, ic, TRUE);
9278   freeAsmop (result, NULL, ic, TRUE);
9279 }
9280
9281 /*-----------------------------------------------------------------*/
9282 /* genPointerGet - generate code for pointer get                   */
9283 /*-----------------------------------------------------------------*/
9284 static void
9285 genPointerGet (iCode * ic, iCode *pi)
9286 {
9287   operand *left, *result;
9288   sym_link *type, *etype;
9289   int p_type;
9290
9291   D (emitcode (";", "genPointerGet ");
9292     );
9293
9294   left = IC_LEFT (ic);
9295   result = IC_RESULT (ic);
9296
9297   /* depending on the type of pointer we need to
9298      move it to the correct pointer register */
9299   type = operandType (left);
9300   etype = getSpec (type);
9301   /* if left is of type of pointer then it is simple */
9302   if (IS_PTR (type) && !IS_FUNC (type->next))
9303     p_type = DCL_TYPE (type);
9304   else
9305     {
9306       /* we have to go by the storage class */
9307       p_type = PTR_TYPE (SPEC_OCLS (etype));
9308     }
9309   /* special case when cast remat */
9310   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9311       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9312           left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9313           type =   type = operandType (left);
9314           p_type = DCL_TYPE (type);
9315   }
9316   /* now that we have the pointer type we assign
9317      the pointer values */
9318   switch (p_type)
9319     {
9320
9321     case POINTER:
9322     case IPOINTER:
9323       genNearPointerGet (left, result, ic, pi);
9324       break;
9325
9326     case PPOINTER:
9327       genPagedPointerGet (left, result, ic, pi);
9328       break;
9329
9330     case FPOINTER:
9331       genFarPointerGet (left, result, ic, pi);
9332       break;
9333
9334     case CPOINTER:
9335       emitcodePointerGet (left, result, ic, pi);
9336       break;
9337
9338     case GPOINTER:
9339       genGenPointerGet (left, result, ic, pi);
9340       break;
9341     }
9342
9343 }
9344
9345 /*-----------------------------------------------------------------*/
9346 /* genPackBits - generates code for packed bit storage             */
9347 /*-----------------------------------------------------------------*/
9348 static void
9349 genPackBits (sym_link * etype,
9350              operand * right,
9351              char *rname, int p_type)
9352 {
9353   int shCount = 0;
9354   int offset = 0;
9355   int rLen = 0;
9356   int blen, bstr;
9357   char *l;
9358
9359   blen = SPEC_BLEN (etype);
9360   bstr = SPEC_BSTR (etype);
9361
9362   l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9363   MOVA (l);
9364
9365   /* if the bit lenth is less than or    */
9366   /* it exactly fits a byte then         */
9367   if (SPEC_BLEN (etype) <= 8)
9368     {
9369       shCount = SPEC_BSTR (etype);
9370
9371       /* shift left acc */
9372       AccLsh (shCount);
9373
9374       if (SPEC_BLEN (etype) < 8)
9375         {                       /* if smaller than a byte */
9376
9377
9378           switch (p_type)
9379             {
9380             case POINTER:
9381               emitcode ("mov", "b,a");
9382               emitcode ("mov", "a,@%s", rname);
9383               break;
9384
9385             case FPOINTER:
9386               emitcode ("mov", "b,a");
9387               emitcode ("movx", "a,@dptr");
9388               break;
9389
9390             case GPOINTER:
9391               emitcode ("push", "b");
9392               emitcode ("push", "acc");
9393               emitcode ("lcall", "__gptrget");
9394               emitcode ("pop", "b");
9395               break;
9396             }
9397
9398           emitcode ("anl", "a,#!constbyte", (unsigned char)
9399                     ((unsigned char) (0xFF << (blen + bstr)) |
9400                      (unsigned char) (0xFF >> (8 - bstr))));
9401           emitcode ("orl", "a,b");
9402           if (p_type == GPOINTER)
9403             emitcode ("pop", "b");
9404         }
9405     }
9406
9407   switch (p_type)
9408     {
9409     case POINTER:
9410       emitcode ("mov", "@%s,a", rname);
9411       break;
9412
9413     case FPOINTER:
9414       emitcode ("movx", "@dptr,a");
9415       break;
9416
9417     case GPOINTER:
9418       emitcode ("lcall", "__gptrput");
9419       break;
9420     }
9421
9422   /* if we r done */
9423   if (SPEC_BLEN (etype) <= 8)
9424     return;
9425
9426   emitcode ("inc", "%s", rname);
9427   rLen = SPEC_BLEN (etype);
9428
9429   /* now generate for lengths greater than one byte */
9430   while (1)
9431     {
9432
9433       l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
9434
9435       rLen -= 8;
9436       if (rLen < 8)
9437         break;
9438
9439       switch (p_type)
9440         {
9441         case POINTER:
9442           if (*l == '@')
9443             {
9444               MOVA (l);
9445               emitcode ("mov", "@%s,a", rname);
9446             }
9447           else
9448             emitcode ("mov", "@%s,%s", rname, l);
9449           break;
9450
9451         case FPOINTER:
9452           MOVA (l);
9453           emitcode ("movx", "@dptr,a");
9454           break;
9455
9456         case GPOINTER:
9457           MOVA (l);
9458           emitcode ("lcall", "__gptrput");
9459           break;
9460         }
9461       emitcode ("inc", "%s", rname);
9462     }
9463
9464   MOVA (l);
9465
9466   /* last last was not complete */
9467   if (rLen)
9468     {
9469       /* save the byte & read byte */
9470       switch (p_type)
9471         {
9472         case POINTER:
9473           emitcode ("mov", "b,a");
9474           emitcode ("mov", "a,@%s", rname);
9475           break;
9476
9477         case FPOINTER:
9478           emitcode ("mov", "b,a");
9479           emitcode ("movx", "a,@dptr");
9480           break;
9481
9482         case GPOINTER:
9483           emitcode ("push", "b");
9484           emitcode ("push", "acc");
9485           emitcode ("lcall", "__gptrget");
9486           emitcode ("pop", "b");
9487           break;
9488         }
9489
9490       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1 << rLen));
9491       emitcode ("orl", "a,b");
9492     }
9493
9494   if (p_type == GPOINTER)
9495     emitcode ("pop", "b");
9496
9497   switch (p_type)
9498     {
9499
9500     case POINTER:
9501       emitcode ("mov", "@%s,a", rname);
9502       break;
9503
9504     case FPOINTER:
9505       emitcode ("movx", "@dptr,a");
9506       break;
9507
9508     case GPOINTER:
9509       emitcode ("lcall", "__gptrput");
9510       break;
9511     }
9512 }
9513 /*-----------------------------------------------------------------*/
9514 /* genDataPointerSet - remat pointer to data space                 */
9515 /*-----------------------------------------------------------------*/
9516 static void
9517 genDataPointerSet (operand * right,
9518                    operand * result,
9519                    iCode * ic)
9520 {
9521   int size, offset = 0;
9522   char *l, buffer[256];
9523
9524   aopOp (right, ic, FALSE, FALSE);
9525
9526   l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
9527   size = AOP_SIZE (right);
9528   while (size--)
9529     {
9530       if (offset)
9531         sprintf (buffer, "(%s + %d)", l + 1, offset);
9532       else
9533         sprintf (buffer, "%s", l + 1);
9534       emitcode ("mov", "%s,%s", buffer,
9535                 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
9536     }
9537
9538   freeAsmop (right, NULL, ic, TRUE);
9539   freeAsmop (result, NULL, ic, TRUE);
9540 }
9541
9542 /*-----------------------------------------------------------------*/
9543 /* genNearPointerSet - emitcode for near pointer put                */
9544 /*-----------------------------------------------------------------*/
9545 static void
9546 genNearPointerSet (operand * right,
9547                    operand * result,
9548                    iCode * ic,
9549                    iCode * pi)
9550 {
9551   asmop *aop = NULL;
9552   regs *preg = NULL;
9553   char *rname, *l;
9554   sym_link *retype, *letype;
9555   sym_link *ptype = operandType (result);
9556
9557   retype = getSpec (operandType (right));
9558   letype = getSpec (ptype);
9559
9560   aopOp (result, ic, FALSE, FALSE);
9561
9562   /* if the result is rematerializable &
9563      in data space & not a bit variable */
9564   if (AOP_TYPE (result) == AOP_IMMD &&
9565       DCL_TYPE (ptype) == POINTER &&
9566       !IS_BITVAR (retype) &&
9567       !IS_BITVAR (letype))
9568     {
9569       genDataPointerSet (right, result, ic);
9570       return;
9571     }
9572
9573   /* if the value is already in a pointer register
9574      then don't need anything more */
9575   if (!AOP_INPREG (AOP (result)))
9576     {
9577       /* otherwise get a free pointer register */
9578       aop = newAsmop (0);
9579       preg = getFreePtr (ic, &aop, FALSE);
9580       emitcode ("mov", "%s,%s",
9581                 preg->name,
9582                 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9583       rname = preg->name;
9584     }
9585   else
9586     rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9587
9588   aopOp (right, ic, FALSE, FALSE);
9589
9590   /* if bitfield then unpack the bits */
9591   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9592     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
9593   else
9594     {
9595       /* we have can just get the values */
9596       int size = AOP_SIZE (right);
9597       int offset = 0;
9598
9599       while (size--)
9600         {
9601           l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
9602           if (*l == '@')
9603             {
9604               MOVA (l);
9605               emitcode ("mov", "@%s,a", rname);
9606             }
9607           else
9608             emitcode ("mov", "@%s,%s", rname, l);
9609           if (size || pi)
9610             emitcode ("inc", "%s", rname);
9611           offset++;
9612         }
9613     }
9614
9615   /* now some housekeeping stuff */
9616   if (aop)
9617     {
9618       /* we had to allocate for this iCode */
9619       if (pi) aopPut (AOP (result),rname,0);
9620       freeAsmop (NULL, aop, ic, TRUE);
9621     }
9622   else
9623     {
9624       /* we did not allocate which means left
9625          already in a pointer register, then
9626          if size > 0 && this could be used again
9627          we have to point it back to where it
9628          belongs */
9629       if (AOP_SIZE (right) > 1 &&
9630           !OP_SYMBOL (result)->remat &&
9631           (OP_SYMBOL (result)->liveTo > ic->seq ||
9632            ic->depth) &&
9633           !pi)
9634         {
9635           int size = AOP_SIZE (right) - 1;
9636           while (size--)
9637             emitcode ("dec", "%s", rname);
9638         }
9639     }
9640
9641   /* done */
9642   if (pi) pi->generated = 1;
9643   freeAsmop (result, NULL, ic, TRUE);
9644   freeAsmop (right, NULL, ic, TRUE);
9645
9646
9647 }
9648
9649 /*-----------------------------------------------------------------*/
9650 /* genPagedPointerSet - emitcode for Paged pointer put             */
9651 /*-----------------------------------------------------------------*/
9652 static void
9653 genPagedPointerSet (operand * right,
9654                     operand * result,
9655                     iCode * ic,
9656                     iCode *pi)
9657 {
9658   asmop *aop = NULL;
9659   regs *preg = NULL;
9660   char *rname, *l;
9661   sym_link *retype, *letype;
9662
9663   retype = getSpec (operandType (right));
9664   letype = getSpec (operandType (result));
9665
9666   aopOp (result, ic, FALSE, FALSE);
9667
9668   /* if the value is already in a pointer register
9669      then don't need anything more */
9670   if (!AOP_INPREG (AOP (result)))
9671     {
9672       /* otherwise get a free pointer register */
9673       aop = newAsmop (0);
9674       preg = getFreePtr (ic, &aop, FALSE);
9675       emitcode ("mov", "%s,%s",
9676                 preg->name,
9677                 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9678       rname = preg->name;
9679     }
9680   else
9681     rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9682
9683   aopOp (right, ic, FALSE, FALSE);
9684
9685   /* if bitfield then unpack the bits */
9686   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9687     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
9688   else
9689     {
9690       /* we have can just get the values */
9691       int size = AOP_SIZE (right);
9692       int offset = 0;
9693
9694       while (size--)
9695         {
9696           l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
9697
9698           MOVA (l);
9699           emitcode ("movx", "@%s,a", rname);
9700
9701           if (size || pi)
9702             emitcode ("inc", "%s", rname);
9703
9704           offset++;
9705         }
9706     }
9707
9708   /* now some housekeeping stuff */
9709   if (aop)
9710     {
9711       if (pi) aopPut (AOP (result),rname,0);
9712       /* we had to allocate for this iCode */
9713       freeAsmop (NULL, aop, ic, TRUE);
9714     }
9715   else
9716     {
9717       /* we did not allocate which means left
9718          already in a pointer register, then
9719          if size > 0 && this could be used again
9720          we have to point it back to where it
9721          belongs */
9722       if (AOP_SIZE (right) > 1 &&
9723           !OP_SYMBOL (result)->remat &&
9724           (OP_SYMBOL (result)->liveTo > ic->seq ||
9725            ic->depth) &&
9726           !pi)
9727         {
9728           int size = AOP_SIZE (right) - 1;
9729           while (size--)
9730             emitcode ("dec", "%s", rname);
9731         }
9732     }
9733
9734   /* done */
9735   if (pi) pi->generated = 1;
9736   freeAsmop (result, NULL, ic, TRUE);
9737   freeAsmop (right, NULL, ic, TRUE);
9738
9739
9740 }
9741
9742 /*-----------------------------------------------------------------*/
9743 /* genFarPointerSet - set value from far space                     */
9744 /*-----------------------------------------------------------------*/
9745 static void
9746 genFarPointerSet (operand * right,
9747                   operand * result, iCode * ic, iCode *pi)
9748 {
9749   int size, offset, dopi=1;
9750   sym_link *retype = getSpec (operandType (right));
9751   sym_link *letype = getSpec (operandType (result));
9752
9753   aopOp (result, ic, FALSE, FALSE);
9754
9755   /* if the operand is already in dptr
9756      then we do nothing else we move the value to dptr */
9757   if (AOP_TYPE (result) != AOP_STR)
9758     {
9759       /* if this is remateriazable */
9760       if (AOP_TYPE (result) == AOP_IMMD)
9761         emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9762       else
9763         {
9764           /* we need to get it byte by byte */
9765           _startLazyDPSEvaluation ();
9766           if (AOP_TYPE (result) != AOP_DPTR)
9767             {
9768               emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9769               emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9770               if (options.model == MODEL_FLAT24)
9771                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9772             }
9773           else
9774             {
9775               /* We need to generate a load to DPTR indirect through DPTR. */
9776               D (emitcode (";", "genFarPointerSet -- indirection special case.");
9777                 );
9778               emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
9779               emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
9780               if (options.model == MODEL_FLAT24)
9781                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9782               emitcode ("pop", "dph");
9783               emitcode ("pop", "dpl");
9784               dopi=0;
9785             }
9786           _endLazyDPSEvaluation ();
9787         }
9788     }
9789   /* so dptr know contains the address */
9790   aopOp (right, ic, FALSE, TRUE);
9791
9792   /* if bit then unpack */
9793   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9794     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
9795   else
9796     {
9797       size = AOP_SIZE (right);
9798       offset = 0;
9799
9800       _startLazyDPSEvaluation ();
9801       while (size--)
9802         {
9803           char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9804           MOVA (l);
9805
9806           genSetDPTR (0);
9807           _flushLazyDPS ();
9808
9809           emitcode ("movx", "@dptr,a");
9810           if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
9811             emitcode ("inc", "dptr");
9812         }
9813       _endLazyDPSEvaluation ();
9814     }
9815
9816   if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
9817       aopPut (AOP(result),"dpl",0);
9818       aopPut (AOP(result),"dph",1);
9819       if (options.model == MODEL_FLAT24)
9820           aopPut (AOP(result),"dpx",2);
9821       pi->generated=1;
9822   } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
9823              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
9824       
9825       size = AOP_SIZE (right) - 1;
9826       while (size--) emitcode ("lcall","__decdptr");
9827   }
9828   freeAsmop (result, NULL, ic, TRUE);
9829   freeAsmop (right, NULL, ic, TRUE);
9830 }
9831
9832 /*-----------------------------------------------------------------*/
9833 /* genGenPointerSet - set value from generic pointer space         */
9834 /*-----------------------------------------------------------------*/
9835 static void
9836 genGenPointerSet (operand * right,
9837                   operand * result, iCode * ic, iCode *pi)
9838 {
9839   int size, offset;
9840   sym_link *retype = getSpec (operandType (right));
9841   sym_link *letype = getSpec (operandType (result));
9842
9843   aopOp (result, ic, FALSE, OP_SYMBOL(result)->ruonly ? FALSE : TRUE);
9844
9845   /* if the operand is already in dptr
9846      then we do nothing else we move the value to dptr */
9847   if (AOP_TYPE (result) != AOP_STR)
9848     {
9849       _startLazyDPSEvaluation ();
9850       /* if this is remateriazable */
9851       if (AOP_TYPE (result) == AOP_IMMD)
9852         {
9853           emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9854           if (AOP(result)->aopu.aop_immd.from_cast_remat) 
9855                   emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, FALSE));
9856           else
9857                   emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9858         }
9859       else
9860         {                       /* we need to get it byte by byte */
9861           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9862           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9863           if (options.model == MODEL_FLAT24) {
9864             emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9865             emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
9866           } else {
9867             emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9868           }
9869         }
9870       _endLazyDPSEvaluation ();
9871     }
9872   /* so dptr know contains the address */
9873   aopOp (right, ic, FALSE, TRUE);
9874
9875   /* if bit then unpack */
9876   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9877     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
9878   else
9879     {
9880       size = AOP_SIZE (right);
9881       offset = 0;
9882
9883       _startLazyDPSEvaluation ();
9884       while (size--)
9885         {
9886           char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9887           MOVA (l);
9888
9889           genSetDPTR (0);
9890           _flushLazyDPS ();
9891
9892           emitcode ("lcall", "__gptrput");
9893           if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
9894             emitcode ("inc", "dptr");
9895         }
9896       _endLazyDPSEvaluation ();
9897     }
9898
9899   if (pi && AOP_TYPE (result) != AOP_IMMD) {
9900       aopPut (AOP(result),"dpl",0);
9901       aopPut (AOP(result),"dph",1);
9902       if (options.model == MODEL_FLAT24) {
9903           aopPut (AOP(result),"dpx",2);
9904           aopPut (AOP(result),"b",3);
9905       } else {
9906           aopPut (AOP(result),"b",2);
9907       }
9908       pi->generated=1;
9909   } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
9910              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
9911       
9912       size = AOP_SIZE (right) - 1;
9913       while (size--) emitcode ("lcall","__decdptr");
9914   }
9915   freeAsmop (result, NULL, ic, TRUE);
9916   freeAsmop (right, NULL, ic, TRUE);
9917 }
9918
9919 /*-----------------------------------------------------------------*/
9920 /* genPointerSet - stores the value into a pointer location        */
9921 /*-----------------------------------------------------------------*/
9922 static void
9923 genPointerSet (iCode * ic, iCode *pi)
9924 {
9925   operand *right, *result;
9926   sym_link *type, *etype;
9927   int p_type;
9928
9929   D (emitcode (";", "genPointerSet ");
9930     );
9931
9932   right = IC_RIGHT (ic);
9933   result = IC_RESULT (ic);
9934
9935   /* depending on the type of pointer we need to
9936      move it to the correct pointer register */
9937   type = operandType (result);
9938   etype = getSpec (type);
9939   /* if left is of type of pointer then it is simple */
9940   if (IS_PTR (type) && !IS_FUNC (type->next))
9941     {
9942       p_type = DCL_TYPE (type);
9943     }
9944   else
9945     {
9946       /* we have to go by the storage class */
9947       p_type = PTR_TYPE (SPEC_OCLS (etype));
9948     }
9949   /* special case when cast remat */
9950   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
9951       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
9952           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
9953           type =   type = operandType (result);
9954           p_type = DCL_TYPE (type);
9955   }
9956
9957   /* now that we have the pointer type we assign
9958      the pointer values */
9959   switch (p_type)
9960     {
9961
9962     case POINTER:
9963     case IPOINTER:
9964       genNearPointerSet (right, result, ic, pi);
9965       break;
9966
9967     case PPOINTER:
9968       genPagedPointerSet (right, result, ic, pi);
9969       break;
9970
9971     case FPOINTER:
9972       genFarPointerSet (right, result, ic, pi);
9973       break;
9974
9975     case GPOINTER:
9976       genGenPointerSet (right, result, ic, pi);
9977       break;
9978     }
9979
9980 }
9981
9982 /*-----------------------------------------------------------------*/
9983 /* genIfx - generate code for Ifx statement                        */
9984 /*-----------------------------------------------------------------*/
9985 static void
9986 genIfx (iCode * ic, iCode * popIc)
9987 {
9988   operand *cond = IC_COND (ic);
9989   int isbit = 0;
9990
9991   D (emitcode (";", "genIfx "););
9992
9993   aopOp (cond, ic, FALSE, FALSE);
9994
9995   /* get the value into acc */
9996   if (AOP_TYPE (cond) != AOP_CRY)
9997     toBoolean (cond);
9998   else
9999     isbit = 1;
10000   /* the result is now in the accumulator */
10001   freeAsmop (cond, NULL, ic, TRUE);
10002
10003   /* if there was something to be popped then do it */
10004   if (popIc)
10005     genIpop (popIc);
10006
10007   /* if the condition is  a bit variable */
10008   if (isbit && IS_ITEMP (cond) &&
10009       SPIL_LOC (cond))
10010     genIfxJump (ic, SPIL_LOC (cond)->rname);
10011   else if (isbit && !IS_ITEMP (cond))
10012     genIfxJump (ic, OP_SYMBOL (cond)->rname);
10013   else
10014     genIfxJump (ic, "a");
10015
10016   ic->generated = 1;
10017 }
10018
10019 /*-----------------------------------------------------------------*/
10020 /* genAddrOf - generates code for address of                       */
10021 /*-----------------------------------------------------------------*/
10022 static void
10023 genAddrOf (iCode * ic)
10024 {
10025   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10026   int size, offset;
10027
10028   D (emitcode (";", "genAddrOf ");
10029     );
10030
10031   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10032
10033   /* if the operand is on the stack then we
10034      need to get the stack offset of this
10035      variable */
10036   if (sym->onStack) {
10037       
10038       /* if 10 bit stack */
10039       if (options.stack10bit) {
10040           char buff[10];
10041           tsprintf(buff,"#!constbyte",(options.stack_loc >> 16) & 0xff);
10042           /* if it has an offset then we need to compute it */
10043           emitcode ("subb", "a,#!constbyte",
10044                     -((sym->stack < 0) ?
10045                       ((short) (sym->stack - _G.nRegsSaved)) :
10046                       ((short) sym->stack)) & 0xff);
10047           emitcode ("mov","b,a");
10048           emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ?
10049                                          ((short) (sym->stack - _G.nRegsSaved)) :
10050                                          ((short) sym->stack)) >> 8) & 0xff);
10051           if (sym->stack) {
10052               emitcode ("mov", "a,_bpx");
10053               emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ? 
10054                                              ((char) (sym->stack - _G.nRegsSaved)) :
10055                                              ((char) sym->stack )) & 0xff);
10056               emitcode ("mov", "b,a");
10057               emitcode ("mov", "a,_bpx+1");
10058               emitcode ("addc","a,#!constbyte", (((sym->stack < 0) ? 
10059                                               ((short) (sym->stack - _G.nRegsSaved)) :
10060                                               ((short) sym->stack )) >> 8) & 0xff);
10061               aopPut (AOP (IC_RESULT (ic)), "b", 0);
10062               aopPut (AOP (IC_RESULT (ic)), "a", 1);
10063               aopPut (AOP (IC_RESULT (ic)), buff, 2);
10064           } else {
10065               /* we can just move _bp */
10066               aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
10067               aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
10068               aopPut (AOP (IC_RESULT (ic)), buff, 2);
10069           }       
10070       } else {
10071           /* if it has an offset then we need to compute it */
10072           if (sym->stack) {
10073               emitcode ("mov", "a,_bp");
10074               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
10075               aopPut (AOP (IC_RESULT (ic)), "a", 0);
10076           } else {
10077               /* we can just move _bp */
10078               aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
10079           }
10080           /* fill the result with zero */
10081           size = AOP_SIZE (IC_RESULT (ic)) - 1;
10082           
10083           
10084           if (options.stack10bit && size < (FPTRSIZE - 1)) {
10085               fprintf (stderr,
10086                        "*** warning: pointer to stack var truncated.\n");
10087           }
10088
10089           offset = 1;
10090           while (size--) {
10091               aopPut (AOP (IC_RESULT (ic)), zero, offset++);
10092           }      
10093       }
10094       goto release;
10095   }
10096
10097   /* object not on stack then we need the name */
10098   size = AOP_SIZE (IC_RESULT (ic));
10099   offset = 0;
10100
10101   while (size--)
10102     {
10103       char s[SDCC_NAME_MAX];
10104       if (offset) {
10105           switch (offset) {
10106           case 1:
10107               tsprintf(s,"!his",sym->rname);
10108               break;
10109           case 2:
10110               tsprintf(s,"!hihis",sym->rname);
10111               break;
10112           case 3:
10113               tsprintf(s,"!hihihis",sym->rname);
10114               break;
10115           default: /* should not need this (just in case) */
10116               sprintf (s, "#(%s >> %d)",
10117                        sym->rname,
10118                        offset * 8);
10119           }
10120       } else
10121           sprintf (s, "#%s", sym->rname);
10122       aopPut (AOP (IC_RESULT (ic)), s, offset++);
10123     }
10124
10125 release:
10126   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10127
10128 }
10129
10130 /*-----------------------------------------------------------------*/
10131 /* genArrayInit - generates code for address of                       */
10132 /*-----------------------------------------------------------------*/
10133 static void
10134 genArrayInit (iCode * ic)
10135 {
10136     literalList *iLoop;
10137     int         ix, count;
10138     int         elementSize = 0, eIndex;
10139     unsigned    val, lastVal;
10140     sym_link    *type;
10141     operand     *left=IC_LEFT(ic);
10142     
10143     D (emitcode (";", "genArrayInit "););
10144
10145     aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10146     
10147     if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10148     {
10149         // Load immediate value into DPTR.
10150         emitcode("mov", "dptr, %s",
10151              aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, TRUE));
10152     }
10153     else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10154     {
10155 #if 0
10156       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10157               "Unexpected operand to genArrayInit.\n");
10158       exit(1);
10159 #else
10160       // a regression because of SDCCcse.c:1.52
10161       emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
10162       emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
10163       if (options.model == MODEL_FLAT24)
10164         emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
10165 #endif
10166     }
10167     
10168     type = operandType(IC_LEFT(ic));
10169     
10170     if (type && type->next)
10171     {
10172         elementSize = getSize(type->next);
10173     }
10174     else
10175     {
10176         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10177                                 "can't determine element size in genArrayInit.\n");
10178         exit(1);
10179     }
10180     
10181     iLoop = IC_ARRAYILIST(ic);
10182     lastVal = 0xffff;
10183     
10184     while (iLoop)
10185     {
10186         bool firstpass = TRUE;
10187         
10188         emitcode(";", "store %d x 0x%x to DPTR (element size %d)", 
10189                  iLoop->count, (int)iLoop->literalValue, elementSize);
10190         
10191         ix = iLoop->count;
10192         
10193         while (ix)
10194         {
10195             symbol *tlbl = NULL;
10196             
10197             count = ix > 256 ? 256 : ix;
10198             
10199             if (count > 1)
10200             {
10201                 tlbl = newiTempLabel (NULL);
10202                 if (firstpass || (count & 0xff))
10203                 {
10204                     emitcode("mov", "b, #!constbyte", count & 0xff);
10205                 }
10206                 
10207                 emitcode ("", "!tlabeldef", tlbl->key + 100);
10208             }
10209             
10210             firstpass = FALSE;
10211                 
10212             for (eIndex = 0; eIndex < elementSize; eIndex++)
10213             {
10214                 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10215                 if (val != lastVal)
10216                 {
10217                     emitcode("mov", "a, #!constbyte", val);
10218                     lastVal = val;
10219                 }
10220                 
10221                 emitcode("movx", "@dptr, a");
10222                 emitcode("inc", "dptr");
10223             }
10224             
10225             if (count > 1)
10226             {
10227                 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
10228             }
10229             
10230             ix -= count;
10231         }
10232         
10233         iLoop = iLoop->next;
10234     }
10235     
10236     freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10237 }
10238
10239 /*-----------------------------------------------------------------*/
10240 /* genFarFarAssign - assignment when both are in far space         */
10241 /*-----------------------------------------------------------------*/
10242 static void
10243 genFarFarAssign (operand * result, operand * right, iCode * ic)
10244 {
10245   int size = AOP_SIZE (right);
10246   int offset = 0;
10247   symbol *rSym = NULL;
10248
10249   if (size == 1)
10250   {
10251       /* quick & easy case. */
10252       D(emitcode(";","genFarFarAssign (1 byte case)"););      
10253       MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
10254       freeAsmop (right, NULL, ic, FALSE);
10255       /* now assign DPTR to result */
10256       _G.accInUse++;
10257       aopOp(result, ic, FALSE, FALSE);
10258       _G.accInUse--;
10259       aopPut(AOP(result), "a", 0);
10260       freeAsmop(result, NULL, ic, FALSE);
10261       return;
10262   }
10263   
10264   /* See if we've got an underlying symbol to abuse. */
10265   if (IS_SYMOP(result) && OP_SYMBOL(result))
10266   {
10267       if (IS_TRUE_SYMOP(result))
10268       {
10269           rSym = OP_SYMBOL(result);
10270       }
10271       else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10272       {
10273           rSym = OP_SYMBOL(result)->usl.spillLoc;
10274       }
10275   }
10276              
10277   if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10278   {
10279       /* We can use the '390 auto-toggle feature to good effect here. */
10280       
10281       D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10282       emitcode("mov", "dps,#!constbyte",0x21);  /* Select DPTR2 & auto-toggle. */
10283       emitcode ("mov", "dptr,#%s", rSym->rname); 
10284       /* DP2 = result, DP1 = right, DP1 is current. */
10285       while (size)
10286       {
10287           emitcode("movx", "a,@dptr");
10288           emitcode("movx", "@dptr,a");
10289           if (--size)
10290           {
10291                emitcode("inc", "dptr");
10292                emitcode("inc", "dptr");
10293           }
10294       }
10295       emitcode("mov", "dps,#0");
10296       freeAsmop (right, NULL, ic, FALSE);
10297 #if 0
10298 some alternative code for processors without auto-toggle
10299 no time to test now, so later well put in...kpb
10300         D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10301         emitcode("mov", "dps,#1");      /* Select DPTR2. */
10302         emitcode ("mov", "dptr,#%s", rSym->rname); 
10303         /* DP2 = result, DP1 = right, DP1 is current. */
10304         while (size)
10305         {
10306           --size;
10307           emitcode("movx", "a,@dptr");
10308           if (size)
10309             emitcode("inc", "dptr");
10310           emitcode("inc", "dps");
10311           emitcode("movx", "@dptr,a");
10312           if (size)
10313             emitcode("inc", "dptr");
10314           emitcode("inc", "dps");
10315         }
10316         emitcode("mov", "dps,#0");
10317         freeAsmop (right, NULL, ic, FALSE);
10318 #endif
10319   }
10320   else
10321   {
10322       D (emitcode (";", "genFarFarAssign"););
10323       aopOp (result, ic, TRUE, TRUE);
10324
10325       _startLazyDPSEvaluation ();
10326       
10327       while (size--)
10328         {
10329           aopPut (AOP (result),
10330                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
10331           offset++;
10332         }
10333       _endLazyDPSEvaluation ();
10334       freeAsmop (result, NULL, ic, FALSE);
10335       freeAsmop (right, NULL, ic, FALSE);
10336   }
10337 }
10338
10339 /*-----------------------------------------------------------------*/
10340 /* genAssign - generate code for assignment                        */
10341 /*-----------------------------------------------------------------*/
10342 static void
10343 genAssign (iCode * ic)
10344 {
10345   operand *result, *right;
10346   int size, offset;
10347   unsigned long lit = 0L;
10348
10349   D (emitcode (";", "genAssign ");
10350     );
10351
10352   result = IC_RESULT (ic);
10353   right = IC_RIGHT (ic);
10354
10355   /* if they are the same */
10356   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10357     return;
10358
10359   aopOp (right, ic, FALSE, FALSE);
10360
10361   emitcode (";", "genAssign: resultIsFar = %s",
10362             isOperandInFarSpace (result) ?
10363             "TRUE" : "FALSE");
10364
10365   /* special case both in far space */
10366   if ((AOP_TYPE (right) == AOP_DPTR ||
10367        AOP_TYPE (right) == AOP_DPTR2) &&
10368   /* IS_TRUE_SYMOP(result)       && */
10369       isOperandInFarSpace (result))
10370     {
10371       genFarFarAssign (result, right, ic);
10372       return;
10373     }
10374
10375   aopOp (result, ic, TRUE, FALSE);
10376
10377   /* if they are the same registers */
10378   if (sameRegs (AOP (right), AOP (result)))
10379     goto release;
10380
10381   /* if the result is a bit */
10382   if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10383     {
10384       /* if the right size is a literal then
10385          we know what the value is */
10386       if (AOP_TYPE (right) == AOP_LIT)
10387         {
10388           if (((int) operandLitValue (right)))
10389             aopPut (AOP (result), one, 0);
10390           else
10391             aopPut (AOP (result), zero, 0);
10392           goto release;
10393         }
10394
10395       /* the right is also a bit variable */
10396       if (AOP_TYPE (right) == AOP_CRY)
10397         {
10398           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10399           aopPut (AOP (result), "c", 0);
10400           goto release;
10401         }
10402
10403       /* we need to or */
10404       toBoolean (right);
10405       aopPut (AOP (result), "a", 0);
10406       goto release;
10407     }
10408
10409   /* bit variables done */
10410   /* general case */
10411   size = AOP_SIZE (result);
10412   offset = 0;
10413   if (AOP_TYPE (right) == AOP_LIT)
10414     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10415
10416   if ((size > 1) &&
10417       (AOP_TYPE (result) != AOP_REG) &&
10418       (AOP_TYPE (right) == AOP_LIT) &&
10419       !IS_FLOAT (operandType (right)))
10420     {
10421       _startLazyDPSEvaluation ();
10422       while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10423         {
10424           aopPut (AOP (result),
10425                   aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
10426                   offset);
10427           offset++;
10428           size--;
10429         }
10430       /* And now fill the rest with zeros. */
10431       if (size)
10432         {
10433           emitcode ("clr", "a");
10434         }
10435       while (size--)
10436         {
10437           aopPut (AOP (result), "a", offset++);
10438         }
10439       _endLazyDPSEvaluation ();
10440     }
10441   else
10442     {
10443       _startLazyDPSEvaluation ();
10444       while (size--)
10445         {
10446           aopPut (AOP (result),
10447                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10448                   offset);
10449           offset++;
10450         }
10451       _endLazyDPSEvaluation ();
10452     }
10453
10454 release:
10455   freeAsmop (right, NULL, ic, FALSE);
10456   freeAsmop (result, NULL, ic, TRUE);
10457 }
10458
10459 /*-----------------------------------------------------------------*/
10460 /* genJumpTab - generates code for jump table                      */
10461 /*-----------------------------------------------------------------*/
10462 static void
10463 genJumpTab (iCode * ic)
10464 {
10465   symbol *jtab;
10466   char *l;
10467
10468   D (emitcode (";", "genJumpTab ");
10469     );
10470
10471   aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10472   /* get the condition into accumulator */
10473   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
10474   MOVA (l);
10475   /* multiply by four! */
10476   emitcode ("add", "a,acc");
10477   emitcode ("add", "a,acc");
10478   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10479
10480   jtab = newiTempLabel (NULL);
10481   emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
10482   emitcode ("jmp", "@a+dptr");
10483   emitcode ("", "!tlabeldef", jtab->key + 100);
10484   /* now generate the jump labels */
10485   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10486        jtab = setNextItem (IC_JTLABELS (ic)))
10487     emitcode ("ljmp", "!tlabel", jtab->key + 100);
10488
10489 }
10490
10491 /*-----------------------------------------------------------------*/
10492 /* genCast - gen code for casting                                  */
10493 /*-----------------------------------------------------------------*/
10494 static void
10495 genCast (iCode * ic)
10496 {
10497   operand *result = IC_RESULT (ic);
10498   sym_link *ctype = operandType (IC_LEFT (ic));
10499   sym_link *rtype = operandType (IC_RIGHT (ic));
10500   operand *right = IC_RIGHT (ic);
10501   int size, offset;
10502
10503   D (emitcode (";", "genCast ");
10504     );
10505
10506   /* if they are equivalent then do nothing */
10507   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10508     return;
10509
10510   aopOp (right, ic, FALSE, FALSE);
10511   aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
10512
10513   /* if the result is a bit */
10514   // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10515   if (IS_BITVAR(OP_SYMBOL(result)->type))
10516     {
10517       /* if the right size is a literal then
10518          we know what the value is */
10519       if (AOP_TYPE (right) == AOP_LIT)
10520         {
10521           if (((int) operandLitValue (right)))
10522             aopPut (AOP (result), one, 0);
10523           else
10524             aopPut (AOP (result), zero, 0);
10525
10526           goto release;
10527         }
10528
10529       /* the right is also a bit variable */
10530       if (AOP_TYPE (right) == AOP_CRY)
10531         {
10532           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10533           aopPut (AOP (result), "c", 0);
10534           goto release;
10535         }
10536
10537       /* we need to or */
10538       toBoolean (right);
10539       aopPut (AOP (result), "a", 0);
10540       goto release;
10541     }
10542
10543   /* if they are the same size : or less */
10544   if (AOP_SIZE (result) <= AOP_SIZE (right))
10545     {
10546
10547       /* if they are in the same place */
10548       if (sameRegs (AOP (right), AOP (result)))
10549         goto release;
10550
10551       /* if they in different places then copy */
10552       size = AOP_SIZE (result);
10553       offset = 0;
10554       _startLazyDPSEvaluation ();
10555       while (size--)
10556         {
10557           aopPut (AOP (result),
10558                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10559                   offset);
10560           offset++;
10561         }
10562       _endLazyDPSEvaluation ();
10563       goto release;
10564     }
10565
10566
10567   /* if the result is of type pointer */
10568   if (IS_PTR (ctype))
10569     {
10570
10571       int p_type;
10572       sym_link *type = operandType (right);
10573
10574       /* pointer to generic pointer */
10575       if (IS_GENPTR (ctype))
10576         {
10577           char *l = zero;
10578
10579           if (IS_PTR (type))
10580             {
10581               p_type = DCL_TYPE (type);
10582             }
10583           else
10584             {
10585 #if OLD_CAST_BEHAVIOR
10586               /* KV: we are converting a non-pointer type to
10587                * a generic pointer. This (ifdef'd out) code
10588                * says that the resulting generic pointer
10589                * should have the same class as the storage
10590                * location of the non-pointer variable.
10591                *
10592                * For example, converting an int (which happens
10593                * to be stored in DATA space) to a pointer results
10594                * in a DATA generic pointer; if the original int
10595                * in XDATA space, so will be the resulting pointer.
10596                *
10597                * I don't like that behavior, and thus this change:
10598                * all such conversions will be forced to XDATA and
10599                * throw a warning. If you want some non-XDATA
10600                * type, or you want to suppress the warning, you
10601                * must go through an intermediate cast, like so:
10602                *
10603                * char _generic *gp = (char _xdata *)(intVar);
10604                */
10605               sym_link *etype = getSpec (type);
10606
10607               /* we have to go by the storage class */
10608               if (SPEC_OCLS (etype) != generic)
10609                 {
10610                   p_type = PTR_TYPE (SPEC_OCLS (etype));
10611                 }
10612               else
10613 #endif
10614                 {
10615                   /* Converting unknown class (i.e. register variable)
10616                    * to generic pointer. This is not good, but
10617                    * we'll make a guess (and throw a warning).
10618                    */
10619                   p_type = FPOINTER;
10620                   werror (W_INT_TO_GEN_PTR_CAST);
10621                 }
10622             }
10623
10624           /* the first two bytes are known */
10625           size = GPTRSIZE - 1;
10626           offset = 0;
10627           _startLazyDPSEvaluation ();
10628           while (size--)
10629             {
10630               aopPut (AOP (result),
10631                       aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10632                       offset);
10633               offset++;
10634             }
10635           _endLazyDPSEvaluation ();
10636
10637           /* the last byte depending on type */
10638           switch (p_type)
10639             {
10640             case IPOINTER:
10641             case POINTER:
10642               l = zero;
10643               break;
10644             case FPOINTER:
10645               l = one;
10646               break;
10647             case CPOINTER:
10648               l = "#0x02";
10649               break;
10650             case PPOINTER:
10651               l = "#0x03";
10652               break;
10653
10654             default:
10655               /* this should never happen */
10656               werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10657                       "got unknown pointer type");
10658               exit (1);
10659             }
10660           aopPut (AOP (result), l, GPTRSIZE - 1);
10661           goto release;
10662         }
10663
10664       /* just copy the pointers */
10665       size = AOP_SIZE (result);
10666       offset = 0;
10667       _startLazyDPSEvaluation ();
10668       while (size--)
10669         {
10670           aopPut (AOP (result),
10671                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10672                   offset);
10673           offset++;
10674         }
10675       _endLazyDPSEvaluation ();
10676       goto release;
10677     }
10678
10679   /* so we now know that the size of destination is greater
10680      than the size of the source */
10681   /* we move to result for the size of source */
10682   size = AOP_SIZE (right);
10683   offset = 0;
10684   _startLazyDPSEvaluation ();
10685   while (size--)
10686     {
10687       aopPut (AOP (result),
10688               aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10689               offset);
10690       offset++;
10691     }
10692   _endLazyDPSEvaluation ();
10693
10694   /* now depending on the sign of the source && destination */
10695   size = AOP_SIZE (result) - AOP_SIZE (right);
10696   /* if unsigned or not an integral type */
10697   /* also, if the source is a bit, we don't need to sign extend, because
10698    * it can't possibly have set the sign bit.
10699    */
10700   if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
10701     {
10702       while (size--)
10703         {
10704           aopPut (AOP (result), zero, offset++);
10705         }
10706     }
10707   else
10708     {
10709       /* we need to extend the sign :{ */
10710       char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
10711                         FALSE, FALSE, TRUE);
10712       MOVA (l);
10713       emitcode ("rlc", "a");
10714       emitcode ("subb", "a,acc");
10715       while (size--)
10716         aopPut (AOP (result), "a", offset++);
10717     }
10718
10719   /* we are done hurray !!!! */
10720
10721 release:
10722   freeAsmop (right, NULL, ic, TRUE);
10723   freeAsmop (result, NULL, ic, TRUE);
10724
10725 }
10726
10727 /*-----------------------------------------------------------------*/
10728 /* genDjnz - generate decrement & jump if not zero instrucion      */
10729 /*-----------------------------------------------------------------*/
10730 static int
10731 genDjnz (iCode * ic, iCode * ifx)
10732 {
10733   symbol *lbl, *lbl1;
10734   if (!ifx)
10735     return 0;
10736
10737   /* if the if condition has a false label
10738      then we cannot save */
10739   if (IC_FALSE (ifx))
10740     return 0;
10741
10742   /* if the minus is not of the form
10743      a = a - 1 */
10744   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
10745       !IS_OP_LITERAL (IC_RIGHT (ic)))
10746     return 0;
10747
10748   if (operandLitValue (IC_RIGHT (ic)) != 1)
10749     return 0;
10750
10751   /* if the size of this greater than one then no
10752      saving */
10753   if (getSize (operandType (IC_RESULT (ic))) > 1)
10754     return 0;
10755
10756   /* otherwise we can save BIG */
10757   D(emitcode(";", "genDjnz"););
10758
10759   lbl = newiTempLabel (NULL);
10760   lbl1 = newiTempLabel (NULL);
10761
10762   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10763
10764   if (AOP_NEEDSACC(IC_RESULT(ic)))
10765   {
10766       /* If the result is accessed indirectly via
10767        * the accumulator, we must explicitly write
10768        * it back after the decrement.
10769        */
10770       char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
10771       
10772       if (strcmp(rByte, "a"))
10773       {
10774            /* Something is hopelessly wrong */
10775            fprintf(stderr, "*** warning: internal error at %s:%d\n",
10776                    __FILE__, __LINE__);
10777            /* We can just give up; the generated code will be inefficient,
10778             * but what the hey.
10779             */
10780            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10781            return 0;
10782       }
10783       emitcode ("dec", "%s", rByte);
10784       aopPut(AOP(IC_RESULT(ic)), rByte, 0);
10785       emitcode ("jnz", "!tlabel", lbl->key + 100);
10786   }
10787   else if (IS_AOP_PREG (IC_RESULT (ic)))
10788     {
10789       emitcode ("dec", "%s",
10790                 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10791       emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10792       emitcode ("jnz", "!tlabel", lbl->key + 100);
10793     }
10794   else
10795     {
10796       emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
10797                 lbl->key + 100);
10798     }
10799   emitcode ("sjmp", "!tlabel", lbl1->key + 100);
10800   emitcode ("", "!tlabeldef", lbl->key + 100);
10801   emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
10802   emitcode ("", "!tlabeldef", lbl1->key + 100);
10803
10804   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10805   ifx->generated = 1;
10806   return 1;
10807 }
10808
10809 /*-----------------------------------------------------------------*/
10810 /* genReceive - generate code for a receive iCode                  */
10811 /*-----------------------------------------------------------------*/
10812 static void
10813 genReceive (iCode * ic)
10814 {
10815
10816   D (emitcode (";", "genReceive ");
10817     );
10818
10819   if (isOperandInFarSpace (IC_RESULT (ic)) &&
10820       (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
10821        IS_TRUE_SYMOP (IC_RESULT (ic))))
10822     {
10823       int size = getSize (operandType (IC_RESULT (ic)));
10824       int offset = fReturnSizeDS390 - size;
10825       while (size--)
10826         {
10827           emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
10828                             fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
10829           offset++;
10830         }
10831       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10832       size = AOP_SIZE (IC_RESULT (ic));
10833       offset = 0;
10834       while (size--)
10835         {
10836           emitcode ("pop", "acc");
10837           aopPut (AOP (IC_RESULT (ic)), "a", offset++);
10838         }
10839
10840     }
10841   else
10842     {
10843       _G.accInUse++;
10844       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10845       _G.accInUse--;
10846       assignResultValue (IC_RESULT (ic));
10847     }
10848
10849   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10850 }
10851
10852 /*-----------------------------------------------------------------*/
10853 /* genMemcpyX2X - gen code for memcpy xdata to xdata               */
10854 /*-----------------------------------------------------------------*/
10855 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
10856 {
10857     operand *from , *to , *count;
10858     symbol *lbl;
10859     bitVect *rsave;
10860     int i;
10861
10862     /* we know it has to be 3 parameters */
10863     assert (nparms == 3);
10864     
10865     rsave = newBitVect(16);
10866     /* save DPTR if it needs to be saved */
10867     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
10868             if (bitVectBitValue(ic->rMask,i))
10869                     rsave = bitVectSetBit(rsave,i);
10870     }
10871     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
10872                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
10873     savermask(rsave);
10874     
10875     to = parms[0];
10876     from = parms[1];
10877     count = parms[2];
10878
10879     aopOp (from, ic->next, FALSE, FALSE);
10880
10881     /* get from into DPTR1 */
10882     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, TRUE));
10883     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, TRUE));
10884     if (options.model == MODEL_FLAT24) {
10885         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, TRUE));
10886     }
10887
10888     freeAsmop (from, NULL, ic, FALSE);
10889     aopOp (to, ic, FALSE, FALSE);
10890     /* get "to" into DPTR */
10891     /* if the operand is already in dptr
10892        then we do nothing else we move the value to dptr */
10893     if (AOP_TYPE (to) != AOP_STR) {
10894         /* if already in DPTR then we need to push */
10895         if (AOP_TYPE(to) == AOP_DPTR) {
10896             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
10897             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
10898             if (options.model == MODEL_FLAT24)
10899                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
10900             emitcode ("pop", "dph");
10901             emitcode ("pop", "dpl");        
10902         } else {
10903             _startLazyDPSEvaluation ();
10904             /* if this is remateriazable */
10905             if (AOP_TYPE (to) == AOP_IMMD) {
10906                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
10907             } else {                    /* we need to get it byte by byte */
10908                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
10909                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
10910                 if (options.model == MODEL_FLAT24) {
10911                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
10912                 }
10913             }
10914             _endLazyDPSEvaluation ();
10915         }
10916     }
10917     freeAsmop (to, NULL, ic, FALSE);
10918
10919     aopOp (count, ic->next->next, FALSE,FALSE);
10920     lbl =newiTempLabel(NULL);
10921
10922     /* now for the actual copy */
10923     if (AOP_TYPE(count) == AOP_LIT && 
10924         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
10925         emitcode (";","OH  JOY auto increment with djnz (very fast)");
10926         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
10927         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
10928         emitcode ("","!tlabeldef",lbl->key+100);
10929         if (fromc) {
10930             emitcode ("clr","a");
10931             emitcode ("movc", "a,@a+dptr");
10932         } else 
10933             emitcode ("movx", "a,@dptr");
10934         emitcode ("movx", "@dptr,a");
10935         emitcode ("inc", "dptr");
10936         emitcode ("inc", "dptr");
10937         emitcode ("djnz","b,!tlabel",lbl->key+100);
10938     } else {
10939         symbol *lbl1 = newiTempLabel(NULL);
10940         
10941         emitcode (";"," Auto increment but no djnz");
10942         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
10943         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
10944         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
10945         emitcode ("","!tlabeldef",lbl->key+100);
10946         if (fromc) {
10947             emitcode ("clr","a");
10948             emitcode ("movc", "a,@a+dptr");
10949         } else 
10950             emitcode ("movx", "a,@dptr");
10951         emitcode ("movx", "@dptr,a");
10952         emitcode ("inc", "dptr");
10953         emitcode ("inc", "dptr");
10954         emitcode ("mov","a,b");
10955         emitcode ("orl","a,_ap");
10956         emitcode ("jz","!tlabel",lbl1->key+100);
10957         emitcode ("mov","a,_ap");
10958         emitcode ("add","a,#!constbyte",0xFF);
10959         emitcode ("mov","_ap,a");
10960         emitcode ("mov","a,b");
10961         emitcode ("addc","a,#!constbyte",0xFF);
10962         emitcode ("mov","b,a");
10963         emitcode ("sjmp","!tlabel",lbl->key+100);
10964         emitcode ("","!tlabeldef",lbl1->key+100);
10965     }
10966     emitcode ("mov", "dps,#0"); 
10967     freeAsmop (count, NULL, ic, FALSE);
10968     unsavermask(rsave);
10969
10970 }
10971
10972 /*-----------------------------------------------------------------*/
10973 /* genMemsetX - gencode for memSetX data                           */
10974 /*-----------------------------------------------------------------*/
10975 static void genMemsetX(iCode *ic, int nparms, operand **parms)
10976 {
10977     operand *to , *val , *count;
10978     symbol *lbl;
10979     char *l;
10980     int i;
10981     bitVect *rsave = NULL;
10982
10983     /* we know it has to be 3 parameters */
10984     assert (nparms == 3);
10985     
10986     to = parms[0];
10987     val = parms[1];
10988     count = parms[2];
10989         
10990     /* save DPTR if it needs to be saved */
10991     rsave = newBitVect(16);
10992     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
10993             if (bitVectBitValue(ic->rMask,i))
10994                     rsave = bitVectSetBit(rsave,i);
10995     }
10996     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
10997                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
10998     savermask(rsave);
10999
11000     aopOp (to, ic, FALSE, FALSE);
11001     /* get "to" into DPTR */
11002     /* if the operand is already in dptr
11003        then we do nothing else we move the value to dptr */
11004     if (AOP_TYPE (to) != AOP_STR) {
11005         /* if already in DPTR then we need to push */
11006         if (AOP_TYPE(to) == AOP_DPTR) {
11007             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
11008             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
11009             if (options.model == MODEL_FLAT24)
11010                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11011             emitcode ("pop", "dph");
11012             emitcode ("pop", "dpl");        
11013         } else {
11014             _startLazyDPSEvaluation ();
11015             /* if this is remateriazable */
11016             if (AOP_TYPE (to) == AOP_IMMD) {
11017                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
11018             } else {                    /* we need to get it byte by byte */
11019                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
11020                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
11021                 if (options.model == MODEL_FLAT24) {
11022                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11023                 }
11024             }
11025             _endLazyDPSEvaluation ();
11026         }
11027     }
11028     freeAsmop (to, NULL, ic, FALSE);
11029
11030     aopOp (val, ic->next->next, FALSE,FALSE);
11031     aopOp (count, ic->next->next, FALSE,FALSE);    
11032     lbl =newiTempLabel(NULL);
11033     /* now for the actual copy */
11034     if (AOP_TYPE(count) == AOP_LIT && 
11035         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11036         l = aopGet(AOP (val), 0, FALSE, FALSE, TRUE);
11037         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
11038         MOVA(l);
11039         emitcode ("","!tlabeldef",lbl->key+100);
11040         emitcode ("movx", "@dptr,a");
11041         emitcode ("inc", "dptr");
11042         emitcode ("djnz","b,!tlabel",lbl->key+100);
11043     } else {
11044         symbol *lbl1 = newiTempLabel(NULL);
11045         
11046         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
11047         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
11048         emitcode ("","!tlabeldef",lbl->key+100);
11049         l = aopGet(AOP (val), 0, FALSE, FALSE, TRUE);
11050         MOVA(l);
11051         emitcode ("movx", "a,@dptr");
11052         emitcode ("inc", "dptr");
11053         emitcode ("mov","a,b");
11054         emitcode ("orl","a,_ap");
11055         emitcode ("jz","!tlabel",lbl1->key+100);
11056         emitcode ("mov","a,_ap");
11057         emitcode ("add","a,#!constbyte",0xFF);
11058         emitcode ("mov","_ap,a");
11059         emitcode ("mov","a,b");
11060         emitcode ("addc","a,#!constbyte",0xFF);
11061         emitcode ("mov","b,a");
11062         emitcode ("sjmp","!tlabel",lbl->key+100);
11063         emitcode ("","!tlabeldef",lbl1->key+100);
11064     }
11065     freeAsmop (count, NULL, ic, FALSE);
11066     unsavermask(rsave);
11067 }
11068
11069 /*-----------------------------------------------------------------*/
11070 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
11071 /*-----------------------------------------------------------------*/
11072 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
11073 {
11074         bitVect *rsave ;
11075         operand *pnum, *result;
11076         int i;
11077     
11078         assert (nparms==1);
11079         /* save registers that need to be saved */
11080         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11081                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11082     
11083         pnum = parms[0]; 
11084         aopOp (pnum, ic, FALSE, FALSE);
11085         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,FALSE));
11086         freeAsmop (pnum, NULL, ic, FALSE);
11087         emitcode ("lcall","NatLib_LoadPrimitive");
11088         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11089         if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) || 
11090             aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
11091                 for (i = (size-1) ; i >= 0 ; i-- ) {
11092                         emitcode ("push","a%s",javaRet[i]);
11093                 }
11094                 for (i=0; i < size ; i++ ) {
11095                         emitcode ("pop","a%s",aopGet(AOP(result),i,FALSE,FALSE,FALSE));
11096                 }
11097         } else {
11098                 for (i = 0 ; i < size ; i++ ) {
11099                         aopPut(AOP(result),javaRet[i],i);
11100                 }
11101         }    
11102         freeAsmop (result, NULL, ic, FALSE);
11103         unsavermask(rsave);
11104 }
11105
11106 /*-----------------------------------------------------------------*/
11107 /* genNatLibLoadPointer - calls TINI api function to load pointer  */
11108 /*-----------------------------------------------------------------*/
11109 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
11110 {
11111         bitVect *rsave ;
11112         operand *pnum, *result;
11113         int size = 3;
11114         int i;
11115     
11116         assert (nparms==1);
11117         /* save registers that need to be saved */
11118         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11119                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11120     
11121         pnum = parms[0]; 
11122         aopOp (pnum, ic, FALSE, FALSE);
11123         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,FALSE));
11124         freeAsmop (pnum, NULL, ic, FALSE);
11125         emitcode ("lcall","NatLib_LoadPointer");
11126         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11127         if (AOP_TYPE(result)!=AOP_STR) {
11128                 for (i = 0 ; i < size ; i++ ) {
11129                         aopPut(AOP(result),fReturn[i],i);
11130                 }
11131         }    
11132         freeAsmop (result, NULL, ic, FALSE);
11133         unsavermask(rsave);
11134 }
11135
11136 /*-----------------------------------------------------------------*/
11137 /* genNatLibInstallStateBlock -                                    */
11138 /*-----------------------------------------------------------------*/
11139 static void genNatLibInstallStateBlock(iCode *ic, int nparms, 
11140                                        operand **parms, const char *name)
11141 {
11142         bitVect *rsave ;
11143         operand *psb, *handle;
11144         assert (nparms==2);
11145
11146         /* save registers that need to be saved */
11147         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11148                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11149         psb = parms[0];
11150         handle = parms[1];
11151
11152         /* put pointer to state block into DPTR1 */
11153         aopOp (psb, ic, FALSE, FALSE);
11154         if (AOP_TYPE (psb) == AOP_IMMD) {
11155                 emitcode ("mov","dps,#1");
11156                 emitcode ("mov", "dptr,%s", aopGet (AOP (psb), 0, TRUE, FALSE, FALSE));
11157                 emitcode ("mov","dps,#0");
11158         } else {
11159                 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,FALSE));
11160                 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,FALSE));
11161                 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,FALSE));
11162         }
11163         freeAsmop (psb, NULL, ic, FALSE);
11164
11165         /* put libraryID into DPTR */
11166         emitcode ("mov","dptr,#LibraryID");
11167
11168         /* put handle into r3:r2 */
11169         aopOp (handle, ic, FALSE, FALSE);
11170         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11171                 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));  
11172                 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11173                 emitcode ("pop","ar3");
11174                 emitcode ("pop","ar2");
11175         } else {        
11176                 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));        
11177                 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11178         }
11179         freeAsmop (psb, NULL, ic, FALSE);
11180
11181         /* make the call */
11182         emitcode ("lcall","NatLib_Install%sStateBlock",name);
11183
11184         /* put return value into place*/
11185         _G.accInUse++;
11186         aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
11187         _G.accInUse--;
11188         aopPut(AOP(IC_RESULT(ic)),"a",0);
11189         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11190         unsavermask(rsave);
11191 }
11192
11193 /*-----------------------------------------------------------------*/
11194 /* genNatLibRemoveStateBlock -                                     */
11195 /*-----------------------------------------------------------------*/
11196 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
11197 {
11198         bitVect *rsave ;
11199
11200         assert(nparms==0);
11201
11202         /* save registers that need to be saved */
11203         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11204                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11205
11206         /* put libraryID into DPTR */
11207         emitcode ("mov","dptr,#LibraryID");
11208         /* make the call */
11209         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
11210         unsavermask(rsave);
11211 }
11212
11213 /*-----------------------------------------------------------------*/
11214 /* genNatLibGetStateBlock -                                        */
11215 /*-----------------------------------------------------------------*/
11216 static void genNatLibGetStateBlock(iCode *ic,int nparms,
11217                                    operand **parms,const char *name)
11218 {
11219         bitVect *rsave ;
11220         symbol *lbl = newiTempLabel(NULL);
11221         
11222         assert(nparms==0);
11223         /* save registers that need to be saved */
11224         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11225                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11226
11227         /* put libraryID into DPTR */
11228         emitcode ("mov","dptr,#LibraryID");
11229         /* make the call */
11230         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
11231         emitcode ("jnz","!tlabel",lbl->key+100);
11232
11233         /* put return value into place */
11234         aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
11235         if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
11236                 emitcode ("push","ar3");
11237                 emitcode ("push","ar2");
11238                 emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,FALSE));
11239                 emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,FALSE));
11240         } else {
11241                 aopPut(AOP(IC_RESULT(ic)),"r2",0);
11242                 aopPut(AOP(IC_RESULT(ic)),"r3",1);
11243         }
11244         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11245         emitcode ("","!tlabeldef",lbl->key+100);
11246         unsavermask(rsave);
11247 }
11248
11249 /*-----------------------------------------------------------------*/
11250 /* genMMMalloc -                                                   */
11251 /*-----------------------------------------------------------------*/
11252 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
11253                          int size, const char *name)
11254 {
11255         bitVect *rsave ;
11256         operand *bsize;
11257         symbol *rsym;
11258         symbol *lbl = newiTempLabel(NULL);
11259
11260         assert (nparms == 1);
11261         /* save registers that need to be saved */
11262         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11263                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
11264         
11265         bsize=parms[0];
11266         aopOp (bsize,ic,FALSE,FALSE);
11267
11268         /* put the size in R4-R2 */
11269         if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
11270                 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,FALSE));
11271                 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,FALSE));
11272                 if (size==3) {
11273                         emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,FALSE));
11274                         emitcode("pop","ar4");
11275                 }
11276                 emitcode("pop","ar3");
11277                 emitcode("pop","ar2");          
11278         } else {
11279                 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,FALSE));
11280                 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,FALSE));
11281                 if (size==3) {
11282                         emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,FALSE));
11283                 }
11284         }
11285         freeAsmop (bsize, NULL, ic, FALSE);
11286
11287         /* make the call */
11288         emitcode ("lcall","MM_%s",name);
11289         emitcode ("jz","!tlabel",lbl->key+100);
11290         emitcode ("mov","r2,#!constbyte",0xff);
11291         emitcode ("mov","r3,#!constbyte",0xff);
11292         emitcode ("","!tlabeldef",lbl->key+100);
11293         /* we don't care about the pointer : we just save the handle */
11294         rsym = OP_SYMBOL(IC_RESULT(ic));
11295         if (rsym->liveFrom != rsym->liveTo) {
11296                 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
11297                 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
11298                         emitcode ("push","ar3");
11299                         emitcode ("push","ar2");
11300                         emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,FALSE));
11301                         emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,FALSE));
11302                 } else {
11303                         aopPut(AOP(IC_RESULT(ic)),"r2",0);
11304                         aopPut(AOP(IC_RESULT(ic)),"r3",1);
11305                 }
11306                 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11307         }
11308         unsavermask(rsave);
11309 }
11310
11311 /*-----------------------------------------------------------------*/
11312 /* genMMDeref -                                                    */
11313 /*-----------------------------------------------------------------*/
11314 static void genMMDeref (iCode *ic,int nparms, operand **parms)
11315 {
11316         bitVect *rsave ;
11317         operand *handle;
11318
11319         assert (nparms == 1);
11320         /* save registers that need to be saved */
11321         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11322                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
11323         
11324         handle=parms[0];
11325         aopOp (handle,ic,FALSE,FALSE);
11326
11327         /* put the size in R4-R2 */
11328         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11329                 emitcode("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11330                 emitcode("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11331                 emitcode("pop","ar3");
11332                 emitcode("pop","ar2");          
11333         } else {
11334                 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11335                 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11336         }
11337         freeAsmop (handle, NULL, ic, FALSE);
11338
11339         /* make the call */
11340         emitcode ("lcall","MM_Deref");
11341         
11342         {
11343                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11344                 if (rsym->liveFrom != rsym->liveTo) {                   
11345                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11346                         if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
11347                                 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
11348                                 aopPut(AOP(IC_RESULT(ic)),"dph",1);
11349                                 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
11350                         }
11351                 }
11352         }
11353         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11354         unsavermask(rsave);
11355 }
11356
11357 /*-----------------------------------------------------------------*/
11358 /* genMMUnrestrictedPersist -                                      */
11359 /*-----------------------------------------------------------------*/
11360 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
11361 {
11362         bitVect *rsave ;
11363         operand *handle;
11364
11365         assert (nparms == 1);
11366         /* save registers that need to be saved */
11367         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11368                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
11369         
11370         handle=parms[0];
11371         aopOp (handle,ic,FALSE,FALSE);
11372
11373         /* put the size in R3-R2 */
11374         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11375                 emitcode("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11376                 emitcode("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11377                 emitcode("pop","ar3");
11378                 emitcode("pop","ar2");          
11379         } else {
11380                 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11381                 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11382         }
11383         freeAsmop (handle, NULL, ic, FALSE);
11384
11385         /* make the call */
11386         emitcode ("lcall","MM_UnrestrictedPersist");
11387
11388         {
11389                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11390                 if (rsym->liveFrom != rsym->liveTo) {   
11391                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11392                         aopPut(AOP(IC_RESULT(ic)),"a",0);
11393                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11394                 }
11395         }
11396         unsavermask(rsave);
11397 }
11398
11399 /*-----------------------------------------------------------------*/
11400 /* genSystemExecJavaProcess -                                      */
11401 /*-----------------------------------------------------------------*/
11402 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
11403 {
11404         bitVect *rsave ;
11405         operand *handle, *pp;
11406
11407         assert (nparms==2);
11408         /* save registers that need to be saved */
11409         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11410                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
11411         
11412         pp = parms[0];
11413         handle = parms[1];
11414         
11415         /* put the handle in R3-R2 */
11416         aopOp (handle,ic,FALSE,FALSE);
11417         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11418                 emitcode("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11419                 emitcode("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11420                 emitcode("pop","ar3");
11421                 emitcode("pop","ar2");          
11422         } else {
11423                 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11424                 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11425         }
11426         freeAsmop (handle, NULL, ic, FALSE);
11427         
11428         /* put pointer in DPTR */
11429         aopOp (pp,ic,FALSE,FALSE);
11430         if (AOP_TYPE(pp) == AOP_IMMD) {
11431                 emitcode ("mov", "dptr,%s", aopGet (AOP (pp), 0, TRUE, FALSE, FALSE));          
11432         } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
11433                 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,FALSE));
11434                 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,FALSE));
11435                 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,FALSE));
11436         }
11437         freeAsmop (handle, NULL, ic, FALSE);
11438
11439         /* make the call */
11440         emitcode ("lcall","System_ExecJavaProcess");
11441         
11442         /* put result in place */
11443         {
11444                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11445                 if (rsym->liveFrom != rsym->liveTo) {   
11446                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11447                         aopPut(AOP(IC_RESULT(ic)),"a",0);
11448                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11449                 }
11450         }
11451         
11452         unsavermask(rsave);
11453 }
11454
11455 /*-----------------------------------------------------------------*/
11456 /* genSystemRTCRegisters -                                         */
11457 /*-----------------------------------------------------------------*/
11458 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
11459                                   char *name)
11460 {
11461         bitVect *rsave ;
11462         operand *pp;
11463
11464         assert (nparms==1);
11465         /* save registers that need to be saved */
11466         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11467                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
11468         
11469         pp=parms[0];
11470         /* put pointer in DPTR */
11471         aopOp (pp,ic,FALSE,FALSE);
11472         if (AOP_TYPE (pp) == AOP_IMMD) {
11473                 emitcode ("mov","dps,#1");
11474                 emitcode ("mov", "dptr,%s", aopGet (AOP (pp), 0, TRUE, FALSE, FALSE));
11475                 emitcode ("mov","dps,#0");
11476         } else {
11477                 emitcode ("mov","dpl1,%s",aopGet(AOP(pp),0,FALSE,FALSE,FALSE));
11478                 emitcode ("mov","dph1,%s",aopGet(AOP(pp),1,FALSE,FALSE,FALSE));
11479                 emitcode ("mov","dpx1,%s",aopGet(AOP(pp),2,FALSE,FALSE,FALSE));
11480         }
11481         freeAsmop (pp, NULL, ic, FALSE);
11482
11483         /* make the call */
11484         emitcode ("lcall","System_%sRTCRegisters",name);
11485
11486         unsavermask(rsave);
11487 }
11488
11489 /*-----------------------------------------------------------------*/
11490 /* genSystemThreadSleep -                                          */
11491 /*-----------------------------------------------------------------*/
11492 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
11493 {
11494         bitVect *rsave ;
11495         operand *to, *s;
11496
11497         assert (nparms==1);
11498         /* save registers that need to be saved */
11499         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11500                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
11501
11502         to = parms[0];
11503         aopOp(to,ic,FALSE,FALSE);
11504         if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
11505             aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
11506                 emitcode ("push","%s",aopGet(AOP(to),0,FALSE,TRUE,FALSE));
11507                 emitcode ("push","%s",aopGet(AOP(to),1,FALSE,TRUE,FALSE));
11508                 emitcode ("push","%s",aopGet(AOP(to),2,FALSE,TRUE,FALSE));
11509                 emitcode ("push","%s",aopGet(AOP(to),3,FALSE,TRUE,FALSE));
11510                 emitcode ("pop","ar3");
11511                 emitcode ("pop","ar2");
11512                 emitcode ("pop","ar1");
11513                 emitcode ("pop","ar0");
11514         } else {
11515                 emitcode ("mov","r0,%s",aopGet(AOP(to),0,FALSE,TRUE,FALSE));
11516                 emitcode ("mov","r1,%s",aopGet(AOP(to),1,FALSE,TRUE,FALSE));
11517                 emitcode ("mov","r2,%s",aopGet(AOP(to),2,FALSE,TRUE,FALSE));
11518                 emitcode ("mov","r3,%s",aopGet(AOP(to),3,FALSE,TRUE,FALSE));
11519         }
11520         freeAsmop (to, NULL, ic, FALSE);
11521
11522         /* suspend in acc */
11523         s = parms[1];
11524         aopOp(s,ic,FALSE,FALSE);
11525         emitcode ("mov","a,%s",aopGet(AOP(s),0,FALSE,TRUE,FALSE));
11526         freeAsmop (s, NULL, ic, FALSE);
11527
11528         /* make the call */
11529         emitcode ("lcall","System_%s",name);
11530
11531         unsavermask(rsave);
11532 }
11533
11534 /*-----------------------------------------------------------------*/
11535 /* genSystemThreadResume -                                         */
11536 /*-----------------------------------------------------------------*/
11537 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
11538 {
11539         bitVect *rsave ;
11540         operand *tid,*pid;
11541
11542         assert (nparms==2);
11543         /* save registers that need to be saved */
11544         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11545                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11546         
11547         tid = parms[0];
11548         pid = parms[1];
11549         
11550         /* PID in R0 */
11551         aopOp(pid,ic,FALSE,FALSE);
11552         emitcode ("mov","r0,%s",aopGet(AOP(pid),0,FALSE,TRUE,FALSE));
11553         freeAsmop (pid, NULL, ic, FALSE);
11554         
11555         /* tid into ACC */
11556         aopOp(tid,ic,FALSE,FALSE);
11557         emitcode ("mov","a,%s",aopGet(AOP(tid),0,FALSE,TRUE,FALSE));
11558         freeAsmop (tid, NULL, ic, FALSE);
11559         
11560         emitcode ("lcall","System_ThreadResume");
11561
11562         /* put result into place */
11563         {
11564                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11565                 if (rsym->liveFrom != rsym->liveTo) {   
11566                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11567                         aopPut(AOP(IC_RESULT(ic)),"a",0);
11568                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11569                 }
11570         }
11571         unsavermask(rsave);
11572 }
11573
11574 /*-----------------------------------------------------------------*/
11575 /* genSystemProcessResume -                                        */
11576 /*-----------------------------------------------------------------*/
11577 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
11578 {
11579         bitVect *rsave ;
11580         operand *pid;
11581
11582         assert (nparms==1);
11583         /* save registers that need to be saved */
11584         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11585                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11586         
11587         pid = parms[0];
11588         
11589         /* pid into ACC */
11590         aopOp(pid,ic,FALSE,FALSE);
11591         emitcode ("mov","a,%s",aopGet(AOP(pid),0,FALSE,TRUE,FALSE));
11592         freeAsmop (pid, NULL, ic, FALSE);
11593         
11594         emitcode ("lcall","System_ProcessResume");
11595
11596         unsavermask(rsave);
11597 }
11598
11599 /*-----------------------------------------------------------------*/
11600 /* genSystem -                                                     */
11601 /*-----------------------------------------------------------------*/
11602 static void genSystem (iCode *ic,int nparms,char *name)
11603 {
11604         assert(nparms == 0);
11605
11606         emitcode ("lcall","System_%s",name);
11607 }
11608
11609 /*-----------------------------------------------------------------*/
11610 /* genSystemPoll -                                                  */
11611 /*-----------------------------------------------------------------*/
11612 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
11613 {
11614         bitVect *rsave ;
11615         operand *fp;
11616
11617         assert (nparms==1);
11618         /* save registers that need to be saved */
11619         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11620                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11621
11622         fp = parms[0];
11623         aopOp (fp,ic,FALSE,FALSE);
11624         if (AOP_TYPE (fp) == AOP_IMMD) {
11625                 emitcode ("mov", "dptr,%s", aopGet (AOP (fp), 0, TRUE, FALSE, FALSE));
11626         } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
11627                 emitcode ("mov","dpl,%s",aopGet(AOP(fp),0,FALSE,FALSE,FALSE));
11628                 emitcode ("mov","dph,%s",aopGet(AOP(fp),1,FALSE,FALSE,FALSE));
11629                 emitcode ("mov","dpx,%s",aopGet(AOP(fp),2,FALSE,FALSE,FALSE));
11630         }
11631         freeAsmop (fp, NULL, ic, FALSE);
11632
11633         emitcode ("lcall","System_%sPoll",name);
11634
11635         /* put result into place */
11636         {
11637                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11638                 if (rsym->liveFrom != rsym->liveTo) {   
11639                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11640                         aopPut(AOP(IC_RESULT(ic)),"a",0);
11641                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11642                 }
11643         }
11644         unsavermask(rsave);
11645 }
11646
11647 /*-----------------------------------------------------------------*/
11648 /* genSystemGetCurrentID -                                         */
11649 /*-----------------------------------------------------------------*/
11650 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
11651 {
11652         assert (nparms==0);
11653
11654         emitcode ("lcall","System_GetCurrent%sId",name);
11655         /* put result into place */
11656         {
11657                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11658                 if (rsym->liveFrom != rsym->liveTo) {   
11659                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11660                         aopPut(AOP(IC_RESULT(ic)),"a",0);
11661                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11662                 }
11663         }
11664 }
11665
11666 /*-----------------------------------------------------------------*/
11667 /* genBuiltIn - calls the appropriate function to  generating code */
11668 /* for a built in function                                         */
11669 /*-----------------------------------------------------------------*/
11670 static void genBuiltIn (iCode *ic)
11671 {
11672         operand *bi_parms[MAX_BUILTIN_ARGS];
11673         int nbi_parms;
11674         iCode *bi_iCode;
11675         symbol *bif;
11676
11677         /* get all the arguments for a built in function */
11678         bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
11679
11680         /* which function is it */
11681         bif = OP_SYMBOL(IC_LEFT(bi_iCode));
11682         if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
11683                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
11684         } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
11685                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
11686         } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
11687                 genMemsetX(bi_iCode,nbi_parms,bi_parms);
11688         } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
11689                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
11690         } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
11691                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
11692         } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
11693                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
11694         } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
11695                 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
11696         } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
11697                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
11698         } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
11699                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
11700         } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
11701                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
11702         } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
11703                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
11704         } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
11705                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
11706         } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
11707                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
11708         } else if (strcmp(bif->name,"MM_XMalloc")==0) {
11709                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
11710         } else if (strcmp(bif->name,"MM_Malloc")==0) {
11711                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
11712         } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
11713                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
11714         } else if (strcmp(bif->name,"MM_Free")==0) {
11715                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
11716         } else if (strcmp(bif->name,"MM_Deref")==0) {
11717                 genMMDeref(bi_iCode,nbi_parms,bi_parms);
11718         } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
11719                 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
11720         } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
11721                 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
11722         } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
11723                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
11724         } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
11725                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
11726         } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
11727                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
11728         } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
11729                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
11730         } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
11731                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
11732         } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
11733                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
11734         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
11735                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
11736         } else if (strcmp(bif->name,"System_SaveThread")==0) {
11737                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
11738         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
11739                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
11740         } else if (strcmp(bif->name,"System_ProcessResume")==0) {
11741                 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
11742         } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
11743                 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
11744         } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
11745                 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
11746         } else if (strcmp(bif->name,"System_ProcessYield")==0) {
11747                 genSystem(bi_iCode,nbi_parms,"ProcessYield");
11748         } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
11749                 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
11750         } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
11751                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
11752         } else if (strcmp(bif->name,"System_RemovePoll")==0) {
11753                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
11754         } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
11755                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
11756         } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
11757                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
11758         } else {
11759                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
11760                 return ;
11761         }
11762         return ;    
11763 }
11764
11765 /*-----------------------------------------------------------------*/
11766 /* gen390Code - generate code for Dallas 390 based controllers     */
11767 /*-----------------------------------------------------------------*/
11768 void
11769 gen390Code (iCode * lic)
11770 {
11771   iCode *ic;
11772   int cln = 0;
11773
11774   lineHead = lineCurr = NULL;
11775
11776   if (options.model == MODEL_FLAT24) {
11777     fReturnSizeDS390 = 5;
11778     fReturn = fReturn24;
11779   } else {
11780     fReturnSizeDS390 = 4;
11781     fReturn = fReturn16;
11782     options.stack10bit=0;
11783   }
11784 #if 1
11785   /* print the allocation information */
11786   if (allocInfo)
11787     printAllocInfo (currFunc, codeOutFile);
11788 #endif
11789   /* if debug information required */
11790   if (options.debug && currFunc)
11791     {
11792       cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
11793       _G.debugLine = 1;
11794       if (IS_STATIC (currFunc->etype))
11795         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
11796       else
11797         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
11798       _G.debugLine = 0;
11799     }
11800   /* stack pointer name */
11801   if (options.useXstack)
11802     spname = "_spx";
11803   else
11804     spname = "sp";
11805
11806
11807   for (ic = lic; ic; ic = ic->next)
11808     {
11809
11810       if (cln != ic->lineno)
11811         {
11812           if (options.debug)
11813             {
11814               _G.debugLine = 1;
11815               emitcode ("", "C$%s$%d$%d$%d ==.",
11816                         FileBaseName (ic->filename), ic->lineno,
11817                         ic->level, ic->block);
11818               _G.debugLine = 0;
11819             }
11820           emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno, 
11821                     printCLine(ic->filename, ic->lineno));
11822           cln = ic->lineno;
11823         }
11824       /* if the result is marked as
11825          spilt and rematerializable or code for
11826          this has already been generated then
11827          do nothing */
11828       if (resultRemat (ic) || ic->generated)
11829         continue;
11830
11831       /* depending on the operation */
11832       switch (ic->op)
11833         {
11834         case '!':
11835           genNot (ic);
11836           break;
11837
11838         case '~':
11839           genCpl (ic);
11840           break;
11841
11842         case UNARYMINUS:
11843           genUminus (ic);
11844           break;
11845
11846         case IPUSH:
11847           genIpush (ic);
11848           break;
11849
11850         case IPOP:
11851           /* IPOP happens only when trying to restore a
11852              spilt live range, if there is an ifx statement
11853              following this pop then the if statement might
11854              be using some of the registers being popped which
11855              would destory the contents of the register so
11856              we need to check for this condition and handle it */
11857           if (ic->next &&
11858               ic->next->op == IFX &&
11859               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11860             genIfx (ic->next, ic);
11861           else
11862             genIpop (ic);
11863           break;
11864
11865         case CALL:
11866           genCall (ic);
11867           break;
11868
11869         case PCALL:
11870           genPcall (ic);
11871           break;
11872
11873         case FUNCTION:
11874           genFunction (ic);
11875           break;
11876
11877         case ENDFUNCTION:
11878           genEndFunction (ic);
11879           break;
11880
11881         case RETURN:
11882           genRet (ic);
11883           break;
11884
11885         case LABEL:
11886           genLabel (ic);
11887           break;
11888
11889         case GOTO:
11890           genGoto (ic);
11891           break;
11892
11893         case '+':
11894           genPlus (ic);
11895           break;
11896
11897         case '-':
11898           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11899             genMinus (ic);
11900           break;
11901
11902         case '*':
11903           genMult (ic);
11904           break;
11905
11906         case '/':
11907           genDiv (ic);
11908           break;
11909
11910         case '%':
11911           genMod (ic);
11912           break;
11913
11914         case '>':
11915           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11916           break;
11917
11918         case '<':
11919           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11920           break;
11921
11922         case LE_OP:
11923         case GE_OP:
11924         case NE_OP:
11925
11926           /* note these two are xlated by algebraic equivalence
11927              during parsing SDCC.y */
11928           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11929                   "got '>=' or '<=' shouldn't have come here");
11930           break;
11931
11932         case EQ_OP:
11933           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11934           break;
11935
11936         case AND_OP:
11937           genAndOp (ic);
11938           break;
11939
11940         case OR_OP:
11941           genOrOp (ic);
11942           break;
11943
11944         case '^':
11945           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11946           break;
11947
11948         case '|':
11949           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11950           break;
11951
11952         case BITWISEAND:
11953           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
11954           break;
11955
11956         case INLINEASM:
11957           genInline (ic);
11958           break;
11959
11960         case RRC:
11961           genRRC (ic);
11962           break;
11963
11964         case RLC:
11965           genRLC (ic);
11966           break;
11967
11968         case GETHBIT:
11969           genGetHbit (ic);
11970           break;
11971
11972         case LEFT_OP:
11973           genLeftShift (ic);
11974           break;
11975
11976         case RIGHT_OP:
11977           genRightShift (ic);
11978           break;
11979
11980         case GET_VALUE_AT_ADDRESS:
11981           genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_LEFT(ic)))));
11982           break;
11983
11984         case '=':
11985           if (POINTER_SET (ic))
11986             genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
11987           else
11988             genAssign (ic);
11989           break;
11990
11991         case IFX:
11992           genIfx (ic, NULL);
11993           break;
11994
11995         case ADDRESS_OF:
11996           genAddrOf (ic);
11997           break;
11998
11999         case JUMPTABLE:
12000           genJumpTab (ic);
12001           break;
12002
12003         case CAST:
12004           genCast (ic);
12005           break;
12006
12007         case RECEIVE:
12008           genReceive (ic);
12009           break;
12010
12011         case SEND:
12012           if (ic->builtinSEND) genBuiltIn(ic);
12013           else addSet (&_G.sendSet, ic);
12014           break;
12015
12016         case ARRAYINIT:
12017             genArrayInit(ic);
12018             break;
12019             
12020         default:
12021           ic = ic;
12022         }
12023     }
12024
12025
12026   /* now we are ready to call the
12027      peep hole optimizer */
12028   if (!options.nopeep)
12029     peepHole (&lineHead);
12030
12031   /* now do the actual printing */
12032   printLine (lineHead, codeOutFile);
12033   return;
12034 }