1) added __builtin_inp & __builtin_outp used to read in data of given length
[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 *dptrn[2][3];
84 static char *javaRet[] = { "r0","r1","r2","r3"};
85 static short rbank = -1;
86
87 static struct
88   {
89     short r0Pushed;
90     short r1Pushed;
91     short accInUse;
92     short bInUse;
93     short inLine;
94     short debugLine;
95     short nRegsSaved;
96     set *sendSet;
97   }
98 _G;
99
100 static char *rb1regs[] = {
101     "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7"
102 };
103
104 static void saveRBank (int, iCode *, bool);
105
106 #define RESULTONSTACK(x) \
107                          (IC_RESULT(x) && IC_RESULT(x)->aop && \
108                          IC_RESULT(x)->aop->type == AOP_STK )
109
110 /* #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x); */
111 #define MOVA(x) { char *_mova_tmp = strdup(x); \
112                  if (strcmp(_mova_tmp,"a") && strcmp(_mova_tmp,"acc")) \
113                  { \
114                     emitcode("mov","a,%s",_mova_tmp); \
115                  } \
116                  free(_mova_tmp); \
117                 }
118 #define CLRC    emitcode("clr","c")
119 #define SETC    emitcode("setb","c")
120
121 // A scratch register which will be used to hold
122 // result bytes from operands in far space via DPTR2.
123 #define DP2_RESULT_REG  "_ap"
124
125 static lineNode *lineHead = NULL;
126 static lineNode *lineCurr = NULL;
127
128 static unsigned char SLMask[] =
129 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
130  0xE0, 0xC0, 0x80, 0x00};
131 static unsigned char SRMask[] =
132 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
133  0x07, 0x03, 0x01, 0x00};
134
135 #define LSB     0
136 #define MSB16   1
137 #define MSB24   2
138 #define MSB32   3
139 #define PROTECT_SP      {if (options.protect_sp_update) {                       \
140                                 symbol *lbl = newiTempLabel(NULL);              \
141                                 emitcode ("setb","F1");                         \
142                                 emitcode ("jbc","EA,!tlabel",lbl->key+100);     \
143                                 emitcode ("clr","F1");                          \
144                                 emitcode ("","!tlabeldef",lbl->key+100);        \
145                         }}
146 #define UNPROTECT_SP    { if (options.protect_sp_update) {                      \
147                                 symbol *lbl = newiTempLabel(NULL);              \
148                                 emitcode ("jnb","F1,!tlabel",lbl->key+100);     \
149                                 emitcode ("setb","EA");                         \
150                                 emitcode ("","!tlabeldef",lbl->key+100);        \
151                         }}
152
153
154 /*-----------------------------------------------------------------*/
155 /* emitcode - writes the code into a file : for now it is simple    */
156 /*-----------------------------------------------------------------*/
157 static void
158 emitcode (char *inst, char *fmt,...)
159 {
160   va_list ap;
161   char lb[INITIAL_INLINEASM];
162   char *lbp = lb;
163
164   va_start (ap, fmt);
165
166   if (inst && *inst)
167     {
168       if (fmt && *fmt)
169         sprintf (lb, "%s\t", inst);
170       else
171         sprintf (lb, "%s", inst);
172       tvsprintf (lb + (strlen (lb)), fmt, ap);
173     }
174   else
175     tvsprintf (lb, fmt, ap);
176
177   while (isspace (*lbp))
178     lbp++;
179
180   if (lbp && *lbp)
181     lineCurr = (lineCurr ?
182                 connectLine (lineCurr, newLineNode (lb)) :
183                 (lineHead = newLineNode (lb)));
184   lineCurr->isInline = _G.inLine;
185   lineCurr->isDebug = _G.debugLine;
186   va_end (ap);
187 }
188
189 /*-----------------------------------------------------------------*/
190 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
191 /*-----------------------------------------------------------------*/
192 static regs *
193 getFreePtr (iCode * ic, asmop ** aopp, bool result)
194 {
195   bool r0iu = FALSE, r1iu = FALSE;
196   bool r0ou = FALSE, r1ou = FALSE;
197
198   /* the logic: if r0 & r1 used in the instruction
199      then we are in trouble otherwise */
200
201   /* first check if r0 & r1 are used by this
202      instruction, in which case we are in trouble */
203   r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
204   r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
205   if (r0iu && r1iu) {
206       goto endOfWorld;
207     }
208
209   r0ou = bitVectBitValue (ic->rMask, R0_IDX);
210   r1ou = bitVectBitValue (ic->rMask, R1_IDX);
211
212   /* if no usage of r0 then return it */
213   if (!r0iu && !r0ou)
214     {
215       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
216       (*aopp)->type = AOP_R0;
217
218       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
219     }
220
221   /* if no usage of r1 then return it */
222   if (!r1iu && !r1ou)
223     {
224       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
225       (*aopp)->type = AOP_R1;
226
227       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R1_IDX);
228     }
229
230   /* now we know they both have usage */
231   /* if r0 not used in this instruction */
232   if (!r0iu)
233     {
234       /* push it if not already pushed */
235       if (!_G.r0Pushed)
236         {
237           emitcode ("push", "%s",
238                     ds390_regWithIdx (R0_IDX)->dname);
239           _G.r0Pushed++;
240         }
241
242       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
243       (*aopp)->type = AOP_R0;
244
245       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
246     }
247
248   /* if r1 not used then */
249
250   if (!r1iu)
251     {
252       /* push it if not already pushed */
253       if (!_G.r1Pushed)
254         {
255           emitcode ("push", "%s",
256                     ds390_regWithIdx (R1_IDX)->dname);
257           _G.r1Pushed++;
258         }
259
260       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
261       (*aopp)->type = AOP_R1;
262       return ds390_regWithIdx (R1_IDX);
263     }
264
265 endOfWorld:
266   /* I said end of world but not quite end of world yet */
267   /* if this is a result then we can push it on the stack */
268   if (result)
269     {
270       (*aopp)->type = AOP_STK;
271       return NULL;
272     }
273
274   /* other wise this is true end of the world */
275   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
276           "getFreePtr should never reach here");
277   exit (1);
278 }
279
280 /*-----------------------------------------------------------------*/
281 /* newAsmop - creates a new asmOp                                  */
282 /*-----------------------------------------------------------------*/
283 static asmop *
284 newAsmop (short type)
285 {
286   asmop *aop;
287
288   aop = Safe_calloc (1, sizeof (asmop));
289   aop->type = type;
290   return aop;
291 }
292
293 static int _currentDPS;         /* Current processor DPS. */
294 static int _desiredDPS;         /* DPS value compiler thinks we should be using. */
295 static int _lazyDPS = 0;        /* if non-zero, we are doing lazy evaluation of DPS changes. */
296
297 /*-----------------------------------------------------------------*/
298 /* genSetDPTR: generate code to select which DPTR is in use (zero  */
299 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390     */
300 /* alternate DPTR (DPL1/DPH1/DPX1).          */
301 /*-----------------------------------------------------------------*/
302 static void
303 genSetDPTR (int n)
304 {
305
306   /* If we are doing lazy evaluation, simply note the desired
307    * change, but don't emit any code yet.
308    */
309   if (_lazyDPS)
310     {
311       _desiredDPS = n;
312       return;
313     }
314
315   if (!n)
316     {
317       emitcode ("mov", "dps,#0");
318     }
319   else
320     {
321       TR_DPTR("#1");
322       emitcode ("mov", "dps,#1");
323     }
324 }
325
326 /*-----------------------------------------------------------------*/
327 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
328 /*                   */
329 /* Any code that operates on DPTR (NB: not on the individual     */
330 /* components, like DPH) *must* call _flushLazyDPS() before using  */
331 /* DPTR within a lazy DPS evaluation block.        */
332 /*                   */
333 /* Note that aopPut and aopGet already contain the proper calls to */
334 /* _flushLazyDPS, so it is safe to use these calls within a lazy   */
335 /* DPS evaluation block.             */
336 /*                   */
337 /* Also, _flushLazyDPS must be called before any flow control      */
338 /* operations that could potentially branch out of the block.    */
339 /*                         */
340 /* Lazy DPS evaluation is simply an optimization (though an      */
341 /* important one), so if in doubt, leave it out.       */
342 /*-----------------------------------------------------------------*/
343 static void
344 _startLazyDPSEvaluation (void)
345 {
346   _currentDPS = 0;
347   _desiredDPS = 0;
348 #ifdef BETTER_LITERAL_SHIFT  
349   _lazyDPS++;
350 #else
351   _lazyDPS = 1;
352 #endif  
353 }
354
355 /*-----------------------------------------------------------------*/
356 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
357 /* desired one. Call before using DPTR within a lazy DPS evaluation */
358 /* block.                */
359 /*-----------------------------------------------------------------*/
360 static void
361 _flushLazyDPS (void)
362 {
363   if (!_lazyDPS)
364     {
365       /* nothing to do. */
366       return;
367     }
368
369   if (_desiredDPS != _currentDPS)
370     {
371       if (_desiredDPS)
372         {
373           emitcode ("inc", "dps");
374         }
375       else
376         {
377           emitcode ("dec", "dps");
378         }
379       _currentDPS = _desiredDPS;
380     }
381 }
382
383 /*-----------------------------------------------------------------*/
384 /* _endLazyDPSEvaluation: end lazy DPS evaluation block.     */
385 /*                   */
386 /* Forces us back to the safe state (standard DPTR selected).    */
387 /*-----------------------------------------------------------------*/
388 static void
389 _endLazyDPSEvaluation (void)
390 {
391 #ifdef BETTER_LITERAL_SHIFT  
392   _lazyDPS--;
393 #else
394   _lazyDPS = 0;
395 #endif    
396   if (!_lazyDPS)
397   {
398     if (_currentDPS)
399     {
400       genSetDPTR (0);
401       _flushLazyDPS ();
402     }
403     _currentDPS = 0;
404     _desiredDPS = 0;
405   }
406 }
407
408
409
410 /*-----------------------------------------------------------------*/
411 /* pointerCode - returns the code for a pointer type               */
412 /*-----------------------------------------------------------------*/
413 static int
414 pointerCode (sym_link * etype)
415 {
416
417   return PTR_TYPE (SPEC_OCLS (etype));
418
419 }
420
421 /*-----------------------------------------------------------------*/
422 /* aopForSym - for a true symbol                                   */
423 /*-----------------------------------------------------------------*/
424 static asmop *
425 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
426 {
427   asmop *aop;
428   memmap *space = SPEC_OCLS (sym->etype);
429
430   /* if already has one */
431   if (sym->aop)
432     return sym->aop;
433
434   /* assign depending on the storage class */
435   /* if it is on the stack or indirectly addressable */
436   /* space we need to assign either r0 or r1 to it   */
437   if ((sym->onStack && !options.stack10bit) || sym->iaccess)
438     {
439       sym->aop = aop = newAsmop (0);
440       aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
441       aop->size = getSize (sym->type);
442
443       /* now assign the address of the variable to
444          the pointer register */
445       if (aop->type != AOP_STK)
446         {
447
448           if (sym->onStack)
449             {
450               if (_G.accInUse)
451                 emitcode ("push", "acc");
452
453               if (_G.bInUse)
454                 emitcode ("push", "b");
455
456               emitcode ("mov", "a,_bp");
457               emitcode ("add", "a,#!constbyte",
458                         ((sym->stack < 0) ?
459                          ((char) (sym->stack - _G.nRegsSaved)) :
460                          ((char) sym->stack)) & 0xff);
461               emitcode ("mov", "%s,a",
462                         aop->aopu.aop_ptr->name);
463
464               if (_G.bInUse)
465                 emitcode ("pop", "b");
466
467               if (_G.accInUse)
468                 emitcode ("pop", "acc");
469             }
470           else
471             emitcode ("mov", "%s,#%s",
472                       aop->aopu.aop_ptr->name,
473                       sym->rname);
474           aop->paged = space->paged;
475         }
476       else
477         aop->aopu.aop_stk = sym->stack;
478       return aop;
479     }
480
481   if (sym->onStack && options.stack10bit)
482     {
483         short stack_val = -((sym->stack < 0) ?
484                             ((short) (sym->stack - _G.nRegsSaved)) :
485                             ((short) sym->stack)) ;
486       /* It's on the 10 bit stack, which is located in
487        * far data space.
488        */
489         if (stack_val < 0 && stack_val > -5) { /* between -5 & -1 */
490             if (useDP2) {
491                 if (options.model == MODEL_FLAT24)
492                     emitcode ("mov", "dpx1,#!constbyte", (options.stack_loc >> 16) & 0xff);
493                 TR_DPTR("#2");
494                 emitcode ("mov", "dph1,_bpx+1");
495                 emitcode ("mov", "dpl1,_bpx");
496                 emitcode ("mov","dps,#1");
497             } else {
498                 if (options.model == MODEL_FLAT24)
499                     emitcode ("mov", "dpx,#!constbyte", (options.stack_loc >> 16) & 0xff);
500                 emitcode ("mov", "dph,_bpx+1");
501                 emitcode ("mov", "dpl,_bpx");
502             }
503             stack_val = -stack_val;
504             while (stack_val--) {
505                 emitcode ("inc","dptr");
506             }
507             if (useDP2) {
508                 emitcode("mov","dps,#0");
509             }
510         }  else {
511             if (_G.accInUse)
512                 emitcode ("push", "acc");
513             
514             if (_G.bInUse)
515                 emitcode ("push", "b");
516         
517             emitcode ("mov", "a,_bpx");
518             emitcode ("clr","c");
519             emitcode ("subb", "a,#!constbyte", stack_val & 0xff);
520             emitcode ("mov","b,a");
521             emitcode ("mov","a,_bpx+1");
522             emitcode ("subb","a,#!constbyte",(stack_val >> 8) & 0xff);
523             if (useDP2) {
524                 if (options.model == MODEL_FLAT24)
525                     emitcode ("mov", "dpx1,#!constbyte", (options.stack_loc >> 16) & 0xff);
526                 TR_DPTR("#2");
527                 emitcode ("mov", "dph1,a");
528                 emitcode ("mov", "dpl1,b");
529             } else {
530                 if (options.model == MODEL_FLAT24)
531                     emitcode ("mov", "dpx,#!constbyte", (options.stack_loc >> 16) & 0xff);
532                 emitcode ("mov", "dph,a");
533                 emitcode ("mov", "dpl,b");
534             }
535             
536             if (_G.bInUse)
537                 emitcode ("pop", "b");
538             
539             if (_G.accInUse)
540                 emitcode ("pop", "acc");
541         }
542         sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
543         aop->size = getSize (sym->type);
544         return aop;
545     }
546
547   /* if in bit space */
548   if (IN_BITSPACE (space))
549     {
550       sym->aop = aop = newAsmop (AOP_CRY);
551       aop->aopu.aop_dir = sym->rname;
552       aop->size = getSize (sym->type);
553       return aop;
554     }
555   /* if it is in direct space */
556   if (IN_DIRSPACE (space))
557     {
558       sym->aop = aop = newAsmop (AOP_DIR);
559       aop->aopu.aop_dir = sym->rname;
560       aop->size = getSize (sym->type);
561       return aop;
562     }
563
564   /* special case for a function */
565   if (IS_FUNC (sym->type))
566     {
567       sym->aop = aop = newAsmop (AOP_IMMD);
568       aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
569       strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
570       aop->size = FPTRSIZE;
571       return aop;
572     }
573   
574   /* only remaining is far space */
575   /* in which case DPTR gets the address */
576   sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
577   if (useDP2)
578     {
579       genSetDPTR (1);
580       _flushLazyDPS ();
581       emitcode ("mov", "dptr,#%s", sym->rname);
582       genSetDPTR (0);
583     }
584   else
585     {
586       emitcode ("mov", "dptr,#%s", sym->rname);
587     }
588   aop->size = getSize (sym->type);
589
590   /* if it is in code space */
591   if (IN_CODESPACE (space))
592     aop->code = 1;
593
594   return aop;
595 }
596
597 /*-----------------------------------------------------------------*/
598 /* aopForRemat - rematerialzes an object                           */
599 /*-----------------------------------------------------------------*/
600 static asmop *
601 aopForRemat (symbol * sym)
602 {
603   iCode *ic = sym->rematiCode;
604   asmop *aop = newAsmop (AOP_IMMD);
605   int ptr_type =0;
606   int val = 0;
607
608   for (;;)
609     {
610       if (ic->op == '+')
611         val += (int) operandLitValue (IC_RIGHT (ic));
612       else if (ic->op == '-')
613         val -= (int) operandLitValue (IC_RIGHT (ic));
614       else if (IS_CAST_ICODE(ic)) {
615               sym_link *from_type = operandType(IC_RIGHT(ic));
616               aop->aopu.aop_immd.from_cast_remat = 1;
617               ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
618               ptr_type = DCL_TYPE(from_type);
619               if (ptr_type == IPOINTER) {
620                 // bug #481053
621                 ptr_type = POINTER;
622               }
623               continue ;
624       } else break;
625       
626       ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
627     }
628
629   if (val)
630     sprintf (buffer, "(%s %c 0x%04x)",
631              OP_SYMBOL (IC_LEFT (ic))->rname,
632              val >= 0 ? '+' : '-',
633              abs (val) & 0xffff);
634   else {
635       if (IS_ASSIGN_ICODE(ic) && isOperandLiteral(IC_RIGHT(ic)))
636           sprintf(buffer,"0x%x",(int) operandLitValue (IC_RIGHT (ic)));
637       else
638           strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
639   }
640
641   aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
642   strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
643   /* set immd2 field if required */
644   if (aop->aopu.aop_immd.from_cast_remat) {
645           tsprintf(buffer,"#!constbyte",ptr_type);
646           aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
647           strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
648   }
649
650   return aop;
651 }
652
653 /*-----------------------------------------------------------------*/
654 /* aopHasRegs - returns true if aop has regs between from-to       */
655 /*-----------------------------------------------------------------*/
656 static int aopHasRegs(asmop *aop, int from, int to)
657 {
658     int size =0;
659
660     if (aop->type != AOP_REG) return 0; /* if not assigned to regs */
661
662     for (; size < aop->size ; size++) {
663         int reg;
664         for (reg = from ; reg <= to ; reg++)
665             if (aop->aopu.aop_reg[size] == ds390_regWithIdx(reg)) return 1;
666     }
667     return 0;
668 }
669
670 /*-----------------------------------------------------------------*/
671 /* regsInCommon - two operands have some registers in common       */
672 /*-----------------------------------------------------------------*/
673 static bool
674 regsInCommon (operand * op1, operand * op2)
675 {
676   symbol *sym1, *sym2;
677   int i;
678
679   /* if they have registers in common */
680   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
681     return FALSE;
682
683   sym1 = OP_SYMBOL (op1);
684   sym2 = OP_SYMBOL (op2);
685
686   if (sym1->nRegs == 0 || sym2->nRegs == 0)
687     return FALSE;
688
689   for (i = 0; i < sym1->nRegs; i++)
690     {
691       int j;
692       if (!sym1->regs[i])
693         continue;
694
695       for (j = 0; j < sym2->nRegs; j++)
696         {
697           if (!sym2->regs[j])
698             continue;
699
700           if (sym2->regs[j] == sym1->regs[i])
701             return TRUE;
702         }
703     }
704
705   return FALSE;
706 }
707
708 /*-----------------------------------------------------------------*/
709 /* operandsEqu - equivalent                                        */
710 /*-----------------------------------------------------------------*/
711 static bool
712 operandsEqu (operand * op1, operand * op2)
713 {
714   symbol *sym1, *sym2;
715
716   /* if they not symbols */
717   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
718     return FALSE;
719
720   sym1 = OP_SYMBOL (op1);
721   sym2 = OP_SYMBOL (op2);
722
723   /* if both are itemps & one is spilt
724      and the other is not then false */
725   if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
726       sym1->isspilt != sym2->isspilt)
727     return FALSE;
728
729   /* if they are the same */
730   if (sym1 == sym2)
731     return TRUE;
732
733   if (strcmp (sym1->rname, sym2->rname) == 0)
734     return TRUE;
735
736
737   /* if left is a tmp & right is not */
738   if (IS_ITEMP (op1) &&
739       !IS_ITEMP (op2) &&
740       sym1->isspilt &&
741       (sym1->usl.spillLoc == sym2))
742     return TRUE;
743
744   if (IS_ITEMP (op2) &&
745       !IS_ITEMP (op1) &&
746       sym2->isspilt &&
747       sym1->level > 0 &&
748       (sym2->usl.spillLoc == sym1))
749     return TRUE;
750
751   return FALSE;
752 }
753
754 /*-----------------------------------------------------------------*/
755 /* sameRegs - two asmops have the same registers                   */
756 /*-----------------------------------------------------------------*/
757 static bool
758 sameRegs (asmop * aop1, asmop * aop2)
759 {
760   int i;
761
762   if (aop1 == aop2)
763     {
764       if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
765         {
766           return FALSE;
767         }
768       return TRUE;
769     }
770
771   if (aop1->type != AOP_REG ||
772       aop2->type != AOP_REG)
773     return FALSE;
774
775   if (aop1->size != aop2->size)
776     return FALSE;
777
778   for (i = 0; i < aop1->size; i++)
779     if (aop1->aopu.aop_reg[i] !=
780         aop2->aopu.aop_reg[i])
781       return FALSE;
782
783   return TRUE;
784 }
785
786 /*-----------------------------------------------------------------*/
787 /* aopOp - allocates an asmop for an operand  :                    */
788 /*-----------------------------------------------------------------*/
789 static void
790 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
791 {
792   asmop *aop;
793   symbol *sym;
794   int i;
795
796   if (!op)
797     return;
798
799   /* if this a literal */
800   if (IS_OP_LITERAL (op))
801     {
802       op->aop = aop = newAsmop (AOP_LIT);
803       aop->aopu.aop_lit = op->operand.valOperand;
804       aop->size = getSize (operandType (op));
805       return;
806     }
807
808   /* if already has a asmop then continue */
809   if (op->aop)
810     return;
811
812   /* if the underlying symbol has a aop */
813   if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
814     {
815       op->aop = OP_SYMBOL (op)->aop;
816       return;
817     }
818
819   /* if this is a true symbol */
820   if (IS_TRUE_SYMOP (op))
821     {
822       op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
823       return;
824     }
825
826   /* this is a temporary : this has
827      only four choices :
828      a) register
829      b) spillocation
830      c) rematerialize
831      d) conditional
832      e) can be a return use only */
833
834   sym = OP_SYMBOL (op);
835
836
837   /* if the type is a conditional */
838   if (sym->regType == REG_CND)
839     {
840       aop = op->aop = sym->aop = newAsmop (AOP_CRY);
841       aop->size = 0;
842       return;
843     }
844
845   /* if it is spilt then two situations
846      a) is rematerialize
847      b) has a spill location */
848   if (sym->isspilt || sym->nRegs == 0)
849     {
850
851       /* rematerialize it NOW */
852       if (sym->remat)
853         {
854           sym->aop = op->aop = aop =
855             aopForRemat (sym);
856           aop->size = getSize (sym->type);
857           return;
858         }
859
860       if (sym->accuse)
861         {
862           int i;
863           aop = op->aop = sym->aop = newAsmop (AOP_ACC);
864           aop->size = getSize (sym->type);
865           for (i = 0; i < 2; i++)
866             aop->aopu.aop_str[i] = accUse[i];
867           return;
868         }
869
870       if (sym->ruonly)
871         {
872           int i;
873
874           if (useDP2)
875             {
876               /* a AOP_STR uses DPTR, but DPTR is already in use;
877                * we're just hosed.
878                */
879                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"AOP_STR with DPTR in use!");
880             }
881
882           aop = op->aop = sym->aop = newAsmop (AOP_STR);
883           aop->size = getSize (sym->type);
884           for (i = 0; i < (int) fReturnSizeDS390; i++)
885             aop->aopu.aop_str[i] = fReturn[i];
886           return;
887         }
888       
889       if (sym->dptr) { /* has been allocated to a DPTRn */
890           aop = op->aop = sym->aop = newAsmop (AOP_DPTRn);
891           aop->size = getSize (sym->type);
892           aop->aopu.dptr = sym->dptr;
893           return ;
894       }
895       /* else spill location  */
896       if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
897           /* force a new aop if sizes differ */
898           sym->usl.spillLoc->aop = NULL;
899       }
900       sym->aop = op->aop = aop =
901         aopForSym (ic, sym->usl.spillLoc, result, useDP2);
902       aop->size = getSize (sym->type);
903       return;
904     }
905
906   /* must be in a register */
907   sym->aop = op->aop = aop = newAsmop (AOP_REG);
908   aop->size = sym->nRegs;
909   for (i = 0; i < sym->nRegs; i++)
910     aop->aopu.aop_reg[i] = sym->regs[i];
911 }
912
913 /*-----------------------------------------------------------------*/
914 /* freeAsmop - free up the asmop given to an operand               */
915 /*----------------------------------------------------------------*/
916 static void
917 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
918 {
919   asmop *aop;
920
921   if (!op)
922     aop = aaop;
923   else
924     aop = op->aop;
925
926   if (!aop)
927     return;
928
929   if (aop->freed)
930     goto dealloc;
931
932   aop->freed = 1;
933
934   /* depending on the asmop type only three cases need work AOP_RO
935      , AOP_R1 && AOP_STK */
936   switch (aop->type)
937     {
938     case AOP_R0:
939       if (_G.r0Pushed)
940         {
941           if (pop)
942             {
943               emitcode ("pop", "ar0");
944               _G.r0Pushed--;
945             }
946         }
947       bitVectUnSetBit (ic->rUsed, R0_IDX);
948       break;
949
950     case AOP_R1:
951       if (_G.r1Pushed)
952         {
953           if (pop)
954             {
955               emitcode ("pop", "ar1");
956               _G.r1Pushed--;
957             }
958         }
959       bitVectUnSetBit (ic->rUsed, R1_IDX);
960       break;
961
962     case AOP_STK:
963       {
964         int sz = aop->size;
965         int stk = aop->aopu.aop_stk + aop->size;
966         bitVectUnSetBit (ic->rUsed, R0_IDX);
967         bitVectUnSetBit (ic->rUsed, R1_IDX);
968
969         getFreePtr (ic, &aop, FALSE);
970
971         if (options.stack10bit)
972           {
973             /* I'm not sure what to do here yet... */
974             /* #STUB */
975             fprintf (stderr,
976                      "*** Warning: probably generating bad code for "
977                      "10 bit stack mode.\n");
978           }
979
980         if (stk)
981           {
982             emitcode ("mov", "a,_bp");
983             emitcode ("add", "a,#!constbyte", ((char) stk) & 0xff);
984             emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
985           }
986         else
987           {
988             emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
989           }
990
991         while (sz--)
992           {
993             emitcode ("pop", "acc");
994             emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
995             if (!sz)
996               break;
997             emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
998           }
999         op->aop = aop;
1000         freeAsmop (op, NULL, ic, TRUE);
1001         if (_G.r0Pushed)
1002           {
1003             emitcode ("pop", "ar0");
1004             _G.r0Pushed--;
1005           }
1006
1007         if (_G.r1Pushed)
1008           {
1009             emitcode ("pop", "ar1");
1010             _G.r1Pushed--;
1011           }
1012       }
1013     }
1014
1015 dealloc:
1016   /* all other cases just dealloc */
1017   if (op)
1018     {
1019       op->aop = NULL;
1020       if (IS_SYMOP (op))
1021         {
1022           OP_SYMBOL (op)->aop = NULL;
1023           /* if the symbol has a spill */
1024           if (SPIL_LOC (op))
1025             SPIL_LOC (op)->aop = NULL;
1026         }
1027     }
1028 }
1029
1030 /*------------------------------------------------------------------*/
1031 /* aopGet - for fetching value of the aop                           */
1032 /*                    */
1033 /* Set canClobberACC if you are sure it is OK to clobber the value  */
1034 /* in the accumulator. Set it FALSE otherwise; FALSE is always safe, */
1035 /* just less efficient.               */
1036 /*------------------------------------------------------------------*/
1037
1038 static char *
1039 aopGet (asmop * aop,
1040         int offset,
1041         bool bit16,
1042         bool dname,
1043         bool canClobberACC)
1044 {
1045   char *s = buffer;
1046   char *rs;
1047
1048   /* offset is greater than
1049      size then zero */
1050   if (offset > (aop->size - 1) &&
1051       aop->type != AOP_LIT)
1052     return zero;
1053
1054   /* depending on type */
1055   switch (aop->type)
1056     {
1057
1058     case AOP_R0:
1059     case AOP_R1:
1060       /* if we need to increment it */
1061       while (offset > aop->coff)
1062         {
1063           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1064           aop->coff++;
1065         }
1066
1067       while (offset < aop->coff)
1068         {
1069           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1070           aop->coff--;
1071         }
1072
1073       aop->coff = offset;
1074       if (aop->paged)
1075         {
1076           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1077           return (dname ? "acc" : "a");
1078         }
1079       sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1080       rs = Safe_calloc (1, strlen (s) + 1);
1081       strcpy (rs, s);
1082       return rs;
1083
1084     case AOP_DPTRn:
1085         assert(offset <= 3);
1086         return dptrn[aop->aopu.dptr][offset];
1087
1088     case AOP_DPTR:
1089     case AOP_DPTR2:
1090
1091       if (aop->type == AOP_DPTR2)
1092         {
1093           genSetDPTR (1);
1094           if (!canClobberACC)
1095             {
1096                     TR_AP("#1");
1097                     emitcode ("xch", "a, %s", DP2_RESULT_REG);
1098             }
1099         }
1100
1101       _flushLazyDPS ();
1102
1103       while (offset > aop->coff)
1104         {
1105           emitcode ("inc", "dptr");
1106           aop->coff++;
1107         }
1108
1109       while (offset < aop->coff)
1110         {
1111           emitcode ("lcall", "__decdptr");
1112           aop->coff--;
1113         }
1114
1115       aop->coff = offset;
1116       if (aop->code)
1117         {
1118           emitcode ("clr", "a");
1119           emitcode ("movc", "a,@a+dptr");
1120         }
1121       else
1122         {
1123           emitcode ("movx", "a,@dptr");
1124         }
1125
1126       if (aop->type == AOP_DPTR2)
1127         {
1128           genSetDPTR (0);
1129           if (!canClobberACC)
1130             {
1131        TR_AP("#2");
1132               emitcode ("xch", "a, %s", DP2_RESULT_REG);
1133               return DP2_RESULT_REG;
1134             }
1135         }
1136       return (dname ? "acc" : "a");
1137
1138     case AOP_IMMD:
1139       if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
1140               sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
1141       } else if (bit16)
1142         sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
1143       else if (offset) {
1144           switch (offset) {
1145           case 1:
1146               tsprintf(s,"#!his",aop->aopu.aop_immd.aop_immd1);
1147               break;
1148           case 2:
1149               tsprintf(s,"#!hihis",aop->aopu.aop_immd.aop_immd1);
1150               break;
1151           case 3:
1152               tsprintf(s,"#!hihihis",aop->aopu.aop_immd.aop_immd1);
1153               break;
1154           default: /* should not need this (just in case) */
1155               sprintf (s, "#(%s >> %d)",
1156                        aop->aopu.aop_immd.aop_immd1,
1157                        offset * 8);
1158           }
1159       }
1160       else
1161         sprintf (s, "#%s",
1162                  aop->aopu.aop_immd.aop_immd1);
1163       rs = Safe_calloc (1, strlen (s) + 1);
1164       strcpy (rs, s);
1165       return rs;
1166
1167     case AOP_DIR:
1168       if (offset)
1169         sprintf (s, "(%s + %d)",
1170                  aop->aopu.aop_dir,
1171                  offset);
1172       else
1173         sprintf (s, "%s", aop->aopu.aop_dir);
1174       rs = Safe_calloc (1, strlen (s) + 1);
1175       strcpy (rs, s);
1176       return rs;
1177
1178     case AOP_REG:
1179       if (dname)
1180         return aop->aopu.aop_reg[offset]->dname;
1181       else
1182         return aop->aopu.aop_reg[offset]->name;
1183
1184     case AOP_CRY:
1185       emitcode ("clr", "a");
1186       emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1187       emitcode ("rlc", "a");
1188       return (dname ? "acc" : "a");
1189
1190     case AOP_ACC:
1191       if (!offset && dname)
1192         return "acc";
1193       return aop->aopu.aop_str[offset];
1194
1195     case AOP_LIT:
1196       return aopLiteral (aop->aopu.aop_lit, offset);
1197
1198     case AOP_STR:
1199       aop->coff = offset;
1200       if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1201           dname)
1202         return "acc";
1203
1204       return aop->aopu.aop_str[offset];
1205
1206     }
1207
1208   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1209           "aopget got unsupported aop->type");
1210   exit (1);
1211 }
1212 /*-----------------------------------------------------------------*/
1213 /* aopPut - puts a string for a aop                                */
1214 /*-----------------------------------------------------------------*/
1215 static void
1216 aopPut (asmop * aop, char *s, int offset)
1217 {
1218   char *d = buffer;
1219
1220   if (aop->size && offset > (aop->size - 1))
1221     {
1222       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1223               "aopPut got offset > aop->size");
1224       exit (1);
1225     }
1226
1227   /* will assign value to value */
1228   /* depending on where it is ofcourse */
1229   switch (aop->type)
1230     {
1231     case AOP_DIR:
1232       if (offset)
1233         sprintf (d, "(%s + %d)",
1234                  aop->aopu.aop_dir, offset);
1235       else
1236         sprintf (d, "%s", aop->aopu.aop_dir);
1237
1238       if (strcmp (d, s))
1239         emitcode ("mov", "%s,%s", d, s);
1240
1241       break;
1242
1243     case AOP_REG:
1244       if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1245           strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1246         {
1247           if (*s == '@' ||
1248               strcmp (s, "r0") == 0 ||
1249               strcmp (s, "r1") == 0 ||
1250               strcmp (s, "r2") == 0 ||
1251               strcmp (s, "r3") == 0 ||
1252               strcmp (s, "r4") == 0 ||
1253               strcmp (s, "r5") == 0 ||
1254               strcmp (s, "r6") == 0 ||
1255               strcmp (s, "r7") == 0)
1256             emitcode ("mov", "%s,%s",
1257                       aop->aopu.aop_reg[offset]->dname, s);
1258           else
1259             emitcode ("mov", "%s,%s",
1260                       aop->aopu.aop_reg[offset]->name, s);
1261         }
1262       break;
1263
1264     case AOP_DPTRn:
1265         emitcode ("mov","%s,%s",dptrn[aop->aopu.dptr][offset],s);
1266         break;
1267
1268     case AOP_DPTR:
1269     case AOP_DPTR2:
1270
1271       if (aop->type == AOP_DPTR2)
1272         {
1273           genSetDPTR (1);
1274         }
1275       _flushLazyDPS ();
1276
1277       if (aop->code)
1278         {
1279           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1280                   "aopPut writting to code space");
1281           exit (1);
1282         }
1283
1284       while (offset > aop->coff)
1285         {
1286           aop->coff++;
1287           emitcode ("inc", "dptr");
1288         }
1289
1290       while (offset < aop->coff)
1291         {
1292           aop->coff--;
1293           emitcode ("lcall", "__decdptr");
1294         }
1295
1296       aop->coff = offset;
1297
1298       /* if not in accumulater */
1299       MOVA (s);
1300
1301       emitcode ("movx", "@dptr,a");
1302
1303       if (aop->type == AOP_DPTR2)
1304         {
1305           genSetDPTR (0);
1306         }
1307       break;
1308
1309     case AOP_R0:
1310     case AOP_R1:
1311       while (offset > aop->coff)
1312         {
1313           aop->coff++;
1314           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1315         }
1316       while (offset < aop->coff)
1317         {
1318           aop->coff--;
1319           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1320         }
1321       aop->coff = offset;
1322
1323       if (aop->paged)
1324         {
1325           MOVA (s);
1326           emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1327
1328         }
1329       else if (*s == '@')
1330         {
1331           MOVA (s);
1332           emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1333         }
1334       else if (strcmp (s, "r0") == 0 ||
1335                strcmp (s, "r1") == 0 ||
1336                strcmp (s, "r2") == 0 ||
1337                strcmp (s, "r3") == 0 ||
1338                strcmp (s, "r4") == 0 ||
1339                strcmp (s, "r5") == 0 ||
1340                strcmp (s, "r6") == 0 ||
1341                strcmp (s, "r7") == 0)
1342         {
1343           char buffer[10];
1344           sprintf (buffer, "a%s", s);
1345           emitcode ("mov", "@%s,%s",
1346                     aop->aopu.aop_ptr->name, buffer);
1347         }
1348       else
1349         emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1350
1351       break;
1352
1353     case AOP_STK:
1354       if (strcmp (s, "a") == 0)
1355         emitcode ("push", "acc");
1356       else
1357         if (*s=='@') {
1358           MOVA(s);
1359           emitcode ("push", "acc");
1360         } else {
1361           emitcode ("push", s);
1362         }
1363
1364       break;
1365
1366     case AOP_CRY:
1367       /* if bit variable */
1368       if (!aop->aopu.aop_dir)
1369         {
1370           emitcode ("clr", "a");
1371           emitcode ("rlc", "a");
1372         }
1373       else
1374         {
1375           if (s == zero)
1376             emitcode ("clr", "%s", aop->aopu.aop_dir);
1377           else if (s == one)
1378             emitcode ("setb", "%s", aop->aopu.aop_dir);
1379           else if (!strcmp (s, "c"))
1380             emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1381           else
1382             {
1383               if (strcmp (s, "a"))
1384                 {
1385                   MOVA (s);
1386                 }
1387               {
1388                 symbol *lbl = newiTempLabel (NULL);
1389                 emitcode ("clr", "c");
1390                 emitcode ("jz", "!tlabel", lbl->key + 100);
1391                 emitcode ("cpl", "c");
1392                 emitcode ("", "!tlabeldef", lbl->key + 100);
1393                 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1394               }
1395             }
1396         }
1397       break;
1398
1399     case AOP_STR:
1400       aop->coff = offset;
1401       if (strcmp (aop->aopu.aop_str[offset], s))
1402         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1403       break;
1404
1405     case AOP_ACC:
1406       aop->coff = offset;
1407       if (!offset && (strcmp (s, "acc") == 0))
1408         break;
1409
1410       if (strcmp (aop->aopu.aop_str[offset], s))
1411         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1412       break;
1413
1414     default:
1415       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1416               "aopPut got unsupported aop->type");
1417       exit (1);
1418     }
1419
1420 }
1421
1422
1423 /*--------------------------------------------------------------------*/
1424 /* reAdjustPreg - points a register back to where it should (coff==0) */
1425 /*--------------------------------------------------------------------*/
1426 static void
1427 reAdjustPreg (asmop * aop)
1428 {
1429   if ((aop->coff==0) || (aop->size <= 1)) {
1430     return;
1431   }
1432
1433   switch (aop->type)
1434     {
1435     case AOP_R0:
1436     case AOP_R1:
1437       while (aop->coff--)
1438         emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1439       break;
1440     case AOP_DPTR:
1441     case AOP_DPTR2:
1442       if (aop->type == AOP_DPTR2)
1443         {
1444           genSetDPTR (1);
1445           _flushLazyDPS ();
1446         }
1447       while (aop->coff--)
1448         {
1449           emitcode ("lcall", "__decdptr");
1450         }
1451
1452       if (aop->type == AOP_DPTR2)
1453         {
1454           genSetDPTR (0);
1455         }
1456       break;
1457
1458     }
1459   aop->coff=0;
1460 }
1461
1462 #define AOP(op) op->aop
1463 #define AOP_TYPE(op) AOP(op)->type
1464 #define AOP_SIZE(op) AOP(op)->size
1465 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1466                        AOP_TYPE(x) == AOP_R0))
1467
1468 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
1469                         AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1470                          AOP(x)->paged))
1471
1472 #define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
1473                       (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1474                       x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1475 #define AOP_INDPTRn(x) (AOP_TYPE(x) == AOP_DPTRn)
1476 #define AOP_USESDPTR(x) (AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_STR)
1477
1478 /* Workaround for DS80C390 bug: div ab may return bogus results
1479  * if A is accessed in instruction immediately before the div.
1480  *
1481  * Will be fixed in B4 rev of processor, Dallas claims.
1482  */
1483
1484 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L)       \
1485     if (!AOP_NEEDSACC(RIGHT))         \
1486     {               \
1487       /* We can load A first, then B, since     \
1488        * B (the RIGHT operand) won't clobber A,   \
1489        * thus avoiding touching A right before the div. \
1490        */             \
1491       D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1492       L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE);     \
1493       MOVA(L);            \
1494       emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1495     }               \
1496     else              \
1497     {               \
1498       /* Just stuff in a nop after loading A. */    \
1499       emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1500       L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE);   \
1501       MOVA(L);            \
1502       emitcode("nop", "; workaround for DS80C390 div bug.");  \
1503     }
1504
1505 /*-----------------------------------------------------------------*/
1506 /* genNotFloat - generates not for float operations              */
1507 /*-----------------------------------------------------------------*/
1508 static void
1509 genNotFloat (operand * op, operand * res)
1510 {
1511   int size, offset;
1512   char *l;
1513   symbol *tlbl;
1514
1515   D (emitcode (";", "genNotFloat ");
1516     );
1517
1518   /* we will put 127 in the first byte of
1519      the result */
1520   aopPut (AOP (res), "#127", 0);
1521   size = AOP_SIZE (op) - 1;
1522   offset = 1;
1523
1524   _startLazyDPSEvaluation ();
1525   l = aopGet (op->aop, offset++, FALSE, FALSE, TRUE);
1526   MOVA (l);
1527
1528   while (size--)
1529     {
1530       emitcode ("orl", "a,%s",
1531                 aopGet (op->aop,
1532                         offset++, FALSE, FALSE, FALSE));
1533     }
1534   _endLazyDPSEvaluation ();
1535
1536   tlbl = newiTempLabel (NULL);
1537   aopPut (res->aop, one, 1);
1538   emitcode ("jz", "!tlabel", (tlbl->key + 100));
1539   aopPut (res->aop, zero, 1);
1540   emitcode ("", "!tlabeldef", (tlbl->key + 100));
1541
1542   size = res->aop->size - 2;
1543   offset = 2;
1544   /* put zeros in the rest */
1545   while (size--)
1546     aopPut (res->aop, zero, offset++);
1547 }
1548
1549 /*-----------------------------------------------------------------*/
1550 /* opIsGptr: returns non-zero if the passed operand is       */
1551 /* a generic pointer type.             */
1552 /*-----------------------------------------------------------------*/
1553 static int
1554 opIsGptr (operand * op)
1555 {
1556   sym_link *type = operandType (op);
1557
1558   if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1559     {
1560       return 1;
1561     }
1562   return 0;
1563 }
1564
1565 /*-----------------------------------------------------------------*/
1566 /* getDataSize - get the operand data size                         */
1567 /*-----------------------------------------------------------------*/
1568 static int
1569 getDataSize (operand * op)
1570 {
1571   int size;
1572   size = AOP_SIZE (op);
1573   if (size == GPTRSIZE)
1574     {
1575       sym_link *type = operandType (op);
1576       if (IS_GENPTR (type))
1577         {
1578           /* generic pointer; arithmetic operations
1579            * should ignore the high byte (pointer type).
1580            */
1581           size--;
1582         }
1583     }
1584   return size;
1585 }
1586
1587 /*-----------------------------------------------------------------*/
1588 /* outAcc - output Acc                                             */
1589 /*-----------------------------------------------------------------*/
1590 static void
1591 outAcc (operand * result)
1592 {
1593   int size, offset;
1594   size = getDataSize (result);
1595   if (size)
1596     {
1597       aopPut (AOP (result), "a", 0);
1598       size--;
1599       offset = 1;
1600       /* unsigned or positive */
1601       while (size--)
1602         {
1603           aopPut (AOP (result), zero, offset++);
1604         }
1605     }
1606 }
1607
1608 /*-----------------------------------------------------------------*/
1609 /* outBitC - output a bit C                                        */
1610 /*-----------------------------------------------------------------*/
1611 static void
1612 outBitC (operand * result)
1613 {
1614   /* if the result is bit */
1615   if (AOP_TYPE (result) == AOP_CRY)
1616     {
1617       aopPut (AOP (result), "c", 0);
1618     }
1619   else
1620     {
1621       emitcode ("clr", "a");
1622       emitcode ("rlc", "a");
1623       outAcc (result);
1624     }
1625 }
1626
1627 /*-----------------------------------------------------------------*/
1628 /* toBoolean - emit code for orl a,operator(sizeop)                */
1629 /*-----------------------------------------------------------------*/
1630 static void
1631 toBoolean (operand * oper)
1632 {
1633   int   size = AOP_SIZE (oper) - 1;
1634   int   offset = 1;
1635   bool usedB = FALSE;
1636
1637   /* The generic part of a generic pointer should
1638    * not participate in it's truth value.
1639    *
1640    * i.e. 0x10000000 is zero.
1641    */
1642   if (opIsGptr (oper))
1643     {
1644       D (emitcode (";", "toBoolean: generic ptr special case.");
1645         );
1646       size--;
1647     }
1648
1649   _startLazyDPSEvaluation ();
1650   if (AOP_NEEDSACC (oper) && size)
1651     {
1652       usedB = TRUE;
1653       emitcode ("push", "b");
1654       emitcode ("mov", "b, %s", aopGet (AOP (oper), 0, FALSE, FALSE, FALSE));
1655     }
1656   else
1657     {
1658       MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, TRUE));
1659     }
1660   while (size--)
1661     {
1662       if (usedB)
1663         {
1664           emitcode ("orl", "b,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1665         }
1666       else
1667         {
1668           emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1669         }
1670     }
1671   _endLazyDPSEvaluation ();
1672
1673   if (usedB)
1674     {
1675       emitcode ("mov", "a,b");
1676       emitcode ("pop", "b");
1677     }
1678 }
1679
1680
1681 /*-----------------------------------------------------------------*/
1682 /* genNot - generate code for ! operation                          */
1683 /*-----------------------------------------------------------------*/
1684 static void
1685 genNot (iCode * ic)
1686 {
1687   symbol *tlbl;
1688   sym_link *optype = operandType (IC_LEFT (ic));
1689
1690   D (emitcode (";", "genNot ");
1691     );
1692
1693   /* assign asmOps to operand & result */
1694   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1695   aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1696
1697   /* if in bit space then a special case */
1698   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1699     {
1700       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1701       emitcode ("cpl", "c");
1702       outBitC (IC_RESULT (ic));
1703       goto release;
1704     }
1705
1706   /* if type float then do float */
1707   if (IS_FLOAT (optype))
1708     {
1709       genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1710       goto release;
1711     }
1712
1713   toBoolean (IC_LEFT (ic));
1714
1715   tlbl = newiTempLabel (NULL);
1716   emitcode ("cjne", "a,#1,!tlabel", tlbl->key + 100);
1717   emitcode ("", "!tlabeldef", tlbl->key + 100);
1718   outBitC (IC_RESULT (ic));
1719
1720 release:
1721   /* release the aops */
1722   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1723   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1724 }
1725
1726
1727 /*-----------------------------------------------------------------*/
1728 /* genCpl - generate code for complement                           */
1729 /*-----------------------------------------------------------------*/
1730 static void
1731 genCpl (iCode * ic)
1732 {
1733   int offset = 0;
1734   int size;
1735   symbol *tlbl;
1736
1737   D (emitcode (";", "genCpl ");
1738     );
1739
1740
1741   /* assign asmOps to operand & result */
1742   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1743   aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1744
1745   /* special case if in bit space */
1746   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
1747     if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
1748       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1749       emitcode ("cpl", "c");
1750       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1751       goto release;
1752     }
1753     tlbl=newiTempLabel(NULL);
1754     emitcode ("cjne", "%s,#0x01,%05d$", 
1755               aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE,TRUE), tlbl->key+100);
1756     emitcode ("", "%05d$:", tlbl->key+100);
1757     outBitC (IC_RESULT(ic));
1758     goto release;
1759   }
1760
1761   size = AOP_SIZE (IC_RESULT (ic));
1762   _startLazyDPSEvaluation ();
1763   while (size--)
1764     {
1765       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1766       MOVA (l);
1767       emitcode ("cpl", "a");
1768       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1769     }
1770   _endLazyDPSEvaluation ();
1771
1772
1773 release:
1774   /* release the aops */
1775   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1776   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1777 }
1778
1779 /*-----------------------------------------------------------------*/
1780 /* genUminusFloat - unary minus for floating points                */
1781 /*-----------------------------------------------------------------*/
1782 static void
1783 genUminusFloat (operand * op, operand * result)
1784 {
1785   int size, offset = 0;
1786   char *l;
1787   /* for this we just need to flip the
1788      first it then copy the rest in place */
1789   D (emitcode (";", "genUminusFloat");
1790     );
1791
1792   _startLazyDPSEvaluation ();
1793   size = AOP_SIZE (op) - 1;
1794   l = aopGet (AOP (op), 3, FALSE, FALSE, TRUE);
1795   MOVA (l);
1796
1797   emitcode ("cpl", "acc.7");
1798   aopPut (AOP (result), "a", 3);
1799
1800   while (size--)
1801     {
1802       aopPut (AOP (result),
1803               aopGet (AOP (op), offset, FALSE, FALSE, FALSE),
1804               offset);
1805       offset++;
1806     }
1807   _endLazyDPSEvaluation ();
1808 }
1809
1810 /*-----------------------------------------------------------------*/
1811 /* genUminus - unary minus code generation                         */
1812 /*-----------------------------------------------------------------*/
1813 static void
1814 genUminus (iCode * ic)
1815 {
1816   int offset, size;
1817   sym_link *optype, *rtype;
1818
1819   D (emitcode (";", "genUminus ");
1820     );
1821
1822
1823   /* assign asmops */
1824   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1825   aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1826
1827   /* if both in bit space then special
1828      case */
1829   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1830       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1831     {
1832
1833       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1834       emitcode ("cpl", "c");
1835       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1836       goto release;
1837     }
1838
1839   optype = operandType (IC_LEFT (ic));
1840   rtype = operandType (IC_RESULT (ic));
1841
1842   /* if float then do float stuff */
1843   if (IS_FLOAT (optype))
1844     {
1845       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1846       goto release;
1847     }
1848
1849   /* otherwise subtract from zero */
1850   size = AOP_SIZE (IC_LEFT (ic));
1851   offset = 0;
1852   _startLazyDPSEvaluation ();
1853   while (size--)
1854     {
1855       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1856       if (!strcmp (l, "a"))
1857         {
1858           if (offset == 0)
1859             SETC;
1860           emitcode ("cpl", "a");
1861           emitcode ("addc", "a,#0");
1862         }
1863       else
1864         {
1865           if (offset == 0)
1866             CLRC;
1867           emitcode ("clr", "a");
1868           emitcode ("subb", "a,%s", l);
1869         }
1870       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1871     }
1872   _endLazyDPSEvaluation ();
1873
1874   /* if any remaining bytes in the result */
1875   /* we just need to propagate the sign   */
1876   if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1877     {
1878       emitcode ("rlc", "a");
1879       emitcode ("subb", "a,acc");
1880       while (size--)
1881         aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1882     }
1883
1884 release:
1885   /* release the aops */
1886   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1887   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1888 }
1889
1890 /*-----------------------------------------------------------------*/
1891 /* savermask - saves registers in the mask                         */
1892 /*-----------------------------------------------------------------*/
1893 static void savermask(bitVect *rs_mask)
1894 {
1895     int i;
1896     if (options.useXstack) {
1897         if (bitVectBitValue (rs_mask, R0_IDX))
1898             emitcode ("mov", "b,r0");
1899         emitcode ("mov", "r0,%s", spname);
1900         for (i = 0; i < ds390_nRegs; i++) {
1901             if (bitVectBitValue (rs_mask, i)) {
1902                 if (i == R0_IDX)
1903                     emitcode ("mov", "a,b");
1904                 else
1905                     emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
1906                 emitcode ("movx", "@r0,a");
1907                 emitcode ("inc", "r0");
1908             }
1909         }
1910         emitcode ("mov", "%s,r0", spname);
1911         if (bitVectBitValue (rs_mask, R0_IDX))
1912             emitcode ("mov", "r0,b");
1913     } else {
1914         for (i = 0; i < ds390_nRegs; i++) {
1915             if (bitVectBitValue (rs_mask, i))
1916                 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
1917         }
1918     }
1919 }
1920
1921 /*-----------------------------------------------------------------*/
1922 /* saveRegisters - will look for a call and save the registers     */
1923 /*-----------------------------------------------------------------*/
1924 static void
1925 saveRegisters (iCode * lic)
1926 {
1927   iCode *ic;
1928   bitVect *rsave;
1929
1930   /* look for call */
1931   for (ic = lic; ic; ic = ic->next)
1932     if (ic->op == CALL || ic->op == PCALL)
1933       break;
1934
1935   if (!ic)
1936     {
1937       fprintf (stderr, "found parameter push with no function call\n");
1938       return;
1939     }
1940
1941   /* if the registers have been saved already then
1942      do nothing */
1943   if (ic->regsSaved || IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic)))) return ;
1944
1945   /* special case if DPTR alive across a function call then must save it 
1946      even though callee saves */
1947   if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
1948       int i =0;
1949       rsave = newBitVect(ic->rMask->size);
1950       for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
1951           if (bitVectBitValue(ic->rMask,i))
1952               rsave = bitVectSetBit(rsave,i);
1953       }
1954       rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
1955   } else {
1956     /* safe the registers in use at this time but skip the
1957        ones for the result */
1958     rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1959                            ds390_rUmaskForOp (IC_RESULT(ic)));
1960   }
1961   ic->regsSaved = 1;
1962   savermask(rsave);
1963 }
1964
1965 /*-----------------------------------------------------------------*/
1966 /* usavermask - restore registers with mask                        */
1967 /*-----------------------------------------------------------------*/
1968 static void unsavermask(bitVect *rs_mask)
1969 {
1970     int i;
1971     if (options.useXstack) {
1972         emitcode ("mov", "r0,%s", spname);
1973         for (i = ds390_nRegs; i >= 0; i--) {
1974             if (bitVectBitValue (rs_mask, i)) {
1975                 emitcode ("dec", "r0");
1976                 emitcode ("movx", "a,@r0");
1977                 if (i == R0_IDX)
1978                     emitcode ("mov", "b,a");
1979                 else
1980                     emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
1981             }       
1982         }
1983         emitcode ("mov", "%s,r0", spname);
1984         if (bitVectBitValue (rs_mask, R0_IDX))
1985             emitcode ("mov", "r0,b");
1986     } else {
1987         for (i = ds390_nRegs; i >= 0; i--) {
1988             if (bitVectBitValue (rs_mask, i))
1989                 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
1990         }
1991     }
1992 }
1993
1994 /*-----------------------------------------------------------------*/
1995 /* unsaveRegisters - pop the pushed registers                      */
1996 /*-----------------------------------------------------------------*/
1997 static void
1998 unsaveRegisters (iCode * ic)
1999 {
2000   bitVect *rsave;
2001
2002   if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2003       int i =0;
2004       rsave = newBitVect(ic->rMask->size);
2005       for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2006           if (bitVectBitValue(ic->rMask,i))
2007               rsave = bitVectSetBit(rsave,i);
2008       }
2009       rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2010   } else {
2011     /* restore the registers in use at this time but skip the
2012        ones for the result */
2013     rsave = bitVectCplAnd (bitVectCopy (ic->rMask), 
2014                            ds390_rUmaskForOp (IC_RESULT(ic)));
2015   }
2016   unsavermask(rsave);
2017 }
2018
2019
2020 /*-----------------------------------------------------------------*/
2021 /* pushSide -                */
2022 /*-----------------------------------------------------------------*/
2023 static void
2024 pushSide (operand * oper, int size)
2025 {
2026   int offset = 0;
2027   _startLazyDPSEvaluation ();
2028   while (size--)
2029     {
2030       char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, FALSE);
2031       if (AOP_TYPE (oper) != AOP_REG &&
2032           AOP_TYPE (oper) != AOP_DIR &&
2033           strcmp (l, "a"))
2034         {
2035           emitcode ("mov", "a,%s", l);
2036           emitcode ("push", "acc");
2037         }
2038       else
2039         emitcode ("push", "%s", l);
2040     }
2041   _endLazyDPSEvaluation ();
2042 }
2043
2044 /*-----------------------------------------------------------------*/
2045 /* assignResultValue -               */
2046 /*-----------------------------------------------------------------*/
2047 static void
2048 assignResultValue (operand * oper)
2049 {
2050   int offset = 0;
2051   int size = AOP_SIZE (oper);
2052
2053   _startLazyDPSEvaluation ();
2054   while (size--)
2055     {
2056       aopPut (AOP (oper), fReturn[offset], offset);
2057       offset++;
2058     }
2059   _endLazyDPSEvaluation ();
2060 }
2061
2062
2063 /*-----------------------------------------------------------------*/
2064 /* genXpush - pushes onto the external stack                       */
2065 /*-----------------------------------------------------------------*/
2066 static void
2067 genXpush (iCode * ic)
2068 {
2069   asmop *aop = newAsmop (0);
2070   regs *r;
2071   int size, offset = 0;
2072
2073   D (emitcode (";", "genXpush ");
2074     );
2075
2076   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2077   r = getFreePtr (ic, &aop, FALSE);
2078
2079
2080   emitcode ("mov", "%s,_spx", r->name);
2081
2082   size = AOP_SIZE (IC_LEFT (ic));
2083   _startLazyDPSEvaluation ();
2084   while (size--)
2085     {
2086
2087       char *l = aopGet (AOP (IC_LEFT (ic)),
2088                         offset++, FALSE, FALSE, TRUE);
2089       MOVA (l);
2090       emitcode ("movx", "@%s,a", r->name);
2091       emitcode ("inc", "%s", r->name);
2092
2093     }
2094   _endLazyDPSEvaluation ();
2095
2096
2097   emitcode ("mov", "_spx,%s", r->name);
2098
2099   freeAsmop (NULL, aop, ic, TRUE);
2100   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2101 }
2102
2103 /*-----------------------------------------------------------------*/
2104 /* genIpush - genrate code for pushing this gets a little complex  */
2105 /*-----------------------------------------------------------------*/
2106 static void
2107 genIpush (iCode * ic)
2108 {
2109   int size, offset = 0;
2110   char *l;
2111
2112   D (emitcode (";", "genIpush ");
2113     );
2114
2115   /* if this is not a parm push : ie. it is spill push
2116      and spill push is always done on the local stack */
2117   if (!ic->parmPush)
2118     {
2119
2120       /* and the item is spilt then do nothing */
2121       if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2122         return;
2123
2124       aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2125       size = AOP_SIZE (IC_LEFT (ic));
2126       /* push it on the stack */
2127       _startLazyDPSEvaluation ();
2128       while (size--)
2129         {
2130           l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, TRUE);
2131           if (*l == '#')
2132             {
2133               MOVA (l);
2134               l = "acc";
2135             }
2136           emitcode ("push", "%s", l);
2137         }
2138       _endLazyDPSEvaluation ();
2139       return;
2140     }
2141
2142   /* this is a paramter push: in this case we call
2143      the routine to find the call and save those
2144      registers that need to be saved */
2145   saveRegisters (ic);
2146
2147   /* if use external stack then call the external
2148      stack pushing routine */
2149   if (options.useXstack)
2150     {
2151       genXpush (ic);
2152       return;
2153     }
2154
2155   /* then do the push */
2156   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2157
2158   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2159   size = AOP_SIZE (IC_LEFT (ic));
2160
2161   _startLazyDPSEvaluation ();
2162   while (size--)
2163     {
2164       l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, FALSE);
2165       if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2166           AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2167           strcmp (l, "a"))
2168         {
2169           emitcode ("mov", "a,%s", l);
2170           emitcode ("push", "acc");
2171         }
2172       else
2173         emitcode ("push", "%s", l);
2174     }
2175   _endLazyDPSEvaluation ();
2176
2177   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2178 }
2179
2180 /*-----------------------------------------------------------------*/
2181 /* genIpop - recover the registers: can happen only for spilling   */
2182 /*-----------------------------------------------------------------*/
2183 static void
2184 genIpop (iCode * ic)
2185 {
2186   int size, offset;
2187
2188   D (emitcode (";", "genIpop ");
2189     );
2190
2191
2192   /* if the temp was not pushed then */
2193   if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2194     return;
2195
2196   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2197   size = AOP_SIZE (IC_LEFT (ic));
2198   offset = (size - 1);
2199   _startLazyDPSEvaluation ();
2200   while (size--)
2201     {
2202       emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2203                                      FALSE, TRUE, TRUE));
2204     }
2205   _endLazyDPSEvaluation ();
2206
2207   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2208 }
2209
2210 /*-----------------------------------------------------------------*/
2211 /* unsaveRBank - restores the resgister bank from stack            */
2212 /*-----------------------------------------------------------------*/
2213 static void
2214 unsaveRBank (int bank, iCode * ic, bool popPsw)
2215 {
2216   int i;
2217   asmop *aop = NULL;
2218   regs *r = NULL;
2219
2220   if (options.useXstack)
2221   {
2222       if (!ic)
2223       {
2224           /* Assume r0 is available for use. */
2225           r = ds390_regWithIdx (R0_IDX);;          
2226       } 
2227       else
2228       {
2229           aop = newAsmop (0);
2230           r = getFreePtr (ic, &aop, FALSE);
2231       }
2232       emitcode ("mov", "%s,_spx", r->name);      
2233   }
2234   
2235   if (popPsw)
2236     {
2237       if (options.useXstack)
2238       {
2239           emitcode ("movx", "a,@%s", r->name);
2240           emitcode ("mov", "psw,a");
2241           emitcode ("dec", "%s", r->name);
2242         }
2243       else
2244       {
2245         emitcode ("pop", "psw");
2246       }
2247     }
2248
2249   for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2250     {
2251       if (options.useXstack)
2252         {
2253           emitcode ("movx", "a,@%s", r->name);
2254           emitcode ("mov", "(%s+%d),a",
2255                     regs390[i].base, 8 * bank + regs390[i].offset);
2256           emitcode ("dec", "%s", r->name);
2257
2258         }
2259       else
2260         emitcode ("pop", "(%s+%d)",
2261                   regs390[i].base, 8 * bank + regs390[i].offset);
2262     }
2263
2264   if (options.useXstack)
2265     {
2266       emitcode ("mov", "_spx,%s", r->name);
2267     }
2268     
2269   if (aop)
2270   {
2271       freeAsmop (NULL, aop, ic, TRUE);  
2272   }    
2273 }
2274
2275 /*-----------------------------------------------------------------*/
2276 /* saveRBank - saves an entire register bank on the stack          */
2277 /*-----------------------------------------------------------------*/
2278 static void
2279 saveRBank (int bank, iCode * ic, bool pushPsw)
2280 {
2281   int i;
2282   asmop *aop = NULL;
2283   regs *r = NULL;
2284
2285   if (options.useXstack)
2286     {
2287         if (!ic)
2288         {
2289           /* Assume r0 is available for use. */
2290                   r = ds390_regWithIdx (R0_IDX);;
2291         }
2292         else
2293         {
2294           aop = newAsmop (0);
2295           r = getFreePtr (ic, &aop, FALSE);
2296         }
2297         emitcode ("mov", "%s,_spx", r->name);    
2298     }
2299
2300   for (i = 0; i < 8 ; i++) /* only R0-R7 needs saving */
2301     {
2302       if (options.useXstack)
2303         {
2304           emitcode ("inc", "%s", r->name);
2305           emitcode ("mov", "a,(%s+%d)",
2306                     regs390[i].base, 8 * bank + regs390[i].offset);
2307           emitcode ("movx", "@%s,a", r->name);
2308         }
2309       else
2310         emitcode ("push", "(%s+%d)",
2311                   regs390[i].base, 8 * bank + regs390[i].offset);
2312     }
2313
2314   if (pushPsw)
2315     {
2316       if (options.useXstack)
2317         {
2318           emitcode ("mov", "a,psw");
2319           emitcode ("movx", "@%s,a", r->name);
2320           emitcode ("inc", "%s", r->name);
2321           emitcode ("mov", "_spx,%s", r->name);
2322         }
2323       else
2324       {
2325         emitcode ("push", "psw");
2326       }
2327
2328       emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2329     }
2330   
2331   if (aop)
2332   {
2333        freeAsmop (NULL, aop, ic, TRUE);
2334   }    
2335     
2336   if (ic)
2337   {  
2338       ic->bankSaved = 1;
2339   }
2340 }
2341
2342 /*-----------------------------------------------------------------*/
2343 /* genSend - gen code for SEND                                     */
2344 /*-----------------------------------------------------------------*/
2345 static void genSend(set *sendSet)
2346 {
2347     iCode *sic;
2348     int sendCount = 0 ;
2349     static int rb1_count = 0;
2350
2351     for (sic = setFirstItem (sendSet); sic;
2352          sic = setNextItem (sendSet)) {     
2353         int size, offset = 0;
2354         
2355         size=getSize(operandType(IC_LEFT(sic)));
2356         D (emitcode (";", "genSend argreg = %d, size = %d ",sic->argreg,size));
2357         if (sendCount == 0) { /* first parameter */
2358             // we know that dpl(hxb) is the result, so
2359             rb1_count = 0 ;
2360             _startLazyDPSEvaluation ();
2361             if (size>1) {
2362                 aopOp (IC_LEFT (sic), sic, FALSE, 
2363                        (IS_SYMOP(IC_LEFT(sic)) && OP_SYMBOL(IC_LEFT(sic))->ruonly ? FALSE : TRUE));
2364             } else {
2365                 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2366             }
2367             while (size--) {
2368                 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2369                                   FALSE, FALSE, TRUE);
2370                 if (strcmp (l, fReturn[offset])) {
2371                     emitcode ("mov", "%s,%s",
2372                               fReturn[offset],
2373                               l);
2374                 }
2375                 offset++;
2376             }
2377             _endLazyDPSEvaluation ();
2378             freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2379             rb1_count =0;
2380         } else { /* if more parameter in registers */
2381             aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2382             while (size--) {
2383                 emitcode ("mov","b1_%d,%s",rb1_count++,aopGet (AOP (IC_LEFT (sic)), offset++,
2384                                                                 FALSE, FALSE, TRUE));
2385             }
2386             freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2387         }
2388         sendCount++;
2389     }
2390 }
2391
2392 /*-----------------------------------------------------------------*/
2393 /* genCall - generates a call statement                            */
2394 /*-----------------------------------------------------------------*/
2395 static void
2396 genCall (iCode * ic)
2397 {
2398   sym_link *dtype;
2399   bool restoreBank = FALSE;
2400   bool swapBanks = FALSE;
2401
2402   D (emitcode (";", "genCall "););
2403
2404   /* if we are calling a not _naked function that is not using
2405      the same register bank then we need to save the
2406      destination registers on the stack */
2407   dtype = operandType (IC_LEFT (ic));
2408   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2409       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2410       IFFUNC_ISISR (currFunc->type))
2411   {
2412       if (!ic->bankSaved) 
2413       {
2414            /* This is unexpected; the bank should have been saved in
2415             * genFunction.
2416             */
2417            saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2418            restoreBank = TRUE;
2419       }
2420       swapBanks = TRUE;
2421   }
2422   
2423     /* if caller saves & we have not saved then */
2424     if (!ic->regsSaved)
2425       saveRegisters (ic);
2426   
2427   /* if send set is not empty the assign */
2428   /* We've saved all the registers we care about;
2429   * therefore, we may clobber any register not used
2430   * in the calling convention (i.e. anything not in
2431   * fReturn.
2432   */
2433   if (_G.sendSet)
2434     {
2435         if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2436             genSend(reverseSet(_G.sendSet));
2437         } else {
2438             genSend(_G.sendSet);
2439         }
2440       _G.sendSet = NULL;
2441     }  
2442     
2443   if (swapBanks)
2444   {
2445         emitcode ("mov", "psw,#!constbyte", 
2446            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2447   }
2448
2449   /* make the call */
2450   emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2451                             OP_SYMBOL (IC_LEFT (ic))->rname :
2452                             OP_SYMBOL (IC_LEFT (ic))->name));
2453
2454   if (swapBanks)
2455   {
2456        emitcode ("mov", "psw,#!constbyte", 
2457           ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2458   }
2459
2460   /* if we need assign a result value */
2461   if ((IS_ITEMP (IC_RESULT (ic)) &&
2462        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2463         OP_SYMBOL (IC_RESULT (ic))->accuse ||
2464         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2465       IS_TRUE_SYMOP (IC_RESULT (ic)))
2466     {
2467       if (isOperandInFarSpace (IC_RESULT (ic))
2468           && getSize (operandType (IC_RESULT (ic))) <= 2)
2469         {
2470           int size = getSize (operandType (IC_RESULT (ic)));
2471
2472           /* Special case for 1 or 2 byte return in far space. */
2473           MOVA (fReturn[0]);
2474           if (size > 1)
2475             {
2476               emitcode ("mov", "b,%s", fReturn[1]);
2477             }
2478
2479           aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2480           aopPut (AOP (IC_RESULT (ic)), "a", 0);
2481
2482           if (size > 1)
2483             {
2484               aopPut (AOP (IC_RESULT (ic)), "b", 1);
2485             }
2486           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2487         }
2488       else
2489         {
2490           _G.accInUse++;
2491           aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2492           _G.accInUse--;
2493
2494           assignResultValue (IC_RESULT (ic));
2495
2496           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2497         }
2498     }
2499
2500   /* adjust the stack for parameters if
2501      required */
2502   if (ic->parmBytes) {
2503       int i;
2504       if (options.stack10bit) {
2505           if (ic->parmBytes <= 10) {
2506               emitcode(";","stack adjustment for parms");
2507               for (i=0; i < ic->parmBytes ; i++) {
2508                   emitcode("pop","acc");
2509               }
2510           } else {            
2511               PROTECT_SP;
2512               emitcode ("clr","c");
2513               emitcode ("mov","a,sp");
2514               emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2515               emitcode ("mov","sp,a");
2516               emitcode ("mov","a,esp");
2517               emitcode ("anl","a,#3");
2518               emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2519               emitcode ("mov","esp,a");   
2520               UNPROTECT_SP;
2521           }
2522       } else {
2523           if (ic->parmBytes > 3) {
2524               emitcode ("mov", "a,%s", spname);
2525               emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2526               emitcode ("mov", "%s,a", spname);
2527           } else
2528               for (i = 0; i < ic->parmBytes; i++)
2529                   emitcode ("dec", "%s", spname);
2530       }
2531   }
2532
2533   /* if we hade saved some registers then unsave them */
2534   if (ic->regsSaved)
2535     unsaveRegisters (ic);
2536
2537   /* if register bank was saved then pop them */
2538   if (restoreBank)
2539     unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2540 }
2541
2542 /*-----------------------------------------------------------------*/
2543 /* genPcall - generates a call by pointer statement                */
2544 /*-----------------------------------------------------------------*/
2545 static void
2546 genPcall (iCode * ic)
2547 {
2548   sym_link *dtype;
2549   symbol *rlbl = newiTempLabel (NULL);
2550   bool restoreBank=FALSE;
2551
2552   D (emitcode (";", "genPcall ");
2553     );
2554
2555
2556   /* if caller saves & we have not saved then */
2557   if (!ic->regsSaved)
2558     saveRegisters (ic);
2559
2560   /* if we are calling a function that is not using
2561      the same register bank then we need to save the
2562      destination registers on the stack */
2563   dtype = operandType (IC_LEFT (ic));
2564   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2565       IFFUNC_ISISR (currFunc->type) &&
2566       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2567     saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2568     restoreBank=TRUE;
2569   }
2570
2571   /* push the return address on to the stack */
2572   emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
2573   emitcode ("push", "acc");
2574   emitcode ("mov", "a,#!hil", (rlbl->key + 100));
2575   emitcode ("push", "acc");
2576
2577   if (options.model == MODEL_FLAT24)
2578     {
2579       emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
2580       emitcode ("push", "acc");
2581     }
2582
2583   /* now push the calling address */
2584   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2585
2586   pushSide (IC_LEFT (ic), FPTRSIZE);
2587
2588   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2589
2590   /* if send set is not empty the assign */
2591   if (_G.sendSet)
2592     {
2593         genSend(reverseSet(_G.sendSet));
2594         _G.sendSet = NULL;
2595     }
2596
2597   emitcode ("ret", "");
2598   emitcode ("", "!tlabeldef", (rlbl->key + 100));
2599
2600
2601   /* if we need assign a result value */
2602   if ((IS_ITEMP (IC_RESULT (ic)) &&
2603        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2604         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2605       IS_TRUE_SYMOP (IC_RESULT (ic)))
2606     {
2607
2608       _G.accInUse++;
2609       aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2610       _G.accInUse--;
2611
2612       assignResultValue (IC_RESULT (ic));
2613
2614       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2615     }
2616
2617   /* adjust the stack for parameters if
2618      required */
2619   if (ic->parmBytes)
2620     {
2621       int i;
2622       if (options.stack10bit) {
2623           if (ic->parmBytes <= 10) {
2624               emitcode(";","stack adjustment for parms");
2625               for (i=0; i < ic->parmBytes ; i++) {
2626                   emitcode("pop","acc");
2627               }
2628           } else {            
2629               PROTECT_SP;
2630               emitcode ("clr","c");
2631               emitcode ("mov","a,sp");
2632               emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2633               emitcode ("mov","sp,a");
2634               emitcode ("mov","a,esp");
2635               emitcode ("anl","a,#3");
2636               emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2637               emitcode ("mov","esp,a");   
2638               UNPROTECT_SP;
2639           }
2640       } else {
2641           if (ic->parmBytes > 3) {
2642               emitcode ("mov", "a,%s", spname);
2643               emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2644               emitcode ("mov", "%s,a", spname);
2645           }
2646           else
2647               for (i = 0; i < ic->parmBytes; i++)
2648                   emitcode ("dec", "%s", spname);
2649           
2650       }
2651     }
2652   /* if register bank was saved then unsave them */
2653   if (restoreBank)
2654     unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2655   
2656   /* if we hade saved some registers then
2657      unsave them */
2658   if (ic->regsSaved)
2659     unsaveRegisters (ic);
2660
2661 }
2662
2663 /*-----------------------------------------------------------------*/
2664 /* resultRemat - result  is rematerializable                       */
2665 /*-----------------------------------------------------------------*/
2666 static int
2667 resultRemat (iCode * ic)
2668 {
2669   if (SKIP_IC (ic) || ic->op == IFX)
2670     return 0;
2671
2672   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2673     {
2674       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2675       if (sym->remat && !POINTER_SET (ic))
2676         return 1;
2677     }
2678
2679   return 0;
2680 }
2681
2682 #if defined(__BORLANDC__) || defined(_MSC_VER)
2683 #define STRCASECMP stricmp
2684 #else
2685 #define STRCASECMP strcasecmp
2686 #endif
2687
2688 /*-----------------------------------------------------------------*/
2689 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2690 /*-----------------------------------------------------------------*/
2691 static bool
2692 inExcludeList (char *s)
2693 {
2694   int i = 0;
2695
2696   if (options.excludeRegs[i] &&
2697       STRCASECMP (options.excludeRegs[i], "none") == 0)
2698     return FALSE;
2699
2700   for (i = 0; options.excludeRegs[i]; i++)
2701     {
2702       if (options.excludeRegs[i] &&
2703           STRCASECMP (s, options.excludeRegs[i]) == 0)
2704         return TRUE;
2705     }
2706   return FALSE;
2707 }
2708
2709 /*-----------------------------------------------------------------*/
2710 /* genFunction - generated code for function entry                 */
2711 /*-----------------------------------------------------------------*/
2712 static void
2713 genFunction (iCode * ic)
2714 {
2715   symbol *sym;
2716   sym_link *ftype;
2717   bool   switchedPSW = FALSE;
2718
2719   D (emitcode (";", "genFunction "););
2720
2721   _G.nRegsSaved = 0;
2722   /* create the function header */
2723   emitcode (";", "-----------------------------------------");
2724   emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2725   emitcode (";", "-----------------------------------------");
2726
2727   emitcode ("", "%s:", sym->rname);
2728   ftype = operandType (IC_LEFT (ic));
2729
2730   if (IFFUNC_ISNAKED(ftype))
2731   {
2732       emitcode(";", "naked function: no prologue.");
2733       return;
2734   }
2735   
2736   if (options.stack_probe) 
2737       emitcode ("lcall","__stack_probe");
2738   /* if critical function then turn interrupts off */
2739   if (IFFUNC_ISCRITICAL (ftype))
2740     emitcode ("clr", "ea");
2741
2742   /* here we need to generate the equates for the
2743      register bank if required */
2744   if (FUNC_REGBANK (ftype) != rbank)
2745     {
2746       int i;
2747
2748       rbank = FUNC_REGBANK (ftype);
2749       for (i = 0; i < ds390_nRegs; i++)
2750         {
2751           if (regs390[i].print) {
2752               if (strcmp (regs390[i].base, "0") == 0)
2753                   emitcode ("", "%s !equ !constbyte",
2754                             regs390[i].dname,
2755                             8 * rbank + regs390[i].offset);
2756               else
2757                   emitcode ("", "%s !equ %s + !constbyte",
2758                             regs390[i].dname,
2759                             regs390[i].base,
2760                             8 * rbank + regs390[i].offset);
2761           }
2762         }
2763     }
2764
2765   /* if this is an interrupt service routine then
2766      save acc, b, dpl, dph  */
2767   if (IFFUNC_ISISR (sym->type))
2768       { /* is ISR */
2769       if (!inExcludeList ("acc"))
2770         emitcode ("push", "acc");
2771       if (!inExcludeList ("b"))
2772         emitcode ("push", "b");
2773       if (!inExcludeList ("dpl"))
2774         emitcode ("push", "dpl");
2775       if (!inExcludeList ("dph"))
2776         emitcode ("push", "dph");
2777       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2778         {
2779           emitcode ("push", "dpx");
2780           /* Make sure we're using standard DPTR */
2781           emitcode ("push", "dps");
2782           emitcode ("mov", "dps,#0");
2783           if (options.stack10bit)
2784             {
2785               /* This ISR could conceivably use DPTR2. Better save it. */
2786               emitcode ("push", "dpl1");
2787               emitcode ("push", "dph1");
2788               emitcode ("push", "dpx1");
2789               emitcode ("push",  DP2_RESULT_REG);
2790             }
2791         }
2792       /* if this isr has no bank i.e. is going to
2793          run with bank 0 , then we need to save more
2794          registers :-) */
2795       if (!FUNC_REGBANK (sym->type))
2796         {
2797             int i;
2798
2799           /* if this function does not call any other
2800              function then we can be economical and
2801              save only those registers that are used */
2802           if (!IFFUNC_HASFCALL(sym->type))
2803             {
2804
2805               /* if any registers used */
2806               if (sym->regsUsed)
2807                 {
2808                   /* save the registers used */
2809                   for (i = 0; i < sym->regsUsed->size; i++)
2810                     {
2811                       if (bitVectBitValue (sym->regsUsed, i) ||
2812                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2813                         emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2814                     }
2815                 }
2816
2817             }
2818           else
2819             {
2820               /* this function has  a function call cannot
2821                  determines register usage so we will have to push the
2822                  entire bank */
2823               saveRBank (0, ic, FALSE);
2824               if (options.parms_in_bank1) {
2825                   for (i=0; i < 8 ; i++ ) {
2826                       emitcode ("push","%s",rb1regs[i]);
2827                   }
2828               }
2829             }
2830         }
2831         else
2832         {
2833             /* This ISR uses a non-zero bank.
2834              *
2835              * We assume that the bank is available for our
2836              * exclusive use.
2837              *
2838              * However, if this ISR calls a function which uses some
2839              * other bank, we must save that bank entirely.
2840              */
2841             unsigned long banksToSave = 0;
2842             
2843             if (IFFUNC_HASFCALL(sym->type))
2844             {
2845
2846 #define MAX_REGISTER_BANKS 4
2847
2848                 iCode *i;
2849                 int ix;
2850
2851                 for (i = ic; i; i = i->next)
2852                 {
2853                     if (i->op == ENDFUNCTION)
2854                     {
2855                         /* we got to the end OK. */
2856                         break;
2857                     }
2858                     
2859                     if (i->op == CALL)
2860                     {
2861                         sym_link *dtype;
2862                         
2863                         dtype = operandType (IC_LEFT(i));
2864                         if (dtype 
2865                          && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2866                         {
2867                              /* Mark this bank for saving. */
2868                              if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2869                              {
2870                                  werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2871                              }
2872                              else
2873                              {
2874                                  banksToSave |= (1 << FUNC_REGBANK(dtype));
2875                              }
2876                              
2877                              /* And note that we don't need to do it in 
2878                               * genCall.
2879                               */
2880                              i->bankSaved = 1;
2881                         }
2882                     }
2883                     if (i->op == PCALL)
2884                     {
2885                         /* This is a mess; we have no idea what
2886                          * register bank the called function might
2887                          * use.
2888                          *
2889                          * The only thing I can think of to do is
2890                          * throw a warning and hope.
2891                          */
2892                         werror(W_FUNCPTR_IN_USING_ISR);   
2893                     }
2894                 }
2895
2896                 if (banksToSave && options.useXstack)
2897                 {
2898                     /* Since we aren't passing it an ic, 
2899                      * saveRBank will assume r0 is available to abuse.
2900                      *
2901                      * So switch to our (trashable) bank now, so
2902                      * the caller's R0 isn't trashed.
2903                      */
2904                     emitcode ("push", "psw");
2905                     emitcode ("mov", "psw,#!constbyte", 
2906                               (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2907                     switchedPSW = TRUE;
2908                 }
2909                 
2910                 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2911                 {
2912                      if (banksToSave & (1 << ix))
2913                      {
2914                          saveRBank(ix, NULL, FALSE);
2915                      }
2916                 }
2917             }
2918             // jwk: this needs a closer look
2919             SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2920         }
2921     }
2922   else
2923     {
2924       /* if callee-save to be used for this function
2925          then save the registers being used in this function */
2926       if (IFFUNC_CALLEESAVES(sym->type))
2927         {
2928           int i;
2929
2930           /* if any registers used */
2931           if (sym->regsUsed)
2932             {
2933               /* save the registers used */
2934               for (i = 0; i < sym->regsUsed->size; i++)
2935                 {
2936                   if (bitVectBitValue (sym->regsUsed, i) ||
2937                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2938                     {
2939                       emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2940                       _G.nRegsSaved++;
2941                     }
2942                 }
2943             }
2944         }
2945     }
2946
2947   /* set the register bank to the desired value */
2948   if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
2949    && !switchedPSW)
2950     {
2951       emitcode ("push", "psw");
2952       emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2953     }
2954
2955   if ( (IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
2956        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
2957       if (options.stack10bit) {
2958           emitcode ("push","_bpx");
2959           emitcode ("push","_bpx+1");
2960           emitcode ("mov","_bpx,%s",spname);
2961           emitcode ("mov","_bpx+1,esp");
2962           emitcode ("anl","_bpx+1,#3");
2963       } else {
2964           if (options.useXstack) {
2965               emitcode ("mov", "r0,%s", spname);
2966               emitcode ("mov", "a,_bp");
2967               emitcode ("movx", "@r0,a");
2968               emitcode ("inc", "%s", spname);
2969           } else {
2970               /* set up the stack */
2971               emitcode ("push", "_bp"); /* save the callers stack  */
2972           }
2973           emitcode ("mov", "_bp,%s", spname);
2974       }
2975   }
2976
2977   /* adjust the stack for the function */
2978   if (sym->stack) {
2979       int i = sym->stack;
2980       if (options.stack10bit) {
2981           if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);    
2982           assert (sym->recvSize <= 4);
2983           if (sym->stack <= 8) {
2984               while (i--) emitcode ("push","acc");
2985           } else {
2986               PROTECT_SP;
2987               emitcode ("mov","a,sp");
2988               emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
2989               emitcode ("mov","sp,a");
2990               emitcode ("mov","a,esp");
2991               emitcode ("anl","a,#3");
2992               emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
2993               emitcode ("mov","esp,a");
2994               UNPROTECT_SP;
2995           }
2996       } else {
2997           if (i > 256)
2998               werror (W_STACK_OVERFLOW, sym->name);
2999           
3000           if (i > 3 && sym->recvSize < 4) {
3001               
3002               emitcode ("mov", "a,sp");
3003               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3004               emitcode ("mov", "sp,a");
3005               
3006           } else
3007               while (i--)
3008                   emitcode ("inc", "sp");
3009       }
3010   }
3011
3012   if (sym->xstack)
3013     {
3014
3015       emitcode ("mov", "a,_spx");
3016       emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3017       emitcode ("mov", "_spx,a");
3018     }
3019
3020 }
3021
3022 /*-----------------------------------------------------------------*/
3023 /* genEndFunction - generates epilogue for functions               */
3024 /*-----------------------------------------------------------------*/
3025 static void
3026 genEndFunction (iCode * ic)
3027 {
3028   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3029
3030   D (emitcode (";", "genEndFunction "););
3031
3032   if (IFFUNC_ISNAKED(sym->type))
3033   {
3034       emitcode(";", "naked function: no epilogue.");
3035       return;
3036   }
3037
3038   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3039        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3040
3041       if (options.stack10bit) {
3042           PROTECT_SP;     
3043           emitcode ("mov", "sp,_bpx", spname);
3044           emitcode ("mov", "esp,_bpx+1", spname);
3045           UNPROTECT_SP;
3046       } else {
3047           emitcode ("mov", "%s,_bp", spname);
3048       }
3049   }
3050
3051   /* if use external stack but some variables were
3052      added to the local stack then decrement the
3053      local stack */
3054   if (options.useXstack && sym->stack) {
3055       emitcode ("mov", "a,sp");
3056       emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3057       emitcode ("mov", "sp,a");
3058   }
3059
3060
3061   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3062        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3063
3064       if (options.useXstack) {
3065           emitcode ("mov", "r0,%s", spname);
3066           emitcode ("movx", "a,@r0");
3067           emitcode ("mov", "_bp,a");
3068           emitcode ("dec", "%s", spname);
3069       } else {
3070           if (options.stack10bit) {
3071               emitcode ("pop", "_bpx+1");
3072               emitcode ("pop", "_bpx");
3073           } else {
3074               emitcode ("pop", "_bp");
3075           }
3076       }
3077   }
3078
3079   /* restore the register bank  */
3080   if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3081   {
3082     if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3083      || !options.useXstack)
3084     {
3085         /* Special case of ISR using non-zero bank with useXstack
3086          * is handled below.
3087          */
3088         emitcode ("pop", "psw");
3089     }
3090   } 
3091
3092   if (IFFUNC_ISISR (sym->type))
3093       { /* is ISR */  
3094
3095       /* now we need to restore the registers */
3096       /* if this isr has no bank i.e. is going to
3097          run with bank 0 , then we need to save more
3098          registers :-) */
3099       if (!FUNC_REGBANK (sym->type))
3100         {
3101             int i;
3102           /* if this function does not call any other
3103              function then we can be economical and
3104              save only those registers that are used */
3105           if (!IFFUNC_HASFCALL(sym->type))
3106             {
3107
3108               /* if any registers used */
3109               if (sym->regsUsed)
3110                 {
3111                   /* save the registers used */
3112                   for (i = sym->regsUsed->size; i >= 0; i--)
3113                     {
3114                       if (bitVectBitValue (sym->regsUsed, i) ||
3115                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3116                         emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3117                     }
3118                 }
3119
3120             }
3121           else
3122             {
3123               /* this function has  a function call cannot
3124                  determines register usage so we will have to pop the
3125                  entire bank */
3126               if (options.parms_in_bank1) {
3127                   for (i = 7 ; i >= 0 ; i-- ) {
3128                       emitcode ("pop","%s",rb1regs[i]);
3129                   }
3130               }
3131               unsaveRBank (0, ic, FALSE);
3132             }
3133         }
3134         else
3135         {
3136             /* This ISR uses a non-zero bank.
3137              *
3138              * Restore any register banks saved by genFunction
3139              * in reverse order.
3140              */
3141           // jwk: this needs a closer look
3142             unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3143             int ix;
3144           
3145             for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3146             {
3147                 if (savedBanks & (1 << ix))
3148                 {
3149                     unsaveRBank(ix, NULL, FALSE);
3150                 }
3151             }
3152             
3153             if (options.useXstack)
3154             {
3155                 /* Restore bank AFTER calling unsaveRBank,
3156                  * since it can trash r0.
3157                  */
3158                 emitcode ("pop", "psw");
3159             }
3160         }
3161
3162       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3163         {
3164           if (options.stack10bit)
3165             {
3166               emitcode ("pop", DP2_RESULT_REG);
3167               emitcode ("pop", "dpx1");
3168               emitcode ("pop", "dph1");
3169               emitcode ("pop", "dpl1");
3170             }
3171           emitcode ("pop", "dps");
3172           emitcode ("pop", "dpx");
3173         }
3174       if (!inExcludeList ("dph"))
3175         emitcode ("pop", "dph");
3176       if (!inExcludeList ("dpl"))
3177         emitcode ("pop", "dpl");
3178       if (!inExcludeList ("b"))
3179         emitcode ("pop", "b");
3180       if (!inExcludeList ("acc"))
3181         emitcode ("pop", "acc");
3182
3183       if (IFFUNC_ISCRITICAL (sym->type))
3184         emitcode ("setb", "ea");
3185
3186       /* if debug then send end of function */
3187       if (options.debug && currFunc) {
3188           _G.debugLine = 1;
3189           emitcode ("", "C$%s$%d$%d$%d ==.",
3190                     FileBaseName (ic->filename), currFunc->lastLine,
3191                     ic->level, ic->block);
3192           if (IS_STATIC (currFunc->etype))
3193             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3194           else
3195             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3196           _G.debugLine = 0;
3197         }
3198
3199       emitcode ("reti", "");
3200     }
3201   else
3202     {
3203       if (IFFUNC_ISCRITICAL (sym->type))
3204         emitcode ("setb", "ea");
3205
3206       if (IFFUNC_CALLEESAVES(sym->type))
3207         {
3208           int i;
3209
3210           /* if any registers used */
3211           if (sym->regsUsed)
3212             {
3213               /* save the registers used */
3214               for (i = sym->regsUsed->size; i >= 0; i--)
3215                 {
3216                   if (bitVectBitValue (sym->regsUsed, i) ||
3217                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3218                     emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3219                 }
3220             }
3221
3222         }
3223
3224       /* if debug then send end of function */
3225       if (options.debug && currFunc)
3226         {
3227           _G.debugLine = 1;
3228           emitcode ("", "C$%s$%d$%d$%d ==.",
3229                     FileBaseName (ic->filename), currFunc->lastLine,
3230                     ic->level, ic->block);
3231           if (IS_STATIC (currFunc->etype))
3232             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3233           else
3234             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3235           _G.debugLine = 0;
3236         }
3237
3238       emitcode ("ret", "");
3239     }
3240
3241 }
3242
3243 /*-----------------------------------------------------------------*/
3244 /* genJavaNativeRet - generate code for return JavaNative          */
3245 /*-----------------------------------------------------------------*/
3246 static void genJavaNativeRet(iCode *ic)
3247 {
3248     int i, size;
3249
3250     aopOp (IC_LEFT (ic), ic, FALSE, 
3251            (IS_SYMOP(IC_LEFT(ic)) && OP_SYMBOL(IC_LEFT(ic))->ruonly ? FALSE :TRUE));
3252     size = AOP_SIZE (IC_LEFT (ic));
3253
3254     assert (size <= 4);
3255
3256     /* it is assigned to GPR0-R3 then push them */
3257     if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3258         aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3259         for (i = 0 ; i < size ; i++ ) {
3260             emitcode ("push","%s",aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,FALSE));     
3261         }
3262         for (i = (size-1) ; i >= 0 ; i--) {
3263             emitcode ("pop","a%s",javaRet[i]);
3264         }
3265     } else {
3266         for (i = 0 ; i < size ; i++) 
3267             emitcode ("mov","%s,%s",javaRet[i],aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,FALSE));
3268     }
3269     for (i = size ; i < 4 ; i++ )
3270             emitcode ("mov","%s,#0",javaRet[i]);
3271     return;
3272 }
3273
3274 /*-----------------------------------------------------------------*/
3275 /* genRet - generate code for return statement                     */
3276 /*-----------------------------------------------------------------*/
3277 static void
3278 genRet (iCode * ic)
3279 {
3280   int size, offset = 0, pushed = 0;
3281
3282   D (emitcode (";", "genRet ");
3283     );
3284
3285   /* if we have no return value then
3286      just generate the "ret" */
3287   if (!IC_LEFT (ic))
3288     goto jumpret;
3289
3290   /* if this is a JavaNative function then return 
3291      value in different register */
3292   if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3293       genJavaNativeRet(ic);
3294       goto jumpret;
3295   }
3296   /* we have something to return then
3297      move the return value into place */
3298   aopOp (IC_LEFT (ic), ic, FALSE, 
3299          (IS_SYMOP(IC_LEFT(ic)) && OP_SYMBOL(IC_LEFT(ic))->ruonly ? FALSE :TRUE));
3300   size = AOP_SIZE (IC_LEFT (ic));
3301
3302   _startLazyDPSEvaluation ();
3303   while (size--)
3304     {
3305       char *l;
3306       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3307         {
3308           l = aopGet (AOP (IC_LEFT (ic)), offset++,
3309                       FALSE, TRUE, FALSE);
3310           emitcode ("push", "%s", l);
3311           pushed++;
3312         }
3313       else
3314         {
3315           /* Since A is the last element of fReturn,
3316            * is is OK to clobber it in the aopGet.
3317            */
3318           l = aopGet (AOP (IC_LEFT (ic)), offset,
3319                       FALSE, FALSE, TRUE);
3320           if (strcmp (fReturn[offset], l))
3321             emitcode ("mov", "%s,%s", fReturn[offset++], l);
3322         }
3323     }
3324   _endLazyDPSEvaluation ();
3325
3326   if (pushed)
3327     {
3328       while (pushed)
3329         {
3330           pushed--;
3331           if (strcmp (fReturn[pushed], "a"))
3332             emitcode ("pop", fReturn[pushed]);
3333           else
3334             emitcode ("pop", "acc");
3335         }
3336     }
3337   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3338
3339 jumpret:
3340   /* generate a jump to the return label
3341      if the next is not the return statement */
3342   if (!(ic->next && ic->next->op == LABEL &&
3343         IC_LABEL (ic->next) == returnLabel))
3344
3345     emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3346
3347 }
3348
3349 /*-----------------------------------------------------------------*/
3350 /* genLabel - generates a label                                    */
3351 /*-----------------------------------------------------------------*/
3352 static void
3353 genLabel (iCode * ic)
3354 {
3355   /* special case never generate */
3356   if (IC_LABEL (ic) == entryLabel)
3357     return;
3358
3359   D (emitcode (";", "genLabel ");
3360     );
3361
3362   emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3363 }
3364
3365 /*-----------------------------------------------------------------*/
3366 /* genGoto - generates a ljmp                                      */
3367 /*-----------------------------------------------------------------*/
3368 static void
3369 genGoto (iCode * ic)
3370 {
3371   D (emitcode (";", "genGoto ");
3372     );
3373   emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3374 }
3375
3376 /*-----------------------------------------------------------------*/
3377 /* findLabelBackwards: walks back through the iCode chain looking  */
3378 /* for the given label. Returns number of iCode instructions     */
3379 /* between that label and given ic.          */
3380 /* Returns zero if label not found.          */
3381 /*-----------------------------------------------------------------*/
3382 static int
3383 findLabelBackwards (iCode * ic, int key)
3384 {
3385   int count = 0;
3386
3387   while (ic->prev)
3388     {
3389       ic = ic->prev;
3390       count++;
3391
3392       /* If we have any pushes or pops, we cannot predict the distance.
3393          I don't like this at all, this should be dealt with in the 
3394          back-end */
3395       if (ic->op == IPUSH || ic->op == IPOP) {
3396         return 0;
3397       }
3398
3399       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3400         {
3401           /* printf("findLabelBackwards = %d\n", count); */
3402           return count;
3403         }
3404     }
3405
3406   return 0;
3407 }
3408
3409 /*-----------------------------------------------------------------*/
3410 /* genPlusIncr :- does addition with increment if possible         */
3411 /*-----------------------------------------------------------------*/
3412 static bool
3413 genPlusIncr (iCode * ic)
3414 {
3415   unsigned int icount;
3416   unsigned int size = getDataSize (IC_RESULT (ic));
3417
3418   /* will try to generate an increment */
3419   /* if the right side is not a literal
3420      we cannot */
3421   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3422     return FALSE;
3423
3424   /* if the literal value of the right hand side
3425      is greater than 4 then it is not worth it */
3426   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3427     return FALSE;
3428
3429   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3430       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3431       while (icount--) {
3432           emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
3433       }
3434       return TRUE;
3435   }
3436   /* if increment 16 bits in register */
3437   if (
3438        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3439        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3440        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3441        (size > 1) &&
3442        (icount == 1))
3443     {
3444       symbol *tlbl;
3445       int emitTlbl;
3446       int labelRange;
3447
3448       /* If the next instruction is a goto and the goto target
3449        * is <= 5 instructions previous to this, we can generate
3450        * jumps straight to that target.
3451        */
3452       if (ic->next && ic->next->op == GOTO
3453           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3454           && labelRange <= 5)
3455         {
3456           emitcode (";", "tail increment optimized (range %d)", labelRange);
3457           tlbl = IC_LABEL (ic->next);
3458           emitTlbl = 0;
3459         }
3460       else
3461         {
3462           tlbl = newiTempLabel (NULL);
3463           emitTlbl = 1;
3464         }
3465       emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3466       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3467           IS_AOP_PREG (IC_RESULT (ic)))
3468         emitcode ("cjne", "%s,#0,!tlabel"
3469                   ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3470                   ,tlbl->key + 100);
3471       else
3472         {
3473           emitcode ("clr", "a");
3474           emitcode ("cjne", "a,%s,!tlabel"
3475                     ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3476                     ,tlbl->key + 100);
3477         }
3478
3479       emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3480       if (size > 2)
3481         {
3482           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3483               IS_AOP_PREG (IC_RESULT (ic)))
3484             emitcode ("cjne", "%s,#0,!tlabel"
3485                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3486                       ,tlbl->key + 100);
3487           else
3488             emitcode ("cjne", "a,%s,!tlabel"
3489                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3490                       ,tlbl->key + 100);
3491
3492           emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3493         }
3494       if (size > 3)
3495         {
3496           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3497               IS_AOP_PREG (IC_RESULT (ic)))
3498             emitcode ("cjne", "%s,#0,!tlabel"
3499                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3500                       ,tlbl->key + 100);
3501           else
3502             {
3503               emitcode ("cjne", "a,%s,!tlabel"
3504                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3505                         ,tlbl->key + 100);
3506             }
3507           emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3508         }
3509
3510       if (emitTlbl)
3511         {
3512           emitcode ("", "!tlabeldef", tlbl->key + 100);
3513         }
3514       return TRUE;
3515     }
3516
3517   if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
3518       AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
3519       icount <= 5 ) {
3520       emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
3521       while (icount--) emitcode ("inc","dptr");
3522       emitcode ("mov","dps,#0");
3523       return TRUE;
3524   }
3525
3526   /* if the sizes are greater than 1 then we cannot */
3527   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3528       AOP_SIZE (IC_LEFT (ic)) > 1)
3529     return FALSE;
3530
3531   /* we can if the aops of the left & result match or
3532      if they are in registers and the registers are the
3533      same */
3534   if (
3535        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3536        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3537        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3538     {
3539
3540       if (icount > 3)
3541         {
3542           MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3543           emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3544           aopPut (AOP (IC_RESULT (ic)), "a", 0);
3545         }
3546       else
3547         {
3548
3549           _startLazyDPSEvaluation ();
3550           while (icount--)
3551             {
3552               emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3553             }
3554           _endLazyDPSEvaluation ();
3555         }
3556
3557       return TRUE;
3558     }
3559
3560   return FALSE;
3561 }
3562
3563 /*-----------------------------------------------------------------*/
3564 /* outBitAcc - output a bit in acc                                 */
3565 /*-----------------------------------------------------------------*/
3566 static void
3567 outBitAcc (operand * result)
3568 {
3569   symbol *tlbl = newiTempLabel (NULL);
3570   /* if the result is a bit */
3571   if (AOP_TYPE (result) == AOP_CRY)
3572     {
3573       aopPut (AOP (result), "a", 0);
3574     }
3575   else
3576     {
3577       emitcode ("jz", "!tlabel", tlbl->key + 100);
3578       emitcode ("mov", "a,%s", one);
3579       emitcode ("", "!tlabeldef", tlbl->key + 100);
3580       outAcc (result);
3581     }
3582 }
3583
3584 /*-----------------------------------------------------------------*/
3585 /* genPlusBits - generates code for addition of two bits           */
3586 /*-----------------------------------------------------------------*/
3587 static void
3588 genPlusBits (iCode * ic)
3589 {
3590   D (emitcode (";", "genPlusBits ");
3591     );
3592   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3593     {
3594       symbol *lbl = newiTempLabel (NULL);
3595       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3596       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3597       emitcode ("cpl", "c");
3598       emitcode ("", "!tlabeldef", (lbl->key + 100));
3599       outBitC (IC_RESULT (ic));
3600     }
3601   else
3602     {
3603       emitcode ("clr", "a");
3604       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3605       emitcode ("rlc", "a");
3606       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3607       emitcode ("addc", "a,#0");
3608       outAcc (IC_RESULT (ic));
3609     }
3610 }
3611
3612 static void
3613 adjustArithmeticResult (iCode * ic)
3614 {
3615   if (opIsGptr (IC_RESULT (ic)) &&
3616       opIsGptr (IC_LEFT (ic)) &&
3617       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3618     {
3619       aopPut (AOP (IC_RESULT (ic)),
3620               aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3621               GPTRSIZE - 1);
3622     }
3623
3624   if (opIsGptr (IC_RESULT (ic)) &&
3625       opIsGptr (IC_RIGHT (ic)) &&
3626       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3627     {
3628       aopPut (AOP (IC_RESULT (ic)),
3629             aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3630               GPTRSIZE - 1);
3631     }
3632
3633   if (opIsGptr (IC_RESULT (ic)) &&
3634       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3635       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3636       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3637       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3638     {
3639       char buffer[5];
3640       sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3641       aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3642     }
3643 }
3644
3645 // Macro to aopOp all three operands of an ic. If this cannot be done, 
3646 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3647 // will be set TRUE. The caller must then handle the case specially, noting
3648 // that the IC_RESULT operand is not aopOp'd.
3649 #define AOP_OP_3_NOFATAL(ic, rc) \
3650     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3651     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR) || \
3652                                   ((OP_SYMBOL(IC_RESULT(ic))->ruonly) && !isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)))); \
3653     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3654         (isOperandInFarSpace(IC_RESULT(ic)) || (OP_SYMBOL(IC_RESULT(ic))->ruonly && !isOperandEqual(IC_LEFT(ic),IC_RESULT(ic))))) \
3655     { \
3656        /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3657        rc = TRUE; \
3658     }  \
3659     else \
3660     { \
3661        aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3662                                      (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3663        rc = FALSE; \
3664        if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3665            AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3666        { \
3667             /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3668             fprintf(stderr,                                  \
3669                     "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno);   \
3670        } \
3671     }
3672
3673 // aopOp the left & right operands of an ic.
3674 #define AOP_OP_2(ic) \
3675     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3676     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3677
3678 // convienience macro.
3679 #define AOP_SET_LOCALS(ic) \
3680     left = IC_LEFT(ic); \
3681     right = IC_RIGHT(ic); \
3682     result = IC_RESULT(ic);
3683
3684
3685 // Given an integer value of pushedSize bytes on the stack,
3686 // adjust it to be resultSize bytes, either by discarding
3687 // the most significant bytes or by zero-padding.
3688 //
3689 // On exit from this macro, pushedSize will have been adjusted to
3690 // equal resultSize, and ACC may be trashed.
3691 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize)            \
3692       /* If the pushed data is bigger than the result,          \
3693        * simply discard unused bytes. Icky, but works.          \
3694        */                                                       \
3695       while (pushedSize > resultSize)                           \
3696       {                                                         \
3697           D (emitcode (";", "discarding unused result byte."););\
3698           emitcode ("pop", "acc");                              \
3699           pushedSize--;                                         \
3700       }                                                         \
3701       if (pushedSize < resultSize)                              \
3702       {                                                         \
3703           emitcode ("clr", "a");                                \
3704           /* Conversly, we haven't pushed enough here.          \
3705            * just zero-pad, and all is well.                    \
3706            */                                                   \
3707           while (pushedSize < resultSize)                       \
3708           {                                                     \
3709               emitcode("push", "acc");                          \
3710               pushedSize++;                                     \
3711           }                                                     \
3712       }                                                         \
3713       assert(pushedSize == resultSize);
3714
3715 /*-----------------------------------------------------------------*/
3716 /* genPlus - generates code for addition                           */
3717 /*-----------------------------------------------------------------*/
3718 static void
3719 genPlus (iCode * ic)
3720 {
3721   int size, offset = 0;
3722   bool pushResult = FALSE;
3723   int rSize;
3724
3725   D (emitcode (";", "genPlus "););
3726
3727   /* special cases :- */
3728   if ( IS_SYMOP(IC_LEFT(ic)) && OP_SYMBOL(IC_LEFT(ic))->ruonly &&
3729       isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
3730       aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
3731       size = floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
3732       if (size <= 9) {
3733           while (size--) emitcode ("inc","dptr");
3734       } else {
3735           emitcode ("mov","a,dpl");
3736           emitcode ("add","a,#!constbyte",size & 0xff);
3737           emitcode ("mov","dpl,a");
3738           emitcode ("mov","a,dph");
3739           emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
3740           emitcode ("mov","dph,a");
3741           emitcode ("mov","a,dpx");
3742           emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
3743           emitcode ("mov","dpx,a");
3744       }
3745       freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
3746       return ;
3747   }
3748   if ( IS_SYMOP(IC_LEFT(ic)) && 
3749        OP_SYMBOL(IC_LEFT(ic))->remat &&
3750        isOperandInFarSpace(IC_RIGHT(ic))) {
3751       operand *op = IC_RIGHT(ic);
3752       IC_RIGHT(ic) = IC_LEFT(ic);
3753       IC_LEFT(ic) = op;
3754   }
3755                 
3756   AOP_OP_3_NOFATAL (ic, pushResult);
3757   if (pushResult)
3758     {
3759       D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3760     }
3761
3762   if (!pushResult)
3763     {
3764       /* if literal, literal on the right or
3765          if left requires ACC or right is already
3766          in ACC */
3767       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3768        || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3769           || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3770         {
3771           operand *t = IC_RIGHT (ic);
3772           IC_RIGHT (ic) = IC_LEFT (ic);
3773           IC_LEFT (ic) = t;
3774           emitcode (";", "Swapped plus args.");
3775         }
3776
3777       /* if both left & right are in bit
3778          space */
3779       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3780           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3781         {
3782           genPlusBits (ic);
3783           goto release;
3784         }
3785
3786       /* if left in bit space & right literal */
3787       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3788           AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3789         {
3790           emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3791           /* if result in bit space */
3792           if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3793             {
3794               if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3795                 emitcode ("cpl", "c");
3796               outBitC (IC_RESULT (ic));
3797             }
3798           else
3799             {
3800               size = getDataSize (IC_RESULT (ic));
3801               _startLazyDPSEvaluation ();
3802               while (size--)
3803                 {
3804                   MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3805                   emitcode ("addc", "a,#0");
3806                   aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3807                 }
3808               _endLazyDPSEvaluation ();
3809             }
3810           goto release;
3811         }
3812
3813       /* if I can do an increment instead
3814          of add then GOOD for ME */
3815       if (genPlusIncr (ic) == TRUE)
3816         {
3817           emitcode (";", "did genPlusIncr");
3818           goto release;
3819         }
3820
3821     }
3822   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3823
3824   _startLazyDPSEvaluation ();
3825   while (size--)
3826     {
3827       if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
3828         {
3829           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3830           if (offset == 0)
3831             emitcode ("add", "a,%s",
3832                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3833           else
3834             emitcode ("addc", "a,%s",
3835                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3836         }
3837       else
3838         {
3839           if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
3840           {
3841               /* right is going to use ACC or we would have taken the
3842                * above branch.
3843                */
3844               assert(AOP_NEEDSACC(IC_RIGHT(ic)));
3845        TR_AP("#3");
3846               D(emitcode(";", "+ AOP_ACC special case."););
3847               emitcode("xch", "a, %s", DP2_RESULT_REG);
3848           }
3849           MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3850           if (offset == 0)
3851           {
3852             if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
3853             {
3854          TR_AP("#4");
3855                 emitcode("add", "a, %s", DP2_RESULT_REG); 
3856             }
3857             else
3858             {
3859                 emitcode ("add", "a,%s",
3860                         aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE, FALSE));
3861             }
3862           }
3863           else
3864           {
3865             emitcode ("addc", "a,%s",
3866                   aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3867           }
3868         }
3869       if (!pushResult)
3870         {
3871           aopPut (AOP (IC_RESULT (ic)), "a", offset);
3872         }
3873       else
3874         {
3875           emitcode ("push", "acc");
3876         }
3877       offset++;
3878     }
3879   _endLazyDPSEvaluation ();
3880
3881   if (pushResult)
3882     {
3883       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3884
3885       size = getDataSize (IC_LEFT (ic));
3886       rSize = getDataSize (IC_RESULT (ic));
3887
3888       ADJUST_PUSHED_RESULT(size, rSize);
3889
3890       _startLazyDPSEvaluation ();
3891       while (size--)
3892         {
3893           emitcode ("pop", "acc");
3894           aopPut (AOP (IC_RESULT (ic)), "a", size);
3895         }
3896       _endLazyDPSEvaluation ();
3897     }
3898
3899   adjustArithmeticResult (ic);
3900
3901 release:
3902   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3903   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3904   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3905 }
3906
3907 /*-----------------------------------------------------------------*/
3908 /* genMinusDec :- does subtraction with deccrement if possible     */
3909 /*-----------------------------------------------------------------*/
3910 static bool
3911 genMinusDec (iCode * ic)
3912 {
3913   unsigned int icount;
3914   unsigned int size = getDataSize (IC_RESULT (ic));
3915
3916   /* will try to generate an increment */
3917   /* if the right side is not a literal
3918      we cannot */
3919   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3920     return FALSE;
3921
3922   /* if the literal value of the right hand side
3923      is greater than 4 then it is not worth it */
3924   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3925     return FALSE;
3926
3927   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3928       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3929       while (icount--) {
3930           emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
3931       }
3932       return TRUE;
3933   }
3934   /* if decrement 16 bits in register */
3935   if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3936       AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3937       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3938       (size > 1) &&
3939       (icount == 1))
3940     {
3941       symbol *tlbl;
3942       int emitTlbl;
3943       int labelRange;
3944
3945       /* If the next instruction is a goto and the goto target
3946          * is <= 5 instructions previous to this, we can generate
3947          * jumps straight to that target.
3948        */
3949       if (ic->next && ic->next->op == GOTO
3950           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3951           && labelRange <= 5)
3952         {
3953           emitcode (";", "tail decrement optimized (range %d)", labelRange);
3954           tlbl = IC_LABEL (ic->next);
3955           emitTlbl = 0;
3956         }
3957       else
3958         {
3959           tlbl = newiTempLabel (NULL);
3960           emitTlbl = 1;
3961         }
3962
3963       emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3964       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3965           AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3966           IS_AOP_PREG (IC_RESULT (ic)))
3967         emitcode ("cjne", "%s,#!constbyte,!tlabel"
3968                   ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE), 0xff
3969                   ,tlbl->key + 100);
3970       else
3971         {
3972           emitcode ("mov", "a,#!constbyte",0xff);
3973           emitcode ("cjne", "a,%s,!tlabel"
3974                     ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3975                     ,tlbl->key + 100);
3976         }
3977       emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3978       if (size > 2)
3979         {
3980           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3981               AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3982               IS_AOP_PREG (IC_RESULT (ic)))
3983             emitcode ("cjne", "%s,#!constbyte,!tlabel"
3984                       ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE),0xff
3985                       ,tlbl->key + 100);
3986           else
3987             {
3988               emitcode ("cjne", "a,%s,!tlabel"
3989                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3990                         ,tlbl->key + 100);
3991             }
3992           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3993         }
3994       if (size > 3)
3995         {
3996           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3997               AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3998               IS_AOP_PREG (IC_RESULT (ic)))
3999             emitcode ("cjne", "%s,#!constbyte,!tlabel"
4000                       ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE),0xff
4001                       ,tlbl->key + 100);
4002           else
4003             {
4004               emitcode ("cjne", "a,%s,!tlabel"
4005                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
4006                         ,tlbl->key + 100);
4007             }
4008           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
4009         }
4010       if (emitTlbl)
4011         {
4012           emitcode ("", "!tlabeldef", tlbl->key + 100);
4013         }
4014       return TRUE;
4015     }
4016
4017   /* if the sizes are greater than 1 then we cannot */
4018   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4019       AOP_SIZE (IC_LEFT (ic)) > 1)
4020     return FALSE;
4021
4022   /* we can if the aops of the left & result match or
4023      if they are in registers and the registers are the
4024      same */
4025   if (
4026        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4027        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4028        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4029     {
4030
4031       _startLazyDPSEvaluation ();
4032       while (icount--)
4033         {
4034           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
4035         }
4036       _endLazyDPSEvaluation ();
4037
4038       return TRUE;
4039     }
4040
4041   return FALSE;
4042 }
4043
4044 /*-----------------------------------------------------------------*/
4045 /* addSign - complete with sign                                    */
4046 /*-----------------------------------------------------------------*/
4047 static void
4048 addSign (operand * result, int offset, int sign)
4049 {
4050   int size = (getDataSize (result) - offset);
4051   if (size > 0)
4052     {
4053       _startLazyDPSEvaluation();
4054       if (sign)
4055         {
4056           emitcode ("rlc", "a");
4057           emitcode ("subb", "a,acc");
4058           while (size--)
4059           {
4060             aopPut (AOP (result), "a", offset++);
4061           }
4062         }
4063       else
4064       {
4065         while (size--)
4066         {
4067           aopPut (AOP (result), zero, offset++);
4068         }
4069       }
4070       _endLazyDPSEvaluation();
4071     }
4072 }
4073
4074 /*-----------------------------------------------------------------*/
4075 /* genMinusBits - generates code for subtraction  of two bits      */
4076 /*-----------------------------------------------------------------*/
4077 static void
4078 genMinusBits (iCode * ic)
4079 {
4080   symbol *lbl = newiTempLabel (NULL);
4081
4082   D (emitcode (";", "genMinusBits "););
4083
4084   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4085     {
4086       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4087       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4088       emitcode ("cpl", "c");
4089       emitcode ("", "!tlabeldef", (lbl->key + 100));
4090       outBitC (IC_RESULT (ic));
4091     }
4092   else
4093     {
4094       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4095       emitcode ("subb", "a,acc");
4096       emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4097       emitcode ("inc", "a");
4098       emitcode ("", "!tlabeldef", (lbl->key + 100));
4099       aopPut (AOP (IC_RESULT (ic)), "a", 0);
4100       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4101     }
4102 }
4103
4104 /*-----------------------------------------------------------------*/
4105 /* genMinus - generates code for subtraction                       */
4106 /*-----------------------------------------------------------------*/
4107 static void
4108 genMinus (iCode * ic)
4109 {
4110   int size, offset = 0;
4111   int rSize;
4112   unsigned long lit = 0L;
4113   bool pushResult = FALSE;
4114
4115   D (emitcode (";", "genMinus "););
4116
4117   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
4118   aopOp (IC_RIGHT (ic), ic, FALSE, 
4119          (AOP_INDPTRn(IC_LEFT(ic)) ? FALSE : (AOP_USESDPTR(IC_LEFT(ic)) ? TRUE : FALSE)));
4120   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
4121       (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
4122     {
4123       pushResult = TRUE;
4124     }
4125   else
4126     {
4127       aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
4128
4129       /* special cases :- */
4130       /* if both left & right are in bit space */
4131       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4132           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4133         {
4134           genMinusBits (ic);
4135           goto release;
4136         }
4137
4138       /* if I can do an decrement instead
4139          of subtract then GOOD for ME */
4140       if (genMinusDec (ic) == TRUE)
4141         goto release;
4142
4143     }
4144
4145   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4146
4147   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4148     {
4149       CLRC;
4150     }
4151   else
4152     {
4153       lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4154       lit = -(long) lit;
4155     }
4156
4157
4158   /* if literal, add a,#-lit, else normal subb */
4159   _startLazyDPSEvaluation ();
4160   while (size--) {
4161       MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
4162       if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
4163           if (AOP_USESDPTR(IC_RIGHT(ic))) {
4164               emitcode ("mov","b,a");
4165               MOVA(aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
4166               emitcode ("xch","a,b");
4167               emitcode ("subb","a,b");
4168           } else {
4169               emitcode ("subb", "a,%s",
4170                         aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
4171           }
4172       } else {
4173           /* first add without previous c */
4174           if (!offset) {
4175               if (!size && lit==-1) {
4176                   emitcode ("dec", "a");
4177               } else {
4178                   emitcode ("add", "a,#!constbyte",
4179                             (unsigned int) (lit & 0x0FFL));
4180               }
4181           } else {
4182               emitcode ("addc", "a,#!constbyte",
4183                         (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4184           }
4185       }
4186       
4187       if (pushResult) {
4188           emitcode ("push", "acc");
4189       } else {
4190           aopPut (AOP (IC_RESULT (ic)), "a", offset);
4191       }
4192       offset++;
4193   }
4194   _endLazyDPSEvaluation ();
4195   
4196   if (pushResult)
4197     {
4198       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4199
4200       size = getDataSize (IC_LEFT (ic));
4201       rSize = getDataSize (IC_RESULT (ic));
4202
4203       ADJUST_PUSHED_RESULT(size, rSize);
4204
4205       _startLazyDPSEvaluation ();
4206       while (size--)
4207         {
4208           emitcode ("pop", "acc");
4209           aopPut (AOP (IC_RESULT (ic)), "a", size);
4210         }
4211       _endLazyDPSEvaluation ();
4212     }
4213
4214   adjustArithmeticResult (ic);
4215
4216 release:
4217   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4218   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4219   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4220 }
4221
4222
4223 /*-----------------------------------------------------------------*/
4224 /* genMultbits :- multiplication of bits                           */
4225 /*-----------------------------------------------------------------*/
4226 static void
4227 genMultbits (operand * left,
4228              operand * right,
4229              operand * result,
4230              iCode   * ic)
4231 {
4232   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4233   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4234   aopOp(result, ic, TRUE, FALSE);
4235   outBitC (result);
4236 }
4237
4238
4239 /*-----------------------------------------------------------------*/
4240 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
4241 /*-----------------------------------------------------------------*/
4242 static void
4243 genMultOneByte (operand * left,
4244                 operand * right,
4245                 operand * result,
4246                 iCode   * ic)
4247 {
4248   sym_link *opetype = operandType (result);
4249   symbol *lbl;
4250
4251
4252   /* (if two literals: the value is computed before) */
4253   /* if one literal, literal on the right */
4254   if (AOP_TYPE (left) == AOP_LIT)
4255     {
4256       operand *t = right;
4257       right = left;
4258       left = t;
4259       emitcode (";", "swapped left and right");
4260     }
4261
4262   if (SPEC_USIGN(opetype)
4263       // ignore the sign of left and right, what else can we do?
4264       || (SPEC_USIGN(operandType(left)) && 
4265           SPEC_USIGN(operandType(right)))) {
4266     // just an unsigned 8*8=8/16 multiply
4267     //emitcode (";","unsigned");
4268     emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4269     MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4270     emitcode ("mul", "ab");
4271    
4272     _G.accInUse++; _G.bInUse++;
4273     aopOp(result, ic, TRUE, FALSE);
4274       
4275       if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4276       {
4277           // this should never happen
4278           fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4279                    AOP_SIZE(result), __FILE__, lineno);
4280           exit (1);
4281       }      
4282       
4283     aopPut (AOP (result), "a", 0);
4284     _G.accInUse--; _G.bInUse--;
4285     if (AOP_SIZE(result)==2) 
4286     {
4287       aopPut (AOP (result), "b", 1);
4288     }
4289     return;
4290   }
4291
4292   // we have to do a signed multiply
4293
4294   emitcode (";", "signed");
4295   emitcode ("clr", "F0"); // reset sign flag
4296   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4297
4298   lbl=newiTempLabel(NULL);
4299   emitcode ("jnb", "acc.7,!tlabel",  lbl->key+100);
4300   // left side is negative, 8-bit two's complement, this fails for -128
4301   emitcode ("setb", "F0"); // set sign flag
4302   emitcode ("cpl", "a");
4303   emitcode ("inc", "a");
4304
4305   emitcode ("", "!tlabeldef", lbl->key+100);
4306
4307   /* if literal */
4308   if (AOP_TYPE(right)==AOP_LIT) {
4309     signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
4310     /* AND literal negative */
4311     if ((int) val < 0) {
4312       emitcode ("cpl", "F0"); // complement sign flag
4313       emitcode ("mov", "b,#!constbyte", -val);
4314     } else {
4315       emitcode ("mov", "b,#!constbyte", val);
4316     }
4317   } else {
4318     lbl=newiTempLabel(NULL);
4319     emitcode ("mov", "b,a");
4320     emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4321     emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4322     // right side is negative, 8-bit two's complement
4323     emitcode ("cpl", "F0"); // complement sign flag
4324     emitcode ("cpl", "a");
4325     emitcode ("inc", "a");
4326     emitcode ("", "!tlabeldef", lbl->key+100);
4327   }
4328   emitcode ("mul", "ab");
4329     
4330   _G.accInUse++;_G.bInUse++;
4331   aopOp(result, ic, TRUE, FALSE);
4332     
4333   if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4334   {
4335     // this should never happen
4336       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4337                AOP_SIZE(result), __FILE__, lineno);
4338       exit (1);
4339   }    
4340     
4341   lbl=newiTempLabel(NULL);
4342   emitcode ("jnb", "F0,!tlabel", lbl->key+100);
4343   // only ONE op was negative, we have to do a 8/16-bit two's complement
4344   emitcode ("cpl", "a"); // lsb
4345   if (AOP_SIZE(result)==1) {
4346     emitcode ("inc", "a");
4347   } else {
4348     emitcode ("add", "a,#1");
4349     emitcode ("xch", "a,b");
4350     emitcode ("cpl", "a"); // msb
4351     emitcode ("addc", "a,#0");
4352     emitcode ("xch", "a,b");
4353   }
4354
4355   emitcode ("", "!tlabeldef", lbl->key+100);
4356   aopPut (AOP (result), "a", 0);
4357   _G.accInUse--;_G.bInUse--;
4358   if (AOP_SIZE(result)==2) {
4359     aopPut (AOP (result), "b", 1);
4360   }
4361 }
4362
4363 /*-----------------------------------------------------------------*/
4364 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply    */
4365 /*-----------------------------------------------------------------*/
4366 static void genMultTwoByte (operand *left, operand *right, 
4367                             operand *result, iCode *ic)
4368 {
4369         sym_link *retype = getSpec(operandType(right));
4370         sym_link *letype = getSpec(operandType(left));
4371         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4372         symbol *lbl;
4373
4374         if (AOP_TYPE (left) == AOP_LIT) {
4375                 operand *t = right;
4376                 right = left;
4377                 left = t;
4378         }
4379         /* save EA bit in F1 */
4380         lbl = newiTempLabel(NULL);
4381         emitcode ("setb","F1");
4382         emitcode ("jbc","EA,!tlabel",lbl->key+100);
4383         emitcode ("clr","F1");
4384         emitcode("","!tlabeldef",lbl->key+100);
4385
4386         /* load up MB with right */
4387         if (!umult) {
4388                 emitcode("clr","F0");
4389                 if (AOP_TYPE(right) == AOP_LIT) {
4390                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
4391                         if (val < 0) {
4392                                 emitcode("setb","F0");
4393                                 val = -val;
4394                         }
4395                         emitcode ("mov","mb,#!constbyte",val & 0xff);
4396                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
4397                 } else {
4398                         lbl = newiTempLabel(NULL);
4399                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4400                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4401                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
4402                         emitcode ("xch", "a,b");
4403                         emitcode ("cpl","a");
4404                         emitcode ("add", "a,#1");
4405                         emitcode ("xch", "a,b");
4406                         emitcode ("cpl", "a"); // msb
4407                         emitcode ("addc", "a,#0");
4408                         emitcode ("setb","F0");
4409                         emitcode ("","!tlabeldef",lbl->key+100);
4410                         emitcode ("mov","mb,b");
4411                         emitcode ("mov","mb,a");
4412                 }
4413         } else {
4414                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4415                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4416         }
4417         /* load up MA with left */
4418         if (!umult) {
4419                 lbl = newiTempLabel(NULL);
4420                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4421                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4422                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4423                 emitcode ("xch", "a,b");
4424                 emitcode ("cpl","a");
4425                 emitcode ("add", "a,#1");
4426                 emitcode ("xch", "a,b");
4427                 emitcode ("cpl", "a"); // msb
4428                 emitcode ("addc","a,#0");
4429                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4430                 emitcode ("setb","F0");
4431                 emitcode ("","!tlabeldef",lbl->key+100);
4432                 emitcode ("mov","ma,b");
4433                 emitcode ("mov","ma,a");
4434         } else {
4435                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4436                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4437         }
4438         /* wait for multiplication to finish */
4439         lbl = newiTempLabel(NULL);
4440         emitcode("","!tlabeldef", lbl->key+100);
4441         emitcode("mov","a,mcnt1");
4442         emitcode("anl","a,#!constbyte",0x80);
4443         emitcode("jnz","!tlabel",lbl->key+100);
4444         
4445         freeAsmop (left, NULL, ic, TRUE);
4446         freeAsmop (right, NULL, ic,TRUE);
4447         aopOp(result, ic, TRUE, FALSE);
4448
4449         /* if unsigned then simple */   
4450         if (umult) {
4451                 emitcode ("mov","a,ma");
4452                 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4453                 emitcode ("mov","a,ma");
4454                 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4455                 aopPut(AOP(result),"ma",1);
4456                 aopPut(AOP(result),"ma",0);
4457         } else {
4458                 emitcode("push","ma");
4459                 emitcode("push","ma");
4460                 emitcode("push","ma");
4461                 MOVA("ma");
4462                 /* negate result if needed */
4463                 lbl = newiTempLabel(NULL);      
4464                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4465                 emitcode("cpl","a");
4466                 emitcode("add","a,#1");
4467                 emitcode("","!tlabeldef", lbl->key+100);
4468                 if (AOP_TYPE(result) == AOP_ACC)
4469                 {
4470                     D(emitcode(";", "ACC special case."););
4471                     /* We know result is the only live aop, and 
4472                      * it's obviously not a DPTR2, so AP is available.
4473                      */
4474                     emitcode("mov", "%s,acc", DP2_RESULT_REG);
4475                 }
4476                 else
4477                 {
4478                     aopPut(AOP(result),"a",0);
4479                 }
4480             
4481                 emitcode("pop","acc");
4482                 lbl = newiTempLabel(NULL);      
4483                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4484                 emitcode("cpl","a");
4485                 emitcode("addc","a,#0");
4486                 emitcode("","!tlabeldef", lbl->key+100);
4487                 aopPut(AOP(result),"a",1);
4488                 emitcode("pop","acc");
4489                 if (AOP_SIZE(result) >= 3) {
4490                         lbl = newiTempLabel(NULL);      
4491                         emitcode("jnb","F0,!tlabel",lbl->key+100);
4492                         emitcode("cpl","a");
4493                         emitcode("addc","a,#0");                        
4494                         emitcode("","!tlabeldef", lbl->key+100);
4495                         aopPut(AOP(result),"a",2);
4496                 }
4497                 emitcode("pop","acc");
4498                 if (AOP_SIZE(result) >= 4) {
4499                         lbl = newiTempLabel(NULL);      
4500                         emitcode("jnb","F0,!tlabel",lbl->key+100);
4501                         emitcode("cpl","a");
4502                         emitcode("addc","a,#0");                        
4503                         emitcode("","!tlabeldef", lbl->key+100);
4504                         aopPut(AOP(result),"a",3);
4505                 }
4506                 if (AOP_TYPE(result) == AOP_ACC)
4507                 {
4508                     /* We stashed the result away above. */
4509                     emitcode("mov", "acc,%s", DP2_RESULT_REG);
4510                 }           
4511                 
4512         }
4513         freeAsmop (result, NULL, ic, TRUE);
4514
4515         /* restore EA bit in F1 */
4516         lbl = newiTempLabel(NULL);
4517         emitcode ("jnb","F1,!tlabel",lbl->key+100);
4518         emitcode ("setb","EA");
4519         emitcode("","!tlabeldef",lbl->key+100);
4520         return ;
4521 }
4522
4523 /*-----------------------------------------------------------------*/
4524 /* genMult - generates code for multiplication                     */
4525 /*-----------------------------------------------------------------*/
4526 static void
4527 genMult (iCode * ic)
4528 {
4529   operand *left = IC_LEFT (ic);
4530   operand *right = IC_RIGHT (ic);
4531   operand *result = IC_RESULT (ic);
4532
4533   D (emitcode (";", "genMult "););
4534
4535   /* assign the amsops */
4536   AOP_OP_2 (ic);
4537
4538   /* special cases first */
4539   /* both are bits */
4540   if (AOP_TYPE (left) == AOP_CRY &&
4541       AOP_TYPE (right) == AOP_CRY)
4542     {
4543       genMultbits (left, right, result, ic);
4544       goto release;
4545     }
4546
4547   /* if both are of size == 1 */
4548   if (AOP_SIZE (left) == 1 &&
4549       AOP_SIZE (right) == 1)
4550     {
4551       genMultOneByte (left, right, result, ic);
4552       goto release;
4553     }
4554
4555   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4556           /* use the ds390 ARITHMETIC accel UNIT */
4557           genMultTwoByte (left, right, result, ic);
4558           return ;
4559   }
4560   /* should have been converted to function call */
4561   assert (0);
4562
4563 release:
4564   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4565   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4566   freeAsmop (result, NULL, ic, TRUE);
4567 }
4568
4569 /*-----------------------------------------------------------------*/
4570 /* genDivbits :- division of bits                                  */
4571 /*-----------------------------------------------------------------*/
4572 static void
4573 genDivbits (operand * left,
4574             operand * right,
4575             operand * result,
4576             iCode   * ic)
4577 {
4578
4579   char *l;
4580
4581   /* the result must be bit */
4582   LOAD_AB_FOR_DIV (left, right, l);
4583   emitcode ("div", "ab");
4584   emitcode ("rrc", "a");
4585   aopOp(result, ic, TRUE, FALSE);
4586     
4587   aopPut (AOP (result), "c", 0);
4588 }
4589
4590 /*-----------------------------------------------------------------*/
4591 /* genDivOneByte : 8 bit division                                  */
4592 /*-----------------------------------------------------------------*/
4593 static void
4594 genDivOneByte (operand * left,
4595                operand * right,
4596                operand * result,
4597                iCode   * ic)
4598 {
4599   sym_link *opetype = operandType (result);
4600   char *l;
4601   symbol *lbl;
4602   int size, offset;
4603
4604   offset = 1;
4605   /* signed or unsigned */
4606   if (SPEC_USIGN (opetype))
4607     {
4608         /* unsigned is easy */
4609         LOAD_AB_FOR_DIV (left, right, l);
4610         emitcode ("div", "ab");
4611
4612         _G.accInUse++;
4613         aopOp(result, ic, TRUE, FALSE);
4614         aopPut (AOP (result), "a", 0);
4615         _G.accInUse--;
4616
4617         size = AOP_SIZE (result) - 1;
4618         
4619         while (size--)
4620         {
4621             aopPut (AOP (result), zero, offset++);
4622         }
4623       return;
4624     }
4625
4626   /* signed is a little bit more difficult */
4627
4628   /* save the signs of the operands */
4629   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4630   MOVA (l);
4631   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4632   emitcode ("push", "acc");     /* save it on the stack */
4633
4634   /* now sign adjust for both left & right */
4635   l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4636   MOVA (l);
4637   lbl = newiTempLabel (NULL);
4638   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4639   emitcode ("cpl", "a");
4640   emitcode ("inc", "a");
4641   emitcode ("", "!tlabeldef", (lbl->key + 100));
4642   emitcode ("mov", "b,a");
4643
4644   /* sign adjust left side */
4645   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4646   MOVA (l);
4647
4648   lbl = newiTempLabel (NULL);
4649   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4650   emitcode ("cpl", "a");
4651   emitcode ("inc", "a");
4652   emitcode ("", "!tlabeldef", (lbl->key + 100));
4653
4654   /* now the division */
4655   emitcode ("nop", "; workaround for DS80C390 div bug.");
4656   emitcode ("div", "ab");
4657   /* we are interested in the lower order
4658      only */
4659   emitcode ("mov", "b,a");
4660   lbl = newiTempLabel (NULL);
4661   emitcode ("pop", "acc");
4662   /* if there was an over flow we don't
4663      adjust the sign of the result */
4664   emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4665   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4666   CLRC;
4667   emitcode ("clr", "a");
4668   emitcode ("subb", "a,b");
4669   emitcode ("mov", "b,a");
4670   emitcode ("", "!tlabeldef", (lbl->key + 100));
4671
4672   /* now we are done */
4673   _G.accInUse++;     _G.bInUse++;
4674     aopOp(result, ic, TRUE, FALSE);
4675     
4676     aopPut (AOP (result), "b", 0);
4677     
4678     size = AOP_SIZE (result) - 1;
4679     
4680     if (size > 0)
4681     {
4682       emitcode ("mov", "c,b.7");
4683       emitcode ("subb", "a,acc");
4684     }
4685     while (size--)
4686     {
4687         aopPut (AOP (result), "a", offset++);
4688     }
4689     _G.accInUse--;     _G.bInUse--;
4690
4691 }
4692
4693 /*-----------------------------------------------------------------*/
4694 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide       */
4695 /*-----------------------------------------------------------------*/
4696 static void genDivTwoByte (operand *left, operand *right, 
4697                             operand *result, iCode *ic)
4698 {
4699         sym_link *retype = getSpec(operandType(right));
4700         sym_link *letype = getSpec(operandType(left));
4701         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4702         symbol *lbl;
4703
4704         /* save EA bit in F1 */
4705         lbl = newiTempLabel(NULL);
4706         emitcode ("setb","F1");
4707         emitcode ("jbc","EA,!tlabel",lbl->key+100);
4708         emitcode ("clr","F1");
4709         emitcode("","!tlabeldef",lbl->key+100);
4710
4711         /* load up MA with left */
4712         if (!umult) {
4713                 emitcode("clr","F0");
4714                 lbl = newiTempLabel(NULL);
4715                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4716                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4717                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4718                 emitcode ("xch", "a,b");
4719                 emitcode ("cpl","a");
4720                 emitcode ("add", "a,#1");
4721                 emitcode ("xch", "a,b");
4722                 emitcode ("cpl", "a"); // msb
4723                 emitcode ("addc","a,#0");
4724                 emitcode ("setb","F0");
4725                 emitcode ("","!tlabeldef",lbl->key+100);
4726                 emitcode ("mov","ma,b");
4727                 emitcode ("mov","ma,a");
4728         } else {
4729                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4730                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4731         }
4732
4733         /* load up MB with right */
4734         if (!umult) {
4735                 if (AOP_TYPE(right) == AOP_LIT) {
4736                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
4737                         if (val < 0) {
4738                                 lbl = newiTempLabel(NULL);
4739                                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4740                                 emitcode("setb","F0");
4741                                 emitcode ("","!tlabeldef",lbl->key+100);
4742                                 val = -val;
4743                         } 
4744                         emitcode ("mov","mb,#!constbyte",val & 0xff);               
4745                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4746                 } else {
4747                         lbl = newiTempLabel(NULL);
4748                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4749                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4750                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
4751                         emitcode ("xch", "a,b");
4752                         emitcode ("cpl","a");
4753                         emitcode ("add", "a,#1");
4754                         emitcode ("xch", "a,b");
4755                         emitcode ("cpl", "a"); // msb
4756                         emitcode ("addc", "a,#0");
4757                         emitcode ("jbc","F0,!tlabel",lbl->key+100);
4758                         emitcode ("setb","F0");
4759                         emitcode ("","!tlabeldef",lbl->key+100);
4760                         emitcode ("mov","mb,b");
4761                         emitcode ("mov","mb,a");
4762                 }
4763         } else {
4764                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4765                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4766         }
4767
4768         /* wait for multiplication to finish */
4769         lbl = newiTempLabel(NULL);
4770         emitcode("","!tlabeldef", lbl->key+100);
4771         emitcode("mov","a,mcnt1");
4772         emitcode("anl","a,#!constbyte",0x80);
4773         emitcode("jnz","!tlabel",lbl->key+100);
4774         
4775         freeAsmop (left, NULL, ic, TRUE);
4776         freeAsmop (right, NULL, ic,TRUE);
4777         aopOp(result, ic, TRUE, FALSE);
4778
4779         /* if unsigned then simple */   
4780         if (umult) {
4781                 aopPut(AOP(result),"ma",1);
4782                 aopPut(AOP(result),"ma",0);
4783         } else {
4784                 emitcode("push","ma");
4785                 MOVA("ma");
4786                 /* negate result if needed */
4787                 lbl = newiTempLabel(NULL);      
4788                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4789                 emitcode("cpl","a");
4790                 emitcode("add","a,#1");
4791                 emitcode("","!tlabeldef", lbl->key+100);
4792                 aopPut(AOP(result),"a",0);
4793                 emitcode("pop","acc");
4794                 lbl = newiTempLabel(NULL);      
4795                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4796                 emitcode("cpl","a");
4797                 emitcode("addc","a,#0");
4798                 emitcode("","!tlabeldef", lbl->key+100);
4799                 aopPut(AOP(result),"a",1);
4800         }
4801         freeAsmop (result, NULL, ic, TRUE);
4802         /* restore EA bit in F1 */
4803         lbl = newiTempLabel(NULL);
4804         emitcode ("jnb","F1,!tlabel",lbl->key+100);
4805         emitcode ("setb","EA");
4806         emitcode("","!tlabeldef",lbl->key+100);
4807         return ;
4808 }
4809
4810 /*-----------------------------------------------------------------*/
4811 /* genDiv - generates code for division                            */
4812 /*-----------------------------------------------------------------*/
4813 static void
4814 genDiv (iCode * ic)
4815 {
4816   operand *left = IC_LEFT (ic);
4817   operand *right = IC_RIGHT (ic);
4818   operand *result = IC_RESULT (ic);
4819
4820   D (emitcode (";", "genDiv "););
4821
4822   /* assign the amsops */
4823   AOP_OP_2 (ic);
4824
4825   /* special cases first */
4826   /* both are bits */
4827   if (AOP_TYPE (left) == AOP_CRY &&
4828       AOP_TYPE (right) == AOP_CRY)
4829     {
4830       genDivbits (left, right, result, ic);
4831       goto release;
4832     }
4833
4834   /* if both are of size == 1 */
4835   if (AOP_SIZE (left) == 1 &&
4836       AOP_SIZE (right) == 1)
4837     {
4838       genDivOneByte (left, right, result, ic);
4839       goto release;
4840     }
4841
4842   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4843           /* use the ds390 ARITHMETIC accel UNIT */
4844           genDivTwoByte (left, right, result, ic);
4845           return ;
4846   }
4847   /* should have been converted to function call */
4848   assert (0);
4849 release:
4850   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4851   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4852   freeAsmop (result, NULL, ic, TRUE);
4853 }
4854
4855 /*-----------------------------------------------------------------*/
4856 /* genModbits :- modulus of bits                                   */
4857 /*-----------------------------------------------------------------*/
4858 static void
4859 genModbits (operand * left,
4860             operand * right,
4861             operand * result,
4862             iCode   * ic)
4863 {
4864
4865   char *l;
4866
4867   /* the result must be bit */
4868   LOAD_AB_FOR_DIV (left, right, l);
4869   emitcode ("div", "ab");
4870   emitcode ("mov", "a,b");
4871   emitcode ("rrc", "a");
4872   aopOp(result, ic, TRUE, FALSE);
4873   aopPut (AOP (result), "c", 0);
4874 }
4875
4876 /*-----------------------------------------------------------------*/
4877 /* genModOneByte : 8 bit modulus                                   */
4878 /*-----------------------------------------------------------------*/
4879 static void
4880 genModOneByte (operand * left,
4881                operand * right,
4882                operand * result,
4883                iCode   * ic)
4884 {
4885   sym_link *opetype = operandType (result);
4886   char *l;
4887   symbol *lbl;
4888
4889   /* signed or unsigned */
4890   if (SPEC_USIGN (opetype))
4891     {
4892       /* unsigned is easy */
4893       LOAD_AB_FOR_DIV (left, right, l);
4894       emitcode ("div", "ab");
4895       aopOp(result, ic, TRUE, FALSE);   
4896       aopPut (AOP (result), "b", 0);
4897       return;
4898     }
4899
4900   /* signed is a little bit more difficult */
4901
4902   /* save the signs of the operands */
4903   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4904   MOVA (l);
4905
4906   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4907   emitcode ("push", "acc");     /* save it on the stack */
4908
4909   /* now sign adjust for both left & right */
4910   l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4911   MOVA (l);
4912
4913   lbl = newiTempLabel (NULL);
4914   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4915   emitcode ("cpl", "a");
4916   emitcode ("inc", "a");
4917   emitcode ("", "!tlabeldef", (lbl->key + 100));
4918   emitcode ("mov", "b,a");
4919
4920   /* sign adjust left side */
4921   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4922   MOVA (l);
4923
4924   lbl = newiTempLabel (NULL);
4925   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4926   emitcode ("cpl", "a");
4927   emitcode ("inc", "a");
4928   emitcode ("", "!tlabeldef", (lbl->key + 100));
4929
4930   /* now the multiplication */
4931   emitcode ("nop", "; workaround for DS80C390 div bug.");
4932   emitcode ("div", "ab");
4933   /* we are interested in the lower order
4934      only */
4935   lbl = newiTempLabel (NULL);
4936   emitcode ("pop", "acc");
4937   /* if there was an over flow we don't
4938      adjust the sign of the result */
4939   emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4940   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4941   CLRC;
4942   emitcode ("clr", "a");
4943   emitcode ("subb", "a,b");
4944   emitcode ("mov", "b,a");
4945   emitcode ("", "!tlabeldef", (lbl->key + 100));
4946   
4947   _G.bInUse++;
4948   /* now we are done */
4949   aopOp(result, ic, TRUE, FALSE);    
4950   aopPut (AOP (result), "b", 0);
4951   _G.bInUse--;
4952
4953 }
4954
4955 /*-----------------------------------------------------------------*/
4956 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus      */
4957 /*-----------------------------------------------------------------*/
4958 static void genModTwoByte (operand *left, operand *right, 
4959                             operand *result, iCode *ic)
4960 {
4961         sym_link *retype = getSpec(operandType(right));
4962         sym_link *letype = getSpec(operandType(left));
4963         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4964         symbol *lbl;
4965
4966         /* load up MA with left */
4967         /* save EA bit in F1 */
4968         lbl = newiTempLabel(NULL);
4969         emitcode ("setb","F1");
4970         emitcode ("jbc","EA,!tlabel",lbl->key+100);
4971         emitcode ("clr","F1");
4972         emitcode("","!tlabeldef",lbl->key+100);
4973
4974         if (!umult) {
4975                 lbl = newiTempLabel(NULL);
4976                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4977                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4978                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4979                 emitcode ("xch", "a,b");
4980                 emitcode ("cpl","a");
4981                 emitcode ("add", "a,#1");
4982                 emitcode ("xch", "a,b");
4983                 emitcode ("cpl", "a"); // msb
4984                 emitcode ("addc","a,#0");
4985                 emitcode ("","!tlabeldef",lbl->key+100);
4986                 emitcode ("mov","ma,b");
4987                 emitcode ("mov","ma,a");
4988         } else {
4989                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4990                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4991         }
4992
4993         /* load up MB with right */
4994         if (!umult) {
4995                 if (AOP_TYPE(right) == AOP_LIT) {
4996                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
4997                         if (val < 0) {
4998                                 val = -val;
4999                         } 
5000                         emitcode ("mov","mb,#!constbyte",val & 0xff);
5001                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
5002                 } else {
5003                         lbl = newiTempLabel(NULL);
5004                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
5005                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
5006                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
5007                         emitcode ("xch", "a,b");
5008                         emitcode ("cpl","a");
5009                         emitcode ("add", "a,#1");
5010                         emitcode ("xch", "a,b");
5011                         emitcode ("cpl", "a"); // msb
5012                         emitcode ("addc", "a,#0");
5013                         emitcode ("","!tlabeldef",lbl->key+100);
5014                         emitcode ("mov","mb,b");
5015                         emitcode ("mov","mb,a");
5016                 }
5017         } else {
5018                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
5019                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
5020         }
5021
5022         /* wait for multiplication to finish */
5023         lbl = newiTempLabel(NULL);
5024         emitcode("","!tlabeldef", lbl->key+100);
5025         emitcode("mov","a,mcnt1");
5026         emitcode("anl","a,#!constbyte",0x80);
5027         emitcode("jnz","!tlabel",lbl->key+100);
5028         
5029         freeAsmop (left, NULL, ic, TRUE);
5030         freeAsmop (right, NULL, ic,TRUE);
5031         aopOp(result, ic, TRUE, FALSE);
5032
5033         aopPut(AOP(result),"mb",1);
5034         aopPut(AOP(result),"mb",0);
5035         freeAsmop (result, NULL, ic, TRUE);
5036
5037         /* restore EA bit in F1 */
5038         lbl = newiTempLabel(NULL);
5039         emitcode ("jnb","F1,!tlabel",lbl->key+100);
5040         emitcode ("setb","EA");
5041         emitcode("","!tlabeldef",lbl->key+100);
5042         return ;
5043 }
5044
5045 /*-----------------------------------------------------------------*/
5046 /* genMod - generates code for division                            */
5047 /*-----------------------------------------------------------------*/
5048 static void
5049 genMod (iCode * ic)
5050 {
5051   operand *left = IC_LEFT (ic);
5052   operand *right = IC_RIGHT (ic);
5053   operand *result = IC_RESULT (ic);
5054
5055   D (emitcode (";", "genMod "); );
5056
5057   /* assign the amsops */
5058   AOP_OP_2 (ic);
5059
5060   /* special cases first */
5061   /* both are bits */
5062   if (AOP_TYPE (left) == AOP_CRY &&
5063       AOP_TYPE (right) == AOP_CRY)
5064     {
5065       genModbits (left, right, result, ic);
5066       goto release;
5067     }
5068
5069   /* if both are of size == 1 */
5070   if (AOP_SIZE (left) == 1 &&
5071       AOP_SIZE (right) == 1)
5072     {
5073       genModOneByte (left, right, result, ic);
5074       goto release;
5075     }
5076
5077   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5078           /* use the ds390 ARITHMETIC accel UNIT */
5079           genModTwoByte (left, right, result, ic);
5080           return ;
5081   }
5082
5083   /* should have been converted to function call */
5084   assert (0);
5085
5086 release:
5087   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5088   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5089   freeAsmop (result, NULL, ic, TRUE);
5090 }
5091
5092 /*-----------------------------------------------------------------*/
5093 /* genIfxJump :- will create a jump depending on the ifx           */
5094 /*-----------------------------------------------------------------*/
5095 static void
5096 genIfxJump (iCode * ic, char *jval)
5097 {
5098   symbol *jlbl;
5099   symbol *tlbl = newiTempLabel (NULL);
5100   char *inst;
5101
5102   D (emitcode (";", "genIfxJump ");
5103     );
5104
5105   /* if true label then we jump if condition
5106      supplied is true */
5107   if (IC_TRUE (ic))
5108     {
5109       jlbl = IC_TRUE (ic);
5110       inst = ((strcmp (jval, "a") == 0 ? "jz" :
5111                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5112     }
5113   else
5114     {
5115       /* false label is present */
5116       jlbl = IC_FALSE (ic);
5117       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5118                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5119     }
5120   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5121     emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5122   else
5123     emitcode (inst, "!tlabel", tlbl->key + 100);
5124   emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5125   emitcode ("", "!tlabeldef", tlbl->key + 100);
5126
5127   /* mark the icode as generated */
5128   ic->generated = 1;
5129 }
5130
5131 /*-----------------------------------------------------------------*/
5132 /* genCmp :- greater or less than comparison                       */
5133 /*-----------------------------------------------------------------*/
5134 static void
5135 genCmp (operand * left, operand * right,
5136         iCode * ic, iCode * ifx, int sign)
5137 {
5138   int size, offset = 0;
5139   unsigned long lit = 0L;
5140   operand *result;
5141
5142   D (emitcode (";", "genCmp");
5143     );
5144
5145   result = IC_RESULT (ic);
5146
5147   /* if left & right are bit variables */
5148   if (AOP_TYPE (left) == AOP_CRY &&
5149       AOP_TYPE (right) == AOP_CRY)
5150     {
5151       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5152       emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
5153     }
5154   else
5155     {
5156       /* subtract right from left if at the
5157          end the carry flag is set then we know that
5158          left is greater than right */
5159       size = max (AOP_SIZE (left), AOP_SIZE (right));
5160
5161       /* if unsigned char cmp with lit, do cjne left,#right,zz */
5162       if ((size == 1) && !sign &&
5163           (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5164         {
5165           symbol *lbl = newiTempLabel (NULL);
5166           emitcode ("cjne", "%s,%s,!tlabel",
5167                     aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5168                     aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
5169                     lbl->key + 100);
5170           emitcode ("", "!tlabeldef", lbl->key + 100);
5171         }
5172       else
5173         {
5174           if (AOP_TYPE (right) == AOP_LIT)
5175             {
5176               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5177               /* optimize if(x < 0) or if(x >= 0) */
5178               if (lit == 0L)
5179                 {
5180                   if (!sign)
5181                     {
5182                       CLRC;
5183                     }
5184                   else
5185                     {
5186                       MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
5187
5188                       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5189                       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5190
5191                       aopOp (result, ic, FALSE, FALSE);
5192
5193                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5194                         {
5195                           freeAsmop (result, NULL, ic, TRUE);
5196                           genIfxJump (ifx, "acc.7");
5197                           return;
5198                         }
5199                       else
5200                         {
5201                           emitcode ("rlc", "a");
5202                         }
5203                       goto release_freedLR;
5204                     }
5205                   goto release;
5206                 }
5207             }
5208           CLRC;
5209           while (size--)
5210             {
5211               //emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5212               MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5213               //emitcode (";", "genCmp #2");
5214               if (sign && (size == 0))
5215                 {
5216                     //emitcode (";", "genCmp #3");
5217                   emitcode ("xrl", "a,#!constbyte",0x80);
5218                   if (AOP_TYPE (right) == AOP_LIT)
5219                     {
5220                       unsigned long lit = (unsigned long)
5221                       floatFromVal (AOP (right)->aopu.aop_lit);
5222                       //emitcode (";", "genCmp #3.1");
5223                       emitcode ("subb", "a,#!constbyte",
5224                                 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5225                     }
5226                   else
5227                     {
5228                       //emitcode (";", "genCmp #3.2");
5229                       if (AOP_NEEDSACC (right))
5230                         {
5231                           emitcode ("push", "acc");
5232                         }
5233                       emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
5234                                                        FALSE, FALSE, FALSE));
5235                       emitcode ("xrl", "b,#!constbyte",0x80);
5236                       if (AOP_NEEDSACC (right))
5237                         {
5238                           emitcode ("pop", "acc");
5239                         }
5240                       emitcode ("subb", "a,b");
5241                     }
5242                 }
5243               else
5244                 {
5245                   const char *s;
5246
5247                   //emitcode (";", "genCmp #4");
5248                   if (AOP_NEEDSACC (right))
5249                     {
5250                       /* Yuck!! */
5251                       //emitcode (";", "genCmp #4.1");
5252                       emitcode ("xch", "a, b");
5253                       MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
5254                       emitcode ("xch", "a, b");
5255                       s = "b";
5256                     }
5257                   else
5258                     {
5259                       //emitcode (";", "genCmp #4.2");
5260                       s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
5261                     }
5262
5263                   emitcode ("subb", "a,%s", s);
5264                 }
5265             }
5266         }
5267     }
5268
5269 release:
5270 /* Don't need the left & right operands any more; do need the result. */
5271   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5272   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5273
5274   aopOp (result, ic, FALSE, FALSE);
5275
5276 release_freedLR:
5277
5278   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5279     {
5280       outBitC (result);
5281     }
5282   else
5283     {
5284       /* if the result is used in the next
5285          ifx conditional branch then generate
5286          code a little differently */
5287       if (ifx)
5288         {
5289           genIfxJump (ifx, "c");
5290         }
5291       else
5292         {
5293           outBitC (result);
5294         }
5295       /* leave the result in acc */
5296     }
5297   freeAsmop (result, NULL, ic, TRUE);
5298 }
5299
5300 /*-----------------------------------------------------------------*/
5301 /* genCmpGt :- greater than comparison                             */
5302 /*-----------------------------------------------------------------*/
5303 static void
5304 genCmpGt (iCode * ic, iCode * ifx)
5305 {
5306   operand *left, *right;
5307   sym_link *letype, *retype;
5308   int sign;
5309
5310   D (emitcode (";", "genCmpGt ");
5311     );
5312
5313   left = IC_LEFT (ic);
5314   right = IC_RIGHT (ic);
5315
5316   letype = getSpec (operandType (left));
5317   retype = getSpec (operandType (right));
5318   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5319
5320   /* assign the left & right amsops */
5321   AOP_OP_2 (ic);
5322
5323   genCmp (right, left, ic, ifx, sign);
5324 }
5325
5326 /*-----------------------------------------------------------------*/
5327 /* genCmpLt - less than comparisons                                */
5328 /*-----------------------------------------------------------------*/
5329 static void
5330 genCmpLt (iCode * ic, iCode * ifx)
5331 {
5332   operand *left, *right;
5333   sym_link *letype, *retype;
5334   int sign;
5335
5336   D (emitcode (";", "genCmpLt "););
5337
5338   left = IC_LEFT (ic);
5339   right = IC_RIGHT (ic);
5340
5341   letype = getSpec (operandType (left));
5342   retype = getSpec (operandType (right));
5343   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5344
5345   /* assign the left & right amsops */
5346   AOP_OP_2 (ic);
5347
5348   genCmp (left, right, ic, ifx, sign);
5349 }
5350
5351 /*-----------------------------------------------------------------*/
5352 /* gencjneshort - compare and jump if not equal                    */
5353 /*-----------------------------------------------------------------*/
5354 static void
5355 gencjneshort (operand * left, operand * right, symbol * lbl)
5356 {
5357   int size = max (AOP_SIZE (left), AOP_SIZE (right));
5358   int offset = 0;
5359   unsigned long lit = 0L;
5360
5361   D (emitcode (";", "gencjneshort");
5362     );
5363
5364   /* if the left side is a literal or
5365      if the right is in a pointer register and left
5366      is not */
5367   if ((AOP_TYPE (left) == AOP_LIT) ||
5368       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5369     {
5370       operand *t = right;
5371       right = left;
5372       left = t;
5373     }
5374
5375   if (AOP_TYPE (right) == AOP_LIT)
5376     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5377
5378   if (opIsGptr (left) || opIsGptr (right))
5379     {
5380       /* We are comparing a generic pointer to something.
5381        * Exclude the generic type byte from the comparison.
5382        */
5383       size--;
5384       D (emitcode (";", "cjneshort: generic ptr special case.");
5385         )
5386     }
5387
5388
5389   /* if the right side is a literal then anything goes */
5390   if (AOP_TYPE (right) == AOP_LIT &&
5391       AOP_TYPE (left) != AOP_DIR)
5392     {
5393       while (size--)
5394         {
5395           char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5396           MOVA (l);
5397           emitcode ("cjne", "a,%s,!tlabel",
5398                     aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
5399                     lbl->key + 100);
5400           offset++;
5401         }
5402     }
5403
5404   /* if the right side is in a register or in direct space or
5405      if the left is a pointer register & right is not */
5406   else if (AOP_TYPE (right) == AOP_REG ||
5407            AOP_TYPE (right) == AOP_DIR ||
5408            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5409            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5410     {
5411       while (size--)
5412         {
5413           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5414           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5415               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5416             emitcode ("jnz", "!tlabel", lbl->key + 100);
5417           else
5418             emitcode ("cjne", "a,%s,!tlabel",
5419                       aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
5420                       lbl->key + 100);
5421           offset++;
5422         }
5423     }
5424   else
5425     {
5426       /* right is a pointer reg need both a & b */
5427       while (size--)
5428         {
5429           char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5430           if (strcmp (l, "b"))
5431             emitcode ("mov", "b,%s", l);
5432           MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5433           emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
5434           offset++;
5435         }
5436     }
5437 }
5438
5439 /*-----------------------------------------------------------------*/
5440 /* gencjne - compare and jump if not equal                         */
5441 /*-----------------------------------------------------------------*/
5442 static void
5443 gencjne (operand * left, operand * right, symbol * lbl)
5444 {
5445   symbol *tlbl = newiTempLabel (NULL);
5446
5447   D (emitcode (";", "gencjne");
5448     );
5449
5450   gencjneshort (left, right, lbl);
5451
5452   emitcode ("mov", "a,%s", one);
5453   emitcode ("sjmp", "!tlabel", tlbl->key + 100);
5454   emitcode ("", "!tlabeldef", lbl->key + 100);
5455   emitcode ("clr", "a");
5456   emitcode ("", "!tlabeldef", tlbl->key + 100);
5457 }
5458
5459 /*-----------------------------------------------------------------*/
5460 /* genCmpEq - generates code for equal to                          */
5461 /*-----------------------------------------------------------------*/
5462 static void
5463 genCmpEq (iCode * ic, iCode * ifx)
5464 {
5465   operand *left, *right, *result;
5466
5467   D (emitcode (";", "genCmpEq ");
5468     );
5469
5470   AOP_OP_2 (ic);
5471   AOP_SET_LOCALS (ic);
5472
5473   /* if literal, literal on the right or
5474      if the right is in a pointer register and left
5475      is not */
5476   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5477       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5478     {
5479       operand *t = IC_RIGHT (ic);
5480       IC_RIGHT (ic) = IC_LEFT (ic);
5481       IC_LEFT (ic) = t;
5482     }
5483
5484   if (ifx &&                    /* !AOP_SIZE(result) */
5485       OP_SYMBOL (result) &&
5486       OP_SYMBOL (result)->regType == REG_CND)
5487     {
5488       symbol *tlbl;
5489       /* if they are both bit variables */
5490       if (AOP_TYPE (left) == AOP_CRY &&
5491           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5492         {
5493           if (AOP_TYPE (right) == AOP_LIT)
5494             {
5495               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5496               if (lit == 0L)
5497                 {
5498                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5499                   emitcode ("cpl", "c");
5500                 }
5501               else if (lit == 1L)
5502                 {
5503                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5504                 }
5505               else
5506                 {
5507                   emitcode ("clr", "c");
5508                 }
5509               /* AOP_TYPE(right) == AOP_CRY */
5510             }
5511           else
5512             {
5513               symbol *lbl = newiTempLabel (NULL);
5514               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5515               emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5516               emitcode ("cpl", "c");
5517               emitcode ("", "!tlabeldef", (lbl->key + 100));
5518             }
5519           /* if true label then we jump if condition
5520              supplied is true */
5521           tlbl = newiTempLabel (NULL);
5522           if (IC_TRUE (ifx))
5523             {
5524               emitcode ("jnc", "!tlabel", tlbl->key + 100);
5525               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5526             }
5527           else
5528             {
5529               emitcode ("jc", "!tlabel", tlbl->key + 100);
5530               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5531             }
5532           emitcode ("", "!tlabeldef", tlbl->key + 100);
5533         }
5534       else
5535         {
5536           tlbl = newiTempLabel (NULL);
5537           gencjneshort (left, right, tlbl);
5538           if (IC_TRUE (ifx))
5539             {
5540               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5541               emitcode ("", "!tlabeldef", tlbl->key + 100);
5542             }
5543           else
5544             {
5545               symbol *lbl = newiTempLabel (NULL);
5546               emitcode ("sjmp", "!tlabel", lbl->key + 100);
5547               emitcode ("", "!tlabeldef", tlbl->key + 100);
5548               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5549               emitcode ("", "!tlabeldef", lbl->key + 100);
5550             }
5551         }
5552       /* mark the icode as generated */
5553       ifx->generated = 1;
5554
5555       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5556       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5557       return;
5558     }
5559
5560   /* if they are both bit variables */
5561   if (AOP_TYPE (left) == AOP_CRY &&
5562       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5563     {
5564       if (AOP_TYPE (right) == AOP_LIT)
5565         {
5566           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5567           if (lit == 0L)
5568             {
5569               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5570               emitcode ("cpl", "c");
5571             }
5572           else if (lit == 1L)
5573             {
5574               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5575             }
5576           else
5577             {
5578               emitcode ("clr", "c");
5579             }
5580           /* AOP_TYPE(right) == AOP_CRY */
5581         }
5582       else
5583         {
5584           symbol *lbl = newiTempLabel (NULL);
5585           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5586           emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5587           emitcode ("cpl", "c");
5588           emitcode ("", "!tlabeldef", (lbl->key + 100));
5589         }
5590
5591       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5592       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5593
5594       aopOp (result, ic, TRUE, FALSE);
5595
5596       /* c = 1 if egal */
5597       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5598         {
5599           outBitC (result);
5600           goto release;
5601         }
5602       if (ifx)
5603         {
5604           genIfxJump (ifx, "c");
5605           goto release;
5606         }
5607       /* if the result is used in an arithmetic operation
5608          then put the result in place */
5609       outBitC (result);
5610     }
5611   else
5612     {
5613       gencjne (left, right, newiTempLabel (NULL));
5614
5615       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5616       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5617
5618       aopOp (result, ic, TRUE, FALSE);
5619
5620       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5621         {
5622           aopPut (AOP (result), "a", 0);
5623           goto release;
5624         }
5625       if (ifx)
5626         {
5627           genIfxJump (ifx, "a");
5628           goto release;
5629         }
5630       /* if the result is used in an arithmetic operation
5631          then put the result in place */
5632       if (AOP_TYPE (result) != AOP_CRY)
5633         outAcc (result);
5634       /* leave the result in acc */
5635     }
5636
5637 release:
5638   freeAsmop (result, NULL, ic, TRUE);
5639 }
5640
5641 /*-----------------------------------------------------------------*/
5642 /* ifxForOp - returns the icode containing the ifx for operand     */
5643 /*-----------------------------------------------------------------*/
5644 static iCode *
5645 ifxForOp (operand * op, iCode * ic)
5646 {
5647   /* if true symbol then needs to be assigned */
5648   if (IS_TRUE_SYMOP (op))
5649     return NULL;
5650
5651   /* if this has register type condition and
5652      the next instruction is ifx with the same operand
5653      and live to of the operand is upto the ifx only then */
5654   if (ic->next &&
5655       ic->next->op == IFX &&
5656       IC_COND (ic->next)->key == op->key &&
5657       OP_SYMBOL (op)->liveTo <= ic->next->seq)
5658     return ic->next;
5659
5660   return NULL;
5661 }
5662 /*-----------------------------------------------------------------*/
5663 /* hasInc - operand is incremented before any other use            */
5664 /*-----------------------------------------------------------------*/
5665 static iCode *
5666 hasInc (operand *op, iCode *ic, int osize)
5667 {
5668   sym_link *type = operandType(op);
5669   sym_link *retype = getSpec (type);
5670   iCode *lic = ic->next;
5671   int isize ;
5672   
5673   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5674   if (!IS_SYMOP(op)) return NULL;
5675
5676   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5677   if (IS_AGGREGATE(type->next)) return NULL;
5678   if (osize != (isize = getSize(type->next))) return NULL;
5679
5680   while (lic) {
5681       /* if operand of the form op = op + <sizeof *op> */
5682       if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5683           isOperandEqual(IC_RESULT(lic),op) && 
5684           isOperandLiteral(IC_RIGHT(lic)) &&
5685           operandLitValue(IC_RIGHT(lic)) == isize) {
5686           return lic;
5687       }
5688       /* if the operand used or deffed */
5689       if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5690           return NULL;
5691       }
5692       /* if GOTO or IFX */
5693       if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5694       lic = lic->next;
5695   }
5696   return NULL;
5697 }
5698
5699 /*-----------------------------------------------------------------*/
5700 /* genAndOp - for && operation                                     */
5701 /*-----------------------------------------------------------------*/
5702 static void
5703 genAndOp (iCode * ic)
5704 {
5705   operand *left, *right, *result;
5706   symbol *tlbl;
5707
5708   D (emitcode (";", "genAndOp "););
5709
5710   /* note here that && operations that are in an
5711      if statement are taken away by backPatchLabels
5712      only those used in arthmetic operations remain */
5713   AOP_OP_2 (ic);
5714   AOP_SET_LOCALS (ic);
5715
5716   /* if both are bit variables */
5717   if (AOP_TYPE (left) == AOP_CRY &&
5718       AOP_TYPE (right) == AOP_CRY)
5719     {
5720       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5721       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5722       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5723       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5724   
5725       aopOp (result,ic,FALSE, FALSE);
5726       outBitC (result);
5727     }
5728   else
5729     {
5730       tlbl = newiTempLabel (NULL);
5731       toBoolean (left);
5732       emitcode ("jz", "!tlabel", tlbl->key + 100);
5733       toBoolean (right);
5734       emitcode ("", "!tlabeldef", tlbl->key + 100);
5735       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5736       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5737   
5738       aopOp (result,ic,FALSE, FALSE);
5739       outBitAcc (result);
5740     }
5741     freeAsmop (result, NULL, ic, TRUE);
5742 }
5743
5744
5745 /*-----------------------------------------------------------------*/
5746 /* genOrOp - for || operation                                      */
5747 /*-----------------------------------------------------------------*/
5748 static void
5749 genOrOp (iCode * ic)
5750 {
5751   operand *left, *right, *result;
5752   symbol *tlbl;
5753
5754   D (emitcode (";", "genOrOp "););
5755
5756   /* note here that || operations that are in an
5757      if statement are taken away by backPatchLabels
5758      only those used in arthmetic operations remain */
5759   AOP_OP_2 (ic);
5760   AOP_SET_LOCALS (ic);
5761
5762   /* if both are bit variables */
5763   if (AOP_TYPE (left) == AOP_CRY &&
5764       AOP_TYPE (right) == AOP_CRY)
5765     {
5766       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5767       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5768       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5769       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5770   
5771       aopOp (result,ic,FALSE, FALSE);
5772       
5773       outBitC (result);
5774     }
5775   else
5776     {
5777       tlbl = newiTempLabel (NULL);
5778       toBoolean (left);
5779       emitcode ("jnz", "!tlabel", tlbl->key + 100);
5780       toBoolean (right);
5781       emitcode ("", "!tlabeldef", tlbl->key + 100);
5782       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5783       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5784   
5785       aopOp (result,ic,FALSE, FALSE);
5786       
5787       outBitAcc (result);
5788     }
5789
5790   freeAsmop (result, NULL, ic, TRUE);
5791 }
5792
5793 /*-----------------------------------------------------------------*/
5794 /* isLiteralBit - test if lit == 2^n                               */
5795 /*-----------------------------------------------------------------*/
5796 static int
5797 isLiteralBit (unsigned long lit)
5798 {
5799   unsigned long pw[32] =
5800   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5801    0x100L, 0x200L, 0x400L, 0x800L,
5802    0x1000L, 0x2000L, 0x4000L, 0x8000L,
5803    0x10000L, 0x20000L, 0x40000L, 0x80000L,
5804    0x100000L, 0x200000L, 0x400000L, 0x800000L,
5805    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5806    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5807   int idx;
5808
5809   for (idx = 0; idx < 32; idx++)
5810     if (lit == pw[idx])
5811       return idx + 1;
5812   return 0;
5813 }
5814
5815 /*-----------------------------------------------------------------*/
5816 /* continueIfTrue -                                                */
5817 /*-----------------------------------------------------------------*/
5818 static void
5819 continueIfTrue (iCode * ic)
5820 {
5821   if (IC_TRUE (ic))
5822     emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
5823   ic->generated = 1;
5824 }
5825
5826 /*-----------------------------------------------------------------*/
5827 /* jmpIfTrue -                                                     */
5828 /*-----------------------------------------------------------------*/
5829 static void
5830 jumpIfTrue (iCode * ic)
5831 {
5832   if (!IC_TRUE (ic))
5833     emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
5834   ic->generated = 1;
5835 }
5836
5837 /*-----------------------------------------------------------------*/
5838 /* jmpTrueOrFalse -                                                */
5839 /*-----------------------------------------------------------------*/
5840 static void
5841 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
5842 {
5843   // ugly but optimized by peephole
5844   if (IC_TRUE (ic))
5845     {
5846       symbol *nlbl = newiTempLabel (NULL);
5847       emitcode ("sjmp", "!tlabel", nlbl->key + 100);
5848       emitcode ("", "!tlabeldef", tlbl->key + 100);
5849       emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
5850       emitcode ("", "!tlabeldef", nlbl->key + 100);
5851     }
5852   else
5853     {
5854       emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
5855       emitcode ("", "!tlabeldef", tlbl->key + 100);
5856     }
5857   ic->generated = 1;
5858 }
5859
5860 // Generate code to perform a bit-wise logic operation
5861 // on two operands in far space (assumed to already have been 
5862 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
5863 // in far space. This requires pushing the result on the stack
5864 // then popping it into the result.
5865 static void
5866 genFarFarLogicOp(iCode *ic, char *logicOp)
5867 {
5868       int size, resultSize, compSize;
5869       int offset = 0;
5870       
5871       TR_AP("#5");
5872       D(emitcode(";", "%s special case for 3 far operands.", logicOp););
5873       compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ? 
5874                   AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
5875       
5876       _startLazyDPSEvaluation();
5877       for (size = compSize; (size--); offset++)
5878       {
5879           MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
5880           emitcode ("mov", "%s, acc", DP2_RESULT_REG);
5881           MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
5882           
5883           emitcode (logicOp, "a,%s", DP2_RESULT_REG);
5884           emitcode ("push", "acc");
5885       }
5886       _endLazyDPSEvaluation();
5887      
5888       freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5889       freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5890       aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
5891      
5892       resultSize = AOP_SIZE(IC_RESULT(ic));
5893
5894       ADJUST_PUSHED_RESULT(compSize, resultSize);
5895
5896       _startLazyDPSEvaluation();
5897       while (compSize--)
5898       {
5899           emitcode ("pop", "acc");
5900           aopPut (AOP (IC_RESULT (ic)), "a", compSize);
5901       }
5902       _endLazyDPSEvaluation();
5903       freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
5904 }
5905
5906
5907 /*-----------------------------------------------------------------*/
5908 /* genAnd  - code for and                                          */
5909 /*-----------------------------------------------------------------*/
5910 static void
5911 genAnd (iCode * ic, iCode * ifx)
5912 {
5913   operand *left, *right, *result;
5914   int size, offset = 0;
5915   unsigned long lit = 0L;
5916   int bytelit = 0;
5917   char buffer[10];
5918   bool pushResult;
5919
5920   D (emitcode (";", "genAnd "););
5921
5922   AOP_OP_3_NOFATAL (ic, pushResult);
5923   AOP_SET_LOCALS (ic);
5924
5925   if (pushResult)
5926   {
5927       genFarFarLogicOp(ic, "anl");
5928       return;
5929   }  
5930
5931 #ifdef DEBUG_TYPE
5932   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5933             AOP_TYPE (result),
5934             AOP_TYPE (left), AOP_TYPE (right));
5935   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5936             AOP_SIZE (result),
5937             AOP_SIZE (left), AOP_SIZE (right));
5938 #endif
5939
5940   /* if left is a literal & right is not then exchange them */
5941   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5942 #ifdef LOGIC_OPS_BROKEN      
5943     ||  AOP_NEEDSACC (left)
5944 #endif
5945     )
5946     {
5947       operand *tmp = right;
5948       right = left;
5949       left = tmp;
5950     }
5951
5952   /* if result = right then exchange them */
5953   if (sameRegs (AOP (result), AOP (right)))
5954     {
5955       operand *tmp = right;
5956       right = left;
5957       left = tmp;
5958     }
5959
5960   /* if right is bit then exchange them */
5961   if (AOP_TYPE (right) == AOP_CRY &&
5962       AOP_TYPE (left) != AOP_CRY)
5963     {
5964       operand *tmp = right;
5965       right = left;
5966       left = tmp;
5967     }
5968   if (AOP_TYPE (right) == AOP_LIT)
5969     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5970
5971   size = AOP_SIZE (result);
5972
5973   // if(bit & yy)
5974   // result = bit & yy;
5975   if (AOP_TYPE (left) == AOP_CRY)
5976     {
5977       // c = bit & literal;
5978       if (AOP_TYPE (right) == AOP_LIT)
5979         {
5980           if (lit & 1)
5981             {
5982               if (size && sameRegs (AOP (result), AOP (left)))
5983                 // no change
5984                 goto release;
5985               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5986             }
5987           else
5988             {
5989               // bit(result) = 0;
5990               if (size && (AOP_TYPE (result) == AOP_CRY))
5991                 {
5992                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5993                   goto release;
5994                 }
5995               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5996                 {
5997                   jumpIfTrue (ifx);
5998                   goto release;
5999                 }
6000               emitcode ("clr", "c");
6001             }
6002         }
6003       else
6004         {
6005           if (AOP_TYPE (right) == AOP_CRY)
6006             {
6007               // c = bit & bit;
6008               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6009               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6010             }
6011           else
6012             {
6013               // c = bit & val;
6014               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
6015               // c = lsb
6016               emitcode ("rrc", "a");
6017               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6018             }
6019         }
6020       // bit = c
6021       // val = c
6022       if (size)
6023         outBitC (result);
6024       // if(bit & ...)
6025       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6026         genIfxJump (ifx, "c");
6027       goto release;
6028     }
6029
6030   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6031   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6032   if ((AOP_TYPE (right) == AOP_LIT) &&
6033       (AOP_TYPE (result) == AOP_CRY) &&
6034       (AOP_TYPE (left) != AOP_CRY))
6035     {
6036       int posbit = isLiteralBit (lit);
6037       /* left &  2^n */
6038       if (posbit)
6039         {
6040           posbit--;
6041           MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
6042           // bit = left & 2^n
6043           if (size)
6044             emitcode ("mov", "c,acc.%d", posbit & 0x07);
6045           // if(left &  2^n)
6046           else
6047             {
6048               if (ifx)
6049                 {
6050                   sprintf (buffer, "acc.%d", posbit & 0x07);
6051                   genIfxJump (ifx, buffer);
6052                 }
6053               else 
6054                   {
6055                       emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6056                   }
6057               goto release;
6058             }
6059         }
6060       else
6061         {
6062           symbol *tlbl = newiTempLabel (NULL);
6063           int sizel = AOP_SIZE (left);
6064           if (size)
6065             emitcode ("setb", "c");
6066           while (sizel--)
6067             {
6068               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6069                 {
6070                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6071                   // byte ==  2^n ?
6072                   if ((posbit = isLiteralBit (bytelit)) != 0)
6073                     emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
6074                   else
6075                     {
6076                       if (bytelit != 0x0FFL)
6077                         emitcode ("anl", "a,%s",
6078                           aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
6079                       emitcode ("jnz", "!tlabel", tlbl->key + 100);
6080                     }
6081                 }
6082               offset++;
6083             }
6084           // bit = left & literal
6085           if (size)
6086             {
6087               emitcode ("clr", "c");
6088               emitcode ("", "!tlabeldef", tlbl->key + 100);
6089             }
6090           // if(left & literal)
6091           else
6092             {
6093               if (ifx)
6094                 jmpTrueOrFalse (ifx, tlbl);
6095               goto release;
6096             }
6097         }
6098       outBitC (result);
6099       goto release;
6100     }
6101
6102   /* if left is same as result */
6103   if (sameRegs (AOP (result), AOP (left)))
6104     {
6105       for (; size--; offset++)
6106         {
6107           if (AOP_TYPE (right) == AOP_LIT)
6108             {
6109               if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6110                 continue;
6111               else if (bytelit == 0)
6112                 aopPut (AOP (result), zero, offset);
6113               else if (IS_AOP_PREG (result))
6114                 {
6115                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6116                   emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6117                   aopPut (AOP (result), "a", offset);
6118                 }
6119               else
6120                 emitcode ("anl", "%s,%s",
6121                           aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6122                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6123             }
6124           else
6125             {
6126               if (AOP_TYPE (left) == AOP_ACC)
6127                 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6128               else
6129                 {
6130                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6131                   if (IS_AOP_PREG (result))
6132                     {
6133                       emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6134                       aopPut (AOP (result), "a", offset);
6135
6136                     }
6137                   else
6138                     emitcode ("anl", "%s,a",
6139                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6140                 }
6141             }
6142         }
6143     }
6144   else
6145     {
6146       // left & result in different registers
6147       if (AOP_TYPE (result) == AOP_CRY)
6148         {
6149           // result = bit
6150           // if(size), result in bit
6151           // if(!size && ifx), conditional oper: if(left & right)
6152           symbol *tlbl = newiTempLabel (NULL);
6153           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6154           if (size)
6155             emitcode ("setb", "c");
6156           while (sizer--)
6157             {
6158               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6159                 emitcode ("anl", "a,%s",
6160                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6161               } else {
6162                 if (AOP_TYPE(left)==AOP_ACC) {
6163                   emitcode("mov", "b,a");
6164                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6165                   emitcode("anl", "a,b");
6166                 }else {
6167                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6168                   emitcode ("anl", "a,%s",
6169                             aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6170                 }
6171               }
6172               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6173               offset++;
6174             }
6175           if (size)
6176             {
6177               CLRC;
6178               emitcode ("", "!tlabeldef", tlbl->key + 100);
6179               outBitC (result);
6180             }
6181           else if (ifx)
6182             jmpTrueOrFalse (ifx, tlbl);
6183         }
6184       else
6185         {
6186           for (; (size--); offset++)
6187             {
6188               // normal case
6189               // result = left & right
6190               if (AOP_TYPE (right) == AOP_LIT)
6191                 {
6192                   if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6193                     {
6194                       aopPut (AOP (result),
6195                            aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6196                               offset);
6197                       continue;
6198                     }
6199                   else if (bytelit == 0)
6200                     {
6201                       aopPut (AOP (result), zero, offset);
6202                       continue;
6203                     }
6204                   D (emitcode (";", "better literal AND."););
6205                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6206                   emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6207                                                     FALSE, FALSE, FALSE));
6208
6209                 }
6210               else
6211                 {
6212                   // faster than result <- left, anl result,right
6213                   // and better if result is SFR
6214                   if (AOP_TYPE (left) == AOP_ACC)
6215                     {
6216                       emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
6217                                                        FALSE, FALSE, FALSE));
6218                     }
6219                   else
6220                     {
6221                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6222                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6223                       {
6224                           emitcode("mov", "b,a");
6225                           rOp = "b";
6226                       }
6227                         
6228                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6229                       emitcode ("anl", "a,%s", rOp);
6230                     }                   
6231                 }
6232               aopPut (AOP (result), "a", offset);
6233             }
6234         }
6235     }
6236
6237 release:
6238   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6239   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6240   freeAsmop (result, NULL, ic, TRUE);
6241 }
6242
6243
6244 /*-----------------------------------------------------------------*/
6245 /* genOr  - code for or                                            */
6246 /*-----------------------------------------------------------------*/
6247 static void
6248 genOr (iCode * ic, iCode * ifx)
6249 {
6250   operand *left, *right, *result;
6251   int size, offset = 0;
6252   unsigned long lit = 0L;
6253   bool     pushResult;
6254
6255   D (emitcode (";", "genOr "););
6256
6257   AOP_OP_3_NOFATAL (ic, pushResult);
6258   AOP_SET_LOCALS (ic);
6259
6260   if (pushResult)
6261   {
6262       genFarFarLogicOp(ic, "orl");
6263       return;
6264   }
6265
6266
6267 #ifdef DEBUG_TYPE
6268   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6269             AOP_TYPE (result),
6270             AOP_TYPE (left), AOP_TYPE (right));
6271   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6272             AOP_SIZE (result),
6273             AOP_SIZE (left), AOP_SIZE (right));
6274 #endif
6275
6276   /* if left is a literal & right is not then exchange them */
6277   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6278 #ifdef LOGIC_OPS_BROKEN
6279    || AOP_NEEDSACC (left) // I think this is a net loss now.
6280 #endif      
6281       )
6282     {
6283       operand *tmp = right;
6284       right = left;
6285       left = tmp;
6286     }
6287
6288   /* if result = right then exchange them */
6289   if (sameRegs (AOP (result), AOP (right)))
6290     {
6291       operand *tmp = right;
6292       right = left;
6293       left = tmp;
6294     }
6295
6296   /* if right is bit then exchange them */
6297   if (AOP_TYPE (right) == AOP_CRY &&
6298       AOP_TYPE (left) != AOP_CRY)
6299     {
6300       operand *tmp = right;
6301       right = left;
6302       left = tmp;
6303     }
6304   if (AOP_TYPE (right) == AOP_LIT)
6305     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6306
6307   size = AOP_SIZE (result);
6308
6309   // if(bit | yy)
6310   // xx = bit | yy;
6311   if (AOP_TYPE (left) == AOP_CRY)
6312     {
6313       if (AOP_TYPE (right) == AOP_LIT)
6314         {
6315           // c = bit & literal;
6316           if (lit)
6317             {
6318               // lit != 0 => result = 1
6319               if (AOP_TYPE (result) == AOP_CRY)
6320                 {
6321                   if (size)
6322                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6323                   else if (ifx)
6324                     continueIfTrue (ifx);
6325                   goto release;
6326                 }
6327               emitcode ("setb", "c");
6328             }
6329           else
6330             {
6331               // lit == 0 => result = left
6332               if (size && sameRegs (AOP (result), AOP (left)))
6333                 goto release;
6334               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6335             }
6336         }
6337       else
6338         {
6339           if (AOP_TYPE (right) == AOP_CRY)
6340             {
6341               // c = bit | bit;
6342               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6343               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6344             }
6345           else
6346             {
6347               // c = bit | val;
6348               symbol *tlbl = newiTempLabel (NULL);
6349               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6350                 emitcode ("setb", "c");
6351               emitcode ("jb", "%s,!tlabel",
6352                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
6353               toBoolean (right);
6354               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6355               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6356                 {
6357                   jmpTrueOrFalse (ifx, tlbl);
6358                   goto release;
6359                 }
6360               else
6361                 {
6362                   CLRC;
6363                   emitcode ("", "!tlabeldef", tlbl->key + 100);
6364                 }
6365             }
6366         }
6367       // bit = c
6368       // val = c
6369       if (size)
6370         outBitC (result);
6371       // if(bit | ...)
6372       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6373         genIfxJump (ifx, "c");
6374       goto release;
6375     }
6376
6377   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6378   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6379   if ((AOP_TYPE (right) == AOP_LIT) &&
6380       (AOP_TYPE (result) == AOP_CRY) &&
6381       (AOP_TYPE (left) != AOP_CRY))
6382     {
6383       if (lit)
6384         {
6385           // result = 1
6386           if (size)
6387             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6388           else
6389             continueIfTrue (ifx);
6390           goto release;
6391         }
6392       else
6393         {
6394           // lit = 0, result = boolean(left)
6395           if (size)
6396             emitcode ("setb", "c");
6397           toBoolean (right);
6398           if (size)
6399             {
6400               symbol *tlbl = newiTempLabel (NULL);
6401               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6402               CLRC;
6403               emitcode ("", "!tlabeldef", tlbl->key + 100);
6404             }
6405           else
6406             {
6407               genIfxJump (ifx, "a");
6408               goto release;
6409             }
6410         }
6411       outBitC (result);
6412       goto release;
6413     }
6414
6415   /* if left is same as result */
6416   if (sameRegs (AOP (result), AOP (left)))
6417     {
6418       for (; size--; offset++)
6419         {
6420           if (AOP_TYPE (right) == AOP_LIT)
6421             {
6422               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6423                 {
6424                   continue;
6425                 }
6426               else
6427                 {
6428                   if (IS_AOP_PREG (left))
6429                     {
6430                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6431                       emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6432                       aopPut (AOP (result), "a", offset);
6433                     }
6434                   else
6435                     {
6436                       emitcode ("orl", "%s,%s",
6437                             aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6438                          aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6439                     }
6440                 }
6441             }
6442           else
6443             {
6444               if (AOP_TYPE (left) == AOP_ACC)
6445                 {
6446                   emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6447                 }
6448               else
6449                 {
6450                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6451                   if (IS_AOP_PREG (left))
6452                     {
6453                       emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6454                       aopPut (AOP (result), "a", offset);
6455                     }
6456                   else
6457                     {
6458                       emitcode ("orl", "%s,a",
6459                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6460                     }
6461                 }
6462             }
6463         }
6464     }
6465   else
6466     {
6467       // left & result in different registers
6468       if (AOP_TYPE (result) == AOP_CRY)
6469         {
6470           // result = bit
6471           // if(size), result in bit
6472           // if(!size && ifx), conditional oper: if(left | right)
6473           symbol *tlbl = newiTempLabel (NULL);
6474           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6475           if (size)
6476             emitcode ("setb", "c");
6477           while (sizer--)
6478             {
6479               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6480                 emitcode ("orl", "a,%s",
6481                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6482               } else {
6483                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6484                 emitcode ("orl", "a,%s",
6485                           aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6486               }
6487               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6488               offset++;
6489             }
6490           if (size)
6491             {
6492               CLRC;
6493               emitcode ("", "!tlabeldef", tlbl->key + 100);
6494               outBitC (result);
6495             }
6496           else if (ifx)
6497             jmpTrueOrFalse (ifx, tlbl);
6498         }
6499       else
6500         {
6501             _startLazyDPSEvaluation();
6502           for (; (size--); offset++)
6503             {
6504               // normal case
6505               // result = left & right
6506               if (AOP_TYPE (right) == AOP_LIT)
6507                 {
6508                   if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6509                     {
6510                       aopPut (AOP (result),
6511                            aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6512                               offset);
6513                       continue;
6514                     }
6515                   D (emitcode (";", "better literal OR."););
6516                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6517                   emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
6518                                                     FALSE, FALSE, FALSE));
6519
6520                 }
6521               else
6522                 {
6523                   // faster than result <- left, anl result,right
6524                   // and better if result is SFR
6525                   if (AOP_TYPE (left) == AOP_ACC)
6526                     {
6527                       emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
6528                                                        FALSE, FALSE, FALSE));
6529                     }
6530                   else
6531                     {
6532                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6533                         
6534                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6535                       {
6536                           emitcode("mov", "b,a");
6537                           rOp = "b";
6538                       }
6539                         
6540                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6541                       emitcode ("orl", "a,%s", rOp);
6542                     }
6543                 }
6544               aopPut (AOP (result), "a", offset);
6545             }
6546             _endLazyDPSEvaluation();
6547         }
6548     }
6549
6550 release:
6551   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6552   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6553   freeAsmop (result, NULL, ic, TRUE);
6554 }
6555
6556 /*-----------------------------------------------------------------*/
6557 /* genXor - code for xclusive or                                   */
6558 /*-----------------------------------------------------------------*/
6559 static void
6560 genXor (iCode * ic, iCode * ifx)
6561 {
6562   operand *left, *right, *result;
6563   int size, offset = 0;
6564   unsigned long lit = 0L;
6565   bool pushResult;
6566
6567   D (emitcode (";", "genXor "););
6568
6569   AOP_OP_3_NOFATAL (ic, pushResult);
6570   AOP_SET_LOCALS (ic);
6571
6572   if (pushResult)
6573   {
6574       genFarFarLogicOp(ic, "xrl");
6575       return;
6576   }  
6577
6578 #ifdef DEBUG_TYPE
6579   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6580             AOP_TYPE (result),
6581             AOP_TYPE (left), AOP_TYPE (right));
6582   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6583             AOP_SIZE (result),
6584             AOP_SIZE (left), AOP_SIZE (right));
6585 #endif
6586
6587   /* if left is a literal & right is not ||
6588      if left needs acc & right does not */
6589   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) 
6590 #ifdef LOGIC_OPS_BROKEN      
6591       || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6592 #endif
6593      )
6594     {
6595       operand *tmp = right;
6596       right = left;
6597       left = tmp;
6598     }
6599
6600   /* if result = right then exchange them */
6601   if (sameRegs (AOP (result), AOP (right)))
6602     {
6603       operand *tmp = right;
6604       right = left;
6605       left = tmp;
6606     }
6607
6608   /* if right is bit then exchange them */
6609   if (AOP_TYPE (right) == AOP_CRY &&
6610       AOP_TYPE (left) != AOP_CRY)
6611     {
6612       operand *tmp = right;
6613       right = left;
6614       left = tmp;
6615     }
6616   if (AOP_TYPE (right) == AOP_LIT)
6617     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6618
6619   size = AOP_SIZE (result);
6620
6621   // if(bit ^ yy)
6622   // xx = bit ^ yy;
6623   if (AOP_TYPE (left) == AOP_CRY)
6624     {
6625       if (AOP_TYPE (right) == AOP_LIT)
6626         {
6627           // c = bit & literal;
6628           if (lit >> 1)
6629             {
6630               // lit>>1  != 0 => result = 1
6631               if (AOP_TYPE (result) == AOP_CRY)
6632                 {
6633                   if (size)
6634                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6635                   else if (ifx)
6636                     continueIfTrue (ifx);
6637                   goto release;
6638                 }
6639               emitcode ("setb", "c");
6640             }
6641           else
6642             {
6643               // lit == (0 or 1)
6644               if (lit == 0)
6645                 {
6646                   // lit == 0, result = left
6647                   if (size && sameRegs (AOP (result), AOP (left)))
6648                     goto release;
6649                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6650                 }
6651               else
6652                 {
6653                   // lit == 1, result = not(left)
6654                   if (size && sameRegs (AOP (result), AOP (left)))
6655                     {
6656                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6657                       goto release;
6658                     }
6659                   else
6660                     {
6661                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6662                       emitcode ("cpl", "c");
6663                     }
6664                 }
6665             }
6666
6667         }
6668       else
6669         {
6670           // right != literal
6671           symbol *tlbl = newiTempLabel (NULL);
6672           if (AOP_TYPE (right) == AOP_CRY)
6673             {
6674               // c = bit ^ bit;
6675               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6676             }
6677           else
6678             {
6679               int sizer = AOP_SIZE (right);
6680               // c = bit ^ val
6681               // if val>>1 != 0, result = 1
6682               emitcode ("setb", "c");
6683               while (sizer)
6684                 {
6685                   MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
6686                   if (sizer == 1)
6687                     // test the msb of the lsb
6688                     emitcode ("anl", "a,#!constbyte",0xfe);
6689                   emitcode ("jnz", "!tlabel", tlbl->key + 100);
6690                   sizer--;
6691                 }
6692               // val = (0,1)
6693               emitcode ("rrc", "a");
6694             }
6695           emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6696           emitcode ("cpl", "c");
6697           emitcode ("", "!tlabeldef", (tlbl->key + 100));
6698         }
6699       // bit = c
6700       // val = c
6701       if (size)
6702         outBitC (result);
6703       // if(bit | ...)
6704       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6705         genIfxJump (ifx, "c");
6706       goto release;
6707     }
6708
6709   if (sameRegs (AOP (result), AOP (left)))
6710     {
6711       /* if left is same as result */
6712       for (; size--; offset++)
6713         {
6714           if (AOP_TYPE (right) == AOP_LIT)
6715             {
6716               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6717                 continue;
6718               else if (IS_AOP_PREG (left))
6719                 {
6720                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6721                   emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6722                   aopPut (AOP (result), "a", offset);
6723                 }
6724               else
6725                 emitcode ("xrl", "%s,%s",
6726                           aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6727                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6728             }
6729           else
6730             {
6731               if (AOP_TYPE (left) == AOP_ACC)
6732                 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6733               else
6734                 {
6735                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6736                   if (IS_AOP_PREG (left))
6737                     {
6738                       emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6739                       aopPut (AOP (result), "a", offset);
6740                     }
6741                   else
6742                     emitcode ("xrl", "%s,a",
6743                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6744                 }
6745             }
6746         }
6747     }
6748   else
6749     {
6750       // left & result in different registers
6751       if (AOP_TYPE (result) == AOP_CRY)
6752         {
6753           // result = bit
6754           // if(size), result in bit
6755           // if(!size && ifx), conditional oper: if(left ^ right)
6756           symbol *tlbl = newiTempLabel (NULL);
6757           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6758                   
6759           if (size)
6760             emitcode ("setb", "c");
6761           while (sizer--)
6762             {
6763               if ((AOP_TYPE (right) == AOP_LIT) &&
6764                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6765                 {
6766                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6767                 }
6768               else
6769                 {
6770                   if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6771                     emitcode ("xrl", "a,%s",
6772                               aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6773                   } else {
6774                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6775                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6776                       {
6777                           emitcode("mov", "b,a");
6778                           rOp = "b";
6779                       }
6780                         
6781                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6782                       emitcode ("xrl", "a,%s", rOp);                  
6783                   }
6784                 }
6785               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6786               offset++;
6787             }
6788           if (size)
6789             {
6790               CLRC;
6791               emitcode ("", "!tlabeldef", tlbl->key + 100);
6792               outBitC (result);
6793             }
6794           else if (ifx)
6795             jmpTrueOrFalse (ifx, tlbl);
6796         }
6797       else
6798         {
6799         for (; (size--); offset++)
6800           {
6801             // normal case
6802             // result = left & right
6803             if (AOP_TYPE (right) == AOP_LIT)
6804               {
6805                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6806                   {
6807                     aopPut (AOP (result),
6808                             aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6809                             offset);
6810                     continue;
6811                   }
6812                 D (emitcode (";", "better literal XOR."););
6813                 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6814                 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
6815                                                   FALSE, FALSE, FALSE));
6816               }
6817             else
6818               {
6819                 // faster than result <- left, anl result,right
6820                 // and better if result is SFR
6821                 if (AOP_TYPE (left) == AOP_ACC)
6822                   {
6823                     emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
6824                                                      FALSE, FALSE, FALSE));
6825                   }
6826                 else
6827                   {
6828                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6829                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6830                       {
6831                           emitcode("mov", "b,a");
6832                           rOp = "b";
6833                       }
6834                         
6835                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6836                       emitcode ("xrl", "a,%s", rOp);
6837                   }
6838               }
6839             aopPut (AOP (result), "a", offset);
6840           }
6841         }
6842         
6843     }
6844
6845 release:
6846   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6847   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6848   freeAsmop (result, NULL, ic, TRUE);
6849 }
6850
6851 /*-----------------------------------------------------------------*/
6852 /* genInline - write the inline code out                           */
6853 /*-----------------------------------------------------------------*/
6854 static void
6855 genInline (iCode * ic)
6856 {
6857   char *buffer, *bp, *bp1;
6858
6859   D (emitcode (";", "genInline ");
6860     );
6861
6862   _G.inLine += (!options.asmpeep);
6863
6864   buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6865   strcpy (buffer, IC_INLINE (ic));
6866
6867   /* emit each line as a code */
6868   while (*bp)
6869     {
6870       if (*bp == '\n')
6871         {
6872           *bp++ = '\0';
6873           emitcode (bp1, "");
6874           bp1 = bp;
6875         }
6876       else
6877         {
6878           if (*bp == ':')
6879             {
6880               bp++;
6881               *bp = '\0';
6882               bp++;
6883               emitcode (bp1, "");
6884               bp1 = bp;
6885             }
6886           else
6887             bp++;
6888         }
6889     }
6890   if (bp1 != bp)
6891     emitcode (bp1, "");
6892   /*     emitcode("",buffer); */
6893   _G.inLine -= (!options.asmpeep);
6894 }
6895
6896 /*-----------------------------------------------------------------*/
6897 /* genRRC - rotate right with carry                                */
6898 /*-----------------------------------------------------------------*/
6899 static void
6900 genRRC (iCode * ic)
6901 {
6902   operand *left, *result;
6903   int size, offset = 0;
6904   char *l;
6905
6906   D (emitcode (";", "genRRC ");
6907     );
6908
6909   /* rotate right with carry */
6910   left = IC_LEFT (ic);
6911   result = IC_RESULT (ic);
6912   aopOp (left, ic, FALSE, FALSE);
6913   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6914
6915   /* move it to the result */
6916   size = AOP_SIZE (result);
6917   offset = size - 1;
6918   CLRC;
6919
6920   _startLazyDPSEvaluation ();
6921   while (size--)
6922     {
6923       l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6924       MOVA (l);
6925       emitcode ("rrc", "a");
6926       if (AOP_SIZE (result) > 1)
6927         aopPut (AOP (result), "a", offset--);
6928     }
6929   _endLazyDPSEvaluation ();
6930
6931   /* now we need to put the carry into the
6932      highest order byte of the result */
6933   if (AOP_SIZE (result) > 1)
6934     {
6935       l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
6936       MOVA (l);
6937     }
6938   emitcode ("mov", "acc.7,c");
6939   aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
6940   freeAsmop (left, NULL, ic, TRUE);
6941   freeAsmop (result, NULL, ic, TRUE);
6942 }
6943
6944 /*-----------------------------------------------------------------*/
6945 /* genRLC - generate code for rotate left with carry               */
6946 /*-----------------------------------------------------------------*/
6947 static void
6948 genRLC (iCode * ic)
6949 {
6950   operand *left, *result;
6951   int size, offset = 0;
6952   char *l;
6953
6954   D (emitcode (";", "genRLC ");
6955     );
6956
6957   /* rotate right with carry */
6958   left = IC_LEFT (ic);
6959   result = IC_RESULT (ic);
6960   aopOp (left, ic, FALSE, FALSE);
6961   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6962
6963   /* move it to the result */
6964   size = AOP_SIZE (result);
6965   offset = 0;
6966   if (size--)
6967     {
6968       l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6969       MOVA (l);
6970       emitcode ("add", "a,acc");
6971       if (AOP_SIZE (result) > 1)
6972         {
6973           aopPut (AOP (result), "a", offset++);
6974         }
6975
6976       _startLazyDPSEvaluation ();
6977       while (size--)
6978         {
6979           l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6980           MOVA (l);
6981           emitcode ("rlc", "a");
6982           if (AOP_SIZE (result) > 1)
6983             aopPut (AOP (result), "a", offset++);
6984         }
6985       _endLazyDPSEvaluation ();
6986     }
6987   /* now we need to put the carry into the
6988      highest order byte of the result */
6989   if (AOP_SIZE (result) > 1)
6990     {
6991       l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
6992       MOVA (l);
6993     }
6994   emitcode ("mov", "acc.0,c");
6995   aopPut (AOP (result), "a", 0);
6996   freeAsmop (left, NULL, ic, TRUE);
6997   freeAsmop (result, NULL, ic, TRUE);
6998 }
6999
7000 /*-----------------------------------------------------------------*/
7001 /* genGetHbit - generates code get highest order bit               */
7002 /*-----------------------------------------------------------------*/
7003 static void
7004 genGetHbit (iCode * ic)
7005 {
7006   operand *left, *result;
7007   left = IC_LEFT (ic);
7008   result = IC_RESULT (ic);
7009   aopOp (left, ic, FALSE, FALSE);
7010   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7011
7012   D (emitcode (";", "genGetHbit ");
7013     );
7014
7015   /* get the highest order byte into a */
7016   MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
7017   if (AOP_TYPE (result) == AOP_CRY)
7018     {
7019       emitcode ("rlc", "a");
7020       outBitC (result);
7021     }
7022   else
7023     {
7024       emitcode ("rl", "a");
7025       emitcode ("anl", "a,#1");
7026       outAcc (result);
7027     }
7028
7029
7030   freeAsmop (left, NULL, ic, TRUE);
7031   freeAsmop (result, NULL, ic, TRUE);
7032 }
7033
7034 /*-----------------------------------------------------------------*/
7035 /* AccRol - rotate left accumulator by known count                 */
7036 /*-----------------------------------------------------------------*/
7037 static void
7038 AccRol (int shCount)
7039 {
7040   shCount &= 0x0007;            // shCount : 0..7
7041
7042   switch (shCount)
7043     {
7044     case 0:
7045       break;
7046     case 1:
7047       emitcode ("rl", "a");
7048       break;
7049     case 2:
7050       emitcode ("rl", "a");
7051       emitcode ("rl", "a");
7052       break;
7053     case 3:
7054       emitcode ("swap", "a");
7055       emitcode ("rr", "a");
7056       break;
7057     case 4:
7058       emitcode ("swap", "a");
7059       break;
7060     case 5:
7061       emitcode ("swap", "a");
7062       emitcode ("rl", "a");
7063       break;
7064     case 6:
7065       emitcode ("rr", "a");
7066       emitcode ("rr", "a");
7067       break;
7068     case 7:
7069       emitcode ("rr", "a");
7070       break;
7071     }
7072 }
7073
7074 /*-----------------------------------------------------------------*/
7075 /* AccLsh - left shift accumulator by known count                  */
7076 /*-----------------------------------------------------------------*/
7077 static void
7078 AccLsh (int shCount)
7079 {
7080   if (shCount != 0)
7081     {
7082       if (shCount == 1)
7083         emitcode ("add", "a,acc");
7084       else if (shCount == 2)
7085         {
7086           emitcode ("add", "a,acc");
7087           emitcode ("add", "a,acc");
7088         }
7089       else
7090         {
7091           /* rotate left accumulator */
7092           AccRol (shCount);
7093           /* and kill the lower order bits */
7094           emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7095         }
7096     }
7097 }
7098
7099 /*-----------------------------------------------------------------*/
7100 /* AccRsh - right shift accumulator by known count                 */
7101 /*-----------------------------------------------------------------*/
7102 static void
7103 AccRsh (int shCount)
7104 {
7105   if (shCount != 0)
7106     {
7107       if (shCount == 1)
7108         {
7109           CLRC;
7110           emitcode ("rrc", "a");
7111         }
7112       else
7113         {
7114           /* rotate right accumulator */
7115           AccRol (8 - shCount);
7116           /* and kill the higher order bits */
7117           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7118         }
7119     }
7120 }
7121
7122 #ifdef BETTER_LITERAL_SHIFT
7123 /*-----------------------------------------------------------------*/
7124 /* AccSRsh - signed right shift accumulator by known count                 */
7125 /*-----------------------------------------------------------------*/
7126 static void
7127 AccSRsh (int shCount)
7128 {
7129   symbol *tlbl;
7130   if (shCount != 0)
7131     {
7132       if (shCount == 1)
7133         {
7134           emitcode ("mov", "c,acc.7");
7135           emitcode ("rrc", "a");
7136         }
7137       else if (shCount == 2)
7138         {
7139           emitcode ("mov", "c,acc.7");
7140           emitcode ("rrc", "a");
7141           emitcode ("mov", "c,acc.7");
7142           emitcode ("rrc", "a");
7143         }
7144       else
7145         {
7146           tlbl = newiTempLabel (NULL);
7147           /* rotate right accumulator */
7148           AccRol (8 - shCount);
7149           /* and kill the higher order bits */
7150           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7151           emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7152           emitcode ("orl", "a,#!constbyte",
7153                     (unsigned char) ~SRMask[shCount]);
7154           emitcode ("", "!tlabeldef", tlbl->key + 100);
7155         }
7156     }
7157 }
7158 #endif
7159
7160 #ifdef BETTER_LITERAL_SHIFT
7161 /*-----------------------------------------------------------------*/
7162 /* shiftR1Left2Result - shift right one byte from left to result   */
7163 /*-----------------------------------------------------------------*/
7164 static void
7165 shiftR1Left2Result (operand * left, int offl,
7166                     operand * result, int offr,
7167                     int shCount, int sign)
7168 {
7169   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7170   /* shift right accumulator */
7171   if (sign)
7172     AccSRsh (shCount);
7173   else
7174     AccRsh (shCount);
7175   aopPut (AOP (result), "a", offr);
7176 }
7177 #endif
7178
7179 #ifdef BETTER_LITERAL_SHIFT
7180 /*-----------------------------------------------------------------*/
7181 /* shiftL1Left2Result - shift left one byte from left to result    */
7182 /*-----------------------------------------------------------------*/
7183 static void
7184 shiftL1Left2Result (operand * left, int offl,
7185                     operand * result, int offr, int shCount)
7186 {
7187   MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7188   /* shift left accumulator */
7189   AccLsh (shCount);
7190   aopPut (AOP (result), "a", offr);
7191 }
7192 #endif
7193
7194 #ifdef BETTER_LITERAL_SHIFT
7195 /*-----------------------------------------------------------------*/
7196 /* movLeft2Result - move byte from left to result                  */
7197 /*-----------------------------------------------------------------*/
7198 static void
7199 movLeft2Result (operand * left, int offl,
7200                 operand * result, int offr, int sign)
7201 {
7202   char *l;
7203   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7204   {
7205       l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
7206
7207       if (*l == '@' && (IS_AOP_PREG (result)))
7208       {
7209           emitcode ("mov", "a,%s", l);
7210           aopPut (AOP (result), "a", offr);
7211       }
7212       else
7213       {
7214           if (!sign)
7215           {
7216             aopPut (AOP (result), l, offr);
7217           }
7218           else
7219             {
7220               /* MSB sign in acc.7 ! */
7221               if (getDataSize (left) == offl + 1)
7222                 {
7223                   emitcode ("mov", "a,%s", l);
7224                   aopPut (AOP (result), "a", offr);
7225                 }
7226             }
7227       }
7228   }
7229 }
7230 #endif
7231
7232 #ifdef BETTER_LITERAL_SHIFT
7233 /*-----------------------------------------------------------------*/
7234 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
7235 /*-----------------------------------------------------------------*/
7236 static void
7237 AccAXRrl1 (char *x)
7238 {
7239   emitcode ("rrc", "a");
7240   emitcode ("xch", "a,%s", x);
7241   emitcode ("rrc", "a");
7242   emitcode ("xch", "a,%s", x);
7243 }
7244 #endif
7245
7246 #ifdef BETTER_LITERAL_SHIFT
7247 //REMOVE ME!!!
7248 /*-----------------------------------------------------------------*/
7249 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
7250 /*-----------------------------------------------------------------*/
7251 static void
7252 AccAXLrl1 (char *x)
7253 {
7254   emitcode ("xch", "a,%s", x);
7255   emitcode ("rlc", "a");
7256   emitcode ("xch", "a,%s", x);
7257   emitcode ("rlc", "a");
7258 }
7259 #endif
7260
7261 #ifdef BETTER_LITERAL_SHIFT
7262 /*-----------------------------------------------------------------*/
7263 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
7264 /*-----------------------------------------------------------------*/
7265 static void
7266 AccAXLsh1 (char *x)
7267 {
7268   emitcode ("xch", "a,%s", x);
7269   emitcode ("add", "a,acc");
7270   emitcode ("xch", "a,%s", x);
7271   emitcode ("rlc", "a");
7272 }
7273 #endif
7274
7275 #ifdef BETTER_LITERAL_SHIFT
7276 /*-----------------------------------------------------------------*/
7277 /* AccAXLsh - left shift a:x by known count (0..7)                 */
7278 /*-----------------------------------------------------------------*/
7279 static void
7280 AccAXLsh (char *x, int shCount)
7281 {
7282   switch (shCount)
7283     {
7284     case 0:
7285       break;
7286     case 1:
7287       AccAXLsh1 (x);
7288       break;
7289     case 2:
7290       AccAXLsh1 (x);
7291       AccAXLsh1 (x);
7292       break;
7293     case 3:
7294     case 4:
7295     case 5:                     // AAAAABBB:CCCCCDDD
7296
7297       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
7298
7299       emitcode ("anl", "a,#!constbyte",
7300                 SLMask[shCount]);       // BBB00000:CCCCCDDD
7301
7302       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
7303
7304       AccRol (shCount);         // DDDCCCCC:BBB00000
7305
7306       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
7307
7308       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
7309
7310       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
7311
7312       emitcode ("anl", "a,#!constbyte",
7313                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
7314
7315       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
7316
7317       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
7318
7319       break;
7320     case 6:                     // AAAAAABB:CCCCCCDD
7321       emitcode ("anl", "a,#!constbyte",
7322                 SRMask[shCount]);       // 000000BB:CCCCCCDD
7323       emitcode ("mov", "c,acc.0");      // c = B
7324       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
7325 #if 0
7326       AccAXRrl1 (x);            // BCCCCCCD:D000000B
7327       AccAXRrl1 (x);            // BBCCCCCC:DD000000
7328 #else
7329       emitcode("rrc","a"); 
7330       emitcode("xch","a,%s", x); 
7331       emitcode("rrc","a"); 
7332       emitcode("mov","c,acc.0"); //<< get correct bit 
7333       emitcode("xch","a,%s", x); 
7334
7335       emitcode("rrc","a"); 
7336       emitcode("xch","a,%s", x); 
7337       emitcode("rrc","a"); 
7338       emitcode("xch","a,%s", x); 
7339 #endif
7340       break;
7341     case 7:                     // a:x <<= 7
7342
7343       emitcode ("anl", "a,#!constbyte",
7344                 SRMask[shCount]);       // 0000000B:CCCCCCCD
7345
7346       emitcode ("mov", "c,acc.0");      // c = B
7347
7348       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
7349
7350       AccAXRrl1 (x);            // BCCCCCCC:D0000000
7351
7352       break;
7353     default:
7354       break;
7355     }
7356 }
7357 #endif
7358
7359 #ifdef BETTER_LITERAL_SHIFT
7360 //REMOVE ME!!!
7361 /*-----------------------------------------------------------------*/
7362 /* AccAXRsh - right shift a:x known count (0..7)                   */
7363 /*-----------------------------------------------------------------*/
7364 static void
7365 AccAXRsh (char *x, int shCount)
7366 {
7367   switch (shCount)
7368     {
7369     case 0:
7370       break;
7371     case 1:
7372       CLRC;
7373       AccAXRrl1 (x);            // 0->a:x
7374
7375       break;
7376     case 2:
7377       CLRC;
7378       AccAXRrl1 (x);            // 0->a:x
7379
7380       CLRC;
7381       AccAXRrl1 (x);            // 0->a:x
7382
7383       break;
7384     case 3:
7385     case 4:
7386     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7387
7388       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
7389
7390       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7391
7392       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7393
7394       emitcode ("anl", "a,#!constbyte",
7395                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7396
7397       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7398
7399       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7400
7401       emitcode ("anl", "a,#!constbyte",
7402                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7403
7404       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7405
7406       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7407
7408       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
7409
7410       break;
7411     case 6:                     // AABBBBBB:CCDDDDDD
7412
7413       emitcode ("mov", "c,acc.7");
7414       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7415
7416       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7417
7418       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7419
7420       emitcode ("anl", "a,#!constbyte",
7421                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7422
7423       break;
7424     case 7:                     // ABBBBBBB:CDDDDDDD
7425
7426       emitcode ("mov", "c,acc.7");      // c = A
7427
7428       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7429
7430       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7431
7432       emitcode ("anl", "a,#!constbyte",
7433                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7434
7435       break;
7436     default:
7437       break;
7438     }
7439 }
7440 #endif
7441
7442 #ifdef BETTER_LITERAL_SHIFT
7443 /*-----------------------------------------------------------------*/
7444 /* AccAXRshS - right shift signed a:x known count (0..7)           */
7445 /*-----------------------------------------------------------------*/
7446 static void
7447 AccAXRshS (char *x, int shCount)
7448 {
7449   symbol *tlbl;
7450   switch (shCount)
7451     {
7452     case 0:
7453       break;
7454     case 1:
7455       emitcode ("mov", "c,acc.7");
7456       AccAXRrl1 (x);            // s->a:x
7457
7458       break;
7459     case 2:
7460       emitcode ("mov", "c,acc.7");
7461       AccAXRrl1 (x);            // s->a:x
7462
7463       emitcode ("mov", "c,acc.7");
7464       AccAXRrl1 (x);            // s->a:x
7465
7466       break;
7467     case 3:
7468     case 4:
7469     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7470
7471       tlbl = newiTempLabel (NULL);
7472       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
7473
7474       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7475
7476       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7477
7478       emitcode ("anl", "a,#!constbyte",
7479                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7480
7481       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7482
7483       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7484
7485       emitcode ("anl", "a,#!constbyte",
7486                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7487
7488       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7489
7490       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7491
7492       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
7493
7494       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7495       emitcode ("orl", "a,#!constbyte",
7496                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
7497
7498       emitcode ("", "!tlabeldef", tlbl->key + 100);
7499       break;                    // SSSSAAAA:BBBCCCCC
7500
7501     case 6:                     // AABBBBBB:CCDDDDDD
7502
7503       tlbl = newiTempLabel (NULL);
7504       emitcode ("mov", "c,acc.7");
7505       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7506
7507       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7508
7509       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7510
7511       emitcode ("anl", "a,#!constbyte",
7512                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7513
7514       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7515       emitcode ("orl", "a,#!constbyte",
7516                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
7517
7518       emitcode ("", "!tlabeldef", tlbl->key + 100);
7519       break;
7520     case 7:                     // ABBBBBBB:CDDDDDDD
7521
7522       tlbl = newiTempLabel (NULL);
7523       emitcode ("mov", "c,acc.7");      // c = A
7524
7525       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7526
7527       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7528
7529       emitcode ("anl", "a,#!constbyte",
7530                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7531
7532       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7533       emitcode ("orl", "a,#!constbyte",
7534                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
7535
7536       emitcode ("", "!tlabeldef", tlbl->key + 100);
7537       break;
7538     default:
7539       break;
7540     }
7541 }
7542 #endif
7543
7544 #ifdef BETTER_LITERAL_SHIFT
7545 static void
7546 _loadLeftIntoAx(char    **lsb, 
7547                 operand *left, 
7548                 operand *result,
7549                 int     offl,
7550                 int     offr)
7551 {
7552   // Get the initial value from left into a pair of registers.
7553   // MSB must be in A, LSB can be any register.
7554   //
7555   // If the result is held in registers, it is an optimization
7556   // if the LSB can be held in the register which will hold the,
7557   // result LSB since this saves us from having to copy it into
7558   // the result following AccAXLsh.
7559   //
7560   // If the result is addressed indirectly, this is not a gain.
7561   if (AOP_NEEDSACC(result))
7562   {
7563        char *leftByte;
7564        
7565        _startLazyDPSEvaluation();
7566       if (AOP_TYPE(left) == AOP_DPTR2)
7567        {
7568            // Get MSB in A.
7569            MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
7570            // get LSB in DP2_RESULT_REG.
7571            leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
7572            assert(!strcmp(leftByte, DP2_RESULT_REG));
7573        }
7574        else
7575        {
7576            // get LSB into DP2_RESULT_REG
7577            leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
7578            if (strcmp(leftByte, DP2_RESULT_REG))
7579            {
7580                TR_AP("#7");
7581                emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7582            }
7583            // And MSB in A.
7584            leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
7585            assert(strcmp(leftByte, DP2_RESULT_REG));
7586            MOVA(leftByte);
7587        }
7588        _endLazyDPSEvaluation();
7589        *lsb = DP2_RESULT_REG;
7590   }
7591   else
7592   {
7593       if (sameRegs (AOP (result), AOP (left)) &&
7594         ((offl + MSB16) == offr))
7595       {
7596           /* don't crash result[offr] */
7597           MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
7598           emitcode ("xch", "a,%s", 
7599                     aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
7600       }
7601       else
7602       {
7603           movLeft2Result (left, offl, result, offr, 0);
7604           MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
7605       }
7606       *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
7607       assert(strcmp(*lsb,"a"));      
7608   }
7609 }
7610
7611 static void
7612 _storeAxResults(char    *lsb,
7613                 operand *result,
7614                 int     offr)
7615 {
7616   _startLazyDPSEvaluation();
7617   if (AOP_NEEDSACC(result))
7618   {
7619       /* We have to explicitly update the result LSB.
7620        */
7621       emitcode("xch","a,%s", lsb);
7622       aopPut(AOP(result), "a", offr);
7623       emitcode("mov","a,%s", lsb);
7624   }
7625   if (getDataSize (result) > 1)
7626   {
7627       aopPut (AOP (result), "a", offr + MSB16);
7628   }
7629   _endLazyDPSEvaluation();
7630 }
7631
7632 /*-----------------------------------------------------------------*/
7633 /* shiftL2Left2Result - shift left two bytes from left to result   */
7634 /*-----------------------------------------------------------------*/
7635 static void
7636 shiftL2Left2Result (operand * left, int offl,
7637                     operand * result, int offr, int shCount)
7638 {
7639   char *lsb;
7640
7641   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7642   
7643   AccAXLsh (lsb, shCount);
7644   
7645   _storeAxResults(lsb, result, offr);
7646 }
7647 #endif
7648
7649 #ifdef BETTER_LITERAL_SHIFT
7650 /*-----------------------------------------------------------------*/
7651 /* shiftR2Left2Result - shift right two bytes from left to result  */
7652 /*-----------------------------------------------------------------*/
7653 static void
7654 shiftR2Left2Result (operand * left, int offl,
7655                     operand * result, int offr,
7656                     int shCount, int sign)
7657 {
7658   char *lsb;
7659   
7660   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7661   
7662   /* a:x >> shCount (x = lsb(result)) */
7663   if (sign)
7664   {
7665      AccAXRshS(lsb, shCount);
7666   }
7667   else
7668   {
7669     AccAXRsh(lsb, shCount);
7670   }
7671   
7672   _storeAxResults(lsb, result, offr);
7673 }
7674 #endif
7675
7676 #if 0
7677 //REMOVE ME!!!
7678 /*-----------------------------------------------------------------*/
7679 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7680 /*-----------------------------------------------------------------*/
7681 static void
7682 shiftLLeftOrResult (operand * left, int offl,
7683                     operand * result, int offr, int shCount)
7684 {
7685   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7686   /* shift left accumulator */
7687   AccLsh (shCount);
7688   /* or with result */
7689   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7690   /* back to result */
7691   aopPut (AOP (result), "a", offr);
7692 }
7693 #endif
7694
7695 #if 0
7696 //REMOVE ME!!!
7697 /*-----------------------------------------------------------------*/
7698 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7699 /*-----------------------------------------------------------------*/
7700 static void
7701 shiftRLeftOrResult (operand * left, int offl,
7702                     operand * result, int offr, int shCount)
7703 {
7704   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7705   /* shift right accumulator */
7706   AccRsh (shCount);
7707   /* or with result */
7708   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7709   /* back to result */
7710   aopPut (AOP (result), "a", offr);
7711 }
7712 #endif
7713
7714 #ifdef BETTER_LITERAL_SHIFT
7715 /*-----------------------------------------------------------------*/
7716 /* genlshOne - left shift a one byte quantity by known count       */
7717 /*-----------------------------------------------------------------*/
7718 static void
7719 genlshOne (operand * result, operand * left, int shCount)
7720 {
7721   D (emitcode (";", "genlshOne "););
7722   shiftL1Left2Result (left, LSB, result, LSB, shCount);
7723 }
7724 #endif
7725
7726 #ifdef BETTER_LITERAL_SHIFT
7727 /*-----------------------------------------------------------------*/
7728 /* genlshTwo - left shift two bytes by known amount != 0           */
7729 /*-----------------------------------------------------------------*/
7730 static void
7731 genlshTwo (operand * result, operand * left, int shCount)
7732 {
7733   int size;
7734
7735   D (emitcode (";", "genlshTwo "););
7736
7737   size = getDataSize (result);
7738
7739   /* if shCount >= 8 */
7740   if (shCount >= 8)
7741   {
7742       shCount -= 8;
7743
7744       _startLazyDPSEvaluation();
7745
7746       if (size > 1)
7747         {
7748           if (shCount)
7749           {
7750             _endLazyDPSEvaluation();
7751             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7752             aopPut (AOP (result), zero, LSB);       
7753           }
7754           else
7755           {
7756             movLeft2Result (left, LSB, result, MSB16, 0);
7757             aopPut (AOP (result), zero, LSB);
7758             _endLazyDPSEvaluation();
7759           }
7760         }
7761         else
7762         {
7763           aopPut (AOP (result), zero, LSB);
7764           _endLazyDPSEvaluation();
7765         }
7766   }
7767
7768   /*  1 <= shCount <= 7 */
7769   else
7770     {
7771       if (size == 1)
7772       {
7773         shiftL1Left2Result (left, LSB, result, LSB, shCount);
7774       }
7775       else
7776       {
7777         shiftL2Left2Result (left, LSB, result, LSB, shCount);
7778       }
7779     }
7780 }
7781 #endif
7782
7783 #if 0
7784 //REMOVE ME!!!
7785 /*-----------------------------------------------------------------*/
7786 /* shiftLLong - shift left one long from left to result            */
7787 /* offl = LSB or MSB16                                             */
7788 /*-----------------------------------------------------------------*/
7789 static void
7790 shiftLLong (operand * left, operand * result, int offr)
7791 {
7792   char *l;
7793   int size = AOP_SIZE (result);
7794
7795   if (size >= LSB + offr)
7796     {
7797       l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
7798       MOVA (l);
7799       emitcode ("add", "a,acc");
7800       if (sameRegs (AOP (left), AOP (result)) &&
7801           size >= MSB16 + offr && offr != LSB)
7802         emitcode ("xch", "a,%s",
7803                   aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
7804       else
7805         aopPut (AOP (result), "a", LSB + offr);
7806     }
7807
7808   if (size >= MSB16 + offr)
7809     {
7810       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7811         {
7812           l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
7813           MOVA (l);
7814         }
7815       emitcode ("rlc", "a");
7816       if (sameRegs (AOP (left), AOP (result)) &&
7817           size >= MSB24 + offr && offr != LSB)
7818         emitcode ("xch", "a,%s",
7819                   aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
7820       else
7821         aopPut (AOP (result), "a", MSB16 + offr);
7822     }
7823
7824   if (size >= MSB24 + offr)
7825     {
7826       if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7827         {
7828           l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
7829           MOVA (l);
7830         }
7831       emitcode ("rlc", "a");
7832       if (sameRegs (AOP (left), AOP (result)) &&
7833           size >= MSB32 + offr && offr != LSB)
7834         emitcode ("xch", "a,%s",
7835                   aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
7836       else
7837         aopPut (AOP (result), "a", MSB24 + offr);
7838     }
7839
7840   if (size > MSB32 + offr)
7841     {
7842       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7843         {
7844           l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
7845           MOVA (l);
7846         }
7847       emitcode ("rlc", "a");
7848       aopPut (AOP (result), "a", MSB32 + offr);
7849     }
7850   if (offr != LSB)
7851     aopPut (AOP (result), zero, LSB);
7852 }
7853 #endif
7854
7855 #if 0
7856 //REMOVE ME!!!
7857 /*-----------------------------------------------------------------*/
7858 /* genlshFour - shift four byte by a known amount != 0             */
7859 /*-----------------------------------------------------------------*/
7860 static void
7861 genlshFour (operand * result, operand * left, int shCount)
7862 {
7863   int size;
7864
7865   D (emitcode (";", "genlshFour ");
7866     );
7867
7868   size = AOP_SIZE (result);
7869
7870   /* if shifting more that 3 bytes */
7871   if (shCount >= 24)
7872     {
7873       shCount -= 24;
7874       if (shCount)
7875         /* lowest order of left goes to the highest
7876            order of the destination */
7877         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7878       else
7879         movLeft2Result (left, LSB, result, MSB32, 0);
7880       aopPut (AOP (result), zero, LSB);
7881       aopPut (AOP (result), zero, MSB16);
7882       aopPut (AOP (result), zero, MSB24);
7883       return;
7884     }
7885
7886   /* more than two bytes */
7887   else if (shCount >= 16)
7888     {
7889       /* lower order two bytes goes to higher order two bytes */
7890       shCount -= 16;
7891       /* if some more remaining */
7892       if (shCount)
7893         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7894       else
7895         {
7896           movLeft2Result (left, MSB16, result, MSB32, 0);
7897           movLeft2Result (left, LSB, result, MSB24, 0);
7898         }
7899       aopPut (AOP (result), zero, MSB16);
7900       aopPut (AOP (result), zero, LSB);
7901       return;
7902     }
7903
7904   /* if more than 1 byte */
7905   else if (shCount >= 8)
7906     {
7907       /* lower order three bytes goes to higher order  three bytes */
7908       shCount -= 8;
7909       if (size == 2)
7910         {
7911           if (shCount)
7912             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7913           else
7914             movLeft2Result (left, LSB, result, MSB16, 0);
7915         }
7916       else
7917         {                       /* size = 4 */
7918           if (shCount == 0)
7919             {
7920               movLeft2Result (left, MSB24, result, MSB32, 0);
7921               movLeft2Result (left, MSB16, result, MSB24, 0);
7922               movLeft2Result (left, LSB, result, MSB16, 0);
7923               aopPut (AOP (result), zero, LSB);
7924             }
7925           else if (shCount == 1)
7926             shiftLLong (left, result, MSB16);
7927           else
7928             {
7929               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7930               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7931               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7932               aopPut (AOP (result), zero, LSB);
7933             }
7934         }
7935     }
7936
7937   /* 1 <= shCount <= 7 */
7938   else if (shCount <= 2)
7939     {
7940       shiftLLong (left, result, LSB);
7941       if (shCount == 2)
7942         shiftLLong (result, result, LSB);
7943     }
7944   /* 3 <= shCount <= 7, optimize */
7945   else
7946     {
7947       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7948       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7949       shiftL2Left2Result (left, LSB, result, LSB, shCount);
7950     }
7951 }
7952 #endif
7953
7954 #ifdef BETTER_LITERAL_SHIFT
7955 /*-----------------------------------------------------------------*/
7956 /* genLeftShiftLiteral - left shifting by known count              */
7957 /*-----------------------------------------------------------------*/
7958 static bool
7959 genLeftShiftLiteral (operand * left,
7960                      operand * right,
7961                      operand * result,
7962                      iCode * ic)
7963 {
7964   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7965   int size;
7966
7967   size = getSize (operandType (result));
7968
7969   D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
7970
7971   /* We only handle certain easy cases so far. */
7972   if ((shCount != 0)
7973    && (shCount < (size * 8))
7974    && (size != 1)
7975    && (size != 2))
7976   {
7977       D(emitcode (";", "genLeftShiftLiteral wimping out"););    
7978       return FALSE;
7979   }
7980
7981   freeAsmop (right, NULL, ic, TRUE);
7982
7983   aopOp(left, ic, FALSE, FALSE);
7984   aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
7985
7986 #if 0 // debug spew
7987   if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
7988   {
7989         emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
7990         if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
7991         {
7992            emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
7993         }
7994   }
7995   if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
7996   {
7997         emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
7998         if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
7999         {
8000            emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8001         }       
8002   }  
8003 #endif
8004   
8005 #if VIEW_SIZE
8006   emitcode ("; shift left ", "result %d, left %d", size,
8007             AOP_SIZE (left));
8008 #endif
8009
8010   /* I suppose that the left size >= result size */
8011   if (shCount == 0)
8012   {
8013         _startLazyDPSEvaluation();
8014         while (size--)
8015         {
8016           movLeft2Result (left, size, result, size, 0);
8017         }
8018         _endLazyDPSEvaluation();
8019   }
8020   else if (shCount >= (size * 8))
8021   {
8022     _startLazyDPSEvaluation();
8023     while (size--)
8024     {
8025       aopPut (AOP (result), zero, size);
8026     }
8027     _endLazyDPSEvaluation();
8028   }
8029   else
8030   {
8031       switch (size)
8032         {
8033         case 1:
8034           genlshOne (result, left, shCount);
8035           break;
8036
8037         case 2:
8038           genlshTwo (result, left, shCount);
8039           break;
8040 #if 0
8041         case 4:
8042           genlshFour (result, left, shCount);
8043           break;
8044 #endif
8045         default:
8046           fprintf(stderr, "*** ack! mystery literal shift!\n");   
8047           break;
8048         }
8049     }
8050   freeAsmop (left, NULL, ic, TRUE);
8051   freeAsmop (result, NULL, ic, TRUE);
8052   return TRUE;
8053 }
8054 #endif
8055
8056 /*-----------------------------------------------------------------*/
8057 /* genLeftShift - generates code for left shifting                 */
8058 /*-----------------------------------------------------------------*/
8059 static void
8060 genLeftShift (iCode * ic)
8061 {
8062   operand *left, *right, *result;
8063   int size, offset;
8064   char *l;
8065   symbol *tlbl, *tlbl1;
8066
8067   D (emitcode (";", "genLeftShift "););
8068
8069   right = IC_RIGHT (ic);
8070   left = IC_LEFT (ic);
8071   result = IC_RESULT (ic);
8072
8073   aopOp (right, ic, FALSE, FALSE);
8074
8075
8076 #ifdef BETTER_LITERAL_SHIFT
8077   /* if the shift count is known then do it
8078      as efficiently as possible */
8079   if (AOP_TYPE (right) == AOP_LIT)
8080     {
8081       if (genLeftShiftLiteral (left, right, result, ic))
8082       {
8083         return;
8084       }
8085     }
8086 #endif
8087
8088   /* shift count is unknown then we have to form
8089      a loop get the loop count in B : Note: we take
8090      only the lower order byte since shifting
8091      more that 32 bits make no sense anyway, ( the
8092      largest size of an object can be only 32 bits ) */
8093
8094   if (AOP_TYPE (right) == AOP_LIT)
8095   {
8096       /* Really should be handled by genLeftShiftLiteral,
8097        * but since I'm too lazy to fix that today, at least we can make
8098        * some small improvement.
8099        */
8100        emitcode("mov", "b,#!constbyte",
8101                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8102   }
8103   else
8104   {
8105         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8106         emitcode ("inc", "b");
8107   }
8108   freeAsmop (right, NULL, ic, TRUE);
8109   aopOp (left, ic, FALSE, FALSE);
8110   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8111
8112   /* now move the left to the result if they are not the
8113      same */
8114   if (!sameRegs (AOP (left), AOP (result)) &&
8115       AOP_SIZE (result) > 1)
8116     {
8117
8118       size = AOP_SIZE (result);
8119       offset = 0;
8120       _startLazyDPSEvaluation ();
8121       while (size--)
8122         {
8123           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8124           if (*l == '@' && (IS_AOP_PREG (result)))
8125             {
8126
8127               emitcode ("mov", "a,%s", l);
8128               aopPut (AOP (result), "a", offset);
8129             }
8130           else
8131             aopPut (AOP (result), l, offset);
8132           offset++;
8133         }
8134       _endLazyDPSEvaluation ();
8135     }
8136
8137   tlbl = newiTempLabel (NULL);
8138   size = AOP_SIZE (result);
8139   offset = 0;
8140   tlbl1 = newiTempLabel (NULL);
8141
8142   /* if it is only one byte then */
8143   if (size == 1)
8144     {
8145       symbol *tlbl1 = newiTempLabel (NULL);
8146
8147       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8148       MOVA (l);
8149       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8150       emitcode ("", "!tlabeldef", tlbl->key + 100);
8151       emitcode ("add", "a,acc");
8152       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8153       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8154       aopPut (AOP (result), "a", 0);
8155       goto release;
8156     }
8157
8158   reAdjustPreg (AOP (result));
8159
8160   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8161   emitcode ("", "!tlabeldef", tlbl->key + 100);
8162   l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8163   MOVA (l);
8164   emitcode ("add", "a,acc");
8165   aopPut (AOP (result), "a", offset++);
8166   _startLazyDPSEvaluation ();
8167   while (--size)
8168     {
8169       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8170       MOVA (l);
8171       emitcode ("rlc", "a");
8172       aopPut (AOP (result), "a", offset++);
8173     }
8174   _endLazyDPSEvaluation ();
8175   reAdjustPreg (AOP (result));
8176
8177   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8178   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8179 release:
8180   freeAsmop (left, NULL, ic, TRUE);
8181   freeAsmop (result, NULL, ic, TRUE);
8182 }
8183
8184 #ifdef BETTER_LITERAL_SHIFT
8185 /*-----------------------------------------------------------------*/
8186 /* genrshOne - right shift a one byte quantity by known count      */
8187 /*-----------------------------------------------------------------*/
8188 static void
8189 genrshOne (operand * result, operand * left,
8190            int shCount, int sign)
8191 {
8192   D (emitcode (";", "genrshOne"););
8193   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8194 }
8195 #endif
8196
8197 #ifdef BETTER_LITERAL_SHIFT
8198 /*-----------------------------------------------------------------*/
8199 /* genrshTwo - right shift two bytes by known amount != 0          */
8200 /*-----------------------------------------------------------------*/
8201 static void
8202 genrshTwo (operand * result, operand * left,
8203            int shCount, int sign)
8204 {
8205   D (emitcode (";", "genrshTwo"););
8206
8207   /* if shCount >= 8 */
8208   if (shCount >= 8)
8209     {
8210       shCount -= 8;
8211       _startLazyDPSEvaluation();
8212       if (shCount)
8213       {
8214         shiftR1Left2Result (left, MSB16, result, LSB,
8215                             shCount, sign);
8216       }                     
8217       else
8218       {
8219         movLeft2Result (left, MSB16, result, LSB, sign);
8220       }
8221       addSign (result, MSB16, sign);
8222       _endLazyDPSEvaluation();
8223     }
8224
8225   /*  1 <= shCount <= 7 */
8226   else
8227   {
8228     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8229   }
8230 }
8231 #endif
8232
8233 #if 0
8234 //REMOVE ME!!!
8235 /*-----------------------------------------------------------------*/
8236 /* shiftRLong - shift right one long from left to result           */
8237 /* offl = LSB or MSB16                                             */
8238 /*-----------------------------------------------------------------*/
8239 static void
8240 shiftRLong (operand * left, int offl,
8241             operand * result, int sign)
8242 {
8243   int isSameRegs=sameRegs(AOP(left),AOP(result));
8244
8245   if (isSameRegs && offl>1) {
8246     // we are in big trouble, but this shouldn't happen
8247     werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8248   }
8249
8250   MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
8251   
8252   if (offl==MSB16) {
8253     // shift is > 8
8254     if (sign) {
8255       emitcode ("rlc", "a");
8256       emitcode ("subb", "a,acc");
8257       emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
8258     } else {
8259       aopPut (AOP(result), zero, MSB32);
8260     }
8261   }
8262
8263   if (!sign) {
8264     emitcode ("clr", "c");
8265   } else {
8266     emitcode ("mov", "c,acc.7");
8267   }
8268
8269   emitcode ("rrc", "a");
8270
8271   if (isSameRegs && offl==MSB16) {
8272     emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
8273   } else {
8274     aopPut (AOP (result), "a", MSB32);
8275     MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
8276   }
8277
8278   emitcode ("rrc", "a");
8279   if (isSameRegs && offl==1) {
8280     emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
8281   } else {
8282     aopPut (AOP (result), "a", MSB24);
8283     MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
8284   }
8285   emitcode ("rrc", "a");
8286   aopPut (AOP (result), "a", MSB16 - offl);
8287
8288   if (offl == LSB)
8289     {
8290       MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
8291       emitcode ("rrc", "a");
8292       aopPut (AOP (result), "a", LSB);
8293     }
8294 }
8295 #endif
8296
8297 #if 0
8298 //REMOVE ME!!!
8299 /*-----------------------------------------------------------------*/
8300 /* genrshFour - shift four byte by a known amount != 0             */
8301 /*-----------------------------------------------------------------*/
8302 static void
8303 genrshFour (operand * result, operand * left,
8304             int shCount, int sign)
8305 {
8306   D (emitcode (";", "genrshFour");
8307     );
8308
8309   /* if shifting more that 3 bytes */
8310   if (shCount >= 24)
8311     {
8312       shCount -= 24;
8313       if (shCount)
8314         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8315       else
8316         movLeft2Result (left, MSB32, result, LSB, sign);
8317       addSign (result, MSB16, sign);
8318     }
8319   else if (shCount >= 16)
8320     {
8321       shCount -= 16;
8322       if (shCount)
8323         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8324       else
8325         {
8326           movLeft2Result (left, MSB24, result, LSB, 0);
8327           movLeft2Result (left, MSB32, result, MSB16, sign);
8328         }
8329       addSign (result, MSB24, sign);
8330     }
8331   else if (shCount >= 8)
8332     {
8333       shCount -= 8;
8334       if (shCount == 1)
8335         shiftRLong (left, MSB16, result, sign);
8336       else if (shCount == 0)
8337         {
8338           movLeft2Result (left, MSB16, result, LSB, 0);
8339           movLeft2Result (left, MSB24, result, MSB16, 0);
8340           movLeft2Result (left, MSB32, result, MSB24, sign);
8341           addSign (result, MSB32, sign);
8342         }
8343       else
8344         {
8345           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8346           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8347           /* the last shift is signed */
8348           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8349           addSign (result, MSB32, sign);
8350         }
8351     }
8352   else
8353     {                           /* 1 <= shCount <= 7 */
8354       if (shCount <= 2)
8355         {
8356           shiftRLong (left, LSB, result, sign);
8357           if (shCount == 2)
8358             shiftRLong (result, LSB, result, sign);
8359         }
8360       else
8361         {
8362           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8363           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8364           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8365         }
8366     }
8367 }
8368 #endif
8369
8370 #ifdef BETTER_LITERAL_SHIFT
8371 /*-----------------------------------------------------------------*/
8372 /* genRightShiftLiteral - right shifting by known count            */
8373 /*-----------------------------------------------------------------*/
8374 static bool
8375 genRightShiftLiteral (operand * left,
8376                       operand * right,
8377                       operand * result,
8378                       iCode * ic,
8379                       int sign)
8380 {
8381   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8382   int size;
8383
8384   size = getSize (operandType (result));
8385
8386   D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8387
8388   /* We only handle certain easy cases so far. */
8389   if ((shCount != 0)
8390    && (shCount < (size * 8))
8391    && (size != 1)
8392    && (size != 2))
8393   {
8394       D(emitcode (";", "genRightShiftLiteral wimping out"););   
8395       return FALSE;
8396   }
8397
8398   freeAsmop (right, NULL, ic, TRUE);
8399
8400   aopOp (left, ic, FALSE, FALSE);
8401   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8402
8403 #if VIEW_SIZE
8404   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8405             AOP_SIZE (left));
8406 #endif
8407
8408   /* test the LEFT size !!! */
8409
8410   /* I suppose that the left size >= result size */
8411   if (shCount == 0)
8412   {
8413       size = getDataSize (result);
8414       _startLazyDPSEvaluation();
8415       while (size--)
8416       {
8417         movLeft2Result (left, size, result, size, 0);
8418       }
8419       _endLazyDPSEvaluation();
8420   }
8421   else if (shCount >= (size * 8))
8422     {
8423       if (sign)
8424       {
8425         /* get sign in acc.7 */
8426         MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
8427       }
8428       addSign (result, LSB, sign);
8429     }
8430   else
8431     {
8432       switch (size)
8433         {
8434         case 1:
8435           genrshOne (result, left, shCount, sign);
8436           break;
8437
8438         case 2:
8439           genrshTwo (result, left, shCount, sign);
8440           break;
8441 #if 0
8442         case 4:
8443           genrshFour (result, left, shCount, sign);
8444           break;
8445 #endif    
8446         default:
8447           break;
8448         }
8449
8450       freeAsmop (left, NULL, ic, TRUE);
8451       freeAsmop (result, NULL, ic, TRUE);
8452     }
8453     return TRUE;
8454 }
8455 #endif
8456
8457 /*-----------------------------------------------------------------*/
8458 /* genSignedRightShift - right shift of signed number              */
8459 /*-----------------------------------------------------------------*/
8460 static void
8461 genSignedRightShift (iCode * ic)
8462 {
8463   operand *right, *left, *result;
8464   int size, offset;
8465   char *l;
8466   symbol *tlbl, *tlbl1;
8467
8468   D (emitcode (";", "genSignedRightShift "););
8469
8470   /* we do it the hard way put the shift count in b
8471      and loop thru preserving the sign */
8472
8473   right = IC_RIGHT (ic);
8474   left = IC_LEFT (ic);
8475   result = IC_RESULT (ic);
8476
8477   aopOp (right, ic, FALSE, FALSE);
8478
8479 #ifdef BETTER_LITERAL_SHIFT
8480   if (AOP_TYPE (right) == AOP_LIT)
8481     {
8482       if (genRightShiftLiteral (left, right, result, ic, 1))
8483       {
8484         return;
8485       }
8486     }
8487 #endif
8488   /* shift count is unknown then we have to form
8489      a loop get the loop count in B : Note: we take
8490      only the lower order byte since shifting
8491      more that 32 bits make no sense anyway, ( the
8492      largest size of an object can be only 32 bits ) */
8493
8494   if (AOP_TYPE (right) == AOP_LIT)
8495   {
8496       /* Really should be handled by genRightShiftLiteral,
8497        * but since I'm too lazy to fix that today, at least we can make
8498        * some small improvement.
8499        */
8500        emitcode("mov", "b,#!constbyte",
8501                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8502   }
8503   else
8504   {
8505         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8506         emitcode ("inc", "b");
8507   }
8508   freeAsmop (right, NULL, ic, TRUE);
8509   aopOp (left, ic, FALSE, FALSE);
8510   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8511
8512   /* now move the left to the result if they are not the
8513      same */
8514   if (!sameRegs (AOP (left), AOP (result)) &&
8515       AOP_SIZE (result) > 1)
8516     {
8517
8518       size = AOP_SIZE (result);
8519       offset = 0;
8520       _startLazyDPSEvaluation ();
8521       while (size--)
8522         {
8523           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8524           if (*l == '@' && IS_AOP_PREG (result))
8525             {
8526
8527               emitcode ("mov", "a,%s", l);
8528               aopPut (AOP (result), "a", offset);
8529             }
8530           else
8531             aopPut (AOP (result), l, offset);
8532           offset++;
8533         }
8534       _endLazyDPSEvaluation ();
8535     }
8536
8537   /* mov the highest order bit to OVR */
8538   tlbl = newiTempLabel (NULL);
8539   tlbl1 = newiTempLabel (NULL);
8540
8541   size = AOP_SIZE (result);
8542   offset = size - 1;
8543   emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
8544   emitcode ("rlc", "a");
8545   emitcode ("mov", "ov,c");
8546   /* if it is only one byte then */
8547   if (size == 1)
8548     {
8549       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8550       MOVA (l);
8551       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8552       emitcode ("", "!tlabeldef", tlbl->key + 100);
8553       emitcode ("mov", "c,ov");
8554       emitcode ("rrc", "a");
8555       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8556       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8557       aopPut (AOP (result), "a", 0);
8558       goto release;
8559     }
8560
8561   reAdjustPreg (AOP (result));
8562   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8563   emitcode ("", "!tlabeldef", tlbl->key + 100);
8564   emitcode ("mov", "c,ov");
8565   _startLazyDPSEvaluation ();
8566   while (size--)
8567     {
8568       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8569       MOVA (l);
8570       emitcode ("rrc", "a");
8571       aopPut (AOP (result), "a", offset--);
8572     }
8573   _endLazyDPSEvaluation ();
8574   reAdjustPreg (AOP (result));
8575   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8576   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8577
8578 release:
8579   freeAsmop (left, NULL, ic, TRUE);
8580   freeAsmop (result, NULL, ic, TRUE);
8581 }
8582
8583 /*-----------------------------------------------------------------*/
8584 /* genRightShift - generate code for right shifting                */
8585 /*-----------------------------------------------------------------*/
8586 static void
8587 genRightShift (iCode * ic)
8588 {
8589   operand *right, *left, *result;
8590   sym_link *retype;
8591   int size, offset;
8592   char *l;
8593   symbol *tlbl, *tlbl1;
8594
8595   D (emitcode (";", "genRightShift "););
8596
8597   /* if signed then we do it the hard way preserve the
8598      sign bit moving it inwards */
8599   retype = getSpec (operandType (IC_RESULT (ic)));
8600
8601   if (!SPEC_USIGN (retype))
8602     {
8603       genSignedRightShift (ic);
8604       return;
8605     }
8606
8607   /* signed & unsigned types are treated the same : i.e. the
8608      signed is NOT propagated inwards : quoting from the
8609      ANSI - standard : "for E1 >> E2, is equivalent to division
8610      by 2**E2 if unsigned or if it has a non-negative value,
8611      otherwise the result is implementation defined ", MY definition
8612      is that the sign does not get propagated */
8613
8614   right = IC_RIGHT (ic);
8615   left = IC_LEFT (ic);
8616   result = IC_RESULT (ic);
8617
8618   aopOp (right, ic, FALSE, FALSE);
8619
8620 #ifdef BETTER_LITERAL_SHIFT
8621   /* if the shift count is known then do it
8622      as efficiently as possible */
8623   if (AOP_TYPE (right) == AOP_LIT)
8624     {
8625       if (genRightShiftLiteral (left, right, result, ic, 0))
8626       {
8627         return;
8628       }
8629     }
8630 #endif
8631
8632   /* shift count is unknown then we have to form
8633      a loop get the loop count in B : Note: we take
8634      only the lower order byte since shifting
8635      more that 32 bits make no sense anyway, ( the
8636      largest size of an object can be only 32 bits ) */
8637   
8638   if (AOP_TYPE (right) == AOP_LIT)
8639   {
8640       /* Really should be handled by genRightShiftLiteral,
8641        * but since I'm too lazy to fix that today, at least we can make
8642        * some small improvement.
8643        */
8644        emitcode("mov", "b,#!constbyte",
8645                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8646   }
8647   else
8648   {
8649         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8650         emitcode ("inc", "b");
8651   }
8652   freeAsmop (right, NULL, ic, TRUE);
8653   aopOp (left, ic, FALSE, FALSE);
8654   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8655
8656   /* now move the left to the result if they are not the
8657      same */
8658   if (!sameRegs (AOP (left), AOP (result)) &&
8659       AOP_SIZE (result) > 1)
8660     {
8661
8662       size = AOP_SIZE (result);
8663       offset = 0;
8664       _startLazyDPSEvaluation ();
8665       while (size--)
8666         {
8667           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8668           if (*l == '@' && IS_AOP_PREG (result))
8669             {
8670
8671               emitcode ("mov", "a,%s", l);
8672               aopPut (AOP (result), "a", offset);
8673             }
8674           else
8675             aopPut (AOP (result), l, offset);
8676           offset++;
8677         }
8678       _endLazyDPSEvaluation ();
8679     }
8680
8681   tlbl = newiTempLabel (NULL);
8682   tlbl1 = newiTempLabel (NULL);
8683   size = AOP_SIZE (result);
8684   offset = size - 1;
8685
8686   /* if it is only one byte then */
8687   if (size == 1)
8688     {
8689       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8690       MOVA (l);
8691       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8692       emitcode ("", "!tlabeldef", tlbl->key + 100);
8693       CLRC;
8694       emitcode ("rrc", "a");
8695       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8696       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8697       aopPut (AOP (result), "a", 0);
8698       goto release;
8699     }
8700
8701   reAdjustPreg (AOP (result));
8702   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8703   emitcode ("", "!tlabeldef", tlbl->key + 100);
8704   CLRC;
8705   _startLazyDPSEvaluation ();
8706   while (size--)
8707     {
8708       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8709       MOVA (l);
8710       emitcode ("rrc", "a");
8711       aopPut (AOP (result), "a", offset--);
8712     }
8713   _endLazyDPSEvaluation ();
8714   reAdjustPreg (AOP (result));
8715
8716   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8717   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8718
8719 release:
8720   freeAsmop (left, NULL, ic, TRUE);
8721   freeAsmop (result, NULL, ic, TRUE);
8722 }
8723
8724 /*-----------------------------------------------------------------*/
8725 /* genUnpackBits - generates code for unpacking bits               */
8726 /*-----------------------------------------------------------------*/
8727 static void
8728 genUnpackBits (operand * result, char *rname, int ptype)
8729 {
8730   int shCnt;
8731   int rlen = 0;
8732   sym_link *etype;
8733   int offset = 0;
8734
8735   D (emitcode (";", "genUnpackBits ");
8736     );
8737
8738   etype = getSpec (operandType (result));
8739
8740   /* read the first byte  */
8741   switch (ptype)
8742     {
8743
8744     case POINTER:
8745     case IPOINTER:
8746       emitcode ("mov", "a,@%s", rname);
8747       break;
8748
8749     case PPOINTER:
8750       emitcode ("movx", "a,@%s", rname);
8751       break;
8752
8753     case FPOINTER:
8754       emitcode ("movx", "a,@dptr");
8755       break;
8756
8757     case CPOINTER:
8758       emitcode ("clr", "a");
8759       emitcode ("movc", "a,@a+dptr");
8760       break;
8761
8762     case GPOINTER:
8763       emitcode ("lcall", "__gptrget");
8764       break;
8765     }
8766
8767   /* if we have bitdisplacement then it fits   */
8768   /* into this byte completely or if length is */
8769   /* less than a byte                          */
8770   if ((shCnt = SPEC_BSTR (etype)) ||
8771       (SPEC_BLEN (etype) <= 8))
8772     {
8773
8774       /* shift right acc */
8775       AccRsh (shCnt);
8776
8777       emitcode ("anl", "a,#!constbyte",
8778                 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
8779       aopPut (AOP (result), "a", offset);
8780       return;
8781     }
8782
8783   /* bit field did not fit in a byte  */
8784   rlen = SPEC_BLEN (etype) - 8;
8785   aopPut (AOP (result), "a", offset++);
8786
8787   while (1)
8788     {
8789
8790       switch (ptype)
8791         {
8792         case POINTER:
8793         case IPOINTER:
8794           emitcode ("inc", "%s", rname);
8795           emitcode ("mov", "a,@%s", rname);
8796           break;
8797
8798         case PPOINTER:
8799           emitcode ("inc", "%s", rname);
8800           emitcode ("movx", "a,@%s", rname);
8801           break;
8802
8803         case FPOINTER:
8804           emitcode ("inc", "dptr");
8805           emitcode ("movx", "a,@dptr");
8806           break;
8807
8808         case CPOINTER:
8809           emitcode ("clr", "a");
8810           emitcode ("inc", "dptr");
8811           emitcode ("movc", "a,@a+dptr");
8812           break;
8813
8814         case GPOINTER:
8815           emitcode ("inc", "dptr");
8816           emitcode ("lcall", "__gptrget");
8817           break;
8818         }
8819
8820       rlen -= 8;
8821       /* if we are done */
8822       if (rlen < 8)
8823         break;
8824
8825       aopPut (AOP (result), "a", offset++);
8826
8827     }
8828
8829   if (rlen)
8830     {
8831       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (rlen));
8832       aopPut (AOP (result), "a", offset);
8833     }
8834
8835   return;
8836 }
8837
8838
8839 /*-----------------------------------------------------------------*/
8840 /* genDataPointerGet - generates code when ptr offset is known     */
8841 /*-----------------------------------------------------------------*/
8842 static void
8843 genDataPointerGet (operand * left,
8844                    operand * result,
8845                    iCode * ic)
8846 {
8847   char *l;
8848   char buffer[256];
8849   int size, offset = 0;
8850   aopOp (result, ic, TRUE, FALSE);
8851
8852   /* get the string representation of the name */
8853   l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
8854   size = AOP_SIZE (result);
8855   _startLazyDPSEvaluation ();
8856   while (size--)
8857     {
8858       if (offset)
8859         sprintf (buffer, "(%s + %d)", l + 1, offset);
8860       else
8861         sprintf (buffer, "%s", l + 1);
8862       aopPut (AOP (result), buffer, offset++);
8863     }
8864   _endLazyDPSEvaluation ();
8865
8866   freeAsmop (left, NULL, ic, TRUE);
8867   freeAsmop (result, NULL, ic, TRUE);
8868 }
8869
8870 /*-----------------------------------------------------------------*/
8871 /* genNearPointerGet - emitcode for near pointer fetch             */
8872 /*-----------------------------------------------------------------*/
8873 static void
8874 genNearPointerGet (operand * left,
8875                    operand * result,
8876                    iCode * ic,
8877                    iCode *pi)
8878 {
8879   asmop *aop = NULL;
8880   regs *preg = NULL;
8881   char *rname;
8882   sym_link *rtype, *retype, *letype;
8883   sym_link *ltype = operandType (left);
8884   char buffer[80];
8885
8886   rtype = operandType (result);
8887   retype = getSpec (rtype);
8888   letype = getSpec (ltype);
8889
8890   aopOp (left, ic, FALSE, FALSE);
8891
8892   /* if left is rematerialisable and
8893      result is not bit variable type and
8894      the left is pointer to data space i.e
8895      lower 128 bytes of space */
8896   if (AOP_TYPE (left) == AOP_IMMD &&
8897       !IS_BITVAR (retype) &&
8898       !IS_BITVAR (letype) &&
8899       DCL_TYPE (ltype) == POINTER)
8900     {
8901       genDataPointerGet (left, result, ic);
8902       return;
8903     }
8904
8905   /* if the value is already in a pointer register
8906      then don't need anything more */
8907   if (!AOP_INPREG (AOP (left)))
8908     {
8909       /* otherwise get a free pointer register */
8910       aop = newAsmop (0);
8911       preg = getFreePtr (ic, &aop, FALSE);
8912       emitcode ("mov", "%s,%s",
8913                 preg->name,
8914                 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8915       rname = preg->name;
8916     }
8917   else
8918     rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8919
8920   freeAsmop (left, NULL, ic, TRUE);
8921   aopOp (result, ic, FALSE, FALSE);
8922
8923   /* if bitfield then unpack the bits */
8924   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8925     genUnpackBits (result, rname, POINTER);
8926   else
8927     {
8928       /* we have can just get the values */
8929       int size = AOP_SIZE (result);
8930       int offset = 0;
8931
8932       while (size--)
8933         {
8934           if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8935             {
8936
8937               emitcode ("mov", "a,@%s", rname);
8938               aopPut (AOP (result), "a", offset);
8939             }
8940           else
8941             {
8942               sprintf (buffer, "@%s", rname);
8943               aopPut (AOP (result), buffer, offset);
8944             }
8945           offset++;
8946           if (size || pi)
8947             emitcode ("inc", "%s", rname);
8948         }
8949     }
8950
8951   /* now some housekeeping stuff */
8952   if (aop)
8953     {
8954       /* we had to allocate for this iCode */
8955       if (pi) { /* post increment present */
8956         aopPut(AOP ( left ),rname,0);
8957       }
8958       freeAsmop (NULL, aop, ic, TRUE);
8959     }
8960   else
8961     {
8962       /* we did not allocate which means left
8963          already in a pointer register, then
8964          if size > 0 && this could be used again
8965          we have to point it back to where it
8966          belongs */
8967       if (AOP_SIZE (result) > 1 &&
8968           !OP_SYMBOL (left)->remat &&
8969           (OP_SYMBOL (left)->liveTo > ic->seq ||
8970            ic->depth) &&
8971           !pi)
8972         {
8973           int size = AOP_SIZE (result) - 1;
8974           while (size--)
8975             emitcode ("dec", "%s", rname);
8976         }
8977     }
8978
8979   /* done */
8980   freeAsmop (result, NULL, ic, TRUE);
8981   if (pi) pi->generated = 1;
8982 }
8983
8984 /*-----------------------------------------------------------------*/
8985 /* genPagedPointerGet - emitcode for paged pointer fetch           */
8986 /*-----------------------------------------------------------------*/
8987 static void
8988 genPagedPointerGet (operand * left,
8989                     operand * result,
8990                     iCode * ic,
8991                     iCode * pi)
8992 {
8993   asmop *aop = NULL;
8994   regs *preg = NULL;
8995   char *rname;
8996   sym_link *rtype, *retype, *letype;
8997
8998   rtype = operandType (result);
8999   retype = getSpec (rtype);
9000   letype = getSpec (operandType (left));
9001   aopOp (left, ic, FALSE, FALSE);
9002
9003   /* if the value is already in a pointer register
9004      then don't need anything more */
9005   if (!AOP_INPREG (AOP (left)))
9006     {
9007       /* otherwise get a free pointer register */
9008       aop = newAsmop (0);
9009       preg = getFreePtr (ic, &aop, FALSE);
9010       emitcode ("mov", "%s,%s",
9011                 preg->name,
9012                 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
9013       rname = preg->name;
9014     }
9015   else
9016     rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
9017
9018   freeAsmop (left, NULL, ic, TRUE);
9019   aopOp (result, ic, FALSE, FALSE);
9020
9021   /* if bitfield then unpack the bits */
9022   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9023     genUnpackBits (result, rname, PPOINTER);
9024   else
9025     {
9026       /* we have can just get the values */
9027       int size = AOP_SIZE (result);
9028       int offset = 0;
9029
9030       while (size--)
9031         {
9032
9033           emitcode ("movx", "a,@%s", rname);
9034           aopPut (AOP (result), "a", offset);
9035
9036           offset++;
9037
9038           if (size || pi)
9039             emitcode ("inc", "%s", rname);
9040         }
9041     }
9042
9043   /* now some housekeeping stuff */
9044   if (aop)
9045     {
9046       /* we had to allocate for this iCode */
9047       if (pi) aopPut ( AOP (left), rname, 0);
9048       freeAsmop (NULL, aop, ic, TRUE);
9049     }
9050   else
9051     {
9052       /* we did not allocate which means left
9053          already in a pointer register, then
9054          if size > 0 && this could be used again
9055          we have to point it back to where it
9056          belongs */
9057       if (AOP_SIZE (result) > 1 &&
9058           !OP_SYMBOL (left)->remat &&
9059           (OP_SYMBOL (left)->liveTo > ic->seq ||
9060            ic->depth) &&
9061           !pi)
9062         {
9063           int size = AOP_SIZE (result) - 1;
9064           while (size--)
9065             emitcode ("dec", "%s", rname);
9066         }
9067     }
9068
9069   /* done */
9070   freeAsmop (result, NULL, ic, TRUE);
9071   if (pi) pi->generated = 1;
9072 }
9073
9074 /*-----------------------------------------------------------------*/
9075 /* genFarPointerGet - gget value from far space                    */
9076 /*-----------------------------------------------------------------*/
9077 static void
9078 genFarPointerGet (operand * left,
9079                   operand * result, iCode * ic, iCode *pi)
9080 {
9081     int size, offset, dopi=1;
9082   sym_link *retype = getSpec (operandType (result));
9083   sym_link *letype = getSpec (operandType (left));
9084   D (emitcode (";", "genFarPointerGet");
9085     );
9086
9087   aopOp (left, ic, FALSE, FALSE);
9088
9089   /* if the operand is already in dptr
9090      then we do nothing else we move the value to dptr */
9091   if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9092     {
9093       /* if this is remateriazable */
9094       if (AOP_TYPE (left) == AOP_IMMD)
9095         {
9096           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9097         }
9098       else
9099         {
9100           /* we need to get it byte by byte */
9101           _startLazyDPSEvaluation ();
9102           if (AOP_TYPE (left) != AOP_DPTR)
9103             {
9104               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9105               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9106               if (options.model == MODEL_FLAT24)
9107                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9108             }
9109           else
9110             {
9111               /* We need to generate a load to DPTR indirect through DPTR. */
9112               D (emitcode (";", "genFarPointerGet -- indirection special case.");
9113                 );
9114               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
9115               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
9116               if (options.model == MODEL_FLAT24)
9117                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9118               emitcode ("pop", "dph");
9119               emitcode ("pop", "dpl");
9120               dopi =0;
9121             }
9122           _endLazyDPSEvaluation ();
9123         }
9124     }
9125   /* so dptr know contains the address */
9126   aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9127
9128   /* if bit then unpack */
9129   if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
9130       if (AOP_INDPTRn(left)) {
9131           genSetDPTR(AOP(left)->aopu.dptr);
9132       }
9133       genUnpackBits (result, "dptr", FPOINTER);
9134       if (AOP_INDPTRn(left)) {
9135           genSetDPTR(0);
9136       }
9137   } else
9138     {
9139       size = AOP_SIZE (result);
9140       offset = 0;
9141
9142       if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9143           while (size--) {
9144               genSetDPTR(AOP(left)->aopu.dptr);
9145               emitcode ("movx", "a,@dptr");
9146               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9147                   emitcode ("inc", "dptr");
9148               genSetDPTR (0);
9149               aopPut (AOP (result), "a", offset++);
9150           }
9151       } else {
9152           _startLazyDPSEvaluation ();
9153           while (size--) {
9154               if (AOP_INDPTRn(left)) {
9155                   genSetDPTR(AOP(left)->aopu.dptr);
9156               } else {
9157                   genSetDPTR (0);
9158               }
9159               _flushLazyDPS ();
9160               
9161               emitcode ("movx", "a,@dptr");
9162               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9163                   emitcode ("inc", "dptr");
9164               
9165               aopPut (AOP (result), "a", offset++);
9166           }
9167           _endLazyDPSEvaluation ();
9168       }
9169     }
9170   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9171       if (!AOP_INDPTRn(left)) {
9172           aopPut ( AOP (left), "dpl", 0);
9173           aopPut ( AOP (left), "dph", 1);
9174           if (options.model == MODEL_FLAT24)
9175               aopPut ( AOP (left), "dpx", 2);
9176       }
9177     pi->generated = 1;
9178   } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) && 
9179              AOP_SIZE(result) > 1 &&
9180              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9181       
9182       size = AOP_SIZE (result) - 1;
9183       if (AOP_INDPTRn(left)) {
9184           genSetDPTR(AOP(left)->aopu.dptr);
9185       }
9186       while (size--) emitcode ("lcall","__decdptr");
9187       if (AOP_INDPTRn(left)) {
9188           genSetDPTR(0);
9189       }
9190   }
9191
9192   freeAsmop (left, NULL, ic, TRUE);
9193   freeAsmop (result, NULL, ic, TRUE);
9194 }
9195
9196 /*-----------------------------------------------------------------*/
9197 /* emitcodePointerGet - gget value from code space                  */
9198 /*-----------------------------------------------------------------*/
9199 static void
9200 emitcodePointerGet (operand * left,
9201                     operand * result, iCode * ic, iCode *pi)
9202 {
9203   int size, offset, dopi=1;
9204   sym_link *retype = getSpec (operandType (result));
9205
9206   aopOp (left, ic, FALSE, FALSE);
9207
9208   /* if the operand is already in dptr
9209      then we do nothing else we move the value to dptr */
9210   if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
9211     {
9212       /* if this is remateriazable */
9213       if (AOP_TYPE (left) == AOP_IMMD)
9214         {
9215           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9216         }
9217       else
9218         {                       /* we need to get it byte by byte */
9219           _startLazyDPSEvaluation ();
9220           if (AOP_TYPE (left) != AOP_DPTR)
9221             {
9222               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9223               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9224               if (options.model == MODEL_FLAT24)
9225                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9226             }
9227           else
9228             {
9229               /* We need to generate a load to DPTR indirect through DPTR. */
9230               D (emitcode (";", "gencodePointerGet -- indirection special case.");
9231                 );
9232               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
9233               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
9234               if (options.model == MODEL_FLAT24)
9235                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9236               emitcode ("pop", "dph");
9237               emitcode ("pop", "dpl");
9238               dopi=0;
9239             }
9240           _endLazyDPSEvaluation ();
9241         }
9242     }
9243   /* so dptr know contains the address */
9244   aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9245
9246   /* if bit then unpack */
9247   if (IS_BITVAR (retype)) {
9248       if (AOP_INDPTRn(left)) {
9249           genSetDPTR(AOP(left)->aopu.dptr);
9250       }
9251       genUnpackBits (result, "dptr", CPOINTER);
9252       if (AOP_INDPTRn(left)) {
9253           genSetDPTR(0);
9254       }
9255   } else
9256     {
9257       size = AOP_SIZE (result);
9258       offset = 0;
9259       if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9260           while (size--) {
9261               genSetDPTR(AOP(left)->aopu.dptr);
9262               emitcode ("clr", "a");
9263               emitcode ("movc", "a,@a+dptr");
9264               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9265                   emitcode ("inc", "dptr");
9266               genSetDPTR (0);
9267               aopPut (AOP (result), "a", offset++);
9268           }
9269       } else {
9270           _startLazyDPSEvaluation ();
9271           while (size--)
9272               {
9273                   if (AOP_INDPTRn(left)) {
9274                       genSetDPTR(AOP(left)->aopu.dptr);
9275                   } else {
9276                       genSetDPTR (0);
9277                   }
9278                   _flushLazyDPS ();
9279                   
9280                   emitcode ("clr", "a");
9281                   emitcode ("movc", "a,@a+dptr");
9282                   if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9283                       emitcode ("inc", "dptr");
9284                   aopPut (AOP (result), "a", offset++);
9285               }
9286           _endLazyDPSEvaluation ();
9287       }
9288     }
9289   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9290       if (!AOP_INDPTRn(left)) {
9291           aopPut ( AOP (left), "dpl", 0);
9292           aopPut ( AOP (left), "dph", 1);
9293           if (options.model == MODEL_FLAT24)
9294               aopPut ( AOP (left), "dpx", 2);
9295       }
9296       pi->generated = 1;
9297   } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) && 
9298              AOP_SIZE(result) > 1 &&
9299              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9300       
9301       size = AOP_SIZE (result) - 1;
9302       if (AOP_INDPTRn(left)) {
9303           genSetDPTR(AOP(left)->aopu.dptr);
9304       }
9305       while (size--) emitcode ("lcall","__decdptr");
9306       if (AOP_INDPTRn(left)) {
9307           genSetDPTR(0);
9308       }
9309   }
9310   
9311   freeAsmop (left, NULL, ic, TRUE);
9312   freeAsmop (result, NULL, ic, TRUE);
9313 }
9314
9315 /*-----------------------------------------------------------------*/
9316 /* genGenPointerGet - gget value from generic pointer space        */
9317 /*-----------------------------------------------------------------*/
9318 static void
9319 genGenPointerGet (operand * left,
9320                   operand * result, iCode * ic, iCode * pi)
9321 {
9322   int size, offset;
9323   sym_link *retype = getSpec (operandType (result));
9324   sym_link *letype = getSpec (operandType (left));
9325
9326   D (emitcode (";", "genGenPointerGet "); );
9327
9328   aopOp (left, ic, FALSE, (OP_SYMBOL(left)->ruonly ? FALSE : TRUE));
9329
9330   /* if the operand is already in dptr
9331      then we do nothing else we move the value to dptr */
9332   if (AOP_TYPE (left) != AOP_STR)
9333     {
9334       /* if this is remateriazable */
9335       if (AOP_TYPE (left) == AOP_IMMD)
9336         {
9337           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9338           if (AOP(left)->aopu.aop_immd.from_cast_remat) 
9339                   emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, FALSE));
9340           else
9341                   emitcode ("mov", "b,#%d", pointerCode (retype));
9342         }
9343       else
9344         {                       /* we need to get it byte by byte */
9345           _startLazyDPSEvaluation ();
9346           if (AOP(left)->type==AOP_DPTR2) {
9347             char *l;
9348             l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
9349             genSetDPTR(0);
9350             _flushLazyDPS();
9351             emitcode ("mov", "dpl,%s", l);
9352             l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
9353             genSetDPTR(0);
9354             _flushLazyDPS();
9355             emitcode ("mov", "dph,%s", l);
9356             if (options.model == MODEL_FLAT24) {
9357               l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
9358               genSetDPTR(0);
9359               _flushLazyDPS();
9360               emitcode ("mov", "dpx,%s", l);
9361               emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
9362             } else {
9363               emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9364             }
9365           } else {
9366             emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
9367             emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
9368             if (options.model == MODEL_FLAT24) {
9369               emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9370               emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
9371             } else {
9372               emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9373             }
9374           }
9375           _endLazyDPSEvaluation ();
9376         }
9377     }
9378   /* so dptr know contains the address */
9379   aopOp (result, ic, FALSE, TRUE);
9380
9381   /* if bit then unpack */
9382   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9383     genUnpackBits (result, "dptr", GPOINTER);
9384   else
9385     {
9386       size = AOP_SIZE (result);
9387       offset = 0;
9388
9389       while (size--)
9390         {
9391           emitcode ("lcall", "__gptrget");
9392           aopPut (AOP (result), "a", offset++);
9393           if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9394             emitcode ("inc", "dptr");
9395         }
9396     }
9397
9398   if (pi && AOP_TYPE (left) != AOP_IMMD) {
9399     aopPut ( AOP (left), "dpl", 0);
9400     aopPut ( AOP (left), "dph", 1);
9401     if (options.model == MODEL_FLAT24) {
9402         aopPut ( AOP (left), "dpx", 2);
9403         aopPut ( AOP (left), "b", 3);   
9404     } else  aopPut ( AOP (left), "b", 2);       
9405     pi->generated = 1;
9406   } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9407              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9408       
9409       size = AOP_SIZE (result) - 1;
9410       while (size--) emitcode ("lcall","__decdptr");
9411   }
9412
9413   freeAsmop (left, NULL, ic, TRUE);
9414   freeAsmop (result, NULL, ic, TRUE);
9415 }
9416
9417 /*-----------------------------------------------------------------*/
9418 /* genPointerGet - generate code for pointer get                   */
9419 /*-----------------------------------------------------------------*/
9420 static void
9421 genPointerGet (iCode * ic, iCode *pi)
9422 {
9423   operand *left, *result;
9424   sym_link *type, *etype;
9425   int p_type;
9426
9427   D (emitcode (";", "genPointerGet ");
9428     );
9429
9430   left = IC_LEFT (ic);
9431   result = IC_RESULT (ic);
9432
9433   /* depending on the type of pointer we need to
9434      move it to the correct pointer register */
9435   type = operandType (left);
9436   etype = getSpec (type);
9437   /* if left is of type of pointer then it is simple */
9438   if (IS_PTR (type) && !IS_FUNC (type->next))
9439     p_type = DCL_TYPE (type);
9440   else
9441     {
9442       /* we have to go by the storage class */
9443       p_type = PTR_TYPE (SPEC_OCLS (etype));
9444     }
9445   /* special case when cast remat */
9446   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9447       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9448           left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9449           type =   type = operandType (left);
9450           p_type = DCL_TYPE (type);
9451   }
9452   /* now that we have the pointer type we assign
9453      the pointer values */
9454   switch (p_type)
9455     {
9456
9457     case POINTER:
9458     case IPOINTER:
9459       genNearPointerGet (left, result, ic, pi);
9460       break;
9461
9462     case PPOINTER:
9463       genPagedPointerGet (left, result, ic, pi);
9464       break;
9465
9466     case FPOINTER:
9467       genFarPointerGet (left, result, ic, pi);
9468       break;
9469
9470     case CPOINTER:
9471       emitcodePointerGet (left, result, ic, pi);
9472       break;
9473
9474     case GPOINTER:
9475       genGenPointerGet (left, result, ic, pi);
9476       break;
9477     }
9478
9479 }
9480
9481 /*-----------------------------------------------------------------*/
9482 /* genPackBits - generates code for packed bit storage             */
9483 /*-----------------------------------------------------------------*/
9484 static void
9485 genPackBits (sym_link * etype,
9486              operand * right,
9487              char *rname, int p_type)
9488 {
9489   int shCount = 0;
9490   int offset = 0;
9491   int rLen = 0;
9492   int blen, bstr;
9493   char *l;
9494
9495   blen = SPEC_BLEN (etype);
9496   bstr = SPEC_BSTR (etype);
9497
9498   l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9499   MOVA (l);
9500
9501   /* if the bit lenth is less than or    */
9502   /* it exactly fits a byte then         */
9503   if (SPEC_BLEN (etype) <= 8)
9504     {
9505       shCount = SPEC_BSTR (etype);
9506
9507       /* shift left acc */
9508       AccLsh (shCount);
9509
9510       if (SPEC_BLEN (etype) < 8)
9511         {                       /* if smaller than a byte */
9512
9513
9514           switch (p_type)
9515             {
9516             case POINTER:
9517               emitcode ("mov", "b,a");
9518               emitcode ("mov", "a,@%s", rname);
9519               break;
9520
9521             case FPOINTER:
9522               emitcode ("mov", "b,a");
9523               emitcode ("movx", "a,@dptr");
9524               break;
9525
9526             case GPOINTER:
9527               emitcode ("push", "b");
9528               emitcode ("push", "acc");
9529               emitcode ("lcall", "__gptrget");
9530               emitcode ("pop", "b");
9531               break;
9532             }
9533
9534           emitcode ("anl", "a,#!constbyte", (unsigned char)
9535                     ((unsigned char) (0xFF << (blen + bstr)) |
9536                      (unsigned char) (0xFF >> (8 - bstr))));
9537           emitcode ("orl", "a,b");
9538           if (p_type == GPOINTER)
9539             emitcode ("pop", "b");
9540         }
9541     }
9542
9543   switch (p_type)
9544     {
9545     case POINTER:
9546       emitcode ("mov", "@%s,a", rname);
9547       break;
9548
9549     case FPOINTER:
9550       emitcode ("movx", "@dptr,a");
9551       break;
9552
9553     case GPOINTER:
9554       emitcode ("lcall", "__gptrput");
9555       break;
9556     }
9557
9558   /* if we r done */
9559   if (SPEC_BLEN (etype) <= 8)
9560     return;
9561
9562   emitcode ("inc", "%s", rname);
9563   rLen = SPEC_BLEN (etype);
9564
9565   /* now generate for lengths greater than one byte */
9566   while (1)
9567     {
9568
9569       l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
9570
9571       rLen -= 8;
9572       if (rLen < 8)
9573         break;
9574
9575       switch (p_type)
9576         {
9577         case POINTER:
9578           if (*l == '@')
9579             {
9580               MOVA (l);
9581               emitcode ("mov", "@%s,a", rname);
9582             }
9583           else
9584             emitcode ("mov", "@%s,%s", rname, l);
9585           break;
9586
9587         case FPOINTER:
9588           MOVA (l);
9589           emitcode ("movx", "@dptr,a");
9590           break;
9591
9592         case GPOINTER:
9593           MOVA (l);
9594           emitcode ("lcall", "__gptrput");
9595           break;
9596         }
9597       emitcode ("inc", "%s", rname);
9598     }
9599
9600   MOVA (l);
9601
9602   /* last last was not complete */
9603   if (rLen)
9604     {
9605       /* save the byte & read byte */
9606       switch (p_type)
9607         {
9608         case POINTER:
9609           emitcode ("mov", "b,a");
9610           emitcode ("mov", "a,@%s", rname);
9611           break;
9612
9613         case FPOINTER:
9614           emitcode ("mov", "b,a");
9615           emitcode ("movx", "a,@dptr");
9616           break;
9617
9618         case GPOINTER:
9619           emitcode ("push", "b");
9620           emitcode ("push", "acc");
9621           emitcode ("lcall", "__gptrget");
9622           emitcode ("pop", "b");
9623           break;
9624         }
9625
9626       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1 << rLen));
9627       emitcode ("orl", "a,b");
9628     }
9629
9630   if (p_type == GPOINTER)
9631     emitcode ("pop", "b");
9632
9633   switch (p_type)
9634     {
9635
9636     case POINTER:
9637       emitcode ("mov", "@%s,a", rname);
9638       break;
9639
9640     case FPOINTER:
9641       emitcode ("movx", "@dptr,a");
9642       break;
9643
9644     case GPOINTER:
9645       emitcode ("lcall", "__gptrput");
9646       break;
9647     }
9648 }
9649 /*-----------------------------------------------------------------*/
9650 /* genDataPointerSet - remat pointer to data space                 */
9651 /*-----------------------------------------------------------------*/
9652 static void
9653 genDataPointerSet (operand * right,
9654                    operand * result,
9655                    iCode * ic)
9656 {
9657   int size, offset = 0;
9658   char *l, buffer[256];
9659
9660   aopOp (right, ic, FALSE, FALSE);
9661
9662   l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
9663   size = AOP_SIZE (right);
9664   while (size--)
9665     {
9666       if (offset)
9667         sprintf (buffer, "(%s + %d)", l + 1, offset);
9668       else
9669         sprintf (buffer, "%s", l + 1);
9670       emitcode ("mov", "%s,%s", buffer,
9671                 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
9672     }
9673
9674   freeAsmop (right, NULL, ic, TRUE);
9675   freeAsmop (result, NULL, ic, TRUE);
9676 }
9677
9678 /*-----------------------------------------------------------------*/
9679 /* genNearPointerSet - emitcode for near pointer put                */
9680 /*-----------------------------------------------------------------*/
9681 static void
9682 genNearPointerSet (operand * right,
9683                    operand * result,
9684                    iCode * ic,
9685                    iCode * pi)
9686 {
9687   asmop *aop = NULL;
9688   regs *preg = NULL;
9689   char *rname, *l;
9690   sym_link *retype, *letype;
9691   sym_link *ptype = operandType (result);
9692
9693   retype = getSpec (operandType (right));
9694   letype = getSpec (ptype);
9695
9696   aopOp (result, ic, FALSE, FALSE);
9697
9698   /* if the result is rematerializable &
9699      in data space & not a bit variable */
9700   if (AOP_TYPE (result) == AOP_IMMD &&
9701       DCL_TYPE (ptype) == POINTER &&
9702       !IS_BITVAR (retype) &&
9703       !IS_BITVAR (letype))
9704     {
9705       genDataPointerSet (right, result, ic);
9706       return;
9707     }
9708
9709   /* if the value is already in a pointer register
9710      then don't need anything more */
9711   if (!AOP_INPREG (AOP (result)))
9712     {
9713       /* otherwise get a free pointer register */
9714       aop = newAsmop (0);
9715       preg = getFreePtr (ic, &aop, FALSE);
9716       emitcode ("mov", "%s,%s",
9717                 preg->name,
9718                 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9719       rname = preg->name;
9720     }
9721   else
9722     rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9723
9724   aopOp (right, ic, FALSE, FALSE);
9725
9726   /* if bitfield then unpack the bits */
9727   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9728     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
9729   else
9730     {
9731       /* we have can just get the values */
9732       int size = AOP_SIZE (right);
9733       int offset = 0;
9734
9735       while (size--)
9736         {
9737           l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
9738           if (*l == '@')
9739             {
9740               MOVA (l);
9741               emitcode ("mov", "@%s,a", rname);
9742             }
9743           else
9744             emitcode ("mov", "@%s,%s", rname, l);
9745           if (size || pi)
9746             emitcode ("inc", "%s", rname);
9747           offset++;
9748         }
9749     }
9750
9751   /* now some housekeeping stuff */
9752   if (aop)
9753     {
9754       /* we had to allocate for this iCode */
9755       if (pi) aopPut (AOP (result),rname,0);
9756       freeAsmop (NULL, aop, ic, TRUE);
9757     }
9758   else
9759     {
9760       /* we did not allocate which means left
9761          already in a pointer register, then
9762          if size > 0 && this could be used again
9763          we have to point it back to where it
9764          belongs */
9765       if (AOP_SIZE (right) > 1 &&
9766           !OP_SYMBOL (result)->remat &&
9767           (OP_SYMBOL (result)->liveTo > ic->seq ||
9768            ic->depth) &&
9769           !pi)
9770         {
9771           int size = AOP_SIZE (right) - 1;
9772           while (size--)
9773             emitcode ("dec", "%s", rname);
9774         }
9775     }
9776
9777   /* done */
9778   if (pi) pi->generated = 1;
9779   freeAsmop (result, NULL, ic, TRUE);
9780   freeAsmop (right, NULL, ic, TRUE);
9781
9782
9783 }
9784
9785 /*-----------------------------------------------------------------*/
9786 /* genPagedPointerSet - emitcode for Paged pointer put             */
9787 /*-----------------------------------------------------------------*/
9788 static void
9789 genPagedPointerSet (operand * right,
9790                     operand * result,
9791                     iCode * ic,
9792                     iCode *pi)
9793 {
9794   asmop *aop = NULL;
9795   regs *preg = NULL;
9796   char *rname, *l;
9797   sym_link *retype, *letype;
9798
9799   retype = getSpec (operandType (right));
9800   letype = getSpec (operandType (result));
9801
9802   aopOp (result, ic, FALSE, FALSE);
9803
9804   /* if the value is already in a pointer register
9805      then don't need anything more */
9806   if (!AOP_INPREG (AOP (result)))
9807     {
9808       /* otherwise get a free pointer register */
9809       aop = newAsmop (0);
9810       preg = getFreePtr (ic, &aop, FALSE);
9811       emitcode ("mov", "%s,%s",
9812                 preg->name,
9813                 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9814       rname = preg->name;
9815     }
9816   else
9817     rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9818
9819   aopOp (right, ic, FALSE, FALSE);
9820
9821   /* if bitfield then unpack the bits */
9822   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9823     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
9824   else
9825     {
9826       /* we have can just get the values */
9827       int size = AOP_SIZE (right);
9828       int offset = 0;
9829
9830       while (size--)
9831         {
9832           l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
9833
9834           MOVA (l);
9835           emitcode ("movx", "@%s,a", rname);
9836
9837           if (size || pi)
9838             emitcode ("inc", "%s", rname);
9839
9840           offset++;
9841         }
9842     }
9843
9844   /* now some housekeeping stuff */
9845   if (aop)
9846     {
9847       if (pi) aopPut (AOP (result),rname,0);
9848       /* we had to allocate for this iCode */
9849       freeAsmop (NULL, aop, ic, TRUE);
9850     }
9851   else
9852     {
9853       /* we did not allocate which means left
9854          already in a pointer register, then
9855          if size > 0 && this could be used again
9856          we have to point it back to where it
9857          belongs */
9858       if (AOP_SIZE (right) > 1 &&
9859           !OP_SYMBOL (result)->remat &&
9860           (OP_SYMBOL (result)->liveTo > ic->seq ||
9861            ic->depth) &&
9862           !pi)
9863         {
9864           int size = AOP_SIZE (right) - 1;
9865           while (size--)
9866             emitcode ("dec", "%s", rname);
9867         }
9868     }
9869
9870   /* done */
9871   if (pi) pi->generated = 1;
9872   freeAsmop (result, NULL, ic, TRUE);
9873   freeAsmop (right, NULL, ic, TRUE);
9874
9875
9876 }
9877
9878 /*-----------------------------------------------------------------*/
9879 /* genFarPointerSet - set value from far space                     */
9880 /*-----------------------------------------------------------------*/
9881 static void
9882 genFarPointerSet (operand * right,
9883                   operand * result, iCode * ic, iCode *pi)
9884 {
9885   int size, offset, dopi=1;
9886   sym_link *retype = getSpec (operandType (right));
9887   sym_link *letype = getSpec (operandType (result));
9888
9889   aopOp (result, ic, FALSE, FALSE);
9890
9891   /* if the operand is already in dptr
9892      then we do nothing else we move the value to dptr */
9893   if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
9894     {
9895       /* if this is remateriazable */
9896       if (AOP_TYPE (result) == AOP_IMMD)
9897         emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9898       else
9899         {
9900           /* we need to get it byte by byte */
9901           _startLazyDPSEvaluation ();
9902           if (AOP_TYPE (result) != AOP_DPTR)
9903             {
9904               emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9905               emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9906               if (options.model == MODEL_FLAT24)
9907                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9908             }
9909           else
9910             {
9911               /* We need to generate a load to DPTR indirect through DPTR. */
9912               D (emitcode (";", "genFarPointerSet -- indirection special case.");
9913                 );
9914               emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
9915               emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
9916               if (options.model == MODEL_FLAT24)
9917                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9918               emitcode ("pop", "dph");
9919               emitcode ("pop", "dpl");
9920               dopi=0;
9921             }
9922           _endLazyDPSEvaluation ();
9923         }
9924     }
9925   /* so dptr know contains the address */
9926   aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
9927
9928   /* if bit then unpack */
9929   if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
9930       if (AOP_INDPTRn(result)) {
9931           genSetDPTR(AOP(result)->aopu.dptr);
9932       }
9933       genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
9934       if (AOP_INDPTRn(result)) {
9935           genSetDPTR(0);
9936       }
9937   } else {
9938       size = AOP_SIZE (right);
9939       offset = 0;
9940       if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
9941           while (size--) {
9942               char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9943               MOVA (l);
9944               
9945               genSetDPTR(AOP(result)->aopu.dptr);
9946               emitcode ("movx", "@dptr,a");
9947               if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
9948                   emitcode ("inc", "dptr");
9949               genSetDPTR (0);
9950           }
9951       } else {
9952           _startLazyDPSEvaluation ();
9953           while (size--) {
9954               char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9955               MOVA (l);
9956               
9957               if (AOP_INDPTRn(result)) {
9958                   genSetDPTR(AOP(result)->aopu.dptr);
9959               } else {
9960                   genSetDPTR (0);
9961               }
9962               _flushLazyDPS ();
9963               
9964               emitcode ("movx", "@dptr,a");
9965               if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
9966                   emitcode ("inc", "dptr");
9967           }
9968           _endLazyDPSEvaluation ();
9969       }
9970   }
9971   
9972   if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
9973       if (!AOP_INDPTRn(result)) {
9974           aopPut (AOP(result),"dpl",0);
9975           aopPut (AOP(result),"dph",1);
9976           if (options.model == MODEL_FLAT24)
9977               aopPut (AOP(result),"dpx",2);
9978       }
9979       pi->generated=1;
9980   } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) && 
9981              AOP_SIZE(right) > 1 &&
9982              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
9983       
9984       size = AOP_SIZE (right) - 1;
9985       if (AOP_INDPTRn(result)) {
9986           genSetDPTR(AOP(result)->aopu.dptr);
9987       } 
9988       while (size--) emitcode ("lcall","__decdptr");
9989       if (AOP_INDPTRn(result)) {
9990           genSetDPTR(0);
9991       }
9992   }
9993   freeAsmop (result, NULL, ic, TRUE);
9994   freeAsmop (right, NULL, ic, TRUE);
9995 }
9996
9997 /*-----------------------------------------------------------------*/
9998 /* genGenPointerSet - set value from generic pointer space         */
9999 /*-----------------------------------------------------------------*/
10000 static void
10001 genGenPointerSet (operand * right,
10002                   operand * result, iCode * ic, iCode *pi)
10003 {
10004   int size, offset;
10005   sym_link *retype = getSpec (operandType (right));
10006   sym_link *letype = getSpec (operandType (result));
10007
10008   aopOp (result, ic, FALSE, OP_SYMBOL(result)->ruonly ? FALSE : TRUE);
10009
10010   /* if the operand is already in dptr
10011      then we do nothing else we move the value to dptr */
10012   if (AOP_TYPE (result) != AOP_STR)
10013     {
10014       _startLazyDPSEvaluation ();
10015       /* if this is remateriazable */
10016       if (AOP_TYPE (result) == AOP_IMMD)
10017         {
10018           emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
10019           if (AOP(result)->aopu.aop_immd.from_cast_remat) 
10020                   emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, FALSE));
10021           else
10022                   emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
10023         }
10024       else
10025         {                       /* we need to get it byte by byte */
10026           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
10027           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
10028           if (options.model == MODEL_FLAT24) {
10029             emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
10030             emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
10031           } else {
10032             emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
10033           }
10034         }
10035       _endLazyDPSEvaluation ();
10036     }
10037   /* so dptr know contains the address */
10038   aopOp (right, ic, FALSE, TRUE);
10039
10040   /* if bit then unpack */
10041   if (IS_BITVAR (retype) || IS_BITVAR (letype))
10042     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
10043   else
10044     {
10045       size = AOP_SIZE (right);
10046       offset = 0;
10047
10048       _startLazyDPSEvaluation ();
10049       while (size--)
10050         {
10051           char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
10052           MOVA (l);
10053
10054           genSetDPTR (0);
10055           _flushLazyDPS ();
10056
10057           emitcode ("lcall", "__gptrput");
10058           if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10059             emitcode ("inc", "dptr");
10060         }
10061       _endLazyDPSEvaluation ();
10062     }
10063
10064   if (pi && AOP_TYPE (result) != AOP_IMMD) {
10065       aopPut (AOP(result),"dpl",0);
10066       aopPut (AOP(result),"dph",1);
10067       if (options.model == MODEL_FLAT24) {
10068           aopPut (AOP(result),"dpx",2);
10069           aopPut (AOP(result),"b",3);
10070       } else {
10071           aopPut (AOP(result),"b",2);
10072       }
10073       pi->generated=1;
10074   } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10075              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10076       
10077       size = AOP_SIZE (right) - 1;
10078       while (size--) emitcode ("lcall","__decdptr");
10079   }
10080   freeAsmop (result, NULL, ic, TRUE);
10081   freeAsmop (right, NULL, ic, TRUE);
10082 }
10083
10084 /*-----------------------------------------------------------------*/
10085 /* genPointerSet - stores the value into a pointer location        */
10086 /*-----------------------------------------------------------------*/
10087 static void
10088 genPointerSet (iCode * ic, iCode *pi)
10089 {
10090   operand *right, *result;
10091   sym_link *type, *etype;
10092   int p_type;
10093
10094   D (emitcode (";", "genPointerSet ");
10095     );
10096
10097   right = IC_RIGHT (ic);
10098   result = IC_RESULT (ic);
10099
10100   /* depending on the type of pointer we need to
10101      move it to the correct pointer register */
10102   type = operandType (result);
10103   etype = getSpec (type);
10104   /* if left is of type of pointer then it is simple */
10105   if (IS_PTR (type) && !IS_FUNC (type->next))
10106     {
10107       p_type = DCL_TYPE (type);
10108     }
10109   else
10110     {
10111       /* we have to go by the storage class */
10112       p_type = PTR_TYPE (SPEC_OCLS (etype));
10113     }
10114   /* special case when cast remat */
10115   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10116       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10117           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10118           type =   type = operandType (result);
10119           p_type = DCL_TYPE (type);
10120   }
10121
10122   /* now that we have the pointer type we assign
10123      the pointer values */
10124   switch (p_type)
10125     {
10126
10127     case POINTER:
10128     case IPOINTER:
10129       genNearPointerSet (right, result, ic, pi);
10130       break;
10131
10132     case PPOINTER:
10133       genPagedPointerSet (right, result, ic, pi);
10134       break;
10135
10136     case FPOINTER:
10137       genFarPointerSet (right, result, ic, pi);
10138       break;
10139
10140     case GPOINTER:
10141       genGenPointerSet (right, result, ic, pi);
10142       break;
10143     }
10144
10145 }
10146
10147 /*-----------------------------------------------------------------*/
10148 /* genIfx - generate code for Ifx statement                        */
10149 /*-----------------------------------------------------------------*/
10150 static void
10151 genIfx (iCode * ic, iCode * popIc)
10152 {
10153   operand *cond = IC_COND (ic);
10154   int isbit = 0;
10155
10156   D (emitcode (";", "genIfx "););
10157
10158   aopOp (cond, ic, FALSE, FALSE);
10159
10160   /* get the value into acc */
10161   if (AOP_TYPE (cond) != AOP_CRY)
10162     toBoolean (cond);
10163   else
10164     isbit = 1;
10165   /* the result is now in the accumulator */
10166   freeAsmop (cond, NULL, ic, TRUE);
10167
10168   /* if there was something to be popped then do it */
10169   if (popIc)
10170     genIpop (popIc);
10171
10172   /* if the condition is  a bit variable */
10173   if (isbit && IS_ITEMP (cond) &&
10174       SPIL_LOC (cond))
10175     genIfxJump (ic, SPIL_LOC (cond)->rname);
10176   else if (isbit && !IS_ITEMP (cond))
10177     genIfxJump (ic, OP_SYMBOL (cond)->rname);
10178   else
10179     genIfxJump (ic, "a");
10180
10181   ic->generated = 1;
10182 }
10183
10184 /*-----------------------------------------------------------------*/
10185 /* genAddrOf - generates code for address of                       */
10186 /*-----------------------------------------------------------------*/
10187 static void
10188 genAddrOf (iCode * ic)
10189 {
10190   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10191   int size, offset;
10192
10193   D (emitcode (";", "genAddrOf ");
10194     );
10195
10196   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10197
10198   /* if the operand is on the stack then we
10199      need to get the stack offset of this
10200      variable */
10201   if (sym->onStack) {
10202       
10203       /* if 10 bit stack */
10204       if (options.stack10bit) {
10205           char buff[10];
10206           tsprintf(buff,"#!constbyte",(options.stack_loc >> 16) & 0xff);
10207           /* if it has an offset then we need to compute it */
10208           emitcode ("subb", "a,#!constbyte",
10209                     -((sym->stack < 0) ?
10210                       ((short) (sym->stack - _G.nRegsSaved)) :
10211                       ((short) sym->stack)) & 0xff);
10212           emitcode ("mov","b,a");
10213           emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ?
10214                                          ((short) (sym->stack - _G.nRegsSaved)) :
10215                                          ((short) sym->stack)) >> 8) & 0xff);
10216           if (sym->stack) {
10217               emitcode ("mov", "a,_bpx");
10218               emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ? 
10219                                              ((char) (sym->stack - _G.nRegsSaved)) :
10220                                              ((char) sym->stack )) & 0xff);
10221               emitcode ("mov", "b,a");
10222               emitcode ("mov", "a,_bpx+1");
10223               emitcode ("addc","a,#!constbyte", (((sym->stack < 0) ? 
10224                                               ((short) (sym->stack - _G.nRegsSaved)) :
10225                                               ((short) sym->stack )) >> 8) & 0xff);
10226               aopPut (AOP (IC_RESULT (ic)), "b", 0);
10227               aopPut (AOP (IC_RESULT (ic)), "a", 1);
10228               aopPut (AOP (IC_RESULT (ic)), buff, 2);
10229           } else {
10230               /* we can just move _bp */
10231               aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
10232               aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
10233               aopPut (AOP (IC_RESULT (ic)), buff, 2);
10234           }       
10235       } else {
10236           /* if it has an offset then we need to compute it */
10237           if (sym->stack) {
10238               emitcode ("mov", "a,_bp");
10239               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
10240               aopPut (AOP (IC_RESULT (ic)), "a", 0);
10241           } else {
10242               /* we can just move _bp */
10243               aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
10244           }
10245           /* fill the result with zero */
10246           size = AOP_SIZE (IC_RESULT (ic)) - 1;
10247           
10248           
10249           if (options.stack10bit && size < (FPTRSIZE - 1)) {
10250               fprintf (stderr,
10251                        "*** warning: pointer to stack var truncated.\n");
10252           }
10253
10254           offset = 1;
10255           while (size--) {
10256               aopPut (AOP (IC_RESULT (ic)), zero, offset++);
10257           }      
10258       }
10259       goto release;
10260   }
10261
10262   /* object not on stack then we need the name */
10263   size = AOP_SIZE (IC_RESULT (ic));
10264   offset = 0;
10265
10266   while (size--)
10267     {
10268       char s[SDCC_NAME_MAX];
10269       if (offset) {
10270           switch (offset) {
10271           case 1:
10272               tsprintf(s,"!his",sym->rname);
10273               break;
10274           case 2:
10275               tsprintf(s,"!hihis",sym->rname);
10276               break;
10277           case 3:
10278               tsprintf(s,"!hihihis",sym->rname);
10279               break;
10280           default: /* should not need this (just in case) */
10281               sprintf (s, "#(%s >> %d)",
10282                        sym->rname,
10283                        offset * 8);
10284           }
10285       } else
10286           sprintf (s, "#%s", sym->rname);
10287       aopPut (AOP (IC_RESULT (ic)), s, offset++);
10288     }
10289
10290 release:
10291   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10292
10293 }
10294
10295 /*-----------------------------------------------------------------*/
10296 /* genArrayInit - generates code for address of                       */
10297 /*-----------------------------------------------------------------*/
10298 static void
10299 genArrayInit (iCode * ic)
10300 {
10301     literalList *iLoop;
10302     int         ix, count;
10303     int         elementSize = 0, eIndex;
10304     unsigned    val, lastVal;
10305     sym_link    *type;
10306     operand     *left=IC_LEFT(ic);
10307     
10308     D (emitcode (";", "genArrayInit "););
10309
10310     aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10311     
10312     if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10313     {
10314         // Load immediate value into DPTR.
10315         emitcode("mov", "dptr, %s",
10316              aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, TRUE));
10317     }
10318     else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10319     {
10320 #if 0
10321       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10322               "Unexpected operand to genArrayInit.\n");
10323       exit(1);
10324 #else
10325       // a regression because of SDCCcse.c:1.52
10326       emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
10327       emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
10328       if (options.model == MODEL_FLAT24)
10329         emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
10330 #endif
10331     }
10332     
10333     type = operandType(IC_LEFT(ic));
10334     
10335     if (type && type->next)
10336     {
10337         elementSize = getSize(type->next);
10338     }
10339     else
10340     {
10341         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10342                                 "can't determine element size in genArrayInit.\n");
10343         exit(1);
10344     }
10345     
10346     iLoop = IC_ARRAYILIST(ic);
10347     lastVal = 0xffff;
10348     
10349     while (iLoop)
10350     {
10351         bool firstpass = TRUE;
10352         
10353         emitcode(";", "store %d x 0x%x to DPTR (element size %d)", 
10354                  iLoop->count, (int)iLoop->literalValue, elementSize);
10355         
10356         ix = iLoop->count;
10357         
10358         while (ix)
10359         {
10360             symbol *tlbl = NULL;
10361             
10362             count = ix > 256 ? 256 : ix;
10363             
10364             if (count > 1)
10365             {
10366                 tlbl = newiTempLabel (NULL);
10367                 if (firstpass || (count & 0xff))
10368                 {
10369                     emitcode("mov", "b, #!constbyte", count & 0xff);
10370                 }
10371                 
10372                 emitcode ("", "!tlabeldef", tlbl->key + 100);
10373             }
10374             
10375             firstpass = FALSE;
10376                 
10377             for (eIndex = 0; eIndex < elementSize; eIndex++)
10378             {
10379                 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10380                 if (val != lastVal)
10381                 {
10382                     emitcode("mov", "a, #!constbyte", val);
10383                     lastVal = val;
10384                 }
10385                 
10386                 emitcode("movx", "@dptr, a");
10387                 emitcode("inc", "dptr");
10388             }
10389             
10390             if (count > 1)
10391             {
10392                 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
10393             }
10394             
10395             ix -= count;
10396         }
10397         
10398         iLoop = iLoop->next;
10399     }
10400     
10401     freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10402 }
10403
10404 /*-----------------------------------------------------------------*/
10405 /* genFarFarAssign - assignment when both are in far space         */
10406 /*-----------------------------------------------------------------*/
10407 static void
10408 genFarFarAssign (operand * result, operand * right, iCode * ic)
10409 {
10410   int size = AOP_SIZE (right);
10411   int offset = 0;
10412   symbol *rSym = NULL;
10413
10414   if (size == 1)
10415   {
10416       /* quick & easy case. */
10417       D(emitcode(";","genFarFarAssign (1 byte case)"););      
10418       MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
10419       freeAsmop (right, NULL, ic, FALSE);
10420       /* now assign DPTR to result */
10421       _G.accInUse++;
10422       aopOp(result, ic, FALSE, FALSE);
10423       _G.accInUse--;
10424       aopPut(AOP(result), "a", 0);
10425       freeAsmop(result, NULL, ic, FALSE);
10426       return;
10427   }
10428   
10429   /* See if we've got an underlying symbol to abuse. */
10430   if (IS_SYMOP(result) && OP_SYMBOL(result))
10431   {
10432       if (IS_TRUE_SYMOP(result))
10433       {
10434           rSym = OP_SYMBOL(result);
10435       }
10436       else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10437       {
10438           rSym = OP_SYMBOL(result)->usl.spillLoc;
10439       }
10440   }
10441              
10442   if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10443   {
10444       /* We can use the '390 auto-toggle feature to good effect here. */
10445       
10446       D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10447       emitcode("mov", "dps,#!constbyte",0x21);  /* Select DPTR2 & auto-toggle. */
10448       emitcode ("mov", "dptr,#%s", rSym->rname); 
10449       /* DP2 = result, DP1 = right, DP1 is current. */
10450       while (size)
10451       {
10452           emitcode("movx", "a,@dptr");
10453           emitcode("movx", "@dptr,a");
10454           if (--size)
10455           {
10456                emitcode("inc", "dptr");
10457                emitcode("inc", "dptr");
10458           }
10459       }
10460       emitcode("mov", "dps,#0");
10461       freeAsmop (right, NULL, ic, FALSE);
10462 #if 0
10463 some alternative code for processors without auto-toggle
10464 no time to test now, so later well put in...kpb
10465         D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10466         emitcode("mov", "dps,#1");      /* Select DPTR2. */
10467         emitcode ("mov", "dptr,#%s", rSym->rname); 
10468         /* DP2 = result, DP1 = right, DP1 is current. */
10469         while (size)
10470         {
10471           --size;
10472           emitcode("movx", "a,@dptr");
10473           if (size)
10474             emitcode("inc", "dptr");
10475           emitcode("inc", "dps");
10476           emitcode("movx", "@dptr,a");
10477           if (size)
10478             emitcode("inc", "dptr");
10479           emitcode("inc", "dps");
10480         }
10481         emitcode("mov", "dps,#0");
10482         freeAsmop (right, NULL, ic, FALSE);
10483 #endif
10484   }
10485   else
10486   {
10487       D (emitcode (";", "genFarFarAssign"););
10488       aopOp (result, ic, TRUE, TRUE);
10489
10490       _startLazyDPSEvaluation ();
10491       
10492       while (size--)
10493         {
10494           aopPut (AOP (result),
10495                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
10496           offset++;
10497         }
10498       _endLazyDPSEvaluation ();
10499       freeAsmop (result, NULL, ic, FALSE);
10500       freeAsmop (right, NULL, ic, FALSE);
10501   }
10502 }
10503
10504 /*-----------------------------------------------------------------*/
10505 /* genAssign - generate code for assignment                        */
10506 /*-----------------------------------------------------------------*/
10507 static void
10508 genAssign (iCode * ic)
10509 {
10510   operand *result, *right;
10511   int size, offset;
10512   unsigned long lit = 0L;
10513
10514   D (emitcode (";", "genAssign ");
10515     );
10516
10517   result = IC_RESULT (ic);
10518   right = IC_RIGHT (ic);
10519
10520   /* if they are the same */
10521   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10522     return;
10523
10524   aopOp (right, ic, FALSE, FALSE);
10525
10526   emitcode (";", "genAssign: resultIsFar = %s",
10527             isOperandInFarSpace (result) ?
10528             "TRUE" : "FALSE");
10529
10530   /* special case both in far space */
10531   if ((AOP_TYPE (right) == AOP_DPTR ||
10532        AOP_TYPE (right) == AOP_DPTR2) &&
10533   /* IS_TRUE_SYMOP(result)       && */
10534       isOperandInFarSpace (result))
10535     {
10536       genFarFarAssign (result, right, ic);
10537       return;
10538     }
10539
10540   aopOp (result, ic, TRUE, FALSE);
10541
10542   /* if they are the same registers */
10543   if (sameRegs (AOP (right), AOP (result)))
10544     goto release;
10545
10546   /* if the result is a bit */
10547   if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10548     {
10549       /* if the right size is a literal then
10550          we know what the value is */
10551       if (AOP_TYPE (right) == AOP_LIT)
10552         {
10553           if (((int) operandLitValue (right)))
10554             aopPut (AOP (result), one, 0);
10555           else
10556             aopPut (AOP (result), zero, 0);
10557           goto release;
10558         }
10559
10560       /* the right is also a bit variable */
10561       if (AOP_TYPE (right) == AOP_CRY)
10562         {
10563           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10564           aopPut (AOP (result), "c", 0);
10565           goto release;
10566         }
10567
10568       /* we need to or */
10569       toBoolean (right);
10570       aopPut (AOP (result), "a", 0);
10571       goto release;
10572     }
10573
10574   /* bit variables done */
10575   /* general case */
10576   size = AOP_SIZE (result);
10577   offset = 0;
10578   if (AOP_TYPE (right) == AOP_LIT)
10579     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10580
10581   if ((size > 1) &&
10582       (AOP_TYPE (result) != AOP_REG) &&
10583       (AOP_TYPE (right) == AOP_LIT) &&
10584       !IS_FLOAT (operandType (right)))
10585     {
10586       _startLazyDPSEvaluation ();
10587       while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10588         {
10589           aopPut (AOP (result),
10590                   aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
10591                   offset);
10592           offset++;
10593           size--;
10594         }
10595       /* And now fill the rest with zeros. */
10596       if (size)
10597         {
10598           emitcode ("clr", "a");
10599         }
10600       while (size--)
10601         {
10602           aopPut (AOP (result), "a", offset++);
10603         }
10604       _endLazyDPSEvaluation ();
10605     }
10606   else
10607     {
10608       _startLazyDPSEvaluation ();
10609       while (size--)
10610         {
10611           aopPut (AOP (result),
10612                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10613                   offset);
10614           offset++;
10615         }
10616       _endLazyDPSEvaluation ();
10617     }
10618
10619 release:
10620   freeAsmop (right, NULL, ic, FALSE);
10621   freeAsmop (result, NULL, ic, TRUE);
10622 }
10623
10624 /*-----------------------------------------------------------------*/
10625 /* genJumpTab - generates code for jump table                      */
10626 /*-----------------------------------------------------------------*/
10627 static void
10628 genJumpTab (iCode * ic)
10629 {
10630   symbol *jtab;
10631   char *l;
10632
10633   D (emitcode (";", "genJumpTab ");
10634     );
10635
10636   aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10637   /* get the condition into accumulator */
10638   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
10639   MOVA (l);
10640   /* multiply by four! */
10641   emitcode ("add", "a,acc");
10642   emitcode ("add", "a,acc");
10643   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10644
10645   jtab = newiTempLabel (NULL);
10646   emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
10647   emitcode ("jmp", "@a+dptr");
10648   emitcode ("", "!tlabeldef", jtab->key + 100);
10649   /* now generate the jump labels */
10650   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10651        jtab = setNextItem (IC_JTLABELS (ic)))
10652     emitcode ("ljmp", "!tlabel", jtab->key + 100);
10653
10654 }
10655
10656 /*-----------------------------------------------------------------*/
10657 /* genCast - gen code for casting                                  */
10658 /*-----------------------------------------------------------------*/
10659 static void
10660 genCast (iCode * ic)
10661 {
10662   operand *result = IC_RESULT (ic);
10663   sym_link *ctype = operandType (IC_LEFT (ic));
10664   sym_link *rtype = operandType (IC_RIGHT (ic));
10665   operand *right = IC_RIGHT (ic);
10666   int size, offset;
10667
10668   D (emitcode (";", "genCast ");
10669     );
10670
10671   /* if they are equivalent then do nothing */
10672   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10673     return;
10674
10675   aopOp (right, ic, FALSE, FALSE);
10676   aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
10677
10678   /* if the result is a bit */
10679   // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10680   if (IS_BITVAR(OP_SYMBOL(result)->type))
10681     {
10682       /* if the right size is a literal then
10683          we know what the value is */
10684       if (AOP_TYPE (right) == AOP_LIT)
10685         {
10686           if (((int) operandLitValue (right)))
10687             aopPut (AOP (result), one, 0);
10688           else
10689             aopPut (AOP (result), zero, 0);
10690
10691           goto release;
10692         }
10693
10694       /* the right is also a bit variable */
10695       if (AOP_TYPE (right) == AOP_CRY)
10696         {
10697           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10698           aopPut (AOP (result), "c", 0);
10699           goto release;
10700         }
10701
10702       /* we need to or */
10703       toBoolean (right);
10704       aopPut (AOP (result), "a", 0);
10705       goto release;
10706     }
10707
10708   /* if they are the same size : or less */
10709   if (AOP_SIZE (result) <= AOP_SIZE (right))
10710     {
10711
10712       /* if they are in the same place */
10713       if (sameRegs (AOP (right), AOP (result)))
10714         goto release;
10715
10716       /* if they in different places then copy */
10717       size = AOP_SIZE (result);
10718       offset = 0;
10719       _startLazyDPSEvaluation ();
10720       while (size--)
10721         {
10722           aopPut (AOP (result),
10723                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10724                   offset);
10725           offset++;
10726         }
10727       _endLazyDPSEvaluation ();
10728       goto release;
10729     }
10730
10731
10732   /* if the result is of type pointer */
10733   if (IS_PTR (ctype))
10734     {
10735
10736       int p_type;
10737       sym_link *type = operandType (right);
10738
10739       /* pointer to generic pointer */
10740       if (IS_GENPTR (ctype))
10741         {
10742           char *l = zero;
10743
10744           if (IS_PTR (type))
10745             {
10746               p_type = DCL_TYPE (type);
10747             }
10748           else
10749             {
10750 #if OLD_CAST_BEHAVIOR
10751               /* KV: we are converting a non-pointer type to
10752                * a generic pointer. This (ifdef'd out) code
10753                * says that the resulting generic pointer
10754                * should have the same class as the storage
10755                * location of the non-pointer variable.
10756                *
10757                * For example, converting an int (which happens
10758                * to be stored in DATA space) to a pointer results
10759                * in a DATA generic pointer; if the original int
10760                * in XDATA space, so will be the resulting pointer.
10761                *
10762                * I don't like that behavior, and thus this change:
10763                * all such conversions will be forced to XDATA and
10764                * throw a warning. If you want some non-XDATA
10765                * type, or you want to suppress the warning, you
10766                * must go through an intermediate cast, like so:
10767                *
10768                * char _generic *gp = (char _xdata *)(intVar);
10769                */
10770               sym_link *etype = getSpec (type);
10771
10772               /* we have to go by the storage class */
10773               if (SPEC_OCLS (etype) != generic)
10774                 {
10775                   p_type = PTR_TYPE (SPEC_OCLS (etype));
10776                 }
10777               else
10778 #endif
10779                 {
10780                   /* Converting unknown class (i.e. register variable)
10781                    * to generic pointer. This is not good, but
10782                    * we'll make a guess (and throw a warning).
10783                    */
10784                   p_type = FPOINTER;
10785                   werror (W_INT_TO_GEN_PTR_CAST);
10786                 }
10787             }
10788
10789           /* the first two bytes are known */
10790           size = GPTRSIZE - 1;
10791           offset = 0;
10792           _startLazyDPSEvaluation ();
10793           while (size--)
10794             {
10795               aopPut (AOP (result),
10796                       aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10797                       offset);
10798               offset++;
10799             }
10800           _endLazyDPSEvaluation ();
10801
10802           /* the last byte depending on type */
10803           switch (p_type)
10804             {
10805             case IPOINTER:
10806             case POINTER:
10807               l = zero;
10808               break;
10809             case FPOINTER:
10810               l = one;
10811               break;
10812             case CPOINTER:
10813               l = "#0x02";
10814               break;
10815             case PPOINTER:
10816               l = "#0x03";
10817               break;
10818
10819             default:
10820               /* this should never happen */
10821               werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10822                       "got unknown pointer type");
10823               exit (1);
10824             }
10825           aopPut (AOP (result), l, GPTRSIZE - 1);
10826           goto release;
10827         }
10828
10829       /* just copy the pointers */
10830       size = AOP_SIZE (result);
10831       offset = 0;
10832       _startLazyDPSEvaluation ();
10833       while (size--)
10834         {
10835           aopPut (AOP (result),
10836                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10837                   offset);
10838           offset++;
10839         }
10840       _endLazyDPSEvaluation ();
10841       goto release;
10842     }
10843
10844   /* so we now know that the size of destination is greater
10845      than the size of the source */
10846   /* we move to result for the size of source */
10847   size = AOP_SIZE (right);
10848   offset = 0;
10849   _startLazyDPSEvaluation ();
10850   while (size--)
10851     {
10852       aopPut (AOP (result),
10853               aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10854               offset);
10855       offset++;
10856     }
10857   _endLazyDPSEvaluation ();
10858
10859   /* now depending on the sign of the source && destination */
10860   size = AOP_SIZE (result) - AOP_SIZE (right);
10861   /* if unsigned or not an integral type */
10862   /* also, if the source is a bit, we don't need to sign extend, because
10863    * it can't possibly have set the sign bit.
10864    */
10865   if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
10866     {
10867       while (size--)
10868         {
10869           aopPut (AOP (result), zero, offset++);
10870         }
10871     }
10872   else
10873     {
10874       /* we need to extend the sign :{ */
10875       char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
10876                         FALSE, FALSE, TRUE);
10877       MOVA (l);
10878       emitcode ("rlc", "a");
10879       emitcode ("subb", "a,acc");
10880       while (size--)
10881         aopPut (AOP (result), "a", offset++);
10882     }
10883
10884   /* we are done hurray !!!! */
10885
10886 release:
10887   freeAsmop (right, NULL, ic, TRUE);
10888   freeAsmop (result, NULL, ic, TRUE);
10889
10890 }
10891
10892 /*-----------------------------------------------------------------*/
10893 /* genDjnz - generate decrement & jump if not zero instrucion      */
10894 /*-----------------------------------------------------------------*/
10895 static int
10896 genDjnz (iCode * ic, iCode * ifx)
10897 {
10898   symbol *lbl, *lbl1;
10899   if (!ifx)
10900     return 0;
10901
10902   /* if the if condition has a false label
10903      then we cannot save */
10904   if (IC_FALSE (ifx))
10905     return 0;
10906
10907   /* if the minus is not of the form
10908      a = a - 1 */
10909   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
10910       !IS_OP_LITERAL (IC_RIGHT (ic)))
10911     return 0;
10912
10913   if (operandLitValue (IC_RIGHT (ic)) != 1)
10914     return 0;
10915
10916   /* if the size of this greater than one then no
10917      saving */
10918   if (getSize (operandType (IC_RESULT (ic))) > 1)
10919     return 0;
10920
10921   /* otherwise we can save BIG */
10922   D(emitcode(";", "genDjnz"););
10923
10924   lbl = newiTempLabel (NULL);
10925   lbl1 = newiTempLabel (NULL);
10926
10927   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10928
10929   if (AOP_NEEDSACC(IC_RESULT(ic)))
10930   {
10931       /* If the result is accessed indirectly via
10932        * the accumulator, we must explicitly write
10933        * it back after the decrement.
10934        */
10935       char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
10936       
10937       if (strcmp(rByte, "a"))
10938       {
10939            /* Something is hopelessly wrong */
10940            fprintf(stderr, "*** warning: internal error at %s:%d\n",
10941                    __FILE__, __LINE__);
10942            /* We can just give up; the generated code will be inefficient,
10943             * but what the hey.
10944             */
10945            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10946            return 0;
10947       }
10948       emitcode ("dec", "%s", rByte);
10949       aopPut(AOP(IC_RESULT(ic)), rByte, 0);
10950       emitcode ("jnz", "!tlabel", lbl->key + 100);
10951   }
10952   else if (IS_AOP_PREG (IC_RESULT (ic)))
10953     {
10954       emitcode ("dec", "%s",
10955                 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10956       emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10957       emitcode ("jnz", "!tlabel", lbl->key + 100);
10958     }
10959   else
10960     {
10961       emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
10962                 lbl->key + 100);
10963     }
10964   emitcode ("sjmp", "!tlabel", lbl1->key + 100);
10965   emitcode ("", "!tlabeldef", lbl->key + 100);
10966   emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
10967   emitcode ("", "!tlabeldef", lbl1->key + 100);
10968
10969   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10970   ifx->generated = 1;
10971   return 1;
10972 }
10973
10974 /*-----------------------------------------------------------------*/
10975 /* genReceive - generate code for a receive iCode                  */
10976 /*-----------------------------------------------------------------*/
10977 static void
10978 genReceive (iCode * ic)
10979 {
10980
10981     int size = getSize (operandType (IC_RESULT (ic)));
10982     int offset = 0;
10983     int rb1off ;
10984     
10985     D (emitcode (";", "genReceive ");
10986        );
10987
10988   if (ic->argreg == 1) { /* first parameter */
10989       if (isOperandInFarSpace (IC_RESULT (ic)) &&
10990           (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
10991            IS_TRUE_SYMOP (IC_RESULT (ic))))
10992           {
10993               offset = fReturnSizeDS390 - size;
10994               while (size--)
10995                   {
10996                       emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
10997                                                fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
10998                       offset++;
10999                   }
11000               aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11001               size = AOP_SIZE (IC_RESULT (ic));
11002               offset = 0;
11003               while (size--)
11004                   {
11005                       emitcode ("pop", "acc");
11006                       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
11007                   }
11008               
11009           } else {
11010               _G.accInUse++;
11011               aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11012               _G.accInUse--;
11013               assignResultValue (IC_RESULT (ic));
11014           }
11015   } else { /* second receive onwards */
11016       /* this gets a little tricky since unused recevies will be
11017          eliminated, we have saved the reg in the type field . and
11018          we use that to figure out which register to use */
11019       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11020       rb1off = ic->argreg;
11021       while (size--) {
11022           aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11023       }
11024       
11025   }
11026   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11027 }
11028
11029 /*-----------------------------------------------------------------*/
11030 /* genMemcpyX2X - gen code for memcpy xdata to xdata               */
11031 /*-----------------------------------------------------------------*/
11032 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11033 {
11034     operand *from , *to , *count;
11035     symbol *lbl;
11036     bitVect *rsave;
11037     int i;
11038
11039     /* we know it has to be 3 parameters */
11040     assert (nparms == 3);
11041     
11042     rsave = newBitVect(16);
11043     /* save DPTR if it needs to be saved */
11044     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11045             if (bitVectBitValue(ic->rMask,i))
11046                     rsave = bitVectSetBit(rsave,i);
11047     }
11048     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11049                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11050     savermask(rsave);
11051     
11052     to = parms[0];
11053     from = parms[1];
11054     count = parms[2];
11055
11056     aopOp (from, ic->next, FALSE, FALSE);
11057
11058     /* get from into DPTR1 */
11059     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, TRUE));
11060     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, TRUE));
11061     if (options.model == MODEL_FLAT24) {
11062         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, TRUE));
11063     }
11064
11065     freeAsmop (from, NULL, ic, FALSE);
11066     aopOp (to, ic, FALSE, FALSE);
11067     /* get "to" into DPTR */
11068     /* if the operand is already in dptr
11069        then we do nothing else we move the value to dptr */
11070     if (AOP_TYPE (to) != AOP_STR) {
11071         /* if already in DPTR then we need to push */
11072         if (AOP_TYPE(to) == AOP_DPTR) {
11073             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
11074             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
11075             if (options.model == MODEL_FLAT24)
11076                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11077             emitcode ("pop", "dph");
11078             emitcode ("pop", "dpl");        
11079         } else {
11080             _startLazyDPSEvaluation ();
11081             /* if this is remateriazable */
11082             if (AOP_TYPE (to) == AOP_IMMD) {
11083                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
11084             } else {                    /* we need to get it byte by byte */
11085                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
11086                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
11087                 if (options.model == MODEL_FLAT24) {
11088                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11089                 }
11090             }
11091             _endLazyDPSEvaluation ();
11092         }
11093     }
11094     freeAsmop (to, NULL, ic, FALSE);
11095
11096     aopOp (count, ic->next->next, FALSE,FALSE);
11097     lbl =newiTempLabel(NULL);
11098
11099     /* now for the actual copy */
11100     if (AOP_TYPE(count) == AOP_LIT && 
11101         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11102         emitcode (";","OH  JOY auto increment with djnz (very fast)");
11103         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
11104         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
11105         emitcode ("","!tlabeldef",lbl->key+100);
11106         if (fromc) {
11107             emitcode ("clr","a");
11108             emitcode ("movc", "a,@a+dptr");
11109         } else 
11110             emitcode ("movx", "a,@dptr");
11111         emitcode ("movx", "@dptr,a");
11112         emitcode ("inc", "dptr");
11113         emitcode ("inc", "dptr");
11114         emitcode ("djnz","b,!tlabel",lbl->key+100);
11115     } else {
11116         symbol *lbl1 = newiTempLabel(NULL);
11117         
11118         emitcode (";"," Auto increment but no djnz");
11119         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
11120         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
11121         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
11122         emitcode ("","!tlabeldef",lbl->key+100);
11123         if (fromc) {
11124             emitcode ("clr","a");
11125             emitcode ("movc", "a,@a+dptr");
11126         } else 
11127             emitcode ("movx", "a,@dptr");
11128         emitcode ("movx", "@dptr,a");
11129         emitcode ("inc", "dptr");
11130         emitcode ("inc", "dptr");
11131         emitcode ("mov","a,b");
11132         emitcode ("orl","a,_ap");
11133         emitcode ("jz","!tlabel",lbl1->key+100);
11134         emitcode ("mov","a,_ap");
11135         emitcode ("add","a,#!constbyte",0xFF);
11136         emitcode ("mov","_ap,a");
11137         emitcode ("mov","a,b");
11138         emitcode ("addc","a,#!constbyte",0xFF);
11139         emitcode ("mov","b,a");
11140         emitcode ("sjmp","!tlabel",lbl->key+100);
11141         emitcode ("","!tlabeldef",lbl1->key+100);
11142     }
11143     emitcode ("mov", "dps,#0"); 
11144     freeAsmop (count, NULL, ic, FALSE);
11145     unsavermask(rsave);
11146
11147 }
11148
11149 /*-----------------------------------------------------------------*/
11150 /* genMemcmpX2X - gen code for memcmp xdata to xdata               */
11151 /*-----------------------------------------------------------------*/
11152 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
11153 {
11154     operand *from , *to , *count;
11155     symbol *lbl,*lbl2;
11156     bitVect *rsave;
11157     int i;
11158
11159     /* we know it has to be 3 parameters */
11160     assert (nparms == 3);
11161     
11162     rsave = newBitVect(16);
11163     /* save DPTR if it needs to be saved */
11164     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11165             if (bitVectBitValue(ic->rMask,i))
11166                     rsave = bitVectSetBit(rsave,i);
11167     }
11168     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11169                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11170     savermask(rsave);
11171     
11172     to = parms[0];
11173     from = parms[1];
11174     count = parms[2];
11175
11176     aopOp (from, ic->next, FALSE, FALSE);
11177
11178     /* get from into DPTR1 */
11179     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, TRUE));
11180     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, TRUE));
11181     if (options.model == MODEL_FLAT24) {
11182         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, TRUE));
11183     }
11184
11185     freeAsmop (from, NULL, ic, FALSE);
11186     aopOp (to, ic, FALSE, FALSE);
11187     /* get "to" into DPTR */
11188     /* if the operand is already in dptr
11189        then we do nothing else we move the value to dptr */
11190     if (AOP_TYPE (to) != AOP_STR) {
11191         /* if already in DPTR then we need to push */
11192         if (AOP_TYPE(to) == AOP_DPTR) {
11193             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
11194             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
11195             if (options.model == MODEL_FLAT24)
11196                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11197             emitcode ("pop", "dph");
11198             emitcode ("pop", "dpl");        
11199         } else {
11200             _startLazyDPSEvaluation ();
11201             /* if this is remateriazable */
11202             if (AOP_TYPE (to) == AOP_IMMD) {
11203                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
11204             } else {                    /* we need to get it byte by byte */
11205                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
11206                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
11207                 if (options.model == MODEL_FLAT24) {
11208                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11209                 }
11210             }
11211             _endLazyDPSEvaluation ();
11212         }
11213     }
11214     freeAsmop (to, NULL, ic, FALSE);
11215
11216     aopOp (count, ic->next->next, FALSE,FALSE);
11217     lbl =newiTempLabel(NULL);
11218     lbl2 =newiTempLabel(NULL);
11219
11220     /* now for the actual compare */
11221     emitcode("push","ar0");
11222     if (AOP_TYPE(count) == AOP_LIT && 
11223         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11224         emitcode (";","OH  JOY auto increment with djnz (very fast)");
11225         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
11226         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
11227         emitcode ("","!tlabeldef",lbl->key+100);
11228         if (fromc) {
11229             emitcode ("clr","a");
11230             emitcode ("movc", "a,@a+dptr");
11231         } else 
11232             emitcode ("movx", "a,@dptr");
11233         emitcode ("mov","r0,a");
11234         emitcode ("movx", "a,@dptr");
11235         emitcode ("clr","c");
11236         emitcode ("subb","a,r0");
11237         emitcode ("jnz","!tlabel",lbl2->key+100);
11238         emitcode ("inc", "dptr");
11239         emitcode ("inc", "dptr");
11240         emitcode ("djnz","b,!tlabel",lbl->key+100);
11241         emitcode ("clr","a");   
11242     } else {
11243         symbol *lbl1 = newiTempLabel(NULL);
11244         
11245         emitcode (";"," Auto increment but no djnz");
11246         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
11247         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
11248         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
11249         emitcode ("","!tlabeldef",lbl->key+100);
11250         if (fromc) {
11251             emitcode ("clr","a");
11252             emitcode ("movc", "a,@a+dptr");
11253         } else 
11254             emitcode ("movx", "a,@dptr");
11255         emitcode ("mov","r0,a");
11256         emitcode ("movx", "a,@dptr");
11257         emitcode ("clr","c");
11258         emitcode ("subb","a,r0");
11259         emitcode ("jnz","!tlabel",lbl2->key+100);
11260         emitcode ("inc", "dptr");
11261         emitcode ("inc", "dptr");
11262         emitcode ("mov","a,b");
11263         emitcode ("orl","a,_ap");
11264         emitcode ("jz","!tlabel",lbl1->key+100);
11265         emitcode ("mov","a,_ap");
11266         emitcode ("add","a,#!constbyte",0xFF);
11267         emitcode ("mov","_ap,a");
11268         emitcode ("mov","a,b");
11269         emitcode ("addc","a,#!constbyte",0xFF);
11270         emitcode ("mov","b,a");
11271         emitcode ("sjmp","!tlabel",lbl->key+100);
11272         emitcode ("","!tlabeldef",lbl1->key+100);
11273         emitcode ("clr","a");
11274     }
11275     freeAsmop (count, NULL, ic, FALSE);
11276     emitcode ("","!tlabeldef",lbl2->key+100);
11277     aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11278     aopPut(AOP(IC_RESULT(ic)),"a",0);
11279     freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11280     emitcode("pop","ar0");
11281     emitcode ("mov", "dps,#0"); 
11282     
11283     unsavermask(rsave);
11284
11285 }
11286
11287 /*-----------------------------------------------------------------*/
11288 /* genInp - gen code for __builtin_inp read data from a mem mapped */
11289 /* port, first parameter output area second parameter pointer to   */
11290 /* port third parameter count                                      */
11291 /*-----------------------------------------------------------------*/
11292 static void genInp( iCode *ic, int nparms, operand **parms)
11293 {
11294     operand *from , *to , *count;
11295     symbol *lbl;
11296     bitVect *rsave;
11297     int i;
11298
11299     /* we know it has to be 3 parameters */
11300     assert (nparms == 3);
11301     
11302     rsave = newBitVect(16);
11303     /* save DPTR if it needs to be saved */
11304     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11305             if (bitVectBitValue(ic->rMask,i))
11306                     rsave = bitVectSetBit(rsave,i);
11307     }
11308     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11309                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11310     savermask(rsave);
11311     
11312     to = parms[0];
11313     from = parms[1];
11314     count = parms[2];
11315
11316     aopOp (from, ic->next, FALSE, FALSE);
11317
11318     /* get from into DPTR1 */
11319     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, TRUE));
11320     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, TRUE));
11321     if (options.model == MODEL_FLAT24) {
11322         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, TRUE));
11323     }
11324
11325     freeAsmop (from, NULL, ic, FALSE);
11326     aopOp (to, ic, FALSE, FALSE);
11327     /* get "to" into DPTR */
11328     /* if the operand is already in dptr
11329        then we do nothing else we move the value to dptr */
11330     if (AOP_TYPE (to) != AOP_STR) {
11331         /* if already in DPTR then we need to push */
11332         if (AOP_TYPE(to) == AOP_DPTR) {
11333             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
11334             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
11335             if (options.model == MODEL_FLAT24)
11336                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11337             emitcode ("pop", "dph");
11338             emitcode ("pop", "dpl");        
11339         } else {
11340             _startLazyDPSEvaluation ();
11341             /* if this is remateriazable */
11342             if (AOP_TYPE (to) == AOP_IMMD) {
11343                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
11344             } else {                    /* we need to get it byte by byte */
11345                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
11346                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
11347                 if (options.model == MODEL_FLAT24) {
11348                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11349                 }
11350             }
11351             _endLazyDPSEvaluation ();
11352         }
11353     }
11354     freeAsmop (to, NULL, ic, FALSE);
11355
11356     aopOp (count, ic->next->next, FALSE,FALSE);
11357     lbl =newiTempLabel(NULL);
11358
11359     /* now for the actual copy */
11360     if (AOP_TYPE(count) == AOP_LIT && 
11361         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11362         emitcode (";","OH  JOY auto increment with djnz (very fast)");
11363         emitcode ("mov", "dps,#!constbyte",0x1);        /* Select DPTR2 */
11364         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
11365         emitcode ("","!tlabeldef",lbl->key+100);
11366         emitcode ("movx", "a,@dptr");   /* read data from port */
11367         emitcode ("dec","dps");         /* switch to DPTR */
11368         emitcode ("movx", "@dptr,a");   /* save into location */
11369         emitcode ("inc", "dptr");       /* point to next area */
11370         emitcode ("inc","dps");         /* switch to DPTR2 */
11371         emitcode ("djnz","b,!tlabel",lbl->key+100);
11372     } else {
11373         symbol *lbl1 = newiTempLabel(NULL);
11374         
11375         emitcode (";"," Auto increment but no djnz");
11376         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
11377         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
11378         emitcode ("mov", "dps,#!constbyte",0x1);        /* Select DPTR2 */
11379         emitcode ("","!tlabeldef",lbl->key+100);
11380         emitcode ("movx", "a,@dptr");
11381         emitcode ("dec","dps");         /* switch to DPTR */
11382         emitcode ("movx", "@dptr,a");
11383         emitcode ("inc", "dptr");
11384         emitcode ("inc","dps");         /* switch to DPTR2 */
11385 /*      emitcode ("djnz","b,!tlabel",lbl->key+100); */
11386 /*      emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
11387         emitcode ("mov","a,b");
11388         emitcode ("orl","a,_ap");
11389         emitcode ("jz","!tlabel",lbl1->key+100);
11390         emitcode ("mov","a,_ap");
11391         emitcode ("add","a,#!constbyte",0xFF);
11392         emitcode ("mov","_ap,a");
11393         emitcode ("mov","a,b");
11394         emitcode ("addc","a,#!constbyte",0xFF);
11395         emitcode ("mov","b,a");
11396         emitcode ("sjmp","!tlabel",lbl->key+100);
11397         emitcode ("","!tlabeldef",lbl1->key+100);
11398     }
11399     emitcode ("mov", "dps,#0"); 
11400     freeAsmop (count, NULL, ic, FALSE);
11401     unsavermask(rsave);
11402
11403 }
11404
11405 /*-----------------------------------------------------------------*/
11406 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
11407 /* port, first parameter output area second parameter pointer to   */
11408 /* port third parameter count                                      */
11409 /*-----------------------------------------------------------------*/
11410 static void genOutp( iCode *ic, int nparms, operand **parms)
11411 {
11412     operand *from , *to , *count;
11413     symbol *lbl;
11414     bitVect *rsave;
11415     int i;
11416
11417     /* we know it has to be 3 parameters */
11418     assert (nparms == 3);
11419     
11420     rsave = newBitVect(16);
11421     /* save DPTR if it needs to be saved */
11422     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11423             if (bitVectBitValue(ic->rMask,i))
11424                     rsave = bitVectSetBit(rsave,i);
11425     }
11426     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11427                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11428     savermask(rsave);
11429     
11430     to = parms[0];
11431     from = parms[1];
11432     count = parms[2];
11433
11434     aopOp (from, ic->next, FALSE, FALSE);
11435
11436     /* get from into DPTR1 */
11437     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, TRUE));
11438     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, TRUE));
11439     if (options.model == MODEL_FLAT24) {
11440         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, TRUE));
11441     }
11442
11443     freeAsmop (from, NULL, ic, FALSE);
11444     aopOp (to, ic, FALSE, FALSE);
11445     /* get "to" into DPTR */
11446     /* if the operand is already in dptr
11447        then we do nothing else we move the value to dptr */
11448     if (AOP_TYPE (to) != AOP_STR) {
11449         /* if already in DPTR then we need to push */
11450         if (AOP_TYPE(to) == AOP_DPTR) {
11451             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
11452             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
11453             if (options.model == MODEL_FLAT24)
11454                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11455             emitcode ("pop", "dph");
11456             emitcode ("pop", "dpl");        
11457         } else {
11458             _startLazyDPSEvaluation ();
11459             /* if this is remateriazable */
11460             if (AOP_TYPE (to) == AOP_IMMD) {
11461                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
11462             } else {                    /* we need to get it byte by byte */
11463                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
11464                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
11465                 if (options.model == MODEL_FLAT24) {
11466                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11467                 }
11468             }
11469             _endLazyDPSEvaluation ();
11470         }
11471     }
11472     freeAsmop (to, NULL, ic, FALSE);
11473
11474     aopOp (count, ic->next->next, FALSE,FALSE);
11475     lbl =newiTempLabel(NULL);
11476
11477     /* now for the actual copy */
11478     if (AOP_TYPE(count) == AOP_LIT && 
11479         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11480         emitcode (";","OH  JOY auto increment with djnz (very fast)");
11481         emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
11482         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
11483         emitcode ("","!tlabeldef",lbl->key+100);
11484         emitcode ("movx", "a,@dptr");   /* read data from port */
11485         emitcode ("inc","dps");         /* switch to DPTR2 */
11486         emitcode ("movx", "@dptr,a");   /* save into location */
11487         emitcode ("inc", "dptr");       /* point to next area */
11488         emitcode ("dec","dps");         /* switch to DPTR */
11489         emitcode ("djnz","b,!tlabel",lbl->key+100);
11490     } else {
11491         symbol *lbl1 = newiTempLabel(NULL);
11492         
11493         emitcode (";"," Auto increment but no djnz");
11494         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
11495         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
11496         emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
11497         emitcode ("","!tlabeldef",lbl->key+100);
11498 /*      emitcode ("push","acc"); */
11499         emitcode ("movx", "a,@dptr");
11500         emitcode ("inc", "dptr");
11501         emitcode ("inc","dps");         /* switch to DPTR2 */
11502         emitcode ("movx", "@dptr,a");
11503         emitcode ("dec","dps");         /* switch to DPTR */
11504 /*      emitcode ("pop","acc"); */
11505 /*      emitcode ("djnz","acc,!tlabel",lbl->key+100); */
11506 /*      emitcode ("djnz","b,!tlabel",lbl->key+100); */
11507         emitcode ("mov","a,b");
11508         emitcode ("orl","a,_ap");
11509         emitcode ("jz","!tlabel",lbl1->key+100);
11510         emitcode ("mov","a,_ap");
11511         emitcode ("add","a,#!constbyte",0xFF);
11512         emitcode ("mov","_ap,a");
11513         emitcode ("mov","a,b");
11514         emitcode ("addc","a,#!constbyte",0xFF);
11515         emitcode ("mov","b,a");
11516         emitcode ("sjmp","!tlabel",lbl->key+100);
11517         emitcode ("","!tlabeldef",lbl1->key+100);
11518     }
11519     emitcode ("mov", "dps,#0"); 
11520     freeAsmop (count, NULL, ic, FALSE);
11521     unsavermask(rsave);
11522
11523 }
11524
11525 /*-----------------------------------------------------------------*/
11526 /* genSwapW - swap lower & high order bytes                        */
11527 /*-----------------------------------------------------------------*/
11528 static void genSwapW(iCode *ic, int nparms, operand **parms)
11529 {
11530     operand *dest;
11531     operand *src;
11532     assert (nparms==1);
11533
11534     src = parms[0];
11535     dest=IC_RESULT(ic);
11536
11537     assert(getSize(operandType(src))==2);
11538
11539     aopOp (src, ic, FALSE, FALSE);
11540     emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,TRUE));
11541     _G.accInUse++;
11542     emitcode ("mov","b,%s",aopGet(AOP(src),1,FALSE,FALSE,FALSE));
11543     _G.accInUse--;
11544     freeAsmop (src, NULL, ic, FALSE);
11545     
11546     aopOp (dest,ic, FALSE, FALSE);
11547     aopPut(AOP(dest),"b",0);
11548     aopPut(AOP(dest),"a",1);
11549     freeAsmop (dest, NULL, ic, FALSE);    
11550 }
11551
11552 /*-----------------------------------------------------------------*/
11553 /* genMemsetX - gencode for memSetX data                           */
11554 /*-----------------------------------------------------------------*/
11555 static void genMemsetX(iCode *ic, int nparms, operand **parms)
11556 {
11557     operand *to , *val , *count;
11558     symbol *lbl;
11559     char *l;
11560     int i;
11561     bitVect *rsave = NULL;
11562
11563     /* we know it has to be 3 parameters */
11564     assert (nparms == 3);
11565     
11566     to = parms[0];
11567     val = parms[1];
11568     count = parms[2];
11569         
11570     /* save DPTR if it needs to be saved */
11571     rsave = newBitVect(16);
11572     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11573             if (bitVectBitValue(ic->rMask,i))
11574                     rsave = bitVectSetBit(rsave,i);
11575     }
11576     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11577                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11578     savermask(rsave);
11579
11580     aopOp (to, ic, FALSE, FALSE);
11581     /* get "to" into DPTR */
11582     /* if the operand is already in dptr
11583        then we do nothing else we move the value to dptr */
11584     if (AOP_TYPE (to) != AOP_STR) {
11585         /* if already in DPTR then we need to push */
11586         if (AOP_TYPE(to) == AOP_DPTR) {
11587             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
11588             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
11589             if (options.model == MODEL_FLAT24)
11590                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11591             emitcode ("pop", "dph");
11592             emitcode ("pop", "dpl");        
11593         } else {
11594             _startLazyDPSEvaluation ();
11595             /* if this is remateriazable */
11596             if (AOP_TYPE (to) == AOP_IMMD) {
11597                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
11598             } else {                    /* we need to get it byte by byte */
11599                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
11600                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
11601                 if (options.model == MODEL_FLAT24) {
11602                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11603                 }
11604             }
11605             _endLazyDPSEvaluation ();
11606         }
11607     }
11608     freeAsmop (to, NULL, ic, FALSE);
11609
11610     aopOp (val, ic->next->next, FALSE,FALSE);
11611     aopOp (count, ic->next->next, FALSE,FALSE);    
11612     lbl =newiTempLabel(NULL);
11613     /* now for the actual copy */
11614     if (AOP_TYPE(count) == AOP_LIT && 
11615         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11616         l = aopGet(AOP (val), 0, FALSE, FALSE, TRUE);
11617         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
11618         MOVA(l);
11619         emitcode ("","!tlabeldef",lbl->key+100);
11620         emitcode ("movx", "@dptr,a");
11621         emitcode ("inc", "dptr");
11622         emitcode ("djnz","b,!tlabel",lbl->key+100);
11623     } else {
11624         symbol *lbl1 = newiTempLabel(NULL);
11625         
11626         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
11627         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
11628         emitcode ("","!tlabeldef",lbl->key+100);
11629         l = aopGet(AOP (val), 0, FALSE, FALSE, TRUE);
11630         MOVA(l);
11631         emitcode ("movx", "@dptr,a");
11632         emitcode ("inc", "dptr");
11633         emitcode ("mov","a,b");
11634         emitcode ("orl","a,_ap");
11635         emitcode ("jz","!tlabel",lbl1->key+100);
11636         emitcode ("mov","a,_ap");
11637         emitcode ("add","a,#!constbyte",0xFF);
11638         emitcode ("mov","_ap,a");
11639         emitcode ("mov","a,b");
11640         emitcode ("addc","a,#!constbyte",0xFF);
11641         emitcode ("mov","b,a");
11642         emitcode ("sjmp","!tlabel",lbl->key+100);
11643         emitcode ("","!tlabeldef",lbl1->key+100);
11644     }
11645     freeAsmop (count, NULL, ic, FALSE);
11646     unsavermask(rsave);
11647 }
11648
11649 /*-----------------------------------------------------------------*/
11650 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
11651 /*-----------------------------------------------------------------*/
11652 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
11653 {
11654         bitVect *rsave ;
11655         operand *pnum, *result;
11656         int i;
11657     
11658         assert (nparms==1);
11659         /* save registers that need to be saved */
11660         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11661                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11662     
11663         pnum = parms[0]; 
11664         aopOp (pnum, ic, FALSE, FALSE);
11665         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,FALSE));
11666         freeAsmop (pnum, NULL, ic, FALSE);
11667         emitcode ("lcall","NatLib_LoadPrimitive");
11668         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11669         if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) || 
11670             aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
11671                 for (i = (size-1) ; i >= 0 ; i-- ) {
11672                         emitcode ("push","a%s",javaRet[i]);
11673                 }
11674                 for (i=0; i < size ; i++ ) {
11675                         emitcode ("pop","a%s",aopGet(AOP(result),i,FALSE,FALSE,FALSE));
11676                 }
11677         } else {
11678                 for (i = 0 ; i < size ; i++ ) {
11679                         aopPut(AOP(result),javaRet[i],i);
11680                 }
11681         }    
11682         freeAsmop (result, NULL, ic, FALSE);
11683         unsavermask(rsave);
11684 }
11685
11686 /*-----------------------------------------------------------------*/
11687 /* genNatLibLoadPointer - calls TINI api function to load pointer  */
11688 /*-----------------------------------------------------------------*/
11689 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
11690 {
11691         bitVect *rsave ;
11692         operand *pnum, *result;
11693         int size = 3;
11694         int i;
11695     
11696         assert (nparms==1);
11697         /* save registers that need to be saved */
11698         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11699                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11700     
11701         pnum = parms[0]; 
11702         aopOp (pnum, ic, FALSE, FALSE);
11703         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,FALSE));
11704         freeAsmop (pnum, NULL, ic, FALSE);
11705         emitcode ("lcall","NatLib_LoadPointer");
11706         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11707         if (AOP_TYPE(result)!=AOP_STR) {
11708                 for (i = 0 ; i < size ; i++ ) {
11709                         aopPut(AOP(result),fReturn[i],i);
11710                 }
11711         }    
11712         freeAsmop (result, NULL, ic, FALSE);
11713         unsavermask(rsave);
11714 }
11715
11716 /*-----------------------------------------------------------------*/
11717 /* genNatLibInstallStateBlock -                                    */
11718 /*-----------------------------------------------------------------*/
11719 static void genNatLibInstallStateBlock(iCode *ic, int nparms, 
11720                                        operand **parms, const char *name)
11721 {
11722         bitVect *rsave ;
11723         operand *psb, *handle;
11724         assert (nparms==2);
11725
11726         /* save registers that need to be saved */
11727         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11728                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11729         psb = parms[0];
11730         handle = parms[1];
11731
11732         /* put pointer to state block into DPTR1 */
11733         aopOp (psb, ic, FALSE, FALSE);
11734         if (AOP_TYPE (psb) == AOP_IMMD) {
11735                 emitcode ("mov","dps,#1");
11736                 emitcode ("mov", "dptr,%s", aopGet (AOP (psb), 0, TRUE, FALSE, FALSE));
11737                 emitcode ("mov","dps,#0");
11738         } else {
11739                 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,FALSE));
11740                 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,FALSE));
11741                 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,FALSE));
11742         }
11743         freeAsmop (psb, NULL, ic, FALSE);
11744
11745         /* put libraryID into DPTR */
11746         emitcode ("mov","dptr,#LibraryID");
11747
11748         /* put handle into r3:r2 */
11749         aopOp (handle, ic, FALSE, FALSE);
11750         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11751                 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));  
11752                 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11753                 emitcode ("pop","ar3");
11754                 emitcode ("pop","ar2");
11755         } else {        
11756                 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));        
11757                 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11758         }
11759         freeAsmop (psb, NULL, ic, FALSE);
11760
11761         /* make the call */
11762         emitcode ("lcall","NatLib_Install%sStateBlock",name);
11763
11764         /* put return value into place*/
11765         _G.accInUse++;
11766         aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
11767         _G.accInUse--;
11768         aopPut(AOP(IC_RESULT(ic)),"a",0);
11769         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11770         unsavermask(rsave);
11771 }
11772
11773 /*-----------------------------------------------------------------*/
11774 /* genNatLibRemoveStateBlock -                                     */
11775 /*-----------------------------------------------------------------*/
11776 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
11777 {
11778         bitVect *rsave ;
11779
11780         assert(nparms==0);
11781
11782         /* save registers that need to be saved */
11783         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11784                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11785
11786         /* put libraryID into DPTR */
11787         emitcode ("mov","dptr,#LibraryID");
11788         /* make the call */
11789         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
11790         unsavermask(rsave);
11791 }
11792
11793 /*-----------------------------------------------------------------*/
11794 /* genNatLibGetStateBlock -                                        */
11795 /*-----------------------------------------------------------------*/
11796 static void genNatLibGetStateBlock(iCode *ic,int nparms,
11797                                    operand **parms,const char *name)
11798 {
11799         bitVect *rsave ;
11800         symbol *lbl = newiTempLabel(NULL);
11801         
11802         assert(nparms==0);
11803         /* save registers that need to be saved */
11804         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11805                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11806
11807         /* put libraryID into DPTR */
11808         emitcode ("mov","dptr,#LibraryID");
11809         /* make the call */
11810         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
11811         emitcode ("jnz","!tlabel",lbl->key+100);
11812
11813         /* put return value into place */
11814         aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
11815         if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
11816                 emitcode ("push","ar3");
11817                 emitcode ("push","ar2");
11818                 emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,FALSE));
11819                 emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,FALSE));
11820         } else {
11821                 aopPut(AOP(IC_RESULT(ic)),"r2",0);
11822                 aopPut(AOP(IC_RESULT(ic)),"r3",1);
11823         }
11824         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11825         emitcode ("","!tlabeldef",lbl->key+100);
11826         unsavermask(rsave);
11827 }
11828
11829 /*-----------------------------------------------------------------*/
11830 /* genMMMalloc -                                                   */
11831 /*-----------------------------------------------------------------*/
11832 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
11833                          int size, const char *name)
11834 {
11835         bitVect *rsave ;
11836         operand *bsize;
11837         symbol *rsym;
11838         symbol *lbl = newiTempLabel(NULL);
11839
11840         assert (nparms == 1);
11841         /* save registers that need to be saved */
11842         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11843                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
11844         
11845         bsize=parms[0];
11846         aopOp (bsize,ic,FALSE,FALSE);
11847
11848         /* put the size in R4-R2 */
11849         if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
11850                 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,FALSE));
11851                 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,FALSE));
11852                 if (size==3) {
11853                         emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,FALSE));
11854                         emitcode("pop","ar4");
11855                 }
11856                 emitcode("pop","ar3");
11857                 emitcode("pop","ar2");          
11858         } else {
11859                 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,FALSE));
11860                 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,FALSE));
11861                 if (size==3) {
11862                         emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,FALSE));
11863                 }
11864         }
11865         freeAsmop (bsize, NULL, ic, FALSE);
11866
11867         /* make the call */
11868         emitcode ("lcall","MM_%s",name);
11869         emitcode ("jz","!tlabel",lbl->key+100);
11870         emitcode ("mov","r2,#!constbyte",0xff);
11871         emitcode ("mov","r3,#!constbyte",0xff);
11872         emitcode ("","!tlabeldef",lbl->key+100);
11873         /* we don't care about the pointer : we just save the handle */
11874         rsym = OP_SYMBOL(IC_RESULT(ic));
11875         if (rsym->liveFrom != rsym->liveTo) {
11876                 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
11877                 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
11878                         emitcode ("push","ar3");
11879                         emitcode ("push","ar2");
11880                         emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,FALSE));
11881                         emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,FALSE));
11882                 } else {
11883                         aopPut(AOP(IC_RESULT(ic)),"r2",0);
11884                         aopPut(AOP(IC_RESULT(ic)),"r3",1);
11885                 }
11886                 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11887         }
11888         unsavermask(rsave);
11889 }
11890
11891 /*-----------------------------------------------------------------*/
11892 /* genMMDeref -                                                    */
11893 /*-----------------------------------------------------------------*/
11894 static void genMMDeref (iCode *ic,int nparms, operand **parms)
11895 {
11896         bitVect *rsave ;
11897         operand *handle;
11898
11899         assert (nparms == 1);
11900         /* save registers that need to be saved */
11901         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11902                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
11903         
11904         handle=parms[0];
11905         aopOp (handle,ic,FALSE,FALSE);
11906
11907         /* put the size in R4-R2 */
11908         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11909                 emitcode("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11910                 emitcode("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11911                 emitcode("pop","ar3");
11912                 emitcode("pop","ar2");          
11913         } else {
11914                 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11915                 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11916         }
11917         freeAsmop (handle, NULL, ic, FALSE);
11918
11919         /* make the call */
11920         emitcode ("lcall","MM_Deref");
11921         
11922         {
11923                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11924                 if (rsym->liveFrom != rsym->liveTo) {                   
11925                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11926                         if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
11927                                 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
11928                                 aopPut(AOP(IC_RESULT(ic)),"dph",1);
11929                                 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
11930                         }
11931                 }
11932         }
11933         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11934         unsavermask(rsave);
11935 }
11936
11937 /*-----------------------------------------------------------------*/
11938 /* genMMUnrestrictedPersist -                                      */
11939 /*-----------------------------------------------------------------*/
11940 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
11941 {
11942         bitVect *rsave ;
11943         operand *handle;
11944
11945         assert (nparms == 1);
11946         /* save registers that need to be saved */
11947         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11948                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
11949         
11950         handle=parms[0];
11951         aopOp (handle,ic,FALSE,FALSE);
11952
11953         /* put the size in R3-R2 */
11954         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11955                 emitcode("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11956                 emitcode("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11957                 emitcode("pop","ar3");
11958                 emitcode("pop","ar2");          
11959         } else {
11960                 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11961                 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11962         }
11963         freeAsmop (handle, NULL, ic, FALSE);
11964
11965         /* make the call */
11966         emitcode ("lcall","MM_UnrestrictedPersist");
11967
11968         {
11969                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11970                 if (rsym->liveFrom != rsym->liveTo) {   
11971                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11972                         aopPut(AOP(IC_RESULT(ic)),"a",0);
11973                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11974                 }
11975         }
11976         unsavermask(rsave);
11977 }
11978
11979 /*-----------------------------------------------------------------*/
11980 /* genSystemExecJavaProcess -                                      */
11981 /*-----------------------------------------------------------------*/
11982 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
11983 {
11984         bitVect *rsave ;
11985         operand *handle, *pp;
11986
11987         assert (nparms==2);
11988         /* save registers that need to be saved */
11989         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11990                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
11991         
11992         pp = parms[0];
11993         handle = parms[1];
11994         
11995         /* put the handle in R3-R2 */
11996         aopOp (handle,ic,FALSE,FALSE);
11997         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11998                 emitcode("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11999                 emitcode("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
12000                 emitcode("pop","ar3");
12001                 emitcode("pop","ar2");          
12002         } else {
12003                 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
12004                 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
12005         }
12006         freeAsmop (handle, NULL, ic, FALSE);
12007         
12008         /* put pointer in DPTR */
12009         aopOp (pp,ic,FALSE,FALSE);
12010         if (AOP_TYPE(pp) == AOP_IMMD) {
12011                 emitcode ("mov", "dptr,%s", aopGet (AOP (pp), 0, TRUE, FALSE, FALSE));          
12012         } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12013                 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,FALSE));
12014                 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,FALSE));
12015                 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,FALSE));
12016         }
12017         freeAsmop (handle, NULL, ic, FALSE);
12018
12019         /* make the call */
12020         emitcode ("lcall","System_ExecJavaProcess");
12021         
12022         /* put result in place */
12023         {
12024                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12025                 if (rsym->liveFrom != rsym->liveTo) {   
12026                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12027                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12028                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12029                 }
12030         }
12031         
12032         unsavermask(rsave);
12033 }
12034
12035 /*-----------------------------------------------------------------*/
12036 /* genSystemRTCRegisters -                                         */
12037 /*-----------------------------------------------------------------*/
12038 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12039                                   char *name)
12040 {
12041         bitVect *rsave ;
12042         operand *pp;
12043
12044         assert (nparms==1);
12045         /* save registers that need to be saved */
12046         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12047                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12048         
12049         pp=parms[0];
12050         /* put pointer in DPTR */
12051         aopOp (pp,ic,FALSE,FALSE);
12052         if (AOP_TYPE (pp) == AOP_IMMD) {
12053                 emitcode ("mov","dps,#1");
12054                 emitcode ("mov", "dptr,%s", aopGet (AOP (pp), 0, TRUE, FALSE, FALSE));
12055                 emitcode ("mov","dps,#0");
12056         } else {
12057                 emitcode ("mov","dpl1,%s",aopGet(AOP(pp),0,FALSE,FALSE,FALSE));
12058                 emitcode ("mov","dph1,%s",aopGet(AOP(pp),1,FALSE,FALSE,FALSE));
12059                 emitcode ("mov","dpx1,%s",aopGet(AOP(pp),2,FALSE,FALSE,FALSE));
12060         }
12061         freeAsmop (pp, NULL, ic, FALSE);
12062
12063         /* make the call */
12064         emitcode ("lcall","System_%sRTCRegisters",name);
12065
12066         unsavermask(rsave);
12067 }
12068
12069 /*-----------------------------------------------------------------*/
12070 /* genSystemThreadSleep -                                          */
12071 /*-----------------------------------------------------------------*/
12072 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12073 {
12074         bitVect *rsave ;
12075         operand *to, *s;
12076
12077         assert (nparms==1);
12078         /* save registers that need to be saved */
12079         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12080                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12081
12082         to = parms[0];
12083         aopOp(to,ic,FALSE,FALSE);
12084         if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
12085             aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
12086                 emitcode ("push","%s",aopGet(AOP(to),0,FALSE,TRUE,FALSE));
12087                 emitcode ("push","%s",aopGet(AOP(to),1,FALSE,TRUE,FALSE));
12088                 emitcode ("push","%s",aopGet(AOP(to),2,FALSE,TRUE,FALSE));
12089                 emitcode ("push","%s",aopGet(AOP(to),3,FALSE,TRUE,FALSE));
12090                 emitcode ("pop","ar3");
12091                 emitcode ("pop","ar2");
12092                 emitcode ("pop","ar1");
12093                 emitcode ("pop","ar0");
12094         } else {
12095                 emitcode ("mov","r0,%s",aopGet(AOP(to),0,FALSE,TRUE,FALSE));
12096                 emitcode ("mov","r1,%s",aopGet(AOP(to),1,FALSE,TRUE,FALSE));
12097                 emitcode ("mov","r2,%s",aopGet(AOP(to),2,FALSE,TRUE,FALSE));
12098                 emitcode ("mov","r3,%s",aopGet(AOP(to),3,FALSE,TRUE,FALSE));
12099         }
12100         freeAsmop (to, NULL, ic, FALSE);
12101
12102         /* suspend in acc */
12103         s = parms[1];
12104         aopOp(s,ic,FALSE,FALSE);
12105         emitcode ("mov","a,%s",aopGet(AOP(s),0,FALSE,TRUE,FALSE));
12106         freeAsmop (s, NULL, ic, FALSE);
12107
12108         /* make the call */
12109         emitcode ("lcall","System_%s",name);
12110
12111         unsavermask(rsave);
12112 }
12113
12114 /*-----------------------------------------------------------------*/
12115 /* genSystemThreadResume -                                         */
12116 /*-----------------------------------------------------------------*/
12117 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
12118 {
12119         bitVect *rsave ;
12120         operand *tid,*pid;
12121
12122         assert (nparms==2);
12123         /* save registers that need to be saved */
12124         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12125                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12126         
12127         tid = parms[0];
12128         pid = parms[1];
12129         
12130         /* PID in R0 */
12131         aopOp(pid,ic,FALSE,FALSE);
12132         emitcode ("mov","r0,%s",aopGet(AOP(pid),0,FALSE,TRUE,FALSE));
12133         freeAsmop (pid, NULL, ic, FALSE);
12134         
12135         /* tid into ACC */
12136         aopOp(tid,ic,FALSE,FALSE);
12137         emitcode ("mov","a,%s",aopGet(AOP(tid),0,FALSE,TRUE,FALSE));
12138         freeAsmop (tid, NULL, ic, FALSE);
12139         
12140         emitcode ("lcall","System_ThreadResume");
12141
12142         /* put result into place */
12143         {
12144                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12145                 if (rsym->liveFrom != rsym->liveTo) {   
12146                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12147                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12148                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12149                 }
12150         }
12151         unsavermask(rsave);
12152 }
12153
12154 /*-----------------------------------------------------------------*/
12155 /* genSystemProcessResume -                                        */
12156 /*-----------------------------------------------------------------*/
12157 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
12158 {
12159         bitVect *rsave ;
12160         operand *pid;
12161
12162         assert (nparms==1);
12163         /* save registers that need to be saved */
12164         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12165                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12166         
12167         pid = parms[0];
12168         
12169         /* pid into ACC */
12170         aopOp(pid,ic,FALSE,FALSE);
12171         emitcode ("mov","a,%s",aopGet(AOP(pid),0,FALSE,TRUE,FALSE));
12172         freeAsmop (pid, NULL, ic, FALSE);
12173         
12174         emitcode ("lcall","System_ProcessResume");
12175
12176         unsavermask(rsave);
12177 }
12178
12179 /*-----------------------------------------------------------------*/
12180 /* genSystem -                                                     */
12181 /*-----------------------------------------------------------------*/
12182 static void genSystem (iCode *ic,int nparms,char *name)
12183 {
12184         assert(nparms == 0);
12185
12186         emitcode ("lcall","System_%s",name);
12187 }
12188
12189 /*-----------------------------------------------------------------*/
12190 /* genSystemPoll -                                                  */
12191 /*-----------------------------------------------------------------*/
12192 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
12193 {
12194         bitVect *rsave ;
12195         operand *fp;
12196
12197         assert (nparms==1);
12198         /* save registers that need to be saved */
12199         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12200                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12201
12202         fp = parms[0];
12203         aopOp (fp,ic,FALSE,FALSE);
12204         if (AOP_TYPE (fp) == AOP_IMMD) {
12205                 emitcode ("mov", "dptr,%s", aopGet (AOP (fp), 0, TRUE, FALSE, FALSE));
12206         } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
12207                 emitcode ("mov","dpl,%s",aopGet(AOP(fp),0,FALSE,FALSE,FALSE));
12208                 emitcode ("mov","dph,%s",aopGet(AOP(fp),1,FALSE,FALSE,FALSE));
12209                 emitcode ("mov","dpx,%s",aopGet(AOP(fp),2,FALSE,FALSE,FALSE));
12210         }
12211         freeAsmop (fp, NULL, ic, FALSE);
12212
12213         emitcode ("lcall","System_%sPoll",name);
12214
12215         /* put result into place */
12216         {
12217                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12218                 if (rsym->liveFrom != rsym->liveTo) {   
12219                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12220                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12221                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12222                 }
12223         }
12224         unsavermask(rsave);
12225 }
12226
12227 /*-----------------------------------------------------------------*/
12228 /* genSystemGetCurrentID -                                         */
12229 /*-----------------------------------------------------------------*/
12230 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
12231 {
12232         assert (nparms==0);
12233
12234         emitcode ("lcall","System_GetCurrent%sId",name);
12235         /* put result into place */
12236         {
12237                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12238                 if (rsym->liveFrom != rsym->liveTo) {   
12239                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12240                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12241                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12242                 }
12243         }
12244 }
12245
12246 /*-----------------------------------------------------------------*/
12247 /* genBuiltIn - calls the appropriate function to  generating code */
12248 /* for a built in function                                         */
12249 /*-----------------------------------------------------------------*/
12250 static void genBuiltIn (iCode *ic)
12251 {
12252         operand *bi_parms[MAX_BUILTIN_ARGS];
12253         int nbi_parms;
12254         iCode *bi_iCode;
12255         symbol *bif;
12256
12257         /* get all the arguments for a built in function */
12258         bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
12259
12260         /* which function is it */
12261         bif = OP_SYMBOL(IC_LEFT(bi_iCode));
12262         if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
12263                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
12264         } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
12265                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
12266         } else  if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
12267                 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
12268         } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
12269                 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
12270         } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
12271                 genMemsetX(bi_iCode,nbi_parms,bi_parms);
12272         } else if (strcmp(bif->name,"__builtin_inp")==0) {
12273                 genInp(bi_iCode,nbi_parms,bi_parms);
12274         } else if (strcmp(bif->name,"__builtin_outp")==0) {
12275                 genOutp(bi_iCode,nbi_parms,bi_parms);
12276         } else if (strcmp(bif->name,"__builtin_swapw")==0) {
12277                 genSwapW(bi_iCode,nbi_parms,bi_parms);
12278                 /* JavaNative builtIns */               
12279         } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
12280                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
12281         } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
12282                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
12283         } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
12284                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
12285         } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
12286                 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
12287         } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
12288                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12289         } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
12290                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12291         } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
12292                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
12293         } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
12294                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
12295         } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
12296                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12297         } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
12298                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12299         } else if (strcmp(bif->name,"MM_XMalloc")==0) {
12300                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
12301         } else if (strcmp(bif->name,"MM_Malloc")==0) {
12302                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
12303         } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
12304                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
12305         } else if (strcmp(bif->name,"MM_Free")==0) {
12306                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
12307         } else if (strcmp(bif->name,"MM_Deref")==0) {
12308                 genMMDeref(bi_iCode,nbi_parms,bi_parms);
12309         } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
12310                 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
12311         } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
12312                 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
12313         } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
12314                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
12315         } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
12316                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
12317         } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
12318                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
12319         } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
12320                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
12321         } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
12322                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
12323         } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
12324                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
12325         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12326                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12327         } else if (strcmp(bif->name,"System_SaveThread")==0) {
12328                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12329         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12330                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12331         } else if (strcmp(bif->name,"System_ProcessResume")==0) {
12332                 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
12333         } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
12334                 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
12335         } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
12336                 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
12337         } else if (strcmp(bif->name,"System_ProcessYield")==0) {
12338                 genSystem(bi_iCode,nbi_parms,"ProcessYield");
12339         } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
12340                 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
12341         } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
12342                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
12343         } else if (strcmp(bif->name,"System_RemovePoll")==0) {
12344                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
12345         } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
12346                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
12347         } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
12348                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
12349         } else {
12350                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
12351                 return ;
12352         }
12353         return ;    
12354 }
12355
12356 /*-----------------------------------------------------------------*/
12357 /* gen390Code - generate code for Dallas 390 based controllers     */
12358 /*-----------------------------------------------------------------*/
12359 void
12360 gen390Code (iCode * lic)
12361 {
12362   iCode *ic;
12363   int cln = 0;
12364
12365   lineHead = lineCurr = NULL;
12366   dptrn[1][0] = "dpl1";
12367   dptrn[1][1] = "dph1";
12368   dptrn[1][2] = "dpx1";
12369   
12370   if (options.model == MODEL_FLAT24) {
12371     fReturnSizeDS390 = 5;
12372     fReturn = fReturn24;
12373   } else {
12374     fReturnSizeDS390 = 4;
12375     fReturn = fReturn16;
12376     options.stack10bit=0;
12377   }
12378 #if 1
12379   /* print the allocation information */
12380   if (allocInfo)
12381     printAllocInfo (currFunc, codeOutFile);
12382 #endif
12383   /* if debug information required */
12384   if (options.debug && currFunc)
12385     {
12386       cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
12387       _G.debugLine = 1;
12388       if (IS_STATIC (currFunc->etype))
12389         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
12390       else
12391         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
12392       _G.debugLine = 0;
12393     }
12394   /* stack pointer name */
12395   if (options.useXstack)
12396     spname = "_spx";
12397   else
12398     spname = "sp";
12399
12400
12401   for (ic = lic; ic; ic = ic->next)
12402     {
12403
12404       if (ic->lineno && cln != ic->lineno)
12405         {
12406           if (options.debug)
12407             {
12408               _G.debugLine = 1;
12409               emitcode ("", "C$%s$%d$%d$%d ==.",
12410                         FileBaseName (ic->filename), ic->lineno,
12411                         ic->level, ic->block);
12412               _G.debugLine = 0;
12413             }
12414           emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno, 
12415                     printCLine(ic->filename, ic->lineno));
12416           cln = ic->lineno;
12417         }
12418       /* if the result is marked as
12419          spilt and rematerializable or code for
12420          this has already been generated then
12421          do nothing */
12422       if (resultRemat (ic) || ic->generated)
12423         continue;
12424
12425       /* depending on the operation */
12426       switch (ic->op)
12427         {
12428         case '!':
12429           genNot (ic);
12430           break;
12431
12432         case '~':
12433           genCpl (ic);
12434           break;
12435
12436         case UNARYMINUS:
12437           genUminus (ic);
12438           break;
12439
12440         case IPUSH:
12441           genIpush (ic);
12442           break;
12443
12444         case IPOP:
12445           /* IPOP happens only when trying to restore a
12446              spilt live range, if there is an ifx statement
12447              following this pop then the if statement might
12448              be using some of the registers being popped which
12449              would destory the contents of the register so
12450              we need to check for this condition and handle it */
12451           if (ic->next &&
12452               ic->next->op == IFX &&
12453               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
12454             genIfx (ic->next, ic);
12455           else
12456             genIpop (ic);
12457           break;
12458
12459         case CALL:
12460           genCall (ic);
12461           break;
12462
12463         case PCALL:
12464           genPcall (ic);
12465           break;
12466
12467         case FUNCTION:
12468           genFunction (ic);
12469           break;
12470
12471         case ENDFUNCTION:
12472           genEndFunction (ic);
12473           break;
12474
12475         case RETURN:
12476           genRet (ic);
12477           break;
12478
12479         case LABEL:
12480           genLabel (ic);
12481           break;
12482
12483         case GOTO:
12484           genGoto (ic);
12485           break;
12486
12487         case '+':
12488           genPlus (ic);
12489           break;
12490
12491         case '-':
12492           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
12493             genMinus (ic);
12494           break;
12495
12496         case '*':
12497           genMult (ic);
12498           break;
12499
12500         case '/':
12501           genDiv (ic);
12502           break;
12503
12504         case '%':
12505           genMod (ic);
12506           break;
12507
12508         case '>':
12509           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
12510           break;
12511
12512         case '<':
12513           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
12514           break;
12515
12516         case LE_OP:
12517         case GE_OP:
12518         case NE_OP:
12519
12520           /* note these two are xlated by algebraic equivalence
12521              during parsing SDCC.y */
12522           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12523                   "got '>=' or '<=' shouldn't have come here");
12524           break;
12525
12526         case EQ_OP:
12527           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
12528           break;
12529
12530         case AND_OP:
12531           genAndOp (ic);
12532           break;
12533
12534         case OR_OP:
12535           genOrOp (ic);
12536           break;
12537
12538         case '^':
12539           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
12540           break;
12541
12542         case '|':
12543           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
12544           break;
12545
12546         case BITWISEAND:
12547           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
12548           break;
12549
12550         case INLINEASM:
12551           genInline (ic);
12552           break;
12553
12554         case RRC:
12555           genRRC (ic);
12556           break;
12557
12558         case RLC:
12559           genRLC (ic);
12560           break;
12561
12562         case GETHBIT:
12563           genGetHbit (ic);
12564           break;
12565
12566         case LEFT_OP:
12567           genLeftShift (ic);
12568           break;
12569
12570         case RIGHT_OP:
12571           genRightShift (ic);
12572           break;
12573
12574         case GET_VALUE_AT_ADDRESS:
12575           genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
12576           break;
12577
12578         case '=':
12579           if (POINTER_SET (ic))
12580             genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
12581           else
12582             genAssign (ic);
12583           break;
12584
12585         case IFX:
12586           genIfx (ic, NULL);
12587           break;
12588
12589         case ADDRESS_OF:
12590           genAddrOf (ic);
12591           break;
12592
12593         case JUMPTABLE:
12594           genJumpTab (ic);
12595           break;
12596
12597         case CAST:
12598           genCast (ic);
12599           break;
12600
12601         case RECEIVE:
12602           genReceive (ic);
12603           break;
12604
12605         case SEND:
12606           if (ic->builtinSEND) genBuiltIn(ic);
12607           else addSet (&_G.sendSet, ic);
12608           break;
12609
12610         case ARRAYINIT:
12611             genArrayInit(ic);
12612             break;
12613             
12614         default:
12615           ic = ic;
12616         }
12617     }
12618
12619
12620   /* now we are ready to call the
12621      peep hole optimizer */
12622   if (!options.nopeep)
12623     peepHole (&lineHead);
12624
12625   /* now do the actual printing */
12626   printLine (lineHead, codeOutFile);
12627   return;
12628 }