Optimise bit assignment
[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                 /* set C, if a >= 1 */
1389                 emitcode ("add", "a,0xff");
1390                 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1391               }
1392             }
1393         }
1394       break;
1395
1396     case AOP_STR:
1397       aop->coff = offset;
1398       if (strcmp (aop->aopu.aop_str[offset], s))
1399         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1400       break;
1401
1402     case AOP_ACC:
1403       aop->coff = offset;
1404       if (!offset && (strcmp (s, "acc") == 0))
1405         break;
1406
1407       if (strcmp (aop->aopu.aop_str[offset], s))
1408         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1409       break;
1410
1411     default:
1412       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1413               "aopPut got unsupported aop->type");
1414       exit (1);
1415     }
1416
1417 }
1418
1419
1420 /*--------------------------------------------------------------------*/
1421 /* reAdjustPreg - points a register back to where it should (coff==0) */
1422 /*--------------------------------------------------------------------*/
1423 static void
1424 reAdjustPreg (asmop * aop)
1425 {
1426   if ((aop->coff==0) || (aop->size <= 1)) {
1427     return;
1428   }
1429
1430   switch (aop->type)
1431     {
1432     case AOP_R0:
1433     case AOP_R1:
1434       while (aop->coff--)
1435         emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1436       break;
1437     case AOP_DPTR:
1438     case AOP_DPTR2:
1439       if (aop->type == AOP_DPTR2)
1440         {
1441           genSetDPTR (1);
1442           _flushLazyDPS ();
1443         }
1444       while (aop->coff--)
1445         {
1446           emitcode ("lcall", "__decdptr");
1447         }
1448
1449       if (aop->type == AOP_DPTR2)
1450         {
1451           genSetDPTR (0);
1452         }
1453       break;
1454
1455     }
1456   aop->coff=0;
1457 }
1458
1459 #define AOP(op) op->aop
1460 #define AOP_TYPE(op) AOP(op)->type
1461 #define AOP_SIZE(op) AOP(op)->size
1462 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1463                        AOP_TYPE(x) == AOP_R0))
1464
1465 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
1466                         AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1467                          AOP(x)->paged))
1468
1469 #define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
1470                       (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1471                       x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1472 #define AOP_INDPTRn(x) (AOP_TYPE(x) == AOP_DPTRn)
1473 #define AOP_USESDPTR(x) (AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_STR)
1474
1475 /* Workaround for DS80C390 bug: div ab may return bogus results
1476  * if A is accessed in instruction immediately before the div.
1477  *
1478  * Will be fixed in B4 rev of processor, Dallas claims.
1479  */
1480
1481 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L)       \
1482     if (!AOP_NEEDSACC(RIGHT))         \
1483     {               \
1484       /* We can load A first, then B, since     \
1485        * B (the RIGHT operand) won't clobber A,   \
1486        * thus avoiding touching A right before the div. \
1487        */             \
1488       D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1489       L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE);     \
1490       MOVA(L);            \
1491       emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1492     }               \
1493     else              \
1494     {               \
1495       /* Just stuff in a nop after loading A. */    \
1496       emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1497       L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE);   \
1498       MOVA(L);            \
1499       emitcode("nop", "; workaround for DS80C390 div bug.");  \
1500     }
1501
1502 /*-----------------------------------------------------------------*/
1503 /* genNotFloat - generates not for float operations              */
1504 /*-----------------------------------------------------------------*/
1505 static void
1506 genNotFloat (operand * op, operand * res)
1507 {
1508   int size, offset;
1509   char *l;
1510   symbol *tlbl;
1511
1512   D (emitcode (";", "genNotFloat ");
1513     );
1514
1515   /* we will put 127 in the first byte of
1516      the result */
1517   aopPut (AOP (res), "#127", 0);
1518   size = AOP_SIZE (op) - 1;
1519   offset = 1;
1520
1521   _startLazyDPSEvaluation ();
1522   l = aopGet (op->aop, offset++, FALSE, FALSE, TRUE);
1523   MOVA (l);
1524
1525   while (size--)
1526     {
1527       emitcode ("orl", "a,%s",
1528                 aopGet (op->aop,
1529                         offset++, FALSE, FALSE, FALSE));
1530     }
1531   _endLazyDPSEvaluation ();
1532
1533   tlbl = newiTempLabel (NULL);
1534   aopPut (res->aop, one, 1);
1535   emitcode ("jz", "!tlabel", (tlbl->key + 100));
1536   aopPut (res->aop, zero, 1);
1537   emitcode ("", "!tlabeldef", (tlbl->key + 100));
1538
1539   size = res->aop->size - 2;
1540   offset = 2;
1541   /* put zeros in the rest */
1542   while (size--)
1543     aopPut (res->aop, zero, offset++);
1544 }
1545
1546 /*-----------------------------------------------------------------*/
1547 /* opIsGptr: returns non-zero if the passed operand is       */
1548 /* a generic pointer type.             */
1549 /*-----------------------------------------------------------------*/
1550 static int
1551 opIsGptr (operand * op)
1552 {
1553   sym_link *type = operandType (op);
1554
1555   if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1556     {
1557       return 1;
1558     }
1559   return 0;
1560 }
1561
1562 /*-----------------------------------------------------------------*/
1563 /* getDataSize - get the operand data size                         */
1564 /*-----------------------------------------------------------------*/
1565 static int
1566 getDataSize (operand * op)
1567 {
1568   int size;
1569   size = AOP_SIZE (op);
1570   if (size == GPTRSIZE)
1571     {
1572       sym_link *type = operandType (op);
1573       if (IS_GENPTR (type))
1574         {
1575           /* generic pointer; arithmetic operations
1576            * should ignore the high byte (pointer type).
1577            */
1578           size--;
1579         }
1580     }
1581   return size;
1582 }
1583
1584 /*-----------------------------------------------------------------*/
1585 /* outAcc - output Acc                                             */
1586 /*-----------------------------------------------------------------*/
1587 static void
1588 outAcc (operand * result)
1589 {
1590   int size, offset;
1591   size = getDataSize (result);
1592   if (size)
1593     {
1594       aopPut (AOP (result), "a", 0);
1595       size--;
1596       offset = 1;
1597       /* unsigned or positive */
1598       while (size--)
1599         {
1600           aopPut (AOP (result), zero, offset++);
1601         }
1602     }
1603 }
1604
1605 /*-----------------------------------------------------------------*/
1606 /* outBitC - output a bit C                                        */
1607 /*-----------------------------------------------------------------*/
1608 static void
1609 outBitC (operand * result)
1610 {
1611   /* if the result is bit */
1612   if (AOP_TYPE (result) == AOP_CRY)
1613     {
1614       aopPut (AOP (result), "c", 0);
1615     }
1616   else
1617     {
1618       emitcode ("clr", "a");
1619       emitcode ("rlc", "a");
1620       outAcc (result);
1621     }
1622 }
1623
1624 /*-----------------------------------------------------------------*/
1625 /* toBoolean - emit code for orl a,operator(sizeop)                */
1626 /*-----------------------------------------------------------------*/
1627 static void
1628 toBoolean (operand * oper)
1629 {
1630   int   size = AOP_SIZE (oper) - 1;
1631   int   offset = 1;
1632   bool usedB = FALSE;
1633
1634   /* The generic part of a generic pointer should
1635    * not participate in it's truth value.
1636    *
1637    * i.e. 0x10000000 is zero.
1638    */
1639   if (opIsGptr (oper))
1640     {
1641       D (emitcode (";", "toBoolean: generic ptr special case.");
1642         );
1643       size--;
1644     }
1645
1646   _startLazyDPSEvaluation ();
1647   if (AOP_NEEDSACC (oper) && size)
1648     {
1649       usedB = TRUE;
1650       emitcode ("push", "b");
1651       emitcode ("mov", "b, %s", aopGet (AOP (oper), 0, FALSE, FALSE, FALSE));
1652     }
1653   else
1654     {
1655       MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, TRUE));
1656     }
1657   while (size--)
1658     {
1659       if (usedB)
1660         {
1661           emitcode ("orl", "b,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1662         }
1663       else
1664         {
1665           emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1666         }
1667     }
1668   _endLazyDPSEvaluation ();
1669
1670   if (usedB)
1671     {
1672       emitcode ("mov", "a,b");
1673       emitcode ("pop", "b");
1674     }
1675 }
1676
1677
1678 /*-----------------------------------------------------------------*/
1679 /* genNot - generate code for ! operation                          */
1680 /*-----------------------------------------------------------------*/
1681 static void
1682 genNot (iCode * ic)
1683 {
1684   symbol *tlbl;
1685   sym_link *optype = operandType (IC_LEFT (ic));
1686
1687   D (emitcode (";", "genNot ");
1688     );
1689
1690   /* assign asmOps to operand & result */
1691   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1692   aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1693
1694   /* if in bit space then a special case */
1695   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1696     {
1697       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1698       emitcode ("cpl", "c");
1699       outBitC (IC_RESULT (ic));
1700       goto release;
1701     }
1702
1703   /* if type float then do float */
1704   if (IS_FLOAT (optype))
1705     {
1706       genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1707       goto release;
1708     }
1709
1710   toBoolean (IC_LEFT (ic));
1711
1712   tlbl = newiTempLabel (NULL);
1713   emitcode ("cjne", "a,#1,!tlabel", tlbl->key + 100);
1714   emitcode ("", "!tlabeldef", tlbl->key + 100);
1715   outBitC (IC_RESULT (ic));
1716
1717 release:
1718   /* release the aops */
1719   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1720   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1721 }
1722
1723
1724 /*-----------------------------------------------------------------*/
1725 /* genCpl - generate code for complement                           */
1726 /*-----------------------------------------------------------------*/
1727 static void
1728 genCpl (iCode * ic)
1729 {
1730   int offset = 0;
1731   int size;
1732   symbol *tlbl;
1733
1734   D (emitcode (";", "genCpl ");
1735     );
1736
1737
1738   /* assign asmOps to operand & result */
1739   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1740   aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1741
1742   /* special case if in bit space */
1743   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
1744     if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
1745       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1746       emitcode ("cpl", "c");
1747       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1748       goto release;
1749     }
1750     tlbl=newiTempLabel(NULL);
1751     emitcode ("cjne", "%s,#0x01,%05d$", 
1752               aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE,TRUE), tlbl->key+100);
1753     emitcode ("", "%05d$:", tlbl->key+100);
1754     outBitC (IC_RESULT(ic));
1755     goto release;
1756   }
1757
1758   size = AOP_SIZE (IC_RESULT (ic));
1759   _startLazyDPSEvaluation ();
1760   while (size--)
1761     {
1762       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1763       MOVA (l);
1764       emitcode ("cpl", "a");
1765       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1766     }
1767   _endLazyDPSEvaluation ();
1768
1769
1770 release:
1771   /* release the aops */
1772   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1773   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1774 }
1775
1776 /*-----------------------------------------------------------------*/
1777 /* genUminusFloat - unary minus for floating points                */
1778 /*-----------------------------------------------------------------*/
1779 static void
1780 genUminusFloat (operand * op, operand * result)
1781 {
1782   int size, offset = 0;
1783   char *l;
1784   /* for this we just need to flip the
1785      first it then copy the rest in place */
1786   D (emitcode (";", "genUminusFloat");
1787     );
1788
1789   _startLazyDPSEvaluation ();
1790   size = AOP_SIZE (op) - 1;
1791   l = aopGet (AOP (op), 3, FALSE, FALSE, TRUE);
1792   MOVA (l);
1793
1794   emitcode ("cpl", "acc.7");
1795   aopPut (AOP (result), "a", 3);
1796
1797   while (size--)
1798     {
1799       aopPut (AOP (result),
1800               aopGet (AOP (op), offset, FALSE, FALSE, FALSE),
1801               offset);
1802       offset++;
1803     }
1804   _endLazyDPSEvaluation ();
1805 }
1806
1807 /*-----------------------------------------------------------------*/
1808 /* genUminus - unary minus code generation                         */
1809 /*-----------------------------------------------------------------*/
1810 static void
1811 genUminus (iCode * ic)
1812 {
1813   int offset, size;
1814   sym_link *optype, *rtype;
1815
1816   D (emitcode (";", "genUminus ");
1817     );
1818
1819
1820   /* assign asmops */
1821   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1822   aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1823
1824   /* if both in bit space then special
1825      case */
1826   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1827       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1828     {
1829
1830       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1831       emitcode ("cpl", "c");
1832       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1833       goto release;
1834     }
1835
1836   optype = operandType (IC_LEFT (ic));
1837   rtype = operandType (IC_RESULT (ic));
1838
1839   /* if float then do float stuff */
1840   if (IS_FLOAT (optype))
1841     {
1842       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1843       goto release;
1844     }
1845
1846   /* otherwise subtract from zero */
1847   size = AOP_SIZE (IC_LEFT (ic));
1848   offset = 0;
1849   _startLazyDPSEvaluation ();
1850   while (size--)
1851     {
1852       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1853       if (!strcmp (l, "a"))
1854         {
1855           if (offset == 0)
1856             SETC;
1857           emitcode ("cpl", "a");
1858           emitcode ("addc", "a,#0");
1859         }
1860       else
1861         {
1862           if (offset == 0)
1863             CLRC;
1864           emitcode ("clr", "a");
1865           emitcode ("subb", "a,%s", l);
1866         }
1867       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1868     }
1869   _endLazyDPSEvaluation ();
1870
1871   /* if any remaining bytes in the result */
1872   /* we just need to propagate the sign   */
1873   if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1874     {
1875       emitcode ("rlc", "a");
1876       emitcode ("subb", "a,acc");
1877       while (size--)
1878         aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1879     }
1880
1881 release:
1882   /* release the aops */
1883   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1884   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1885 }
1886
1887 /*-----------------------------------------------------------------*/
1888 /* savermask - saves registers in the mask                         */
1889 /*-----------------------------------------------------------------*/
1890 static void savermask(bitVect *rs_mask)
1891 {
1892     int i;
1893     if (options.useXstack) {
1894         if (bitVectBitValue (rs_mask, R0_IDX))
1895             emitcode ("mov", "b,r0");
1896         emitcode ("mov", "r0,%s", spname);
1897         for (i = 0; i < ds390_nRegs; i++) {
1898             if (bitVectBitValue (rs_mask, i)) {
1899                 if (i == R0_IDX)
1900                     emitcode ("mov", "a,b");
1901                 else
1902                     emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
1903                 emitcode ("movx", "@r0,a");
1904                 emitcode ("inc", "r0");
1905             }
1906         }
1907         emitcode ("mov", "%s,r0", spname);
1908         if (bitVectBitValue (rs_mask, R0_IDX))
1909             emitcode ("mov", "r0,b");
1910     } else {
1911         for (i = 0; i < ds390_nRegs; i++) {
1912             if (bitVectBitValue (rs_mask, i))
1913                 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
1914         }
1915     }
1916 }
1917
1918 /*-----------------------------------------------------------------*/
1919 /* saveRegisters - will look for a call and save the registers     */
1920 /*-----------------------------------------------------------------*/
1921 static void
1922 saveRegisters (iCode * lic)
1923 {
1924   iCode *ic;
1925   bitVect *rsave;
1926
1927   /* look for call */
1928   for (ic = lic; ic; ic = ic->next)
1929     if (ic->op == CALL || ic->op == PCALL)
1930       break;
1931
1932   if (!ic)
1933     {
1934       fprintf (stderr, "found parameter push with no function call\n");
1935       return;
1936     }
1937
1938   /* if the registers have been saved already then
1939      do nothing */
1940   if (ic->regsSaved || IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic)))) return ;
1941
1942   /* special case if DPTR alive across a function call then must save it 
1943      even though callee saves */
1944   if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
1945       int i =0;
1946       rsave = newBitVect(ic->rMask->size);
1947       for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
1948           if (bitVectBitValue(ic->rMask,i))
1949               rsave = bitVectSetBit(rsave,i);
1950       }
1951       rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
1952   } else {
1953     /* safe the registers in use at this time but skip the
1954        ones for the result */
1955     rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1956                            ds390_rUmaskForOp (IC_RESULT(ic)));
1957   }
1958   ic->regsSaved = 1;
1959   savermask(rsave);
1960 }
1961
1962 /*-----------------------------------------------------------------*/
1963 /* usavermask - restore registers with mask                        */
1964 /*-----------------------------------------------------------------*/
1965 static void unsavermask(bitVect *rs_mask)
1966 {
1967     int i;
1968     if (options.useXstack) {
1969         emitcode ("mov", "r0,%s", spname);
1970         for (i = ds390_nRegs; i >= 0; i--) {
1971             if (bitVectBitValue (rs_mask, i)) {
1972                 emitcode ("dec", "r0");
1973                 emitcode ("movx", "a,@r0");
1974                 if (i == R0_IDX)
1975                     emitcode ("mov", "b,a");
1976                 else
1977                     emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
1978             }       
1979         }
1980         emitcode ("mov", "%s,r0", spname);
1981         if (bitVectBitValue (rs_mask, R0_IDX))
1982             emitcode ("mov", "r0,b");
1983     } else {
1984         for (i = ds390_nRegs; i >= 0; i--) {
1985             if (bitVectBitValue (rs_mask, i))
1986                 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
1987         }
1988     }
1989 }
1990
1991 /*-----------------------------------------------------------------*/
1992 /* unsaveRegisters - pop the pushed registers                      */
1993 /*-----------------------------------------------------------------*/
1994 static void
1995 unsaveRegisters (iCode * ic)
1996 {
1997   bitVect *rsave;
1998
1999   if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2000       int i =0;
2001       rsave = newBitVect(ic->rMask->size);
2002       for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2003           if (bitVectBitValue(ic->rMask,i))
2004               rsave = bitVectSetBit(rsave,i);
2005       }
2006       rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2007   } else {
2008     /* restore the registers in use at this time but skip the
2009        ones for the result */
2010     rsave = bitVectCplAnd (bitVectCopy (ic->rMask), 
2011                            ds390_rUmaskForOp (IC_RESULT(ic)));
2012   }
2013   unsavermask(rsave);
2014 }
2015
2016
2017 /*-----------------------------------------------------------------*/
2018 /* pushSide -                */
2019 /*-----------------------------------------------------------------*/
2020 static void
2021 pushSide (operand * oper, int size)
2022 {
2023   int offset = 0;
2024   _startLazyDPSEvaluation ();
2025   while (size--)
2026     {
2027       char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, FALSE);
2028       if (AOP_TYPE (oper) != AOP_REG &&
2029           AOP_TYPE (oper) != AOP_DIR &&
2030           strcmp (l, "a"))
2031         {
2032           emitcode ("mov", "a,%s", l);
2033           emitcode ("push", "acc");
2034         }
2035       else
2036         emitcode ("push", "%s", l);
2037     }
2038   _endLazyDPSEvaluation ();
2039 }
2040
2041 /*-----------------------------------------------------------------*/
2042 /* assignResultValue -               */
2043 /*-----------------------------------------------------------------*/
2044 static void
2045 assignResultValue (operand * oper)
2046 {
2047   int offset = 0;
2048   int size = AOP_SIZE (oper);
2049
2050   _startLazyDPSEvaluation ();
2051   while (size--)
2052     {
2053       aopPut (AOP (oper), fReturn[offset], offset);
2054       offset++;
2055     }
2056   _endLazyDPSEvaluation ();
2057 }
2058
2059
2060 /*-----------------------------------------------------------------*/
2061 /* genXpush - pushes onto the external stack                       */
2062 /*-----------------------------------------------------------------*/
2063 static void
2064 genXpush (iCode * ic)
2065 {
2066   asmop *aop = newAsmop (0);
2067   regs *r;
2068   int size, offset = 0;
2069
2070   D (emitcode (";", "genXpush ");
2071     );
2072
2073   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2074   r = getFreePtr (ic, &aop, FALSE);
2075
2076
2077   emitcode ("mov", "%s,_spx", r->name);
2078
2079   size = AOP_SIZE (IC_LEFT (ic));
2080   _startLazyDPSEvaluation ();
2081   while (size--)
2082     {
2083
2084       char *l = aopGet (AOP (IC_LEFT (ic)),
2085                         offset++, FALSE, FALSE, TRUE);
2086       MOVA (l);
2087       emitcode ("movx", "@%s,a", r->name);
2088       emitcode ("inc", "%s", r->name);
2089
2090     }
2091   _endLazyDPSEvaluation ();
2092
2093
2094   emitcode ("mov", "_spx,%s", r->name);
2095
2096   freeAsmop (NULL, aop, ic, TRUE);
2097   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2098 }
2099
2100 /*-----------------------------------------------------------------*/
2101 /* genIpush - genrate code for pushing this gets a little complex  */
2102 /*-----------------------------------------------------------------*/
2103 static void
2104 genIpush (iCode * ic)
2105 {
2106   int size, offset = 0;
2107   char *l;
2108
2109   D (emitcode (";", "genIpush ");
2110     );
2111
2112   /* if this is not a parm push : ie. it is spill push
2113      and spill push is always done on the local stack */
2114   if (!ic->parmPush)
2115     {
2116
2117       /* and the item is spilt then do nothing */
2118       if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2119         return;
2120
2121       aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2122       size = AOP_SIZE (IC_LEFT (ic));
2123       /* push it on the stack */
2124       _startLazyDPSEvaluation ();
2125       while (size--)
2126         {
2127           l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, TRUE);
2128           if (*l == '#')
2129             {
2130               MOVA (l);
2131               l = "acc";
2132             }
2133           emitcode ("push", "%s", l);
2134         }
2135       _endLazyDPSEvaluation ();
2136       return;
2137     }
2138
2139   /* this is a paramter push: in this case we call
2140      the routine to find the call and save those
2141      registers that need to be saved */
2142   saveRegisters (ic);
2143
2144   /* if use external stack then call the external
2145      stack pushing routine */
2146   if (options.useXstack)
2147     {
2148       genXpush (ic);
2149       return;
2150     }
2151
2152   /* then do the push */
2153   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2154
2155   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2156   size = AOP_SIZE (IC_LEFT (ic));
2157
2158   _startLazyDPSEvaluation ();
2159   while (size--)
2160     {
2161       l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, FALSE);
2162       if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2163           AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2164           strcmp (l, "a"))
2165         {
2166           emitcode ("mov", "a,%s", l);
2167           emitcode ("push", "acc");
2168         }
2169       else
2170         emitcode ("push", "%s", l);
2171     }
2172   _endLazyDPSEvaluation ();
2173
2174   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2175 }
2176
2177 /*-----------------------------------------------------------------*/
2178 /* genIpop - recover the registers: can happen only for spilling   */
2179 /*-----------------------------------------------------------------*/
2180 static void
2181 genIpop (iCode * ic)
2182 {
2183   int size, offset;
2184
2185   D (emitcode (";", "genIpop ");
2186     );
2187
2188
2189   /* if the temp was not pushed then */
2190   if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2191     return;
2192
2193   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2194   size = AOP_SIZE (IC_LEFT (ic));
2195   offset = (size - 1);
2196   _startLazyDPSEvaluation ();
2197   while (size--)
2198     {
2199       emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2200                                      FALSE, TRUE, TRUE));
2201     }
2202   _endLazyDPSEvaluation ();
2203
2204   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2205 }
2206
2207 /*-----------------------------------------------------------------*/
2208 /* unsaveRBank - restores the resgister bank from stack            */
2209 /*-----------------------------------------------------------------*/
2210 static void
2211 unsaveRBank (int bank, iCode * ic, bool popPsw)
2212 {
2213   int i;
2214   asmop *aop = NULL;
2215   regs *r = NULL;
2216
2217   if (options.useXstack)
2218   {
2219       if (!ic)
2220       {
2221           /* Assume r0 is available for use. */
2222           r = ds390_regWithIdx (R0_IDX);;          
2223       } 
2224       else
2225       {
2226           aop = newAsmop (0);
2227           r = getFreePtr (ic, &aop, FALSE);
2228       }
2229       emitcode ("mov", "%s,_spx", r->name);      
2230   }
2231   
2232   if (popPsw)
2233     {
2234       if (options.useXstack)
2235       {
2236           emitcode ("movx", "a,@%s", r->name);
2237           emitcode ("mov", "psw,a");
2238           emitcode ("dec", "%s", r->name);
2239         }
2240       else
2241       {
2242         emitcode ("pop", "psw");
2243       }
2244     }
2245
2246   for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2247     {
2248       if (options.useXstack)
2249         {
2250           emitcode ("movx", "a,@%s", r->name);
2251           emitcode ("mov", "(%s+%d),a",
2252                     regs390[i].base, 8 * bank + regs390[i].offset);
2253           emitcode ("dec", "%s", r->name);
2254
2255         }
2256       else
2257         emitcode ("pop", "(%s+%d)",
2258                   regs390[i].base, 8 * bank + regs390[i].offset);
2259     }
2260
2261   if (options.useXstack)
2262     {
2263       emitcode ("mov", "_spx,%s", r->name);
2264     }
2265     
2266   if (aop)
2267   {
2268       freeAsmop (NULL, aop, ic, TRUE);  
2269   }    
2270 }
2271
2272 /*-----------------------------------------------------------------*/
2273 /* saveRBank - saves an entire register bank on the stack          */
2274 /*-----------------------------------------------------------------*/
2275 static void
2276 saveRBank (int bank, iCode * ic, bool pushPsw)
2277 {
2278   int i;
2279   asmop *aop = NULL;
2280   regs *r = NULL;
2281
2282   if (options.useXstack)
2283     {
2284         if (!ic)
2285         {
2286           /* Assume r0 is available for use. */
2287                   r = ds390_regWithIdx (R0_IDX);;
2288         }
2289         else
2290         {
2291           aop = newAsmop (0);
2292           r = getFreePtr (ic, &aop, FALSE);
2293         }
2294         emitcode ("mov", "%s,_spx", r->name);    
2295     }
2296
2297   for (i = 0; i < 8 ; i++) /* only R0-R7 needs saving */
2298     {
2299       if (options.useXstack)
2300         {
2301           emitcode ("inc", "%s", r->name);
2302           emitcode ("mov", "a,(%s+%d)",
2303                     regs390[i].base, 8 * bank + regs390[i].offset);
2304           emitcode ("movx", "@%s,a", r->name);
2305         }
2306       else
2307         emitcode ("push", "(%s+%d)",
2308                   regs390[i].base, 8 * bank + regs390[i].offset);
2309     }
2310
2311   if (pushPsw)
2312     {
2313       if (options.useXstack)
2314         {
2315           emitcode ("mov", "a,psw");
2316           emitcode ("movx", "@%s,a", r->name);
2317           emitcode ("inc", "%s", r->name);
2318           emitcode ("mov", "_spx,%s", r->name);
2319         }
2320       else
2321       {
2322         emitcode ("push", "psw");
2323       }
2324
2325       emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2326     }
2327   
2328   if (aop)
2329   {
2330        freeAsmop (NULL, aop, ic, TRUE);
2331   }    
2332     
2333   if (ic)
2334   {  
2335       ic->bankSaved = 1;
2336   }
2337 }
2338
2339 /*-----------------------------------------------------------------*/
2340 /* genSend - gen code for SEND                                     */
2341 /*-----------------------------------------------------------------*/
2342 static void genSend(set *sendSet)
2343 {
2344     iCode *sic;
2345     int sendCount = 0 ;
2346     static int rb1_count = 0;
2347
2348     for (sic = setFirstItem (sendSet); sic;
2349          sic = setNextItem (sendSet)) {     
2350         int size, offset = 0;
2351         
2352         size=getSize(operandType(IC_LEFT(sic)));
2353         D (emitcode (";", "genSend argreg = %d, size = %d ",sic->argreg,size));
2354         if (sendCount == 0) { /* first parameter */
2355             // we know that dpl(hxb) is the result, so
2356             rb1_count = 0 ;
2357             _startLazyDPSEvaluation ();
2358             if (size>1) {
2359                 aopOp (IC_LEFT (sic), sic, FALSE, 
2360                        (IS_SYMOP(IC_LEFT(sic)) && OP_SYMBOL(IC_LEFT(sic))->ruonly ? FALSE : TRUE));
2361             } else {
2362                 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2363             }
2364             while (size--) {
2365                 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2366                                   FALSE, FALSE, TRUE);
2367                 if (strcmp (l, fReturn[offset])) {
2368                     emitcode ("mov", "%s,%s",
2369                               fReturn[offset],
2370                               l);
2371                 }
2372                 offset++;
2373             }
2374             _endLazyDPSEvaluation ();
2375             freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2376             rb1_count =0;
2377         } else { /* if more parameter in registers */
2378             aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2379             while (size--) {
2380                 emitcode ("mov","b1_%d,%s",rb1_count++,aopGet (AOP (IC_LEFT (sic)), offset++,
2381                                                                 FALSE, FALSE, TRUE));
2382             }
2383             freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2384         }
2385         sendCount++;
2386     }
2387 }
2388
2389 /*-----------------------------------------------------------------*/
2390 /* genCall - generates a call statement                            */
2391 /*-----------------------------------------------------------------*/
2392 static void
2393 genCall (iCode * ic)
2394 {
2395   sym_link *dtype;
2396   bool restoreBank = FALSE;
2397   bool swapBanks = FALSE;
2398
2399   D (emitcode (";", "genCall "););
2400
2401   /* if we are calling a not _naked function that is not using
2402      the same register bank then we need to save the
2403      destination registers on the stack */
2404   dtype = operandType (IC_LEFT (ic));
2405   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2406       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2407       IFFUNC_ISISR (currFunc->type))
2408   {
2409       if (!ic->bankSaved) 
2410       {
2411            /* This is unexpected; the bank should have been saved in
2412             * genFunction.
2413             */
2414            saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2415            restoreBank = TRUE;
2416       }
2417       swapBanks = TRUE;
2418   }
2419   
2420     /* if caller saves & we have not saved then */
2421     if (!ic->regsSaved)
2422       saveRegisters (ic);
2423   
2424   /* if send set is not empty the assign */
2425   /* We've saved all the registers we care about;
2426   * therefore, we may clobber any register not used
2427   * in the calling convention (i.e. anything not in
2428   * fReturn.
2429   */
2430   if (_G.sendSet)
2431     {
2432         if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2433             genSend(reverseSet(_G.sendSet));
2434         } else {
2435             genSend(_G.sendSet);
2436         }
2437       _G.sendSet = NULL;
2438     }  
2439     
2440   if (swapBanks)
2441   {
2442         emitcode ("mov", "psw,#!constbyte", 
2443            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2444   }
2445
2446   /* make the call */
2447   emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2448                             OP_SYMBOL (IC_LEFT (ic))->rname :
2449                             OP_SYMBOL (IC_LEFT (ic))->name));
2450
2451   if (swapBanks)
2452   {
2453        emitcode ("mov", "psw,#!constbyte", 
2454           ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2455   }
2456
2457   /* if we need assign a result value */
2458   if ((IS_ITEMP (IC_RESULT (ic)) &&
2459        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2460         OP_SYMBOL (IC_RESULT (ic))->accuse ||
2461         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2462       IS_TRUE_SYMOP (IC_RESULT (ic)))
2463     {
2464       if (isOperandInFarSpace (IC_RESULT (ic))
2465           && getSize (operandType (IC_RESULT (ic))) <= 2)
2466         {
2467           int size = getSize (operandType (IC_RESULT (ic)));
2468
2469           /* Special case for 1 or 2 byte return in far space. */
2470           MOVA (fReturn[0]);
2471           if (size > 1)
2472             {
2473               emitcode ("mov", "b,%s", fReturn[1]);
2474             }
2475
2476           aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2477           aopPut (AOP (IC_RESULT (ic)), "a", 0);
2478
2479           if (size > 1)
2480             {
2481               aopPut (AOP (IC_RESULT (ic)), "b", 1);
2482             }
2483           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2484         }
2485       else
2486         {
2487           _G.accInUse++;
2488           aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2489           _G.accInUse--;
2490
2491           assignResultValue (IC_RESULT (ic));
2492
2493           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2494         }
2495     }
2496
2497   /* adjust the stack for parameters if
2498      required */
2499   if (ic->parmBytes) {
2500       int i;
2501       if (options.stack10bit) {
2502           if (ic->parmBytes <= 10) {
2503               emitcode(";","stack adjustment for parms");
2504               for (i=0; i < ic->parmBytes ; i++) {
2505                   emitcode("pop","acc");
2506               }
2507           } else {            
2508               PROTECT_SP;
2509               emitcode ("clr","c");
2510               emitcode ("mov","a,sp");
2511               emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2512               emitcode ("mov","sp,a");
2513               emitcode ("mov","a,esp");
2514               emitcode ("anl","a,#3");
2515               emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2516               emitcode ("mov","esp,a");   
2517               UNPROTECT_SP;
2518           }
2519       } else {
2520           if (ic->parmBytes > 3) {
2521               emitcode ("mov", "a,%s", spname);
2522               emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2523               emitcode ("mov", "%s,a", spname);
2524           } else
2525               for (i = 0; i < ic->parmBytes; i++)
2526                   emitcode ("dec", "%s", spname);
2527       }
2528   }
2529
2530   /* if we hade saved some registers then unsave them */
2531   if (ic->regsSaved)
2532     unsaveRegisters (ic);
2533
2534   /* if register bank was saved then pop them */
2535   if (restoreBank)
2536     unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2537 }
2538
2539 /*-----------------------------------------------------------------*/
2540 /* genPcall - generates a call by pointer statement                */
2541 /*-----------------------------------------------------------------*/
2542 static void
2543 genPcall (iCode * ic)
2544 {
2545   sym_link *dtype;
2546   symbol *rlbl = newiTempLabel (NULL);
2547   bool restoreBank=FALSE;
2548
2549   D (emitcode (";", "genPcall ");
2550     );
2551
2552
2553   /* if caller saves & we have not saved then */
2554   if (!ic->regsSaved)
2555     saveRegisters (ic);
2556
2557   /* if we are calling a function that is not using
2558      the same register bank then we need to save the
2559      destination registers on the stack */
2560   dtype = operandType (IC_LEFT (ic));
2561   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2562       IFFUNC_ISISR (currFunc->type) &&
2563       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2564     saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2565     restoreBank=TRUE;
2566   }
2567
2568   /* push the return address on to the stack */
2569   emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
2570   emitcode ("push", "acc");
2571   emitcode ("mov", "a,#!hil", (rlbl->key + 100));
2572   emitcode ("push", "acc");
2573
2574   if (options.model == MODEL_FLAT24)
2575     {
2576       emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
2577       emitcode ("push", "acc");
2578     }
2579
2580   /* now push the calling address */
2581   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2582
2583   pushSide (IC_LEFT (ic), FPTRSIZE);
2584
2585   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2586
2587   /* if send set is not empty the assign */
2588   if (_G.sendSet)
2589     {
2590         genSend(reverseSet(_G.sendSet));
2591         _G.sendSet = NULL;
2592     }
2593
2594   emitcode ("ret", "");
2595   emitcode ("", "!tlabeldef", (rlbl->key + 100));
2596
2597
2598   /* if we need assign a result value */
2599   if ((IS_ITEMP (IC_RESULT (ic)) &&
2600        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2601         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2602       IS_TRUE_SYMOP (IC_RESULT (ic)))
2603     {
2604
2605       _G.accInUse++;
2606       aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2607       _G.accInUse--;
2608
2609       assignResultValue (IC_RESULT (ic));
2610
2611       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2612     }
2613
2614   /* adjust the stack for parameters if
2615      required */
2616   if (ic->parmBytes)
2617     {
2618       int i;
2619       if (options.stack10bit) {
2620           if (ic->parmBytes <= 10) {
2621               emitcode(";","stack adjustment for parms");
2622               for (i=0; i < ic->parmBytes ; i++) {
2623                   emitcode("pop","acc");
2624               }
2625           } else {            
2626               PROTECT_SP;
2627               emitcode ("clr","c");
2628               emitcode ("mov","a,sp");
2629               emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2630               emitcode ("mov","sp,a");
2631               emitcode ("mov","a,esp");
2632               emitcode ("anl","a,#3");
2633               emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2634               emitcode ("mov","esp,a");   
2635               UNPROTECT_SP;
2636           }
2637       } else {
2638           if (ic->parmBytes > 3) {
2639               emitcode ("mov", "a,%s", spname);
2640               emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2641               emitcode ("mov", "%s,a", spname);
2642           }
2643           else
2644               for (i = 0; i < ic->parmBytes; i++)
2645                   emitcode ("dec", "%s", spname);
2646           
2647       }
2648     }
2649   /* if register bank was saved then unsave them */
2650   if (restoreBank)
2651     unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2652   
2653   /* if we hade saved some registers then
2654      unsave them */
2655   if (ic->regsSaved)
2656     unsaveRegisters (ic);
2657
2658 }
2659
2660 /*-----------------------------------------------------------------*/
2661 /* resultRemat - result  is rematerializable                       */
2662 /*-----------------------------------------------------------------*/
2663 static int
2664 resultRemat (iCode * ic)
2665 {
2666   if (SKIP_IC (ic) || ic->op == IFX)
2667     return 0;
2668
2669   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2670     {
2671       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2672       if (sym->remat && !POINTER_SET (ic))
2673         return 1;
2674     }
2675
2676   return 0;
2677 }
2678
2679 #if defined(__BORLANDC__) || defined(_MSC_VER)
2680 #define STRCASECMP stricmp
2681 #else
2682 #define STRCASECMP strcasecmp
2683 #endif
2684
2685 /*-----------------------------------------------------------------*/
2686 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2687 /*-----------------------------------------------------------------*/
2688 static bool
2689 inExcludeList (char *s)
2690 {
2691   int i = 0;
2692
2693   if (options.excludeRegs[i] &&
2694       STRCASECMP (options.excludeRegs[i], "none") == 0)
2695     return FALSE;
2696
2697   for (i = 0; options.excludeRegs[i]; i++)
2698     {
2699       if (options.excludeRegs[i] &&
2700           STRCASECMP (s, options.excludeRegs[i]) == 0)
2701         return TRUE;
2702     }
2703   return FALSE;
2704 }
2705
2706 /*-----------------------------------------------------------------*/
2707 /* genFunction - generated code for function entry                 */
2708 /*-----------------------------------------------------------------*/
2709 static void
2710 genFunction (iCode * ic)
2711 {
2712   symbol *sym;
2713   sym_link *ftype;
2714   bool   switchedPSW = FALSE;
2715
2716   D (emitcode (";", "genFunction "););
2717
2718   _G.nRegsSaved = 0;
2719   /* create the function header */
2720   emitcode (";", "-----------------------------------------");
2721   emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2722   emitcode (";", "-----------------------------------------");
2723
2724   emitcode ("", "%s:", sym->rname);
2725   ftype = operandType (IC_LEFT (ic));
2726
2727   if (IFFUNC_ISNAKED(ftype))
2728   {
2729       emitcode(";", "naked function: no prologue.");
2730       return;
2731   }
2732   
2733   if (options.stack_probe) 
2734       emitcode ("lcall","__stack_probe");
2735   /* if critical function then turn interrupts off */
2736   if (IFFUNC_ISCRITICAL (ftype))
2737     emitcode ("clr", "ea");
2738
2739   /* here we need to generate the equates for the
2740      register bank if required */
2741   if (FUNC_REGBANK (ftype) != rbank)
2742     {
2743       int i;
2744
2745       rbank = FUNC_REGBANK (ftype);
2746       for (i = 0; i < ds390_nRegs; i++)
2747         {
2748           if (regs390[i].print) {
2749               if (strcmp (regs390[i].base, "0") == 0)
2750                   emitcode ("", "%s !equ !constbyte",
2751                             regs390[i].dname,
2752                             8 * rbank + regs390[i].offset);
2753               else
2754                   emitcode ("", "%s !equ %s + !constbyte",
2755                             regs390[i].dname,
2756                             regs390[i].base,
2757                             8 * rbank + regs390[i].offset);
2758           }
2759         }
2760     }
2761
2762   /* if this is an interrupt service routine then
2763      save acc, b, dpl, dph  */
2764   if (IFFUNC_ISISR (sym->type))
2765       { /* is ISR */
2766       if (!inExcludeList ("acc"))
2767         emitcode ("push", "acc");
2768       if (!inExcludeList ("b"))
2769         emitcode ("push", "b");
2770       if (!inExcludeList ("dpl"))
2771         emitcode ("push", "dpl");
2772       if (!inExcludeList ("dph"))
2773         emitcode ("push", "dph");
2774       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2775         {
2776           emitcode ("push", "dpx");
2777           /* Make sure we're using standard DPTR */
2778           emitcode ("push", "dps");
2779           emitcode ("mov", "dps,#0");
2780           if (options.stack10bit)
2781             {
2782               /* This ISR could conceivably use DPTR2. Better save it. */
2783               emitcode ("push", "dpl1");
2784               emitcode ("push", "dph1");
2785               emitcode ("push", "dpx1");
2786               emitcode ("push",  DP2_RESULT_REG);
2787             }
2788         }
2789       /* if this isr has no bank i.e. is going to
2790          run with bank 0 , then we need to save more
2791          registers :-) */
2792       if (!FUNC_REGBANK (sym->type))
2793         {
2794             int i;
2795
2796           /* if this function does not call any other
2797              function then we can be economical and
2798              save only those registers that are used */
2799           if (!IFFUNC_HASFCALL(sym->type))
2800             {
2801
2802               /* if any registers used */
2803               if (sym->regsUsed)
2804                 {
2805                   /* save the registers used */
2806                   for (i = 0; i < sym->regsUsed->size; i++)
2807                     {
2808                       if (bitVectBitValue (sym->regsUsed, i) ||
2809                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2810                         emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2811                     }
2812                 }
2813
2814             }
2815           else
2816             {
2817               /* this function has  a function call cannot
2818                  determines register usage so we will have to push the
2819                  entire bank */
2820               saveRBank (0, ic, FALSE);
2821               if (options.parms_in_bank1) {
2822                   for (i=0; i < 8 ; i++ ) {
2823                       emitcode ("push","%s",rb1regs[i]);
2824                   }
2825               }
2826             }
2827         }
2828         else
2829         {
2830             /* This ISR uses a non-zero bank.
2831              *
2832              * We assume that the bank is available for our
2833              * exclusive use.
2834              *
2835              * However, if this ISR calls a function which uses some
2836              * other bank, we must save that bank entirely.
2837              */
2838             unsigned long banksToSave = 0;
2839             
2840             if (IFFUNC_HASFCALL(sym->type))
2841             {
2842
2843 #define MAX_REGISTER_BANKS 4
2844
2845                 iCode *i;
2846                 int ix;
2847
2848                 for (i = ic; i; i = i->next)
2849                 {
2850                     if (i->op == ENDFUNCTION)
2851                     {
2852                         /* we got to the end OK. */
2853                         break;
2854                     }
2855                     
2856                     if (i->op == CALL)
2857                     {
2858                         sym_link *dtype;
2859                         
2860                         dtype = operandType (IC_LEFT(i));
2861                         if (dtype 
2862                          && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2863                         {
2864                              /* Mark this bank for saving. */
2865                              if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2866                              {
2867                                  werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2868                              }
2869                              else
2870                              {
2871                                  banksToSave |= (1 << FUNC_REGBANK(dtype));
2872                              }
2873                              
2874                              /* And note that we don't need to do it in 
2875                               * genCall.
2876                               */
2877                              i->bankSaved = 1;
2878                         }
2879                     }
2880                     if (i->op == PCALL)
2881                     {
2882                         /* This is a mess; we have no idea what
2883                          * register bank the called function might
2884                          * use.
2885                          *
2886                          * The only thing I can think of to do is
2887                          * throw a warning and hope.
2888                          */
2889                         werror(W_FUNCPTR_IN_USING_ISR);   
2890                     }
2891                 }
2892
2893                 if (banksToSave && options.useXstack)
2894                 {
2895                     /* Since we aren't passing it an ic, 
2896                      * saveRBank will assume r0 is available to abuse.
2897                      *
2898                      * So switch to our (trashable) bank now, so
2899                      * the caller's R0 isn't trashed.
2900                      */
2901                     emitcode ("push", "psw");
2902                     emitcode ("mov", "psw,#!constbyte", 
2903                               (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2904                     switchedPSW = TRUE;
2905                 }
2906                 
2907                 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2908                 {
2909                      if (banksToSave & (1 << ix))
2910                      {
2911                          saveRBank(ix, NULL, FALSE);
2912                      }
2913                 }
2914             }
2915             // jwk: this needs a closer look
2916             SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2917         }
2918     }
2919   else
2920     {
2921       /* if callee-save to be used for this function
2922          then save the registers being used in this function */
2923       if (IFFUNC_CALLEESAVES(sym->type))
2924         {
2925           int i;
2926
2927           /* if any registers used */
2928           if (sym->regsUsed)
2929             {
2930               /* save the registers used */
2931               for (i = 0; i < sym->regsUsed->size; i++)
2932                 {
2933                   if (bitVectBitValue (sym->regsUsed, i) ||
2934                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2935                     {
2936                       emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2937                       _G.nRegsSaved++;
2938                     }
2939                 }
2940             }
2941         }
2942     }
2943
2944   /* set the register bank to the desired value */
2945   if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
2946    && !switchedPSW)
2947     {
2948       emitcode ("push", "psw");
2949       emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2950     }
2951
2952   if ( (IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
2953        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
2954       if (options.stack10bit) {
2955           emitcode ("push","_bpx");
2956           emitcode ("push","_bpx+1");
2957           emitcode ("mov","_bpx,%s",spname);
2958           emitcode ("mov","_bpx+1,esp");
2959           emitcode ("anl","_bpx+1,#3");
2960       } else {
2961           if (options.useXstack) {
2962               emitcode ("mov", "r0,%s", spname);
2963               emitcode ("mov", "a,_bp");
2964               emitcode ("movx", "@r0,a");
2965               emitcode ("inc", "%s", spname);
2966           } else {
2967               /* set up the stack */
2968               emitcode ("push", "_bp"); /* save the callers stack  */
2969           }
2970           emitcode ("mov", "_bp,%s", spname);
2971       }
2972   }
2973
2974   /* adjust the stack for the function */
2975   if (sym->stack) {
2976       int i = sym->stack;
2977       if (options.stack10bit) {
2978           if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);    
2979           assert (sym->recvSize <= 4);
2980           if (sym->stack <= 8) {
2981               while (i--) emitcode ("push","acc");
2982           } else {
2983               PROTECT_SP;
2984               emitcode ("mov","a,sp");
2985               emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
2986               emitcode ("mov","sp,a");
2987               emitcode ("mov","a,esp");
2988               emitcode ("anl","a,#3");
2989               emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
2990               emitcode ("mov","esp,a");
2991               UNPROTECT_SP;
2992           }
2993       } else {
2994           if (i > 256)
2995               werror (W_STACK_OVERFLOW, sym->name);
2996           
2997           if (i > 3 && sym->recvSize < 4) {
2998               
2999               emitcode ("mov", "a,sp");
3000               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3001               emitcode ("mov", "sp,a");
3002               
3003           } else
3004               while (i--)
3005                   emitcode ("inc", "sp");
3006       }
3007   }
3008
3009   if (sym->xstack)
3010     {
3011
3012       emitcode ("mov", "a,_spx");
3013       emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3014       emitcode ("mov", "_spx,a");
3015     }
3016
3017 }
3018
3019 /*-----------------------------------------------------------------*/
3020 /* genEndFunction - generates epilogue for functions               */
3021 /*-----------------------------------------------------------------*/
3022 static void
3023 genEndFunction (iCode * ic)
3024 {
3025   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3026
3027   D (emitcode (";", "genEndFunction "););
3028
3029   if (IFFUNC_ISNAKED(sym->type))
3030   {
3031       emitcode(";", "naked function: no epilogue.");
3032       return;
3033   }
3034
3035   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3036        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3037
3038       if (options.stack10bit) {
3039           PROTECT_SP;     
3040           emitcode ("mov", "sp,_bpx", spname);
3041           emitcode ("mov", "esp,_bpx+1", spname);
3042           UNPROTECT_SP;
3043       } else {
3044           emitcode ("mov", "%s,_bp", spname);
3045       }
3046   }
3047
3048   /* if use external stack but some variables were
3049      added to the local stack then decrement the
3050      local stack */
3051   if (options.useXstack && sym->stack) {
3052       emitcode ("mov", "a,sp");
3053       emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3054       emitcode ("mov", "sp,a");
3055   }
3056
3057
3058   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3059        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3060
3061       if (options.useXstack) {
3062           emitcode ("mov", "r0,%s", spname);
3063           emitcode ("movx", "a,@r0");
3064           emitcode ("mov", "_bp,a");
3065           emitcode ("dec", "%s", spname);
3066       } else {
3067           if (options.stack10bit) {
3068               emitcode ("pop", "_bpx+1");
3069               emitcode ("pop", "_bpx");
3070           } else {
3071               emitcode ("pop", "_bp");
3072           }
3073       }
3074   }
3075
3076   /* restore the register bank  */
3077   if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3078   {
3079     if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3080      || !options.useXstack)
3081     {
3082         /* Special case of ISR using non-zero bank with useXstack
3083          * is handled below.
3084          */
3085         emitcode ("pop", "psw");
3086     }
3087   } 
3088
3089   if (IFFUNC_ISISR (sym->type))
3090       { /* is ISR */  
3091
3092       /* now we need to restore the registers */
3093       /* if this isr has no bank i.e. is going to
3094          run with bank 0 , then we need to save more
3095          registers :-) */
3096       if (!FUNC_REGBANK (sym->type))
3097         {
3098             int i;
3099           /* if this function does not call any other
3100              function then we can be economical and
3101              save only those registers that are used */
3102           if (!IFFUNC_HASFCALL(sym->type))
3103             {
3104
3105               /* if any registers used */
3106               if (sym->regsUsed)
3107                 {
3108                   /* save the registers used */
3109                   for (i = sym->regsUsed->size; i >= 0; i--)
3110                     {
3111                       if (bitVectBitValue (sym->regsUsed, i) ||
3112                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3113                         emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3114                     }
3115                 }
3116
3117             }
3118           else
3119             {
3120               /* this function has  a function call cannot
3121                  determines register usage so we will have to pop the
3122                  entire bank */
3123               if (options.parms_in_bank1) {
3124                   for (i = 7 ; i >= 0 ; i-- ) {
3125                       emitcode ("pop","%s",rb1regs[i]);
3126                   }
3127               }
3128               unsaveRBank (0, ic, FALSE);
3129             }
3130         }
3131         else
3132         {
3133             /* This ISR uses a non-zero bank.
3134              *
3135              * Restore any register banks saved by genFunction
3136              * in reverse order.
3137              */
3138           // jwk: this needs a closer look
3139             unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3140             int ix;
3141           
3142             for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3143             {
3144                 if (savedBanks & (1 << ix))
3145                 {
3146                     unsaveRBank(ix, NULL, FALSE);
3147                 }
3148             }
3149             
3150             if (options.useXstack)
3151             {
3152                 /* Restore bank AFTER calling unsaveRBank,
3153                  * since it can trash r0.
3154                  */
3155                 emitcode ("pop", "psw");
3156             }
3157         }
3158
3159       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3160         {
3161           if (options.stack10bit)
3162             {
3163               emitcode ("pop", DP2_RESULT_REG);
3164               emitcode ("pop", "dpx1");
3165               emitcode ("pop", "dph1");
3166               emitcode ("pop", "dpl1");
3167             }
3168           emitcode ("pop", "dps");
3169           emitcode ("pop", "dpx");
3170         }
3171       if (!inExcludeList ("dph"))
3172         emitcode ("pop", "dph");
3173       if (!inExcludeList ("dpl"))
3174         emitcode ("pop", "dpl");
3175       if (!inExcludeList ("b"))
3176         emitcode ("pop", "b");
3177       if (!inExcludeList ("acc"))
3178         emitcode ("pop", "acc");
3179
3180       if (IFFUNC_ISCRITICAL (sym->type))
3181         emitcode ("setb", "ea");
3182
3183       /* if debug then send end of function */
3184       if (options.debug && currFunc) {
3185           _G.debugLine = 1;
3186           emitcode ("", "C$%s$%d$%d$%d ==.",
3187                     FileBaseName (ic->filename), currFunc->lastLine,
3188                     ic->level, ic->block);
3189           if (IS_STATIC (currFunc->etype))
3190             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3191           else
3192             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3193           _G.debugLine = 0;
3194         }
3195
3196       emitcode ("reti", "");
3197     }
3198   else
3199     {
3200       if (IFFUNC_ISCRITICAL (sym->type))
3201         emitcode ("setb", "ea");
3202
3203       if (IFFUNC_CALLEESAVES(sym->type))
3204         {
3205           int i;
3206
3207           /* if any registers used */
3208           if (sym->regsUsed)
3209             {
3210               /* save the registers used */
3211               for (i = sym->regsUsed->size; i >= 0; i--)
3212                 {
3213                   if (bitVectBitValue (sym->regsUsed, i) ||
3214                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3215                     emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3216                 }
3217             }
3218
3219         }
3220
3221       /* if debug then send end of function */
3222       if (options.debug && currFunc)
3223         {
3224           _G.debugLine = 1;
3225           emitcode ("", "C$%s$%d$%d$%d ==.",
3226                     FileBaseName (ic->filename), currFunc->lastLine,
3227                     ic->level, ic->block);
3228           if (IS_STATIC (currFunc->etype))
3229             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3230           else
3231             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3232           _G.debugLine = 0;
3233         }
3234
3235       emitcode ("ret", "");
3236     }
3237
3238 }
3239
3240 /*-----------------------------------------------------------------*/
3241 /* genJavaNativeRet - generate code for return JavaNative          */
3242 /*-----------------------------------------------------------------*/
3243 static void genJavaNativeRet(iCode *ic)
3244 {
3245     int i, size;
3246
3247     aopOp (IC_LEFT (ic), ic, FALSE, 
3248            (IS_SYMOP(IC_LEFT(ic)) && OP_SYMBOL(IC_LEFT(ic))->ruonly ? FALSE :TRUE));
3249     size = AOP_SIZE (IC_LEFT (ic));
3250
3251     assert (size <= 4);
3252
3253     /* it is assigned to GPR0-R3 then push them */
3254     if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3255         aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3256         for (i = 0 ; i < size ; i++ ) {
3257             emitcode ("push","%s",aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,FALSE));     
3258         }
3259         for (i = (size-1) ; i >= 0 ; i--) {
3260             emitcode ("pop","a%s",javaRet[i]);
3261         }
3262     } else {
3263         for (i = 0 ; i < size ; i++) 
3264             emitcode ("mov","%s,%s",javaRet[i],aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,FALSE));
3265     }
3266     for (i = size ; i < 4 ; i++ )
3267             emitcode ("mov","%s,#0",javaRet[i]);
3268     return;
3269 }
3270
3271 /*-----------------------------------------------------------------*/
3272 /* genRet - generate code for return statement                     */
3273 /*-----------------------------------------------------------------*/
3274 static void
3275 genRet (iCode * ic)
3276 {
3277   int size, offset = 0, pushed = 0;
3278
3279   D (emitcode (";", "genRet ");
3280     );
3281
3282   /* if we have no return value then
3283      just generate the "ret" */
3284   if (!IC_LEFT (ic))
3285     goto jumpret;
3286
3287   /* if this is a JavaNative function then return 
3288      value in different register */
3289   if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3290       genJavaNativeRet(ic);
3291       goto jumpret;
3292   }
3293   /* we have something to return then
3294      move the return value into place */
3295   aopOp (IC_LEFT (ic), ic, FALSE, 
3296          (IS_SYMOP(IC_LEFT(ic)) && OP_SYMBOL(IC_LEFT(ic))->ruonly ? FALSE :TRUE));
3297   size = AOP_SIZE (IC_LEFT (ic));
3298
3299   _startLazyDPSEvaluation ();
3300   while (size--)
3301     {
3302       char *l;
3303       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3304         {
3305           l = aopGet (AOP (IC_LEFT (ic)), offset++,
3306                       FALSE, TRUE, FALSE);
3307           emitcode ("push", "%s", l);
3308           pushed++;
3309         }
3310       else
3311         {
3312           /* Since A is the last element of fReturn,
3313            * is is OK to clobber it in the aopGet.
3314            */
3315           l = aopGet (AOP (IC_LEFT (ic)), offset,
3316                       FALSE, FALSE, TRUE);
3317           if (strcmp (fReturn[offset], l))
3318             emitcode ("mov", "%s,%s", fReturn[offset++], l);
3319         }
3320     }
3321   _endLazyDPSEvaluation ();
3322
3323   if (pushed)
3324     {
3325       while (pushed)
3326         {
3327           pushed--;
3328           if (strcmp (fReturn[pushed], "a"))
3329             emitcode ("pop", fReturn[pushed]);
3330           else
3331             emitcode ("pop", "acc");
3332         }
3333     }
3334   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3335
3336 jumpret:
3337   /* generate a jump to the return label
3338      if the next is not the return statement */
3339   if (!(ic->next && ic->next->op == LABEL &&
3340         IC_LABEL (ic->next) == returnLabel))
3341
3342     emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3343
3344 }
3345
3346 /*-----------------------------------------------------------------*/
3347 /* genLabel - generates a label                                    */
3348 /*-----------------------------------------------------------------*/
3349 static void
3350 genLabel (iCode * ic)
3351 {
3352   /* special case never generate */
3353   if (IC_LABEL (ic) == entryLabel)
3354     return;
3355
3356   D (emitcode (";", "genLabel ");
3357     );
3358
3359   emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3360 }
3361
3362 /*-----------------------------------------------------------------*/
3363 /* genGoto - generates a ljmp                                      */
3364 /*-----------------------------------------------------------------*/
3365 static void
3366 genGoto (iCode * ic)
3367 {
3368   D (emitcode (";", "genGoto ");
3369     );
3370   emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3371 }
3372
3373 /*-----------------------------------------------------------------*/
3374 /* findLabelBackwards: walks back through the iCode chain looking  */
3375 /* for the given label. Returns number of iCode instructions     */
3376 /* between that label and given ic.          */
3377 /* Returns zero if label not found.          */
3378 /*-----------------------------------------------------------------*/
3379 static int
3380 findLabelBackwards (iCode * ic, int key)
3381 {
3382   int count = 0;
3383
3384   while (ic->prev)
3385     {
3386       ic = ic->prev;
3387       count++;
3388
3389       /* If we have any pushes or pops, we cannot predict the distance.
3390          I don't like this at all, this should be dealt with in the 
3391          back-end */
3392       if (ic->op == IPUSH || ic->op == IPOP) {
3393         return 0;
3394       }
3395
3396       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3397         {
3398           /* printf("findLabelBackwards = %d\n", count); */
3399           return count;
3400         }
3401     }
3402
3403   return 0;
3404 }
3405
3406 /*-----------------------------------------------------------------*/
3407 /* genPlusIncr :- does addition with increment if possible         */
3408 /*-----------------------------------------------------------------*/
3409 static bool
3410 genPlusIncr (iCode * ic)
3411 {
3412   unsigned int icount;
3413   unsigned int size = getDataSize (IC_RESULT (ic));
3414
3415   /* will try to generate an increment */
3416   /* if the right side is not a literal
3417      we cannot */
3418   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3419     return FALSE;
3420
3421   /* if the literal value of the right hand side
3422      is greater than 4 then it is not worth it */
3423   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3424     return FALSE;
3425
3426   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3427       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3428       while (icount--) {
3429           emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
3430       }
3431       return TRUE;
3432   }
3433   /* if increment 16 bits in register */
3434   if (
3435        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3436        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3437        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3438        (size > 1) &&
3439        (icount == 1))
3440     {
3441       symbol *tlbl;
3442       int emitTlbl;
3443       int labelRange;
3444
3445       /* If the next instruction is a goto and the goto target
3446        * is <= 5 instructions previous to this, we can generate
3447        * jumps straight to that target.
3448        */
3449       if (ic->next && ic->next->op == GOTO
3450           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3451           && labelRange <= 5)
3452         {
3453           emitcode (";", "tail increment optimized (range %d)", labelRange);
3454           tlbl = IC_LABEL (ic->next);
3455           emitTlbl = 0;
3456         }
3457       else
3458         {
3459           tlbl = newiTempLabel (NULL);
3460           emitTlbl = 1;
3461         }
3462       emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3463       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3464           IS_AOP_PREG (IC_RESULT (ic)))
3465         emitcode ("cjne", "%s,#0,!tlabel"
3466                   ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3467                   ,tlbl->key + 100);
3468       else
3469         {
3470           emitcode ("clr", "a");
3471           emitcode ("cjne", "a,%s,!tlabel"
3472                     ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3473                     ,tlbl->key + 100);
3474         }
3475
3476       emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3477       if (size > 2)
3478         {
3479           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3480               IS_AOP_PREG (IC_RESULT (ic)))
3481             emitcode ("cjne", "%s,#0,!tlabel"
3482                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3483                       ,tlbl->key + 100);
3484           else
3485             emitcode ("cjne", "a,%s,!tlabel"
3486                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3487                       ,tlbl->key + 100);
3488
3489           emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3490         }
3491       if (size > 3)
3492         {
3493           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3494               IS_AOP_PREG (IC_RESULT (ic)))
3495             emitcode ("cjne", "%s,#0,!tlabel"
3496                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3497                       ,tlbl->key + 100);
3498           else
3499             {
3500               emitcode ("cjne", "a,%s,!tlabel"
3501                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3502                         ,tlbl->key + 100);
3503             }
3504           emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3505         }
3506
3507       if (emitTlbl)
3508         {
3509           emitcode ("", "!tlabeldef", tlbl->key + 100);
3510         }
3511       return TRUE;
3512     }
3513
3514   if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
3515       AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
3516       icount <= 5 ) {
3517       emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
3518       while (icount--) emitcode ("inc","dptr");
3519       emitcode ("mov","dps,#0");
3520       return TRUE;
3521   }
3522
3523   /* if the sizes are greater than 1 then we cannot */
3524   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3525       AOP_SIZE (IC_LEFT (ic)) > 1)
3526     return FALSE;
3527
3528   /* we can if the aops of the left & result match or
3529      if they are in registers and the registers are the
3530      same */
3531   if (
3532        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3533        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3534        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3535     {
3536
3537       if (icount > 3)
3538         {
3539           MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3540           emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3541           aopPut (AOP (IC_RESULT (ic)), "a", 0);
3542         }
3543       else
3544         {
3545
3546           _startLazyDPSEvaluation ();
3547           while (icount--)
3548             {
3549               emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3550             }
3551           _endLazyDPSEvaluation ();
3552         }
3553
3554       return TRUE;
3555     }
3556
3557   return FALSE;
3558 }
3559
3560 /*-----------------------------------------------------------------*/
3561 /* outBitAcc - output a bit in acc                                 */
3562 /*-----------------------------------------------------------------*/
3563 static void
3564 outBitAcc (operand * result)
3565 {
3566   symbol *tlbl = newiTempLabel (NULL);
3567   /* if the result is a bit */
3568   if (AOP_TYPE (result) == AOP_CRY)
3569     {
3570       aopPut (AOP (result), "a", 0);
3571     }
3572   else
3573     {
3574       emitcode ("jz", "!tlabel", tlbl->key + 100);
3575       emitcode ("mov", "a,%s", one);
3576       emitcode ("", "!tlabeldef", tlbl->key + 100);
3577       outAcc (result);
3578     }
3579 }
3580
3581 /*-----------------------------------------------------------------*/
3582 /* genPlusBits - generates code for addition of two bits           */
3583 /*-----------------------------------------------------------------*/
3584 static void
3585 genPlusBits (iCode * ic)
3586 {
3587   D (emitcode (";", "genPlusBits ");
3588     );
3589   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3590     {
3591       symbol *lbl = newiTempLabel (NULL);
3592       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3593       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3594       emitcode ("cpl", "c");
3595       emitcode ("", "!tlabeldef", (lbl->key + 100));
3596       outBitC (IC_RESULT (ic));
3597     }
3598   else
3599     {
3600       emitcode ("clr", "a");
3601       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3602       emitcode ("rlc", "a");
3603       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3604       emitcode ("addc", "a,#0");
3605       outAcc (IC_RESULT (ic));
3606     }
3607 }
3608
3609 static void
3610 adjustArithmeticResult (iCode * ic)
3611 {
3612   if (opIsGptr (IC_RESULT (ic)) &&
3613       opIsGptr (IC_LEFT (ic)) &&
3614       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3615     {
3616       aopPut (AOP (IC_RESULT (ic)),
3617               aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3618               GPTRSIZE - 1);
3619     }
3620
3621   if (opIsGptr (IC_RESULT (ic)) &&
3622       opIsGptr (IC_RIGHT (ic)) &&
3623       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3624     {
3625       aopPut (AOP (IC_RESULT (ic)),
3626             aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3627               GPTRSIZE - 1);
3628     }
3629
3630   if (opIsGptr (IC_RESULT (ic)) &&
3631       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3632       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3633       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3634       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3635     {
3636       char buffer[5];
3637       sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3638       aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3639     }
3640 }
3641
3642 // Macro to aopOp all three operands of an ic. If this cannot be done, 
3643 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3644 // will be set TRUE. The caller must then handle the case specially, noting
3645 // that the IC_RESULT operand is not aopOp'd.
3646 #define AOP_OP_3_NOFATAL(ic, rc) \
3647     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3648     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR) || \
3649                                   ((OP_SYMBOL(IC_RESULT(ic))->ruonly) && !isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)))); \
3650     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3651         (isOperandInFarSpace(IC_RESULT(ic)) || (OP_SYMBOL(IC_RESULT(ic))->ruonly && !isOperandEqual(IC_LEFT(ic),IC_RESULT(ic))))) \
3652     { \
3653        /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3654        rc = TRUE; \
3655     }  \
3656     else \
3657     { \
3658        aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3659                                      (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3660        rc = FALSE; \
3661        if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3662            AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3663        { \
3664             /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3665             fprintf(stderr,                                  \
3666                     "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno);   \
3667        } \
3668     }
3669
3670 // aopOp the left & right operands of an ic.
3671 #define AOP_OP_2(ic) \
3672     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3673     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3674
3675 // convienience macro.
3676 #define AOP_SET_LOCALS(ic) \
3677     left = IC_LEFT(ic); \
3678     right = IC_RIGHT(ic); \
3679     result = IC_RESULT(ic);
3680
3681
3682 // Given an integer value of pushedSize bytes on the stack,
3683 // adjust it to be resultSize bytes, either by discarding
3684 // the most significant bytes or by zero-padding.
3685 //
3686 // On exit from this macro, pushedSize will have been adjusted to
3687 // equal resultSize, and ACC may be trashed.
3688 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize)            \
3689       /* If the pushed data is bigger than the result,          \
3690        * simply discard unused bytes. Icky, but works.          \
3691        */                                                       \
3692       while (pushedSize > resultSize)                           \
3693       {                                                         \
3694           D (emitcode (";", "discarding unused result byte."););\
3695           emitcode ("pop", "acc");                              \
3696           pushedSize--;                                         \
3697       }                                                         \
3698       if (pushedSize < resultSize)                              \
3699       {                                                         \
3700           emitcode ("clr", "a");                                \
3701           /* Conversly, we haven't pushed enough here.          \
3702            * just zero-pad, and all is well.                    \
3703            */                                                   \
3704           while (pushedSize < resultSize)                       \
3705           {                                                     \
3706               emitcode("push", "acc");                          \
3707               pushedSize++;                                     \
3708           }                                                     \
3709       }                                                         \
3710       assert(pushedSize == resultSize);
3711
3712 /*-----------------------------------------------------------------*/
3713 /* genPlus - generates code for addition                           */
3714 /*-----------------------------------------------------------------*/
3715 static void
3716 genPlus (iCode * ic)
3717 {
3718   int size, offset = 0;
3719   bool pushResult = FALSE;
3720   int rSize;
3721
3722   D (emitcode (";", "genPlus "););
3723
3724   /* special cases :- */
3725   if ( IS_SYMOP(IC_LEFT(ic)) && OP_SYMBOL(IC_LEFT(ic))->ruonly &&
3726       isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
3727       aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
3728       size = floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
3729       if (size <= 9) {
3730           while (size--) emitcode ("inc","dptr");
3731       } else {
3732           emitcode ("mov","a,dpl");
3733           emitcode ("add","a,#!constbyte",size & 0xff);
3734           emitcode ("mov","dpl,a");
3735           emitcode ("mov","a,dph");
3736           emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
3737           emitcode ("mov","dph,a");
3738           emitcode ("mov","a,dpx");
3739           emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
3740           emitcode ("mov","dpx,a");
3741       }
3742       freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
3743       return ;
3744   }
3745   if ( IS_SYMOP(IC_LEFT(ic)) && 
3746        OP_SYMBOL(IC_LEFT(ic))->remat &&
3747        isOperandInFarSpace(IC_RIGHT(ic))) {
3748       operand *op = IC_RIGHT(ic);
3749       IC_RIGHT(ic) = IC_LEFT(ic);
3750       IC_LEFT(ic) = op;
3751   }
3752                 
3753   AOP_OP_3_NOFATAL (ic, pushResult);
3754   if (pushResult)
3755     {
3756       D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3757     }
3758
3759   if (!pushResult)
3760     {
3761       /* if literal, literal on the right or
3762          if left requires ACC or right is already
3763          in ACC */
3764       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3765        || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3766           || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3767         {
3768           operand *t = IC_RIGHT (ic);
3769           IC_RIGHT (ic) = IC_LEFT (ic);
3770           IC_LEFT (ic) = t;
3771           emitcode (";", "Swapped plus args.");
3772         }
3773
3774       /* if both left & right are in bit
3775          space */
3776       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3777           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3778         {
3779           genPlusBits (ic);
3780           goto release;
3781         }
3782
3783       /* if left in bit space & right literal */
3784       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3785           AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3786         {
3787           emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3788           /* if result in bit space */
3789           if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3790             {
3791               if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3792                 emitcode ("cpl", "c");
3793               outBitC (IC_RESULT (ic));
3794             }
3795           else
3796             {
3797               size = getDataSize (IC_RESULT (ic));
3798               _startLazyDPSEvaluation ();
3799               while (size--)
3800                 {
3801                   MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3802                   emitcode ("addc", "a,#0");
3803                   aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3804                 }
3805               _endLazyDPSEvaluation ();
3806             }
3807           goto release;
3808         }
3809
3810       /* if I can do an increment instead
3811          of add then GOOD for ME */
3812       if (genPlusIncr (ic) == TRUE)
3813         {
3814           emitcode (";", "did genPlusIncr");
3815           goto release;
3816         }
3817
3818     }
3819   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3820
3821   _startLazyDPSEvaluation ();
3822   while (size--)
3823     {
3824       if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
3825         {
3826           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3827           if (offset == 0)
3828             emitcode ("add", "a,%s",
3829                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3830           else
3831             emitcode ("addc", "a,%s",
3832                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3833         }
3834       else
3835         {
3836           if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
3837           {
3838               /* right is going to use ACC or we would have taken the
3839                * above branch.
3840                */
3841               assert(AOP_NEEDSACC(IC_RIGHT(ic)));
3842        TR_AP("#3");
3843               D(emitcode(";", "+ AOP_ACC special case."););
3844               emitcode("xch", "a, %s", DP2_RESULT_REG);
3845           }
3846           MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3847           if (offset == 0)
3848           {
3849             if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
3850             {
3851          TR_AP("#4");
3852                 emitcode("add", "a, %s", DP2_RESULT_REG); 
3853             }
3854             else
3855             {
3856                 emitcode ("add", "a,%s",
3857                         aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE, FALSE));
3858             }
3859           }
3860           else
3861           {
3862             emitcode ("addc", "a,%s",
3863                   aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3864           }
3865         }
3866       if (!pushResult)
3867         {
3868           aopPut (AOP (IC_RESULT (ic)), "a", offset);
3869         }
3870       else
3871         {
3872           emitcode ("push", "acc");
3873         }
3874       offset++;
3875     }
3876   _endLazyDPSEvaluation ();
3877
3878   if (pushResult)
3879     {
3880       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3881
3882       size = getDataSize (IC_LEFT (ic));
3883       rSize = getDataSize (IC_RESULT (ic));
3884
3885       ADJUST_PUSHED_RESULT(size, rSize);
3886
3887       _startLazyDPSEvaluation ();
3888       while (size--)
3889         {
3890           emitcode ("pop", "acc");
3891           aopPut (AOP (IC_RESULT (ic)), "a", size);
3892         }
3893       _endLazyDPSEvaluation ();
3894     }
3895
3896   adjustArithmeticResult (ic);
3897
3898 release:
3899   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3900   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3901   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3902 }
3903
3904 /*-----------------------------------------------------------------*/
3905 /* genMinusDec :- does subtraction with deccrement if possible     */
3906 /*-----------------------------------------------------------------*/
3907 static bool
3908 genMinusDec (iCode * ic)
3909 {
3910   unsigned int icount;
3911   unsigned int size = getDataSize (IC_RESULT (ic));
3912
3913   /* will try to generate an increment */
3914   /* if the right side is not a literal
3915      we cannot */
3916   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3917     return FALSE;
3918
3919   /* if the literal value of the right hand side
3920      is greater than 4 then it is not worth it */
3921   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3922     return FALSE;
3923
3924   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3925       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3926       while (icount--) {
3927           emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
3928       }
3929       return TRUE;
3930   }
3931   /* if decrement 16 bits in register */
3932   if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3933       AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3934       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3935       (size > 1) &&
3936       (icount == 1))
3937     {
3938       symbol *tlbl;
3939       int emitTlbl;
3940       int labelRange;
3941
3942       /* If the next instruction is a goto and the goto target
3943          * is <= 5 instructions previous to this, we can generate
3944          * jumps straight to that target.
3945        */
3946       if (ic->next && ic->next->op == GOTO
3947           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3948           && labelRange <= 5)
3949         {
3950           emitcode (";", "tail decrement optimized (range %d)", labelRange);
3951           tlbl = IC_LABEL (ic->next);
3952           emitTlbl = 0;
3953         }
3954       else
3955         {
3956           tlbl = newiTempLabel (NULL);
3957           emitTlbl = 1;
3958         }
3959
3960       emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3961       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3962           AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3963           IS_AOP_PREG (IC_RESULT (ic)))
3964         emitcode ("cjne", "%s,#!constbyte,!tlabel"
3965                   ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE), 0xff
3966                   ,tlbl->key + 100);
3967       else
3968         {
3969           emitcode ("mov", "a,#!constbyte",0xff);
3970           emitcode ("cjne", "a,%s,!tlabel"
3971                     ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3972                     ,tlbl->key + 100);
3973         }
3974       emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3975       if (size > 2)
3976         {
3977           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3978               AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3979               IS_AOP_PREG (IC_RESULT (ic)))
3980             emitcode ("cjne", "%s,#!constbyte,!tlabel"
3981                       ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE),0xff
3982                       ,tlbl->key + 100);
3983           else
3984             {
3985               emitcode ("cjne", "a,%s,!tlabel"
3986                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3987                         ,tlbl->key + 100);
3988             }
3989           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3990         }
3991       if (size > 3)
3992         {
3993           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3994               AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3995               IS_AOP_PREG (IC_RESULT (ic)))
3996             emitcode ("cjne", "%s,#!constbyte,!tlabel"
3997                       ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE),0xff
3998                       ,tlbl->key + 100);
3999           else
4000             {
4001               emitcode ("cjne", "a,%s,!tlabel"
4002                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
4003                         ,tlbl->key + 100);
4004             }
4005           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
4006         }
4007       if (emitTlbl)
4008         {
4009           emitcode ("", "!tlabeldef", tlbl->key + 100);
4010         }
4011       return TRUE;
4012     }
4013
4014   /* if the sizes are greater than 1 then we cannot */
4015   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4016       AOP_SIZE (IC_LEFT (ic)) > 1)
4017     return FALSE;
4018
4019   /* we can if the aops of the left & result match or
4020      if they are in registers and the registers are the
4021      same */
4022   if (
4023        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4024        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4025        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4026     {
4027
4028       _startLazyDPSEvaluation ();
4029       while (icount--)
4030         {
4031           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
4032         }
4033       _endLazyDPSEvaluation ();
4034
4035       return TRUE;
4036     }
4037
4038   return FALSE;
4039 }
4040
4041 /*-----------------------------------------------------------------*/
4042 /* addSign - complete with sign                                    */
4043 /*-----------------------------------------------------------------*/
4044 static void
4045 addSign (operand * result, int offset, int sign)
4046 {
4047   int size = (getDataSize (result) - offset);
4048   if (size > 0)
4049     {
4050       _startLazyDPSEvaluation();
4051       if (sign)
4052         {
4053           emitcode ("rlc", "a");
4054           emitcode ("subb", "a,acc");
4055           while (size--)
4056           {
4057             aopPut (AOP (result), "a", offset++);
4058           }
4059         }
4060       else
4061       {
4062         while (size--)
4063         {
4064           aopPut (AOP (result), zero, offset++);
4065         }
4066       }
4067       _endLazyDPSEvaluation();
4068     }
4069 }
4070
4071 /*-----------------------------------------------------------------*/
4072 /* genMinusBits - generates code for subtraction  of two bits      */
4073 /*-----------------------------------------------------------------*/
4074 static void
4075 genMinusBits (iCode * ic)
4076 {
4077   symbol *lbl = newiTempLabel (NULL);
4078
4079   D (emitcode (";", "genMinusBits "););
4080
4081   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4082     {
4083       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4084       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4085       emitcode ("cpl", "c");
4086       emitcode ("", "!tlabeldef", (lbl->key + 100));
4087       outBitC (IC_RESULT (ic));
4088     }
4089   else
4090     {
4091       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4092       emitcode ("subb", "a,acc");
4093       emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4094       emitcode ("inc", "a");
4095       emitcode ("", "!tlabeldef", (lbl->key + 100));
4096       aopPut (AOP (IC_RESULT (ic)), "a", 0);
4097       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4098     }
4099 }
4100
4101 /*-----------------------------------------------------------------*/
4102 /* genMinus - generates code for subtraction                       */
4103 /*-----------------------------------------------------------------*/
4104 static void
4105 genMinus (iCode * ic)
4106 {
4107   int size, offset = 0;
4108   int rSize;
4109   unsigned long lit = 0L;
4110   bool pushResult = FALSE;
4111
4112   D (emitcode (";", "genMinus "););
4113
4114   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
4115   aopOp (IC_RIGHT (ic), ic, FALSE, 
4116          (AOP_INDPTRn(IC_LEFT(ic)) ? FALSE : (AOP_USESDPTR(IC_LEFT(ic)) ? TRUE : FALSE)));
4117   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
4118       (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
4119     {
4120       pushResult = TRUE;
4121     }
4122   else
4123     {
4124       aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
4125
4126       /* special cases :- */
4127       /* if both left & right are in bit space */
4128       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4129           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4130         {
4131           genMinusBits (ic);
4132           goto release;
4133         }
4134
4135       /* if I can do an decrement instead
4136          of subtract then GOOD for ME */
4137       if (genMinusDec (ic) == TRUE)
4138         goto release;
4139
4140     }
4141
4142   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4143
4144   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4145     {
4146       CLRC;
4147     }
4148   else
4149     {
4150       lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4151       lit = -(long) lit;
4152     }
4153
4154
4155   /* if literal, add a,#-lit, else normal subb */
4156   _startLazyDPSEvaluation ();
4157   while (size--) {
4158       MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
4159       if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
4160           if (AOP_USESDPTR(IC_RIGHT(ic))) {
4161               emitcode ("mov","b,a");
4162               MOVA(aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
4163               emitcode ("xch","a,b");
4164               emitcode ("subb","a,b");
4165           } else {
4166               emitcode ("subb", "a,%s",
4167                         aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
4168           }
4169       } else {
4170           /* first add without previous c */
4171           if (!offset) {
4172               if (!size && lit==-1) {
4173                   emitcode ("dec", "a");
4174               } else {
4175                   emitcode ("add", "a,#!constbyte",
4176                             (unsigned int) (lit & 0x0FFL));
4177               }
4178           } else {
4179               emitcode ("addc", "a,#!constbyte",
4180                         (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4181           }
4182       }
4183       
4184       if (pushResult) {
4185           emitcode ("push", "acc");
4186       } else {
4187           aopPut (AOP (IC_RESULT (ic)), "a", offset);
4188       }
4189       offset++;
4190   }
4191   _endLazyDPSEvaluation ();
4192   
4193   if (pushResult)
4194     {
4195       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4196
4197       size = getDataSize (IC_LEFT (ic));
4198       rSize = getDataSize (IC_RESULT (ic));
4199
4200       ADJUST_PUSHED_RESULT(size, rSize);
4201
4202       _startLazyDPSEvaluation ();
4203       while (size--)
4204         {
4205           emitcode ("pop", "acc");
4206           aopPut (AOP (IC_RESULT (ic)), "a", size);
4207         }
4208       _endLazyDPSEvaluation ();
4209     }
4210
4211   adjustArithmeticResult (ic);
4212
4213 release:
4214   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4215   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4216   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4217 }
4218
4219
4220 /*-----------------------------------------------------------------*/
4221 /* genMultbits :- multiplication of bits                           */
4222 /*-----------------------------------------------------------------*/
4223 static void
4224 genMultbits (operand * left,
4225              operand * right,
4226              operand * result,
4227              iCode   * ic)
4228 {
4229   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4230   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4231   aopOp(result, ic, TRUE, FALSE);
4232   outBitC (result);
4233 }
4234
4235
4236 /*-----------------------------------------------------------------*/
4237 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
4238 /*-----------------------------------------------------------------*/
4239 static void
4240 genMultOneByte (operand * left,
4241                 operand * right,
4242                 operand * result,
4243                 iCode   * ic)
4244 {
4245   sym_link *opetype = operandType (result);
4246   symbol *lbl;
4247
4248
4249   /* (if two literals: the value is computed before) */
4250   /* if one literal, literal on the right */
4251   if (AOP_TYPE (left) == AOP_LIT)
4252     {
4253       operand *t = right;
4254       right = left;
4255       left = t;
4256       emitcode (";", "swapped left and right");
4257     }
4258
4259   if (SPEC_USIGN(opetype)
4260       // ignore the sign of left and right, what else can we do?
4261       || (SPEC_USIGN(operandType(left)) && 
4262           SPEC_USIGN(operandType(right)))) {
4263     // just an unsigned 8*8=8/16 multiply
4264     //emitcode (";","unsigned");
4265     emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4266     MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4267     emitcode ("mul", "ab");
4268    
4269     _G.accInUse++; _G.bInUse++;
4270     aopOp(result, ic, TRUE, FALSE);
4271       
4272       if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4273       {
4274           // this should never happen
4275           fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4276                    AOP_SIZE(result), __FILE__, lineno);
4277           exit (1);
4278       }      
4279       
4280     aopPut (AOP (result), "a", 0);
4281     _G.accInUse--; _G.bInUse--;
4282     if (AOP_SIZE(result)==2) 
4283     {
4284       aopPut (AOP (result), "b", 1);
4285     }
4286     return;
4287   }
4288
4289   // we have to do a signed multiply
4290
4291   emitcode (";", "signed");
4292   emitcode ("clr", "F0"); // reset sign flag
4293   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4294
4295   lbl=newiTempLabel(NULL);
4296   emitcode ("jnb", "acc.7,!tlabel",  lbl->key+100);
4297   // left side is negative, 8-bit two's complement, this fails for -128
4298   emitcode ("setb", "F0"); // set sign flag
4299   emitcode ("cpl", "a");
4300   emitcode ("inc", "a");
4301
4302   emitcode ("", "!tlabeldef", lbl->key+100);
4303
4304   /* if literal */
4305   if (AOP_TYPE(right)==AOP_LIT) {
4306     signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
4307     /* AND literal negative */
4308     if ((int) val < 0) {
4309       emitcode ("cpl", "F0"); // complement sign flag
4310       emitcode ("mov", "b,#!constbyte", -val);
4311     } else {
4312       emitcode ("mov", "b,#!constbyte", val);
4313     }
4314   } else {
4315     lbl=newiTempLabel(NULL);
4316     emitcode ("mov", "b,a");
4317     emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4318     emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4319     // right side is negative, 8-bit two's complement
4320     emitcode ("cpl", "F0"); // complement sign flag
4321     emitcode ("cpl", "a");
4322     emitcode ("inc", "a");
4323     emitcode ("", "!tlabeldef", lbl->key+100);
4324   }
4325   emitcode ("mul", "ab");
4326     
4327   _G.accInUse++;_G.bInUse++;
4328   aopOp(result, ic, TRUE, FALSE);
4329     
4330   if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4331   {
4332     // this should never happen
4333       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4334                AOP_SIZE(result), __FILE__, lineno);
4335       exit (1);
4336   }    
4337     
4338   lbl=newiTempLabel(NULL);
4339   emitcode ("jnb", "F0,!tlabel", lbl->key+100);
4340   // only ONE op was negative, we have to do a 8/16-bit two's complement
4341   emitcode ("cpl", "a"); // lsb
4342   if (AOP_SIZE(result)==1) {
4343     emitcode ("inc", "a");
4344   } else {
4345     emitcode ("add", "a,#1");
4346     emitcode ("xch", "a,b");
4347     emitcode ("cpl", "a"); // msb
4348     emitcode ("addc", "a,#0");
4349     emitcode ("xch", "a,b");
4350   }
4351
4352   emitcode ("", "!tlabeldef", lbl->key+100);
4353   aopPut (AOP (result), "a", 0);
4354   _G.accInUse--;_G.bInUse--;
4355   if (AOP_SIZE(result)==2) {
4356     aopPut (AOP (result), "b", 1);
4357   }
4358 }
4359
4360 /*-----------------------------------------------------------------*/
4361 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply    */
4362 /*-----------------------------------------------------------------*/
4363 static void genMultTwoByte (operand *left, operand *right, 
4364                             operand *result, iCode *ic)
4365 {
4366         sym_link *retype = getSpec(operandType(right));
4367         sym_link *letype = getSpec(operandType(left));
4368         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4369         symbol *lbl;
4370
4371         if (AOP_TYPE (left) == AOP_LIT) {
4372                 operand *t = right;
4373                 right = left;
4374                 left = t;
4375         }
4376         /* save EA bit in F1 */
4377         lbl = newiTempLabel(NULL);
4378         emitcode ("setb","F1");
4379         emitcode ("jbc","EA,!tlabel",lbl->key+100);
4380         emitcode ("clr","F1");
4381         emitcode("","!tlabeldef",lbl->key+100);
4382
4383         /* load up MB with right */
4384         if (!umult) {
4385                 emitcode("clr","F0");
4386                 if (AOP_TYPE(right) == AOP_LIT) {
4387                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
4388                         if (val < 0) {
4389                                 emitcode("setb","F0");
4390                                 val = -val;
4391                         }
4392                         emitcode ("mov","mb,#!constbyte",val & 0xff);
4393                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
4394                 } else {
4395                         lbl = newiTempLabel(NULL);
4396                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4397                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4398                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
4399                         emitcode ("xch", "a,b");
4400                         emitcode ("cpl","a");
4401                         emitcode ("add", "a,#1");
4402                         emitcode ("xch", "a,b");
4403                         emitcode ("cpl", "a"); // msb
4404                         emitcode ("addc", "a,#0");
4405                         emitcode ("setb","F0");
4406                         emitcode ("","!tlabeldef",lbl->key+100);
4407                         emitcode ("mov","mb,b");
4408                         emitcode ("mov","mb,a");
4409                 }
4410         } else {
4411                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4412                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4413         }
4414         /* load up MA with left */
4415         if (!umult) {
4416                 lbl = newiTempLabel(NULL);
4417                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4418                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4419                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4420                 emitcode ("xch", "a,b");
4421                 emitcode ("cpl","a");
4422                 emitcode ("add", "a,#1");
4423                 emitcode ("xch", "a,b");
4424                 emitcode ("cpl", "a"); // msb
4425                 emitcode ("addc","a,#0");
4426                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4427                 emitcode ("setb","F0");
4428                 emitcode ("","!tlabeldef",lbl->key+100);
4429                 emitcode ("mov","ma,b");
4430                 emitcode ("mov","ma,a");
4431         } else {
4432                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4433                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4434         }
4435         /* wait for multiplication to finish */
4436         lbl = newiTempLabel(NULL);
4437         emitcode("","!tlabeldef", lbl->key+100);
4438         emitcode("mov","a,mcnt1");
4439         emitcode("anl","a,#!constbyte",0x80);
4440         emitcode("jnz","!tlabel",lbl->key+100);
4441         
4442         freeAsmop (left, NULL, ic, TRUE);
4443         freeAsmop (right, NULL, ic,TRUE);
4444         aopOp(result, ic, TRUE, FALSE);
4445
4446         /* if unsigned then simple */   
4447         if (umult) {
4448                 emitcode ("mov","a,ma");
4449                 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4450                 emitcode ("mov","a,ma");
4451                 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4452                 aopPut(AOP(result),"ma",1);
4453                 aopPut(AOP(result),"ma",0);
4454         } else {
4455                 emitcode("push","ma");
4456                 emitcode("push","ma");
4457                 emitcode("push","ma");
4458                 MOVA("ma");
4459                 /* negate result if needed */
4460                 lbl = newiTempLabel(NULL);      
4461                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4462                 emitcode("cpl","a");
4463                 emitcode("add","a,#1");
4464                 emitcode("","!tlabeldef", lbl->key+100);
4465                 if (AOP_TYPE(result) == AOP_ACC)
4466                 {
4467                     D(emitcode(";", "ACC special case."););
4468                     /* We know result is the only live aop, and 
4469                      * it's obviously not a DPTR2, so AP is available.
4470                      */
4471                     emitcode("mov", "%s,acc", DP2_RESULT_REG);
4472                 }
4473                 else
4474                 {
4475                     aopPut(AOP(result),"a",0);
4476                 }
4477             
4478                 emitcode("pop","acc");
4479                 lbl = newiTempLabel(NULL);      
4480                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4481                 emitcode("cpl","a");
4482                 emitcode("addc","a,#0");
4483                 emitcode("","!tlabeldef", lbl->key+100);
4484                 aopPut(AOP(result),"a",1);
4485                 emitcode("pop","acc");
4486                 if (AOP_SIZE(result) >= 3) {
4487                         lbl = newiTempLabel(NULL);      
4488                         emitcode("jnb","F0,!tlabel",lbl->key+100);
4489                         emitcode("cpl","a");
4490                         emitcode("addc","a,#0");                        
4491                         emitcode("","!tlabeldef", lbl->key+100);
4492                         aopPut(AOP(result),"a",2);
4493                 }
4494                 emitcode("pop","acc");
4495                 if (AOP_SIZE(result) >= 4) {
4496                         lbl = newiTempLabel(NULL);      
4497                         emitcode("jnb","F0,!tlabel",lbl->key+100);
4498                         emitcode("cpl","a");
4499                         emitcode("addc","a,#0");                        
4500                         emitcode("","!tlabeldef", lbl->key+100);
4501                         aopPut(AOP(result),"a",3);
4502                 }
4503                 if (AOP_TYPE(result) == AOP_ACC)
4504                 {
4505                     /* We stashed the result away above. */
4506                     emitcode("mov", "acc,%s", DP2_RESULT_REG);
4507                 }           
4508                 
4509         }
4510         freeAsmop (result, NULL, ic, TRUE);
4511
4512         /* restore EA bit in F1 */
4513         lbl = newiTempLabel(NULL);
4514         emitcode ("jnb","F1,!tlabel",lbl->key+100);
4515         emitcode ("setb","EA");
4516         emitcode("","!tlabeldef",lbl->key+100);
4517         return ;
4518 }
4519
4520 /*-----------------------------------------------------------------*/
4521 /* genMult - generates code for multiplication                     */
4522 /*-----------------------------------------------------------------*/
4523 static void
4524 genMult (iCode * ic)
4525 {
4526   operand *left = IC_LEFT (ic);
4527   operand *right = IC_RIGHT (ic);
4528   operand *result = IC_RESULT (ic);
4529
4530   D (emitcode (";", "genMult "););
4531
4532   /* assign the amsops */
4533   AOP_OP_2 (ic);
4534
4535   /* special cases first */
4536   /* both are bits */
4537   if (AOP_TYPE (left) == AOP_CRY &&
4538       AOP_TYPE (right) == AOP_CRY)
4539     {
4540       genMultbits (left, right, result, ic);
4541       goto release;
4542     }
4543
4544   /* if both are of size == 1 */
4545   if (AOP_SIZE (left) == 1 &&
4546       AOP_SIZE (right) == 1)
4547     {
4548       genMultOneByte (left, right, result, ic);
4549       goto release;
4550     }
4551
4552   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4553           /* use the ds390 ARITHMETIC accel UNIT */
4554           genMultTwoByte (left, right, result, ic);
4555           return ;
4556   }
4557   /* should have been converted to function call */
4558   assert (0);
4559
4560 release:
4561   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4562   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4563   freeAsmop (result, NULL, ic, TRUE);
4564 }
4565
4566 /*-----------------------------------------------------------------*/
4567 /* genDivbits :- division of bits                                  */
4568 /*-----------------------------------------------------------------*/
4569 static void
4570 genDivbits (operand * left,
4571             operand * right,
4572             operand * result,
4573             iCode   * ic)
4574 {
4575
4576   char *l;
4577
4578   /* the result must be bit */
4579   LOAD_AB_FOR_DIV (left, right, l);
4580   emitcode ("div", "ab");
4581   emitcode ("rrc", "a");
4582   aopOp(result, ic, TRUE, FALSE);
4583     
4584   aopPut (AOP (result), "c", 0);
4585 }
4586
4587 /*-----------------------------------------------------------------*/
4588 /* genDivOneByte : 8 bit division                                  */
4589 /*-----------------------------------------------------------------*/
4590 static void
4591 genDivOneByte (operand * left,
4592                operand * right,
4593                operand * result,
4594                iCode   * ic)
4595 {
4596   sym_link *opetype = operandType (result);
4597   char *l;
4598   symbol *lbl;
4599   int size, offset;
4600
4601   offset = 1;
4602   /* signed or unsigned */
4603   if (SPEC_USIGN (opetype))
4604     {
4605         /* unsigned is easy */
4606         LOAD_AB_FOR_DIV (left, right, l);
4607         emitcode ("div", "ab");
4608
4609         _G.accInUse++;
4610         aopOp(result, ic, TRUE, FALSE);
4611         aopPut (AOP (result), "a", 0);
4612         _G.accInUse--;
4613
4614         size = AOP_SIZE (result) - 1;
4615         
4616         while (size--)
4617         {
4618             aopPut (AOP (result), zero, offset++);
4619         }
4620       return;
4621     }
4622
4623   /* signed is a little bit more difficult */
4624
4625   /* save the signs of the operands */
4626   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4627   MOVA (l);
4628   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4629   emitcode ("push", "acc");     /* save it on the stack */
4630
4631   /* now sign adjust for both left & right */
4632   l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4633   MOVA (l);
4634   lbl = newiTempLabel (NULL);
4635   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4636   emitcode ("cpl", "a");
4637   emitcode ("inc", "a");
4638   emitcode ("", "!tlabeldef", (lbl->key + 100));
4639   emitcode ("mov", "b,a");
4640
4641   /* sign adjust left side */
4642   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4643   MOVA (l);
4644
4645   lbl = newiTempLabel (NULL);
4646   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4647   emitcode ("cpl", "a");
4648   emitcode ("inc", "a");
4649   emitcode ("", "!tlabeldef", (lbl->key + 100));
4650
4651   /* now the division */
4652   emitcode ("nop", "; workaround for DS80C390 div bug.");
4653   emitcode ("div", "ab");
4654   /* we are interested in the lower order
4655      only */
4656   emitcode ("mov", "b,a");
4657   lbl = newiTempLabel (NULL);
4658   emitcode ("pop", "acc");
4659   /* if there was an over flow we don't
4660      adjust the sign of the result */
4661   emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4662   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4663   CLRC;
4664   emitcode ("clr", "a");
4665   emitcode ("subb", "a,b");
4666   emitcode ("mov", "b,a");
4667   emitcode ("", "!tlabeldef", (lbl->key + 100));
4668
4669   /* now we are done */
4670   _G.accInUse++;     _G.bInUse++;
4671     aopOp(result, ic, TRUE, FALSE);
4672     
4673     aopPut (AOP (result), "b", 0);
4674     
4675     size = AOP_SIZE (result) - 1;
4676     
4677     if (size > 0)
4678     {
4679       emitcode ("mov", "c,b.7");
4680       emitcode ("subb", "a,acc");
4681     }
4682     while (size--)
4683     {
4684         aopPut (AOP (result), "a", offset++);
4685     }
4686     _G.accInUse--;     _G.bInUse--;
4687
4688 }
4689
4690 /*-----------------------------------------------------------------*/
4691 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide       */
4692 /*-----------------------------------------------------------------*/
4693 static void genDivTwoByte (operand *left, operand *right, 
4694                             operand *result, iCode *ic)
4695 {
4696         sym_link *retype = getSpec(operandType(right));
4697         sym_link *letype = getSpec(operandType(left));
4698         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4699         symbol *lbl;
4700
4701         /* save EA bit in F1 */
4702         lbl = newiTempLabel(NULL);
4703         emitcode ("setb","F1");
4704         emitcode ("jbc","EA,!tlabel",lbl->key+100);
4705         emitcode ("clr","F1");
4706         emitcode("","!tlabeldef",lbl->key+100);
4707
4708         /* load up MA with left */
4709         if (!umult) {
4710                 emitcode("clr","F0");
4711                 lbl = newiTempLabel(NULL);
4712                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4713                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4714                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4715                 emitcode ("xch", "a,b");
4716                 emitcode ("cpl","a");
4717                 emitcode ("add", "a,#1");
4718                 emitcode ("xch", "a,b");
4719                 emitcode ("cpl", "a"); // msb
4720                 emitcode ("addc","a,#0");
4721                 emitcode ("setb","F0");
4722                 emitcode ("","!tlabeldef",lbl->key+100);
4723                 emitcode ("mov","ma,b");
4724                 emitcode ("mov","ma,a");
4725         } else {
4726                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4727                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4728         }
4729
4730         /* load up MB with right */
4731         if (!umult) {
4732                 if (AOP_TYPE(right) == AOP_LIT) {
4733                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
4734                         if (val < 0) {
4735                                 lbl = newiTempLabel(NULL);
4736                                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4737                                 emitcode("setb","F0");
4738                                 emitcode ("","!tlabeldef",lbl->key+100);
4739                                 val = -val;
4740                         } 
4741                         emitcode ("mov","mb,#!constbyte",val & 0xff);               
4742                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4743                 } else {
4744                         lbl = newiTempLabel(NULL);
4745                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4746                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4747                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
4748                         emitcode ("xch", "a,b");
4749                         emitcode ("cpl","a");
4750                         emitcode ("add", "a,#1");
4751                         emitcode ("xch", "a,b");
4752                         emitcode ("cpl", "a"); // msb
4753                         emitcode ("addc", "a,#0");
4754                         emitcode ("jbc","F0,!tlabel",lbl->key+100);
4755                         emitcode ("setb","F0");
4756                         emitcode ("","!tlabeldef",lbl->key+100);
4757                         emitcode ("mov","mb,b");
4758                         emitcode ("mov","mb,a");
4759                 }
4760         } else {
4761                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4762                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4763         }
4764
4765         /* wait for multiplication to finish */
4766         lbl = newiTempLabel(NULL);
4767         emitcode("","!tlabeldef", lbl->key+100);
4768         emitcode("mov","a,mcnt1");
4769         emitcode("anl","a,#!constbyte",0x80);
4770         emitcode("jnz","!tlabel",lbl->key+100);
4771         
4772         freeAsmop (left, NULL, ic, TRUE);
4773         freeAsmop (right, NULL, ic,TRUE);
4774         aopOp(result, ic, TRUE, FALSE);
4775
4776         /* if unsigned then simple */   
4777         if (umult) {
4778                 aopPut(AOP(result),"ma",1);
4779                 aopPut(AOP(result),"ma",0);
4780         } else {
4781                 emitcode("push","ma");
4782                 MOVA("ma");
4783                 /* negate result if needed */
4784                 lbl = newiTempLabel(NULL);      
4785                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4786                 emitcode("cpl","a");
4787                 emitcode("add","a,#1");
4788                 emitcode("","!tlabeldef", lbl->key+100);
4789                 aopPut(AOP(result),"a",0);
4790                 emitcode("pop","acc");
4791                 lbl = newiTempLabel(NULL);      
4792                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4793                 emitcode("cpl","a");
4794                 emitcode("addc","a,#0");
4795                 emitcode("","!tlabeldef", lbl->key+100);
4796                 aopPut(AOP(result),"a",1);
4797         }
4798         freeAsmop (result, NULL, ic, TRUE);
4799         /* restore EA bit in F1 */
4800         lbl = newiTempLabel(NULL);
4801         emitcode ("jnb","F1,!tlabel",lbl->key+100);
4802         emitcode ("setb","EA");
4803         emitcode("","!tlabeldef",lbl->key+100);
4804         return ;
4805 }
4806
4807 /*-----------------------------------------------------------------*/
4808 /* genDiv - generates code for division                            */
4809 /*-----------------------------------------------------------------*/
4810 static void
4811 genDiv (iCode * ic)
4812 {
4813   operand *left = IC_LEFT (ic);
4814   operand *right = IC_RIGHT (ic);
4815   operand *result = IC_RESULT (ic);
4816
4817   D (emitcode (";", "genDiv "););
4818
4819   /* assign the amsops */
4820   AOP_OP_2 (ic);
4821
4822   /* special cases first */
4823   /* both are bits */
4824   if (AOP_TYPE (left) == AOP_CRY &&
4825       AOP_TYPE (right) == AOP_CRY)
4826     {
4827       genDivbits (left, right, result, ic);
4828       goto release;
4829     }
4830
4831   /* if both are of size == 1 */
4832   if (AOP_SIZE (left) == 1 &&
4833       AOP_SIZE (right) == 1)
4834     {
4835       genDivOneByte (left, right, result, ic);
4836       goto release;
4837     }
4838
4839   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4840           /* use the ds390 ARITHMETIC accel UNIT */
4841           genDivTwoByte (left, right, result, ic);
4842           return ;
4843   }
4844   /* should have been converted to function call */
4845   assert (0);
4846 release:
4847   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4848   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4849   freeAsmop (result, NULL, ic, TRUE);
4850 }
4851
4852 /*-----------------------------------------------------------------*/
4853 /* genModbits :- modulus of bits                                   */
4854 /*-----------------------------------------------------------------*/
4855 static void
4856 genModbits (operand * left,
4857             operand * right,
4858             operand * result,
4859             iCode   * ic)
4860 {
4861
4862   char *l;
4863
4864   /* the result must be bit */
4865   LOAD_AB_FOR_DIV (left, right, l);
4866   emitcode ("div", "ab");
4867   emitcode ("mov", "a,b");
4868   emitcode ("rrc", "a");
4869   aopOp(result, ic, TRUE, FALSE);
4870   aopPut (AOP (result), "c", 0);
4871 }
4872
4873 /*-----------------------------------------------------------------*/
4874 /* genModOneByte : 8 bit modulus                                   */
4875 /*-----------------------------------------------------------------*/
4876 static void
4877 genModOneByte (operand * left,
4878                operand * right,
4879                operand * result,
4880                iCode   * ic)
4881 {
4882   sym_link *opetype = operandType (result);
4883   char *l;
4884   symbol *lbl;
4885
4886   /* signed or unsigned */
4887   if (SPEC_USIGN (opetype))
4888     {
4889       /* unsigned is easy */
4890       LOAD_AB_FOR_DIV (left, right, l);
4891       emitcode ("div", "ab");
4892       aopOp(result, ic, TRUE, FALSE);   
4893       aopPut (AOP (result), "b", 0);
4894       return;
4895     }
4896
4897   /* signed is a little bit more difficult */
4898
4899   /* save the signs of the operands */
4900   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4901   MOVA (l);
4902
4903   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4904   emitcode ("push", "acc");     /* save it on the stack */
4905
4906   /* now sign adjust for both left & right */
4907   l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4908   MOVA (l);
4909
4910   lbl = newiTempLabel (NULL);
4911   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4912   emitcode ("cpl", "a");
4913   emitcode ("inc", "a");
4914   emitcode ("", "!tlabeldef", (lbl->key + 100));
4915   emitcode ("mov", "b,a");
4916
4917   /* sign adjust left side */
4918   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4919   MOVA (l);
4920
4921   lbl = newiTempLabel (NULL);
4922   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4923   emitcode ("cpl", "a");
4924   emitcode ("inc", "a");
4925   emitcode ("", "!tlabeldef", (lbl->key + 100));
4926
4927   /* now the multiplication */
4928   emitcode ("nop", "; workaround for DS80C390 div bug.");
4929   emitcode ("div", "ab");
4930   /* we are interested in the lower order
4931      only */
4932   lbl = newiTempLabel (NULL);
4933   emitcode ("pop", "acc");
4934   /* if there was an over flow we don't
4935      adjust the sign of the result */
4936   emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4937   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4938   CLRC;
4939   emitcode ("clr", "a");
4940   emitcode ("subb", "a,b");
4941   emitcode ("mov", "b,a");
4942   emitcode ("", "!tlabeldef", (lbl->key + 100));
4943   
4944   _G.bInUse++;
4945   /* now we are done */
4946   aopOp(result, ic, TRUE, FALSE);    
4947   aopPut (AOP (result), "b", 0);
4948   _G.bInUse--;
4949
4950 }
4951
4952 /*-----------------------------------------------------------------*/
4953 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus      */
4954 /*-----------------------------------------------------------------*/
4955 static void genModTwoByte (operand *left, operand *right, 
4956                             operand *result, iCode *ic)
4957 {
4958         sym_link *retype = getSpec(operandType(right));
4959         sym_link *letype = getSpec(operandType(left));
4960         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4961         symbol *lbl;
4962
4963         /* load up MA with left */
4964         /* save EA bit in F1 */
4965         lbl = newiTempLabel(NULL);
4966         emitcode ("setb","F1");
4967         emitcode ("jbc","EA,!tlabel",lbl->key+100);
4968         emitcode ("clr","F1");
4969         emitcode("","!tlabeldef",lbl->key+100);
4970
4971         if (!umult) {
4972                 lbl = newiTempLabel(NULL);
4973                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4974                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4975                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4976                 emitcode ("xch", "a,b");
4977                 emitcode ("cpl","a");
4978                 emitcode ("add", "a,#1");
4979                 emitcode ("xch", "a,b");
4980                 emitcode ("cpl", "a"); // msb
4981                 emitcode ("addc","a,#0");
4982                 emitcode ("","!tlabeldef",lbl->key+100);
4983                 emitcode ("mov","ma,b");
4984                 emitcode ("mov","ma,a");
4985         } else {
4986                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4987                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4988         }
4989
4990         /* load up MB with right */
4991         if (!umult) {
4992                 if (AOP_TYPE(right) == AOP_LIT) {
4993                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
4994                         if (val < 0) {
4995                                 val = -val;
4996                         } 
4997                         emitcode ("mov","mb,#!constbyte",val & 0xff);
4998                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
4999                 } else {
5000                         lbl = newiTempLabel(NULL);
5001                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
5002                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
5003                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
5004                         emitcode ("xch", "a,b");
5005                         emitcode ("cpl","a");
5006                         emitcode ("add", "a,#1");
5007                         emitcode ("xch", "a,b");
5008                         emitcode ("cpl", "a"); // msb
5009                         emitcode ("addc", "a,#0");
5010                         emitcode ("","!tlabeldef",lbl->key+100);
5011                         emitcode ("mov","mb,b");
5012                         emitcode ("mov","mb,a");
5013                 }
5014         } else {
5015                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
5016                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
5017         }
5018
5019         /* wait for multiplication to finish */
5020         lbl = newiTempLabel(NULL);
5021         emitcode("","!tlabeldef", lbl->key+100);
5022         emitcode("mov","a,mcnt1");
5023         emitcode("anl","a,#!constbyte",0x80);
5024         emitcode("jnz","!tlabel",lbl->key+100);
5025         
5026         freeAsmop (left, NULL, ic, TRUE);
5027         freeAsmop (right, NULL, ic,TRUE);
5028         aopOp(result, ic, TRUE, FALSE);
5029
5030         aopPut(AOP(result),"mb",1);
5031         aopPut(AOP(result),"mb",0);
5032         freeAsmop (result, NULL, ic, TRUE);
5033
5034         /* restore EA bit in F1 */
5035         lbl = newiTempLabel(NULL);
5036         emitcode ("jnb","F1,!tlabel",lbl->key+100);
5037         emitcode ("setb","EA");
5038         emitcode("","!tlabeldef",lbl->key+100);
5039         return ;
5040 }
5041
5042 /*-----------------------------------------------------------------*/
5043 /* genMod - generates code for division                            */
5044 /*-----------------------------------------------------------------*/
5045 static void
5046 genMod (iCode * ic)
5047 {
5048   operand *left = IC_LEFT (ic);
5049   operand *right = IC_RIGHT (ic);
5050   operand *result = IC_RESULT (ic);
5051
5052   D (emitcode (";", "genMod "); );
5053
5054   /* assign the amsops */
5055   AOP_OP_2 (ic);
5056
5057   /* special cases first */
5058   /* both are bits */
5059   if (AOP_TYPE (left) == AOP_CRY &&
5060       AOP_TYPE (right) == AOP_CRY)
5061     {
5062       genModbits (left, right, result, ic);
5063       goto release;
5064     }
5065
5066   /* if both are of size == 1 */
5067   if (AOP_SIZE (left) == 1 &&
5068       AOP_SIZE (right) == 1)
5069     {
5070       genModOneByte (left, right, result, ic);
5071       goto release;
5072     }
5073
5074   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5075           /* use the ds390 ARITHMETIC accel UNIT */
5076           genModTwoByte (left, right, result, ic);
5077           return ;
5078   }
5079
5080   /* should have been converted to function call */
5081   assert (0);
5082
5083 release:
5084   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5085   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5086   freeAsmop (result, NULL, ic, TRUE);
5087 }
5088
5089 /*-----------------------------------------------------------------*/
5090 /* genIfxJump :- will create a jump depending on the ifx           */
5091 /*-----------------------------------------------------------------*/
5092 static void
5093 genIfxJump (iCode * ic, char *jval)
5094 {
5095   symbol *jlbl;
5096   symbol *tlbl = newiTempLabel (NULL);
5097   char *inst;
5098
5099   D (emitcode (";", "genIfxJump ");
5100     );
5101
5102   /* if true label then we jump if condition
5103      supplied is true */
5104   if (IC_TRUE (ic))
5105     {
5106       jlbl = IC_TRUE (ic);
5107       inst = ((strcmp (jval, "a") == 0 ? "jz" :
5108                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5109     }
5110   else
5111     {
5112       /* false label is present */
5113       jlbl = IC_FALSE (ic);
5114       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5115                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5116     }
5117   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5118     emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5119   else
5120     emitcode (inst, "!tlabel", tlbl->key + 100);
5121   emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5122   emitcode ("", "!tlabeldef", tlbl->key + 100);
5123
5124   /* mark the icode as generated */
5125   ic->generated = 1;
5126 }
5127
5128 /*-----------------------------------------------------------------*/
5129 /* genCmp :- greater or less than comparison                       */
5130 /*-----------------------------------------------------------------*/
5131 static void
5132 genCmp (operand * left, operand * right,
5133         iCode * ic, iCode * ifx, int sign)
5134 {
5135   int size, offset = 0;
5136   unsigned long lit = 0L;
5137   operand *result;
5138
5139   D (emitcode (";", "genCmp");
5140     );
5141
5142   result = IC_RESULT (ic);
5143
5144   /* if left & right are bit variables */
5145   if (AOP_TYPE (left) == AOP_CRY &&
5146       AOP_TYPE (right) == AOP_CRY)
5147     {
5148       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5149       emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
5150     }
5151   else
5152     {
5153       /* subtract right from left if at the
5154          end the carry flag is set then we know that
5155          left is greater than right */
5156       size = max (AOP_SIZE (left), AOP_SIZE (right));
5157
5158       /* if unsigned char cmp with lit, do cjne left,#right,zz */
5159       if ((size == 1) && !sign &&
5160           (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5161         {
5162           symbol *lbl = newiTempLabel (NULL);
5163           emitcode ("cjne", "%s,%s,!tlabel",
5164                     aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5165                     aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
5166                     lbl->key + 100);
5167           emitcode ("", "!tlabeldef", lbl->key + 100);
5168         }
5169       else
5170         {
5171           if (AOP_TYPE (right) == AOP_LIT)
5172             {
5173               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5174               /* optimize if(x < 0) or if(x >= 0) */
5175               if (lit == 0L)
5176                 {
5177                   if (!sign)
5178                     {
5179                       CLRC;
5180                     }
5181                   else
5182                     {
5183                       MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
5184
5185                       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5186                       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5187
5188                       aopOp (result, ic, FALSE, FALSE);
5189
5190                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5191                         {
5192                           freeAsmop (result, NULL, ic, TRUE);
5193                           genIfxJump (ifx, "acc.7");
5194                           return;
5195                         }
5196                       else
5197                         {
5198                           emitcode ("rlc", "a");
5199                         }
5200                       goto release_freedLR;
5201                     }
5202                   goto release;
5203                 }
5204             }
5205           CLRC;
5206           while (size--)
5207             {
5208               //emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5209               MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5210               //emitcode (";", "genCmp #2");
5211               if (sign && (size == 0))
5212                 {
5213                     //emitcode (";", "genCmp #3");
5214                   emitcode ("xrl", "a,#!constbyte",0x80);
5215                   if (AOP_TYPE (right) == AOP_LIT)
5216                     {
5217                       unsigned long lit = (unsigned long)
5218                       floatFromVal (AOP (right)->aopu.aop_lit);
5219                       //emitcode (";", "genCmp #3.1");
5220                       emitcode ("subb", "a,#!constbyte",
5221                                 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5222                     }
5223                   else
5224                     {
5225                       //emitcode (";", "genCmp #3.2");
5226                       if (AOP_NEEDSACC (right))
5227                         {
5228                           emitcode ("push", "acc");
5229                         }
5230                       emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
5231                                                        FALSE, FALSE, FALSE));
5232                       emitcode ("xrl", "b,#!constbyte",0x80);
5233                       if (AOP_NEEDSACC (right))
5234                         {
5235                           emitcode ("pop", "acc");
5236                         }
5237                       emitcode ("subb", "a,b");
5238                     }
5239                 }
5240               else
5241                 {
5242                   const char *s;
5243
5244                   //emitcode (";", "genCmp #4");
5245                   if (AOP_NEEDSACC (right))
5246                     {
5247                       /* Yuck!! */
5248                       //emitcode (";", "genCmp #4.1");
5249                       emitcode ("xch", "a, b");
5250                       MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
5251                       emitcode ("xch", "a, b");
5252                       s = "b";
5253                     }
5254                   else
5255                     {
5256                       //emitcode (";", "genCmp #4.2");
5257                       s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
5258                     }
5259
5260                   emitcode ("subb", "a,%s", s);
5261                 }
5262             }
5263         }
5264     }
5265
5266 release:
5267 /* Don't need the left & right operands any more; do need the result. */
5268   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5269   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5270
5271   aopOp (result, ic, FALSE, FALSE);
5272
5273 release_freedLR:
5274
5275   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5276     {
5277       outBitC (result);
5278     }
5279   else
5280     {
5281       /* if the result is used in the next
5282          ifx conditional branch then generate
5283          code a little differently */
5284       if (ifx)
5285         {
5286           genIfxJump (ifx, "c");
5287         }
5288       else
5289         {
5290           outBitC (result);
5291         }
5292       /* leave the result in acc */
5293     }
5294   freeAsmop (result, NULL, ic, TRUE);
5295 }
5296
5297 /*-----------------------------------------------------------------*/
5298 /* genCmpGt :- greater than comparison                             */
5299 /*-----------------------------------------------------------------*/
5300 static void
5301 genCmpGt (iCode * ic, iCode * ifx)
5302 {
5303   operand *left, *right;
5304   sym_link *letype, *retype;
5305   int sign;
5306
5307   D (emitcode (";", "genCmpGt ");
5308     );
5309
5310   left = IC_LEFT (ic);
5311   right = IC_RIGHT (ic);
5312
5313   letype = getSpec (operandType (left));
5314   retype = getSpec (operandType (right));
5315   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5316
5317   /* assign the left & right amsops */
5318   AOP_OP_2 (ic);
5319
5320   genCmp (right, left, ic, ifx, sign);
5321 }
5322
5323 /*-----------------------------------------------------------------*/
5324 /* genCmpLt - less than comparisons                                */
5325 /*-----------------------------------------------------------------*/
5326 static void
5327 genCmpLt (iCode * ic, iCode * ifx)
5328 {
5329   operand *left, *right;
5330   sym_link *letype, *retype;
5331   int sign;
5332
5333   D (emitcode (";", "genCmpLt "););
5334
5335   left = IC_LEFT (ic);
5336   right = IC_RIGHT (ic);
5337
5338   letype = getSpec (operandType (left));
5339   retype = getSpec (operandType (right));
5340   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5341
5342   /* assign the left & right amsops */
5343   AOP_OP_2 (ic);
5344
5345   genCmp (left, right, ic, ifx, sign);
5346 }
5347
5348 /*-----------------------------------------------------------------*/
5349 /* gencjneshort - compare and jump if not equal                    */
5350 /*-----------------------------------------------------------------*/
5351 static void
5352 gencjneshort (operand * left, operand * right, symbol * lbl)
5353 {
5354   int size = max (AOP_SIZE (left), AOP_SIZE (right));
5355   int offset = 0;
5356   unsigned long lit = 0L;
5357
5358   D (emitcode (";", "gencjneshort");
5359     );
5360
5361   /* if the left side is a literal or
5362      if the right is in a pointer register and left
5363      is not */
5364   if ((AOP_TYPE (left) == AOP_LIT) ||
5365       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5366     {
5367       operand *t = right;
5368       right = left;
5369       left = t;
5370     }
5371
5372   if (AOP_TYPE (right) == AOP_LIT)
5373     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5374
5375   if (opIsGptr (left) || opIsGptr (right))
5376     {
5377       /* We are comparing a generic pointer to something.
5378        * Exclude the generic type byte from the comparison.
5379        */
5380       size--;
5381       D (emitcode (";", "cjneshort: generic ptr special case.");
5382         )
5383     }
5384
5385
5386   /* if the right side is a literal then anything goes */
5387   if (AOP_TYPE (right) == AOP_LIT &&
5388       AOP_TYPE (left) != AOP_DIR)
5389     {
5390       while (size--)
5391         {
5392           char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5393           MOVA (l);
5394           emitcode ("cjne", "a,%s,!tlabel",
5395                     aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
5396                     lbl->key + 100);
5397           offset++;
5398         }
5399     }
5400
5401   /* if the right side is in a register or in direct space or
5402      if the left is a pointer register & right is not */
5403   else if (AOP_TYPE (right) == AOP_REG ||
5404            AOP_TYPE (right) == AOP_DIR ||
5405            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5406            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5407     {
5408       while (size--)
5409         {
5410           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5411           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5412               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5413             emitcode ("jnz", "!tlabel", lbl->key + 100);
5414           else
5415             emitcode ("cjne", "a,%s,!tlabel",
5416                       aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
5417                       lbl->key + 100);
5418           offset++;
5419         }
5420     }
5421   else
5422     {
5423       /* right is a pointer reg need both a & b */
5424       while (size--)
5425         {
5426           char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5427           if (strcmp (l, "b"))
5428             emitcode ("mov", "b,%s", l);
5429           MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5430           emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
5431           offset++;
5432         }
5433     }
5434 }
5435
5436 /*-----------------------------------------------------------------*/
5437 /* gencjne - compare and jump if not equal                         */
5438 /*-----------------------------------------------------------------*/
5439 static void
5440 gencjne (operand * left, operand * right, symbol * lbl)
5441 {
5442   symbol *tlbl = newiTempLabel (NULL);
5443
5444   D (emitcode (";", "gencjne");
5445     );
5446
5447   gencjneshort (left, right, lbl);
5448
5449   emitcode ("mov", "a,%s", one);
5450   emitcode ("sjmp", "!tlabel", tlbl->key + 100);
5451   emitcode ("", "!tlabeldef", lbl->key + 100);
5452   emitcode ("clr", "a");
5453   emitcode ("", "!tlabeldef", tlbl->key + 100);
5454 }
5455
5456 /*-----------------------------------------------------------------*/
5457 /* genCmpEq - generates code for equal to                          */
5458 /*-----------------------------------------------------------------*/
5459 static void
5460 genCmpEq (iCode * ic, iCode * ifx)
5461 {
5462   operand *left, *right, *result;
5463
5464   D (emitcode (";", "genCmpEq ");
5465     );
5466
5467   AOP_OP_2 (ic);
5468   AOP_SET_LOCALS (ic);
5469
5470   /* if literal, literal on the right or
5471      if the right is in a pointer register and left
5472      is not */
5473   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5474       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5475     {
5476       operand *t = IC_RIGHT (ic);
5477       IC_RIGHT (ic) = IC_LEFT (ic);
5478       IC_LEFT (ic) = t;
5479     }
5480
5481   if (ifx &&                    /* !AOP_SIZE(result) */
5482       OP_SYMBOL (result) &&
5483       OP_SYMBOL (result)->regType == REG_CND)
5484     {
5485       symbol *tlbl;
5486       /* if they are both bit variables */
5487       if (AOP_TYPE (left) == AOP_CRY &&
5488           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5489         {
5490           if (AOP_TYPE (right) == AOP_LIT)
5491             {
5492               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5493               if (lit == 0L)
5494                 {
5495                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5496                   emitcode ("cpl", "c");
5497                 }
5498               else if (lit == 1L)
5499                 {
5500                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5501                 }
5502               else
5503                 {
5504                   emitcode ("clr", "c");
5505                 }
5506               /* AOP_TYPE(right) == AOP_CRY */
5507             }
5508           else
5509             {
5510               symbol *lbl = newiTempLabel (NULL);
5511               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5512               emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5513               emitcode ("cpl", "c");
5514               emitcode ("", "!tlabeldef", (lbl->key + 100));
5515             }
5516           /* if true label then we jump if condition
5517              supplied is true */
5518           tlbl = newiTempLabel (NULL);
5519           if (IC_TRUE (ifx))
5520             {
5521               emitcode ("jnc", "!tlabel", tlbl->key + 100);
5522               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5523             }
5524           else
5525             {
5526               emitcode ("jc", "!tlabel", tlbl->key + 100);
5527               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5528             }
5529           emitcode ("", "!tlabeldef", tlbl->key + 100);
5530         }
5531       else
5532         {
5533           tlbl = newiTempLabel (NULL);
5534           gencjneshort (left, right, tlbl);
5535           if (IC_TRUE (ifx))
5536             {
5537               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5538               emitcode ("", "!tlabeldef", tlbl->key + 100);
5539             }
5540           else
5541             {
5542               symbol *lbl = newiTempLabel (NULL);
5543               emitcode ("sjmp", "!tlabel", lbl->key + 100);
5544               emitcode ("", "!tlabeldef", tlbl->key + 100);
5545               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5546               emitcode ("", "!tlabeldef", lbl->key + 100);
5547             }
5548         }
5549       /* mark the icode as generated */
5550       ifx->generated = 1;
5551
5552       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5553       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5554       return;
5555     }
5556
5557   /* if they are both bit variables */
5558   if (AOP_TYPE (left) == AOP_CRY &&
5559       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5560     {
5561       if (AOP_TYPE (right) == AOP_LIT)
5562         {
5563           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5564           if (lit == 0L)
5565             {
5566               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5567               emitcode ("cpl", "c");
5568             }
5569           else if (lit == 1L)
5570             {
5571               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5572             }
5573           else
5574             {
5575               emitcode ("clr", "c");
5576             }
5577           /* AOP_TYPE(right) == AOP_CRY */
5578         }
5579       else
5580         {
5581           symbol *lbl = newiTempLabel (NULL);
5582           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5583           emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5584           emitcode ("cpl", "c");
5585           emitcode ("", "!tlabeldef", (lbl->key + 100));
5586         }
5587
5588       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5589       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5590
5591       aopOp (result, ic, TRUE, FALSE);
5592
5593       /* c = 1 if egal */
5594       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5595         {
5596           outBitC (result);
5597           goto release;
5598         }
5599       if (ifx)
5600         {
5601           genIfxJump (ifx, "c");
5602           goto release;
5603         }
5604       /* if the result is used in an arithmetic operation
5605          then put the result in place */
5606       outBitC (result);
5607     }
5608   else
5609     {
5610       gencjne (left, right, newiTempLabel (NULL));
5611
5612       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5613       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5614
5615       aopOp (result, ic, TRUE, FALSE);
5616
5617       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5618         {
5619           aopPut (AOP (result), "a", 0);
5620           goto release;
5621         }
5622       if (ifx)
5623         {
5624           genIfxJump (ifx, "a");
5625           goto release;
5626         }
5627       /* if the result is used in an arithmetic operation
5628          then put the result in place */
5629       if (AOP_TYPE (result) != AOP_CRY)
5630         outAcc (result);
5631       /* leave the result in acc */
5632     }
5633
5634 release:
5635   freeAsmop (result, NULL, ic, TRUE);
5636 }
5637
5638 /*-----------------------------------------------------------------*/
5639 /* ifxForOp - returns the icode containing the ifx for operand     */
5640 /*-----------------------------------------------------------------*/
5641 static iCode *
5642 ifxForOp (operand * op, iCode * ic)
5643 {
5644   /* if true symbol then needs to be assigned */
5645   if (IS_TRUE_SYMOP (op))
5646     return NULL;
5647
5648   /* if this has register type condition and
5649      the next instruction is ifx with the same operand
5650      and live to of the operand is upto the ifx only then */
5651   if (ic->next &&
5652       ic->next->op == IFX &&
5653       IC_COND (ic->next)->key == op->key &&
5654       OP_SYMBOL (op)->liveTo <= ic->next->seq)
5655     return ic->next;
5656
5657   return NULL;
5658 }
5659 /*-----------------------------------------------------------------*/
5660 /* hasInc - operand is incremented before any other use            */
5661 /*-----------------------------------------------------------------*/
5662 static iCode *
5663 hasInc (operand *op, iCode *ic, int osize)
5664 {
5665   sym_link *type = operandType(op);
5666   sym_link *retype = getSpec (type);
5667   iCode *lic = ic->next;
5668   int isize ;
5669   
5670   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5671   if (!IS_SYMOP(op)) return NULL;
5672
5673   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5674   if (IS_AGGREGATE(type->next)) return NULL;
5675   if (osize != (isize = getSize(type->next))) return NULL;
5676
5677   while (lic) {
5678       /* if operand of the form op = op + <sizeof *op> */
5679       if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5680           isOperandEqual(IC_RESULT(lic),op) && 
5681           isOperandLiteral(IC_RIGHT(lic)) &&
5682           operandLitValue(IC_RIGHT(lic)) == isize) {
5683           return lic;
5684       }
5685       /* if the operand used or deffed */
5686       if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5687           return NULL;
5688       }
5689       /* if GOTO or IFX */
5690       if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5691       lic = lic->next;
5692   }
5693   return NULL;
5694 }
5695
5696 /*-----------------------------------------------------------------*/
5697 /* genAndOp - for && operation                                     */
5698 /*-----------------------------------------------------------------*/
5699 static void
5700 genAndOp (iCode * ic)
5701 {
5702   operand *left, *right, *result;
5703   symbol *tlbl;
5704
5705   D (emitcode (";", "genAndOp "););
5706
5707   /* note here that && operations that are in an
5708      if statement are taken away by backPatchLabels
5709      only those used in arthmetic operations remain */
5710   AOP_OP_2 (ic);
5711   AOP_SET_LOCALS (ic);
5712
5713   /* if both are bit variables */
5714   if (AOP_TYPE (left) == AOP_CRY &&
5715       AOP_TYPE (right) == AOP_CRY)
5716     {
5717       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5718       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5719       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5720       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5721   
5722       aopOp (result,ic,FALSE, FALSE);
5723       outBitC (result);
5724     }
5725   else
5726     {
5727       tlbl = newiTempLabel (NULL);
5728       toBoolean (left);
5729       emitcode ("jz", "!tlabel", tlbl->key + 100);
5730       toBoolean (right);
5731       emitcode ("", "!tlabeldef", tlbl->key + 100);
5732       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5733       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5734   
5735       aopOp (result,ic,FALSE, FALSE);
5736       outBitAcc (result);
5737     }
5738     freeAsmop (result, NULL, ic, TRUE);
5739 }
5740
5741
5742 /*-----------------------------------------------------------------*/
5743 /* genOrOp - for || operation                                      */
5744 /*-----------------------------------------------------------------*/
5745 static void
5746 genOrOp (iCode * ic)
5747 {
5748   operand *left, *right, *result;
5749   symbol *tlbl;
5750
5751   D (emitcode (";", "genOrOp "););
5752
5753   /* note here that || operations that are in an
5754      if statement are taken away by backPatchLabels
5755      only those used in arthmetic operations remain */
5756   AOP_OP_2 (ic);
5757   AOP_SET_LOCALS (ic);
5758
5759   /* if both are bit variables */
5760   if (AOP_TYPE (left) == AOP_CRY &&
5761       AOP_TYPE (right) == AOP_CRY)
5762     {
5763       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5764       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5765       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5766       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5767   
5768       aopOp (result,ic,FALSE, FALSE);
5769       
5770       outBitC (result);
5771     }
5772   else
5773     {
5774       tlbl = newiTempLabel (NULL);
5775       toBoolean (left);
5776       emitcode ("jnz", "!tlabel", tlbl->key + 100);
5777       toBoolean (right);
5778       emitcode ("", "!tlabeldef", tlbl->key + 100);
5779       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5780       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5781   
5782       aopOp (result,ic,FALSE, FALSE);
5783       
5784       outBitAcc (result);
5785     }
5786
5787   freeAsmop (result, NULL, ic, TRUE);
5788 }
5789
5790 /*-----------------------------------------------------------------*/
5791 /* isLiteralBit - test if lit == 2^n                               */
5792 /*-----------------------------------------------------------------*/
5793 static int
5794 isLiteralBit (unsigned long lit)
5795 {
5796   unsigned long pw[32] =
5797   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5798    0x100L, 0x200L, 0x400L, 0x800L,
5799    0x1000L, 0x2000L, 0x4000L, 0x8000L,
5800    0x10000L, 0x20000L, 0x40000L, 0x80000L,
5801    0x100000L, 0x200000L, 0x400000L, 0x800000L,
5802    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5803    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5804   int idx;
5805
5806   for (idx = 0; idx < 32; idx++)
5807     if (lit == pw[idx])
5808       return idx + 1;
5809   return 0;
5810 }
5811
5812 /*-----------------------------------------------------------------*/
5813 /* continueIfTrue -                                                */
5814 /*-----------------------------------------------------------------*/
5815 static void
5816 continueIfTrue (iCode * ic)
5817 {
5818   if (IC_TRUE (ic))
5819     emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
5820   ic->generated = 1;
5821 }
5822
5823 /*-----------------------------------------------------------------*/
5824 /* jmpIfTrue -                                                     */
5825 /*-----------------------------------------------------------------*/
5826 static void
5827 jumpIfTrue (iCode * ic)
5828 {
5829   if (!IC_TRUE (ic))
5830     emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
5831   ic->generated = 1;
5832 }
5833
5834 /*-----------------------------------------------------------------*/
5835 /* jmpTrueOrFalse -                                                */
5836 /*-----------------------------------------------------------------*/
5837 static void
5838 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
5839 {
5840   // ugly but optimized by peephole
5841   if (IC_TRUE (ic))
5842     {
5843       symbol *nlbl = newiTempLabel (NULL);
5844       emitcode ("sjmp", "!tlabel", nlbl->key + 100);
5845       emitcode ("", "!tlabeldef", tlbl->key + 100);
5846       emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
5847       emitcode ("", "!tlabeldef", nlbl->key + 100);
5848     }
5849   else
5850     {
5851       emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
5852       emitcode ("", "!tlabeldef", tlbl->key + 100);
5853     }
5854   ic->generated = 1;
5855 }
5856
5857 // Generate code to perform a bit-wise logic operation
5858 // on two operands in far space (assumed to already have been 
5859 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
5860 // in far space. This requires pushing the result on the stack
5861 // then popping it into the result.
5862 static void
5863 genFarFarLogicOp(iCode *ic, char *logicOp)
5864 {
5865       int size, resultSize, compSize;
5866       int offset = 0;
5867       
5868       TR_AP("#5");
5869       D(emitcode(";", "%s special case for 3 far operands.", logicOp););
5870       compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ? 
5871                   AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
5872       
5873       _startLazyDPSEvaluation();
5874       for (size = compSize; (size--); offset++)
5875       {
5876           MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
5877           emitcode ("mov", "%s, acc", DP2_RESULT_REG);
5878           MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
5879           
5880           emitcode (logicOp, "a,%s", DP2_RESULT_REG);
5881           emitcode ("push", "acc");
5882       }
5883       _endLazyDPSEvaluation();
5884      
5885       freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5886       freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5887       aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
5888      
5889       resultSize = AOP_SIZE(IC_RESULT(ic));
5890
5891       ADJUST_PUSHED_RESULT(compSize, resultSize);
5892
5893       _startLazyDPSEvaluation();
5894       while (compSize--)
5895       {
5896           emitcode ("pop", "acc");
5897           aopPut (AOP (IC_RESULT (ic)), "a", compSize);
5898       }
5899       _endLazyDPSEvaluation();
5900       freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
5901 }
5902
5903
5904 /*-----------------------------------------------------------------*/
5905 /* genAnd  - code for and                                          */
5906 /*-----------------------------------------------------------------*/
5907 static void
5908 genAnd (iCode * ic, iCode * ifx)
5909 {
5910   operand *left, *right, *result;
5911   int size, offset = 0;
5912   unsigned long lit = 0L;
5913   int bytelit = 0;
5914   char buffer[10];
5915   bool pushResult;
5916
5917   D (emitcode (";", "genAnd "););
5918
5919   AOP_OP_3_NOFATAL (ic, pushResult);
5920   AOP_SET_LOCALS (ic);
5921
5922   if (pushResult)
5923   {
5924       genFarFarLogicOp(ic, "anl");
5925       return;
5926   }  
5927
5928 #ifdef DEBUG_TYPE
5929   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5930             AOP_TYPE (result),
5931             AOP_TYPE (left), AOP_TYPE (right));
5932   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5933             AOP_SIZE (result),
5934             AOP_SIZE (left), AOP_SIZE (right));
5935 #endif
5936
5937   /* if left is a literal & right is not then exchange them */
5938   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5939 #ifdef LOGIC_OPS_BROKEN      
5940     ||  AOP_NEEDSACC (left)
5941 #endif
5942     )
5943     {
5944       operand *tmp = right;
5945       right = left;
5946       left = tmp;
5947     }
5948
5949   /* if result = right then exchange them */
5950   if (sameRegs (AOP (result), AOP (right)))
5951     {
5952       operand *tmp = right;
5953       right = left;
5954       left = tmp;
5955     }
5956
5957   /* if right is bit then exchange them */
5958   if (AOP_TYPE (right) == AOP_CRY &&
5959       AOP_TYPE (left) != AOP_CRY)
5960     {
5961       operand *tmp = right;
5962       right = left;
5963       left = tmp;
5964     }
5965   if (AOP_TYPE (right) == AOP_LIT)
5966     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5967
5968   size = AOP_SIZE (result);
5969
5970   // if(bit & yy)
5971   // result = bit & yy;
5972   if (AOP_TYPE (left) == AOP_CRY)
5973     {
5974       // c = bit & literal;
5975       if (AOP_TYPE (right) == AOP_LIT)
5976         {
5977           if (lit & 1)
5978             {
5979               if (size && sameRegs (AOP (result), AOP (left)))
5980                 // no change
5981                 goto release;
5982               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5983             }
5984           else
5985             {
5986               // bit(result) = 0;
5987               if (size && (AOP_TYPE (result) == AOP_CRY))
5988                 {
5989                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5990                   goto release;
5991                 }
5992               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5993                 {
5994                   jumpIfTrue (ifx);
5995                   goto release;
5996                 }
5997               emitcode ("clr", "c");
5998             }
5999         }
6000       else
6001         {
6002           if (AOP_TYPE (right) == AOP_CRY)
6003             {
6004               // c = bit & bit;
6005               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6006               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6007             }
6008           else
6009             {
6010               // c = bit & val;
6011               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
6012               // c = lsb
6013               emitcode ("rrc", "a");
6014               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6015             }
6016         }
6017       // bit = c
6018       // val = c
6019       if (size)
6020         outBitC (result);
6021       // if(bit & ...)
6022       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6023         genIfxJump (ifx, "c");
6024       goto release;
6025     }
6026
6027   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6028   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6029   if ((AOP_TYPE (right) == AOP_LIT) &&
6030       (AOP_TYPE (result) == AOP_CRY) &&
6031       (AOP_TYPE (left) != AOP_CRY))
6032     {
6033       int posbit = isLiteralBit (lit);
6034       /* left &  2^n */
6035       if (posbit)
6036         {
6037           posbit--;
6038           MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
6039           // bit = left & 2^n
6040           if (size)
6041             emitcode ("mov", "c,acc.%d", posbit & 0x07);
6042           // if(left &  2^n)
6043           else
6044             {
6045               if (ifx)
6046                 {
6047                   sprintf (buffer, "acc.%d", posbit & 0x07);
6048                   genIfxJump (ifx, buffer);
6049                 }
6050               else 
6051                   {
6052                       emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6053                   }
6054               goto release;
6055             }
6056         }
6057       else
6058         {
6059           symbol *tlbl = newiTempLabel (NULL);
6060           int sizel = AOP_SIZE (left);
6061           if (size)
6062             emitcode ("setb", "c");
6063           while (sizel--)
6064             {
6065               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6066                 {
6067                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6068                   // byte ==  2^n ?
6069                   if ((posbit = isLiteralBit (bytelit)) != 0)
6070                     emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
6071                   else
6072                     {
6073                       if (bytelit != 0x0FFL)
6074                         emitcode ("anl", "a,%s",
6075                           aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
6076                       emitcode ("jnz", "!tlabel", tlbl->key + 100);
6077                     }
6078                 }
6079               offset++;
6080             }
6081           // bit = left & literal
6082           if (size)
6083             {
6084               emitcode ("clr", "c");
6085               emitcode ("", "!tlabeldef", tlbl->key + 100);
6086             }
6087           // if(left & literal)
6088           else
6089             {
6090               if (ifx)
6091                 jmpTrueOrFalse (ifx, tlbl);
6092               goto release;
6093             }
6094         }
6095       outBitC (result);
6096       goto release;
6097     }
6098
6099   /* if left is same as result */
6100   if (sameRegs (AOP (result), AOP (left)))
6101     {
6102       for (; size--; offset++)
6103         {
6104           if (AOP_TYPE (right) == AOP_LIT)
6105             {
6106               if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6107                 continue;
6108               else if (bytelit == 0)
6109                 aopPut (AOP (result), zero, offset);
6110               else if (IS_AOP_PREG (result))
6111                 {
6112                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6113                   emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6114                   aopPut (AOP (result), "a", offset);
6115                 }
6116               else
6117                 emitcode ("anl", "%s,%s",
6118                           aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6119                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6120             }
6121           else
6122             {
6123               if (AOP_TYPE (left) == AOP_ACC)
6124                 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6125               else
6126                 {
6127                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6128                   if (IS_AOP_PREG (result))
6129                     {
6130                       emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6131                       aopPut (AOP (result), "a", offset);
6132
6133                     }
6134                   else
6135                     emitcode ("anl", "%s,a",
6136                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6137                 }
6138             }
6139         }
6140     }
6141   else
6142     {
6143       // left & result in different registers
6144       if (AOP_TYPE (result) == AOP_CRY)
6145         {
6146           // result = bit
6147           // if(size), result in bit
6148           // if(!size && ifx), conditional oper: if(left & right)
6149           symbol *tlbl = newiTempLabel (NULL);
6150           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6151           if (size)
6152             emitcode ("setb", "c");
6153           while (sizer--)
6154             {
6155               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6156                 emitcode ("anl", "a,%s",
6157                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6158               } else {
6159                 if (AOP_TYPE(left)==AOP_ACC) {
6160                   emitcode("mov", "b,a");
6161                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6162                   emitcode("anl", "a,b");
6163                 }else {
6164                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6165                   emitcode ("anl", "a,%s",
6166                             aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6167                 }
6168               }
6169               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6170               offset++;
6171             }
6172           if (size)
6173             {
6174               CLRC;
6175               emitcode ("", "!tlabeldef", tlbl->key + 100);
6176               outBitC (result);
6177             }
6178           else if (ifx)
6179             jmpTrueOrFalse (ifx, tlbl);
6180         }
6181       else
6182         {
6183           for (; (size--); offset++)
6184             {
6185               // normal case
6186               // result = left & right
6187               if (AOP_TYPE (right) == AOP_LIT)
6188                 {
6189                   if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6190                     {
6191                       aopPut (AOP (result),
6192                            aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6193                               offset);
6194                       continue;
6195                     }
6196                   else if (bytelit == 0)
6197                     {
6198                       aopPut (AOP (result), zero, offset);
6199                       continue;
6200                     }
6201                   D (emitcode (";", "better literal AND."););
6202                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6203                   emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6204                                                     FALSE, FALSE, FALSE));
6205
6206                 }
6207               else
6208                 {
6209                   // faster than result <- left, anl result,right
6210                   // and better if result is SFR
6211                   if (AOP_TYPE (left) == AOP_ACC)
6212                     {
6213                       emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
6214                                                        FALSE, FALSE, FALSE));
6215                     }
6216                   else
6217                     {
6218                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6219                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6220                       {
6221                           emitcode("mov", "b,a");
6222                           rOp = "b";
6223                       }
6224                         
6225                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6226                       emitcode ("anl", "a,%s", rOp);
6227                     }                   
6228                 }
6229               aopPut (AOP (result), "a", offset);
6230             }
6231         }
6232     }
6233
6234 release:
6235   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6236   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6237   freeAsmop (result, NULL, ic, TRUE);
6238 }
6239
6240
6241 /*-----------------------------------------------------------------*/
6242 /* genOr  - code for or                                            */
6243 /*-----------------------------------------------------------------*/
6244 static void
6245 genOr (iCode * ic, iCode * ifx)
6246 {
6247   operand *left, *right, *result;
6248   int size, offset = 0;
6249   unsigned long lit = 0L;
6250   bool     pushResult;
6251
6252   D (emitcode (";", "genOr "););
6253
6254   AOP_OP_3_NOFATAL (ic, pushResult);
6255   AOP_SET_LOCALS (ic);
6256
6257   if (pushResult)
6258   {
6259       genFarFarLogicOp(ic, "orl");
6260       return;
6261   }
6262
6263
6264 #ifdef DEBUG_TYPE
6265   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6266             AOP_TYPE (result),
6267             AOP_TYPE (left), AOP_TYPE (right));
6268   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6269             AOP_SIZE (result),
6270             AOP_SIZE (left), AOP_SIZE (right));
6271 #endif
6272
6273   /* if left is a literal & right is not then exchange them */
6274   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6275 #ifdef LOGIC_OPS_BROKEN
6276    || AOP_NEEDSACC (left) // I think this is a net loss now.
6277 #endif      
6278       )
6279     {
6280       operand *tmp = right;
6281       right = left;
6282       left = tmp;
6283     }
6284
6285   /* if result = right then exchange them */
6286   if (sameRegs (AOP (result), AOP (right)))
6287     {
6288       operand *tmp = right;
6289       right = left;
6290       left = tmp;
6291     }
6292
6293   /* if right is bit then exchange them */
6294   if (AOP_TYPE (right) == AOP_CRY &&
6295       AOP_TYPE (left) != AOP_CRY)
6296     {
6297       operand *tmp = right;
6298       right = left;
6299       left = tmp;
6300     }
6301   if (AOP_TYPE (right) == AOP_LIT)
6302     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6303
6304   size = AOP_SIZE (result);
6305
6306   // if(bit | yy)
6307   // xx = bit | yy;
6308   if (AOP_TYPE (left) == AOP_CRY)
6309     {
6310       if (AOP_TYPE (right) == AOP_LIT)
6311         {
6312           // c = bit & literal;
6313           if (lit)
6314             {
6315               // lit != 0 => result = 1
6316               if (AOP_TYPE (result) == AOP_CRY)
6317                 {
6318                   if (size)
6319                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6320                   else if (ifx)
6321                     continueIfTrue (ifx);
6322                   goto release;
6323                 }
6324               emitcode ("setb", "c");
6325             }
6326           else
6327             {
6328               // lit == 0 => result = left
6329               if (size && sameRegs (AOP (result), AOP (left)))
6330                 goto release;
6331               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6332             }
6333         }
6334       else
6335         {
6336           if (AOP_TYPE (right) == AOP_CRY)
6337             {
6338               // c = bit | bit;
6339               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6340               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6341             }
6342           else
6343             {
6344               // c = bit | val;
6345               symbol *tlbl = newiTempLabel (NULL);
6346               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6347                 emitcode ("setb", "c");
6348               emitcode ("jb", "%s,!tlabel",
6349                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
6350               toBoolean (right);
6351               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6352               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6353                 {
6354                   jmpTrueOrFalse (ifx, tlbl);
6355                   goto release;
6356                 }
6357               else
6358                 {
6359                   CLRC;
6360                   emitcode ("", "!tlabeldef", tlbl->key + 100);
6361                 }
6362             }
6363         }
6364       // bit = c
6365       // val = c
6366       if (size)
6367         outBitC (result);
6368       // if(bit | ...)
6369       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6370         genIfxJump (ifx, "c");
6371       goto release;
6372     }
6373
6374   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6375   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6376   if ((AOP_TYPE (right) == AOP_LIT) &&
6377       (AOP_TYPE (result) == AOP_CRY) &&
6378       (AOP_TYPE (left) != AOP_CRY))
6379     {
6380       if (lit)
6381         {
6382           // result = 1
6383           if (size)
6384             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6385           else
6386             continueIfTrue (ifx);
6387           goto release;
6388         }
6389       else
6390         {
6391           // lit = 0, result = boolean(left)
6392           if (size)
6393             emitcode ("setb", "c");
6394           toBoolean (right);
6395           if (size)
6396             {
6397               symbol *tlbl = newiTempLabel (NULL);
6398               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6399               CLRC;
6400               emitcode ("", "!tlabeldef", tlbl->key + 100);
6401             }
6402           else
6403             {
6404               genIfxJump (ifx, "a");
6405               goto release;
6406             }
6407         }
6408       outBitC (result);
6409       goto release;
6410     }
6411
6412   /* if left is same as result */
6413   if (sameRegs (AOP (result), AOP (left)))
6414     {
6415       for (; size--; offset++)
6416         {
6417           if (AOP_TYPE (right) == AOP_LIT)
6418             {
6419               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6420                 {
6421                   continue;
6422                 }
6423               else
6424                 {
6425                   if (IS_AOP_PREG (left))
6426                     {
6427                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6428                       emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6429                       aopPut (AOP (result), "a", offset);
6430                     }
6431                   else
6432                     {
6433                       emitcode ("orl", "%s,%s",
6434                             aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6435                          aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6436                     }
6437                 }
6438             }
6439           else
6440             {
6441               if (AOP_TYPE (left) == AOP_ACC)
6442                 {
6443                   emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6444                 }
6445               else
6446                 {
6447                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6448                   if (IS_AOP_PREG (left))
6449                     {
6450                       emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6451                       aopPut (AOP (result), "a", offset);
6452                     }
6453                   else
6454                     {
6455                       emitcode ("orl", "%s,a",
6456                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6457                     }
6458                 }
6459             }
6460         }
6461     }
6462   else
6463     {
6464       // left & result in different registers
6465       if (AOP_TYPE (result) == AOP_CRY)
6466         {
6467           // result = bit
6468           // if(size), result in bit
6469           // if(!size && ifx), conditional oper: if(left | right)
6470           symbol *tlbl = newiTempLabel (NULL);
6471           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6472           if (size)
6473             emitcode ("setb", "c");
6474           while (sizer--)
6475             {
6476               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6477                 emitcode ("orl", "a,%s",
6478                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6479               } else {
6480                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6481                 emitcode ("orl", "a,%s",
6482                           aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6483               }
6484               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6485               offset++;
6486             }
6487           if (size)
6488             {
6489               CLRC;
6490               emitcode ("", "!tlabeldef", tlbl->key + 100);
6491               outBitC (result);
6492             }
6493           else if (ifx)
6494             jmpTrueOrFalse (ifx, tlbl);
6495         }
6496       else
6497         {
6498             _startLazyDPSEvaluation();
6499           for (; (size--); offset++)
6500             {
6501               // normal case
6502               // result = left & right
6503               if (AOP_TYPE (right) == AOP_LIT)
6504                 {
6505                   if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6506                     {
6507                       aopPut (AOP (result),
6508                            aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6509                               offset);
6510                       continue;
6511                     }
6512                   D (emitcode (";", "better literal OR."););
6513                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6514                   emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
6515                                                     FALSE, FALSE, FALSE));
6516
6517                 }
6518               else
6519                 {
6520                   // faster than result <- left, anl result,right
6521                   // and better if result is SFR
6522                   if (AOP_TYPE (left) == AOP_ACC)
6523                     {
6524                       emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
6525                                                        FALSE, FALSE, FALSE));
6526                     }
6527                   else
6528                     {
6529                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6530                         
6531                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6532                       {
6533                           emitcode("mov", "b,a");
6534                           rOp = "b";
6535                       }
6536                         
6537                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6538                       emitcode ("orl", "a,%s", rOp);
6539                     }
6540                 }
6541               aopPut (AOP (result), "a", offset);
6542             }
6543             _endLazyDPSEvaluation();
6544         }
6545     }
6546
6547 release:
6548   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6549   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6550   freeAsmop (result, NULL, ic, TRUE);
6551 }
6552
6553 /*-----------------------------------------------------------------*/
6554 /* genXor - code for xclusive or                                   */
6555 /*-----------------------------------------------------------------*/
6556 static void
6557 genXor (iCode * ic, iCode * ifx)
6558 {
6559   operand *left, *right, *result;
6560   int size, offset = 0;
6561   unsigned long lit = 0L;
6562   bool pushResult;
6563
6564   D (emitcode (";", "genXor "););
6565
6566   AOP_OP_3_NOFATAL (ic, pushResult);
6567   AOP_SET_LOCALS (ic);
6568
6569   if (pushResult)
6570   {
6571       genFarFarLogicOp(ic, "xrl");
6572       return;
6573   }  
6574
6575 #ifdef DEBUG_TYPE
6576   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6577             AOP_TYPE (result),
6578             AOP_TYPE (left), AOP_TYPE (right));
6579   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6580             AOP_SIZE (result),
6581             AOP_SIZE (left), AOP_SIZE (right));
6582 #endif
6583
6584   /* if left is a literal & right is not ||
6585      if left needs acc & right does not */
6586   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) 
6587 #ifdef LOGIC_OPS_BROKEN      
6588       || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6589 #endif
6590      )
6591     {
6592       operand *tmp = right;
6593       right = left;
6594       left = tmp;
6595     }
6596
6597   /* if result = right then exchange them */
6598   if (sameRegs (AOP (result), AOP (right)))
6599     {
6600       operand *tmp = right;
6601       right = left;
6602       left = tmp;
6603     }
6604
6605   /* if right is bit then exchange them */
6606   if (AOP_TYPE (right) == AOP_CRY &&
6607       AOP_TYPE (left) != AOP_CRY)
6608     {
6609       operand *tmp = right;
6610       right = left;
6611       left = tmp;
6612     }
6613   if (AOP_TYPE (right) == AOP_LIT)
6614     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6615
6616   size = AOP_SIZE (result);
6617
6618   // if(bit ^ yy)
6619   // xx = bit ^ yy;
6620   if (AOP_TYPE (left) == AOP_CRY)
6621     {
6622       if (AOP_TYPE (right) == AOP_LIT)
6623         {
6624           // c = bit & literal;
6625           if (lit >> 1)
6626             {
6627               // lit>>1  != 0 => result = 1
6628               if (AOP_TYPE (result) == AOP_CRY)
6629                 {
6630                   if (size)
6631                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6632                   else if (ifx)
6633                     continueIfTrue (ifx);
6634                   goto release;
6635                 }
6636               emitcode ("setb", "c");
6637             }
6638           else
6639             {
6640               // lit == (0 or 1)
6641               if (lit == 0)
6642                 {
6643                   // lit == 0, result = left
6644                   if (size && sameRegs (AOP (result), AOP (left)))
6645                     goto release;
6646                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6647                 }
6648               else
6649                 {
6650                   // lit == 1, result = not(left)
6651                   if (size && sameRegs (AOP (result), AOP (left)))
6652                     {
6653                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6654                       goto release;
6655                     }
6656                   else
6657                     {
6658                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6659                       emitcode ("cpl", "c");
6660                     }
6661                 }
6662             }
6663
6664         }
6665       else
6666         {
6667           // right != literal
6668           symbol *tlbl = newiTempLabel (NULL);
6669           if (AOP_TYPE (right) == AOP_CRY)
6670             {
6671               // c = bit ^ bit;
6672               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6673             }
6674           else
6675             {
6676               int sizer = AOP_SIZE (right);
6677               // c = bit ^ val
6678               // if val>>1 != 0, result = 1
6679               emitcode ("setb", "c");
6680               while (sizer)
6681                 {
6682                   MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
6683                   if (sizer == 1)
6684                     // test the msb of the lsb
6685                     emitcode ("anl", "a,#!constbyte",0xfe);
6686                   emitcode ("jnz", "!tlabel", tlbl->key + 100);
6687                   sizer--;
6688                 }
6689               // val = (0,1)
6690               emitcode ("rrc", "a");
6691             }
6692           emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6693           emitcode ("cpl", "c");
6694           emitcode ("", "!tlabeldef", (tlbl->key + 100));
6695         }
6696       // bit = c
6697       // val = c
6698       if (size)
6699         outBitC (result);
6700       // if(bit | ...)
6701       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6702         genIfxJump (ifx, "c");
6703       goto release;
6704     }
6705
6706   if (sameRegs (AOP (result), AOP (left)))
6707     {
6708       /* if left is same as result */
6709       for (; size--; offset++)
6710         {
6711           if (AOP_TYPE (right) == AOP_LIT)
6712             {
6713               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6714                 continue;
6715               else if (IS_AOP_PREG (left))
6716                 {
6717                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6718                   emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6719                   aopPut (AOP (result), "a", offset);
6720                 }
6721               else
6722                 emitcode ("xrl", "%s,%s",
6723                           aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6724                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6725             }
6726           else
6727             {
6728               if (AOP_TYPE (left) == AOP_ACC)
6729                 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6730               else
6731                 {
6732                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6733                   if (IS_AOP_PREG (left))
6734                     {
6735                       emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6736                       aopPut (AOP (result), "a", offset);
6737                     }
6738                   else
6739                     emitcode ("xrl", "%s,a",
6740                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6741                 }
6742             }
6743         }
6744     }
6745   else
6746     {
6747       // left & result in different registers
6748       if (AOP_TYPE (result) == AOP_CRY)
6749         {
6750           // result = bit
6751           // if(size), result in bit
6752           // if(!size && ifx), conditional oper: if(left ^ right)
6753           symbol *tlbl = newiTempLabel (NULL);
6754           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6755                   
6756           if (size)
6757             emitcode ("setb", "c");
6758           while (sizer--)
6759             {
6760               if ((AOP_TYPE (right) == AOP_LIT) &&
6761                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6762                 {
6763                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6764                 }
6765               else
6766                 {
6767                   if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6768                     emitcode ("xrl", "a,%s",
6769                               aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6770                   } else {
6771                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6772                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6773                       {
6774                           emitcode("mov", "b,a");
6775                           rOp = "b";
6776                       }
6777                         
6778                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6779                       emitcode ("xrl", "a,%s", rOp);                  
6780                   }
6781                 }
6782               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6783               offset++;
6784             }
6785           if (size)
6786             {
6787               CLRC;
6788               emitcode ("", "!tlabeldef", tlbl->key + 100);
6789               outBitC (result);
6790             }
6791           else if (ifx)
6792             jmpTrueOrFalse (ifx, tlbl);
6793         }
6794       else
6795         {
6796         for (; (size--); offset++)
6797           {
6798             // normal case
6799             // result = left & right
6800             if (AOP_TYPE (right) == AOP_LIT)
6801               {
6802                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6803                   {
6804                     aopPut (AOP (result),
6805                             aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6806                             offset);
6807                     continue;
6808                   }
6809                 D (emitcode (";", "better literal XOR."););
6810                 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6811                 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
6812                                                   FALSE, FALSE, FALSE));
6813               }
6814             else
6815               {
6816                 // faster than result <- left, anl result,right
6817                 // and better if result is SFR
6818                 if (AOP_TYPE (left) == AOP_ACC)
6819                   {
6820                     emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
6821                                                      FALSE, FALSE, FALSE));
6822                   }
6823                 else
6824                   {
6825                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6826                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6827                       {
6828                           emitcode("mov", "b,a");
6829                           rOp = "b";
6830                       }
6831                         
6832                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6833                       emitcode ("xrl", "a,%s", rOp);
6834                   }
6835               }
6836             aopPut (AOP (result), "a", offset);
6837           }
6838         }
6839         
6840     }
6841
6842 release:
6843   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6844   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6845   freeAsmop (result, NULL, ic, TRUE);
6846 }
6847
6848 /*-----------------------------------------------------------------*/
6849 /* genInline - write the inline code out                           */
6850 /*-----------------------------------------------------------------*/
6851 static void
6852 genInline (iCode * ic)
6853 {
6854   char *buffer, *bp, *bp1;
6855
6856   D (emitcode (";", "genInline ");
6857     );
6858
6859   _G.inLine += (!options.asmpeep);
6860
6861   buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6862   strcpy (buffer, IC_INLINE (ic));
6863
6864   /* emit each line as a code */
6865   while (*bp)
6866     {
6867       if (*bp == '\n')
6868         {
6869           *bp++ = '\0';
6870           emitcode (bp1, "");
6871           bp1 = bp;
6872         }
6873       else
6874         {
6875           if (*bp == ':')
6876             {
6877               bp++;
6878               *bp = '\0';
6879               bp++;
6880               emitcode (bp1, "");
6881               bp1 = bp;
6882             }
6883           else
6884             bp++;
6885         }
6886     }
6887   if (bp1 != bp)
6888     emitcode (bp1, "");
6889   /*     emitcode("",buffer); */
6890   _G.inLine -= (!options.asmpeep);
6891 }
6892
6893 /*-----------------------------------------------------------------*/
6894 /* genRRC - rotate right with carry                                */
6895 /*-----------------------------------------------------------------*/
6896 static void
6897 genRRC (iCode * ic)
6898 {
6899   operand *left, *result;
6900   int size, offset = 0;
6901   char *l;
6902
6903   D (emitcode (";", "genRRC ");
6904     );
6905
6906   /* rotate right with carry */
6907   left = IC_LEFT (ic);
6908   result = IC_RESULT (ic);
6909   aopOp (left, ic, FALSE, FALSE);
6910   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6911
6912   /* move it to the result */
6913   size = AOP_SIZE (result);
6914   offset = size - 1;
6915   CLRC;
6916
6917   _startLazyDPSEvaluation ();
6918   while (size--)
6919     {
6920       l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6921       MOVA (l);
6922       emitcode ("rrc", "a");
6923       if (AOP_SIZE (result) > 1)
6924         aopPut (AOP (result), "a", offset--);
6925     }
6926   _endLazyDPSEvaluation ();
6927
6928   /* now we need to put the carry into the
6929      highest order byte of the result */
6930   if (AOP_SIZE (result) > 1)
6931     {
6932       l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
6933       MOVA (l);
6934     }
6935   emitcode ("mov", "acc.7,c");
6936   aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
6937   freeAsmop (left, NULL, ic, TRUE);
6938   freeAsmop (result, NULL, ic, TRUE);
6939 }
6940
6941 /*-----------------------------------------------------------------*/
6942 /* genRLC - generate code for rotate left with carry               */
6943 /*-----------------------------------------------------------------*/
6944 static void
6945 genRLC (iCode * ic)
6946 {
6947   operand *left, *result;
6948   int size, offset = 0;
6949   char *l;
6950
6951   D (emitcode (";", "genRLC ");
6952     );
6953
6954   /* rotate right with carry */
6955   left = IC_LEFT (ic);
6956   result = IC_RESULT (ic);
6957   aopOp (left, ic, FALSE, FALSE);
6958   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6959
6960   /* move it to the result */
6961   size = AOP_SIZE (result);
6962   offset = 0;
6963   if (size--)
6964     {
6965       l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6966       MOVA (l);
6967       emitcode ("add", "a,acc");
6968       if (AOP_SIZE (result) > 1)
6969         {
6970           aopPut (AOP (result), "a", offset++);
6971         }
6972
6973       _startLazyDPSEvaluation ();
6974       while (size--)
6975         {
6976           l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6977           MOVA (l);
6978           emitcode ("rlc", "a");
6979           if (AOP_SIZE (result) > 1)
6980             aopPut (AOP (result), "a", offset++);
6981         }
6982       _endLazyDPSEvaluation ();
6983     }
6984   /* now we need to put the carry into the
6985      highest order byte of the result */
6986   if (AOP_SIZE (result) > 1)
6987     {
6988       l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
6989       MOVA (l);
6990     }
6991   emitcode ("mov", "acc.0,c");
6992   aopPut (AOP (result), "a", 0);
6993   freeAsmop (left, NULL, ic, TRUE);
6994   freeAsmop (result, NULL, ic, TRUE);
6995 }
6996
6997 /*-----------------------------------------------------------------*/
6998 /* genGetHbit - generates code get highest order bit               */
6999 /*-----------------------------------------------------------------*/
7000 static void
7001 genGetHbit (iCode * ic)
7002 {
7003   operand *left, *result;
7004   left = IC_LEFT (ic);
7005   result = IC_RESULT (ic);
7006   aopOp (left, ic, FALSE, FALSE);
7007   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7008
7009   D (emitcode (";", "genGetHbit ");
7010     );
7011
7012   /* get the highest order byte into a */
7013   MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
7014   if (AOP_TYPE (result) == AOP_CRY)
7015     {
7016       emitcode ("rlc", "a");
7017       outBitC (result);
7018     }
7019   else
7020     {
7021       emitcode ("rl", "a");
7022       emitcode ("anl", "a,#1");
7023       outAcc (result);
7024     }
7025
7026
7027   freeAsmop (left, NULL, ic, TRUE);
7028   freeAsmop (result, NULL, ic, TRUE);
7029 }
7030
7031 /*-----------------------------------------------------------------*/
7032 /* AccRol - rotate left accumulator by known count                 */
7033 /*-----------------------------------------------------------------*/
7034 static void
7035 AccRol (int shCount)
7036 {
7037   shCount &= 0x0007;            // shCount : 0..7
7038
7039   switch (shCount)
7040     {
7041     case 0:
7042       break;
7043     case 1:
7044       emitcode ("rl", "a");
7045       break;
7046     case 2:
7047       emitcode ("rl", "a");
7048       emitcode ("rl", "a");
7049       break;
7050     case 3:
7051       emitcode ("swap", "a");
7052       emitcode ("rr", "a");
7053       break;
7054     case 4:
7055       emitcode ("swap", "a");
7056       break;
7057     case 5:
7058       emitcode ("swap", "a");
7059       emitcode ("rl", "a");
7060       break;
7061     case 6:
7062       emitcode ("rr", "a");
7063       emitcode ("rr", "a");
7064       break;
7065     case 7:
7066       emitcode ("rr", "a");
7067       break;
7068     }
7069 }
7070
7071 /*-----------------------------------------------------------------*/
7072 /* AccLsh - left shift accumulator by known count                  */
7073 /*-----------------------------------------------------------------*/
7074 static void
7075 AccLsh (int shCount)
7076 {
7077   if (shCount != 0)
7078     {
7079       if (shCount == 1)
7080         emitcode ("add", "a,acc");
7081       else if (shCount == 2)
7082         {
7083           emitcode ("add", "a,acc");
7084           emitcode ("add", "a,acc");
7085         }
7086       else
7087         {
7088           /* rotate left accumulator */
7089           AccRol (shCount);
7090           /* and kill the lower order bits */
7091           emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7092         }
7093     }
7094 }
7095
7096 /*-----------------------------------------------------------------*/
7097 /* AccRsh - right shift accumulator by known count                 */
7098 /*-----------------------------------------------------------------*/
7099 static void
7100 AccRsh (int shCount)
7101 {
7102   if (shCount != 0)
7103     {
7104       if (shCount == 1)
7105         {
7106           CLRC;
7107           emitcode ("rrc", "a");
7108         }
7109       else
7110         {
7111           /* rotate right accumulator */
7112           AccRol (8 - shCount);
7113           /* and kill the higher order bits */
7114           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7115         }
7116     }
7117 }
7118
7119 #ifdef BETTER_LITERAL_SHIFT
7120 /*-----------------------------------------------------------------*/
7121 /* AccSRsh - signed right shift accumulator by known count                 */
7122 /*-----------------------------------------------------------------*/
7123 static void
7124 AccSRsh (int shCount)
7125 {
7126   symbol *tlbl;
7127   if (shCount != 0)
7128     {
7129       if (shCount == 1)
7130         {
7131           emitcode ("mov", "c,acc.7");
7132           emitcode ("rrc", "a");
7133         }
7134       else if (shCount == 2)
7135         {
7136           emitcode ("mov", "c,acc.7");
7137           emitcode ("rrc", "a");
7138           emitcode ("mov", "c,acc.7");
7139           emitcode ("rrc", "a");
7140         }
7141       else
7142         {
7143           tlbl = newiTempLabel (NULL);
7144           /* rotate right accumulator */
7145           AccRol (8 - shCount);
7146           /* and kill the higher order bits */
7147           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7148           emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7149           emitcode ("orl", "a,#!constbyte",
7150                     (unsigned char) ~SRMask[shCount]);
7151           emitcode ("", "!tlabeldef", tlbl->key + 100);
7152         }
7153     }
7154 }
7155 #endif
7156
7157 #ifdef BETTER_LITERAL_SHIFT
7158 /*-----------------------------------------------------------------*/
7159 /* shiftR1Left2Result - shift right one byte from left to result   */
7160 /*-----------------------------------------------------------------*/
7161 static void
7162 shiftR1Left2Result (operand * left, int offl,
7163                     operand * result, int offr,
7164                     int shCount, int sign)
7165 {
7166   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7167   /* shift right accumulator */
7168   if (sign)
7169     AccSRsh (shCount);
7170   else
7171     AccRsh (shCount);
7172   aopPut (AOP (result), "a", offr);
7173 }
7174 #endif
7175
7176 #ifdef BETTER_LITERAL_SHIFT
7177 /*-----------------------------------------------------------------*/
7178 /* shiftL1Left2Result - shift left one byte from left to result    */
7179 /*-----------------------------------------------------------------*/
7180 static void
7181 shiftL1Left2Result (operand * left, int offl,
7182                     operand * result, int offr, int shCount)
7183 {
7184   MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7185   /* shift left accumulator */
7186   AccLsh (shCount);
7187   aopPut (AOP (result), "a", offr);
7188 }
7189 #endif
7190
7191 #ifdef BETTER_LITERAL_SHIFT
7192 /*-----------------------------------------------------------------*/
7193 /* movLeft2Result - move byte from left to result                  */
7194 /*-----------------------------------------------------------------*/
7195 static void
7196 movLeft2Result (operand * left, int offl,
7197                 operand * result, int offr, int sign)
7198 {
7199   char *l;
7200   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7201   {
7202       l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
7203
7204       if (*l == '@' && (IS_AOP_PREG (result)))
7205       {
7206           emitcode ("mov", "a,%s", l);
7207           aopPut (AOP (result), "a", offr);
7208       }
7209       else
7210       {
7211           if (!sign)
7212           {
7213             aopPut (AOP (result), l, offr);
7214           }
7215           else
7216             {
7217               /* MSB sign in acc.7 ! */
7218               if (getDataSize (left) == offl + 1)
7219                 {
7220                   emitcode ("mov", "a,%s", l);
7221                   aopPut (AOP (result), "a", offr);
7222                 }
7223             }
7224       }
7225   }
7226 }
7227 #endif
7228
7229 #ifdef BETTER_LITERAL_SHIFT
7230 /*-----------------------------------------------------------------*/
7231 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
7232 /*-----------------------------------------------------------------*/
7233 static void
7234 AccAXRrl1 (char *x)
7235 {
7236   emitcode ("rrc", "a");
7237   emitcode ("xch", "a,%s", x);
7238   emitcode ("rrc", "a");
7239   emitcode ("xch", "a,%s", x);
7240 }
7241 #endif
7242
7243 #ifdef BETTER_LITERAL_SHIFT
7244 //REMOVE ME!!!
7245 /*-----------------------------------------------------------------*/
7246 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
7247 /*-----------------------------------------------------------------*/
7248 static void
7249 AccAXLrl1 (char *x)
7250 {
7251   emitcode ("xch", "a,%s", x);
7252   emitcode ("rlc", "a");
7253   emitcode ("xch", "a,%s", x);
7254   emitcode ("rlc", "a");
7255 }
7256 #endif
7257
7258 #ifdef BETTER_LITERAL_SHIFT
7259 /*-----------------------------------------------------------------*/
7260 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
7261 /*-----------------------------------------------------------------*/
7262 static void
7263 AccAXLsh1 (char *x)
7264 {
7265   emitcode ("xch", "a,%s", x);
7266   emitcode ("add", "a,acc");
7267   emitcode ("xch", "a,%s", x);
7268   emitcode ("rlc", "a");
7269 }
7270 #endif
7271
7272 #ifdef BETTER_LITERAL_SHIFT
7273 /*-----------------------------------------------------------------*/
7274 /* AccAXLsh - left shift a:x by known count (0..7)                 */
7275 /*-----------------------------------------------------------------*/
7276 static void
7277 AccAXLsh (char *x, int shCount)
7278 {
7279   switch (shCount)
7280     {
7281     case 0:
7282       break;
7283     case 1:
7284       AccAXLsh1 (x);
7285       break;
7286     case 2:
7287       AccAXLsh1 (x);
7288       AccAXLsh1 (x);
7289       break;
7290     case 3:
7291     case 4:
7292     case 5:                     // AAAAABBB:CCCCCDDD
7293
7294       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
7295
7296       emitcode ("anl", "a,#!constbyte",
7297                 SLMask[shCount]);       // BBB00000:CCCCCDDD
7298
7299       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
7300
7301       AccRol (shCount);         // DDDCCCCC:BBB00000
7302
7303       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
7304
7305       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
7306
7307       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
7308
7309       emitcode ("anl", "a,#!constbyte",
7310                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
7311
7312       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
7313
7314       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
7315
7316       break;
7317     case 6:                     // AAAAAABB:CCCCCCDD
7318       emitcode ("anl", "a,#!constbyte",
7319                 SRMask[shCount]);       // 000000BB:CCCCCCDD
7320       emitcode ("mov", "c,acc.0");      // c = B
7321       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
7322 #if 0
7323       AccAXRrl1 (x);            // BCCCCCCD:D000000B
7324       AccAXRrl1 (x);            // BBCCCCCC:DD000000
7325 #else
7326       emitcode("rrc","a"); 
7327       emitcode("xch","a,%s", x); 
7328       emitcode("rrc","a"); 
7329       emitcode("mov","c,acc.0"); //<< get correct bit 
7330       emitcode("xch","a,%s", x); 
7331
7332       emitcode("rrc","a"); 
7333       emitcode("xch","a,%s", x); 
7334       emitcode("rrc","a"); 
7335       emitcode("xch","a,%s", x); 
7336 #endif
7337       break;
7338     case 7:                     // a:x <<= 7
7339
7340       emitcode ("anl", "a,#!constbyte",
7341                 SRMask[shCount]);       // 0000000B:CCCCCCCD
7342
7343       emitcode ("mov", "c,acc.0");      // c = B
7344
7345       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
7346
7347       AccAXRrl1 (x);            // BCCCCCCC:D0000000
7348
7349       break;
7350     default:
7351       break;
7352     }
7353 }
7354 #endif
7355
7356 #ifdef BETTER_LITERAL_SHIFT
7357 //REMOVE ME!!!
7358 /*-----------------------------------------------------------------*/
7359 /* AccAXRsh - right shift a:x known count (0..7)                   */
7360 /*-----------------------------------------------------------------*/
7361 static void
7362 AccAXRsh (char *x, int shCount)
7363 {
7364   switch (shCount)
7365     {
7366     case 0:
7367       break;
7368     case 1:
7369       CLRC;
7370       AccAXRrl1 (x);            // 0->a:x
7371
7372       break;
7373     case 2:
7374       CLRC;
7375       AccAXRrl1 (x);            // 0->a:x
7376
7377       CLRC;
7378       AccAXRrl1 (x);            // 0->a:x
7379
7380       break;
7381     case 3:
7382     case 4:
7383     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7384
7385       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
7386
7387       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7388
7389       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7390
7391       emitcode ("anl", "a,#!constbyte",
7392                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7393
7394       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7395
7396       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7397
7398       emitcode ("anl", "a,#!constbyte",
7399                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7400
7401       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7402
7403       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7404
7405       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
7406
7407       break;
7408     case 6:                     // AABBBBBB:CCDDDDDD
7409
7410       emitcode ("mov", "c,acc.7");
7411       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7412
7413       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7414
7415       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7416
7417       emitcode ("anl", "a,#!constbyte",
7418                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7419
7420       break;
7421     case 7:                     // ABBBBBBB:CDDDDDDD
7422
7423       emitcode ("mov", "c,acc.7");      // c = A
7424
7425       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7426
7427       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7428
7429       emitcode ("anl", "a,#!constbyte",
7430                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7431
7432       break;
7433     default:
7434       break;
7435     }
7436 }
7437 #endif
7438
7439 #ifdef BETTER_LITERAL_SHIFT
7440 /*-----------------------------------------------------------------*/
7441 /* AccAXRshS - right shift signed a:x known count (0..7)           */
7442 /*-----------------------------------------------------------------*/
7443 static void
7444 AccAXRshS (char *x, int shCount)
7445 {
7446   symbol *tlbl;
7447   switch (shCount)
7448     {
7449     case 0:
7450       break;
7451     case 1:
7452       emitcode ("mov", "c,acc.7");
7453       AccAXRrl1 (x);            // s->a:x
7454
7455       break;
7456     case 2:
7457       emitcode ("mov", "c,acc.7");
7458       AccAXRrl1 (x);            // s->a:x
7459
7460       emitcode ("mov", "c,acc.7");
7461       AccAXRrl1 (x);            // s->a:x
7462
7463       break;
7464     case 3:
7465     case 4:
7466     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7467
7468       tlbl = newiTempLabel (NULL);
7469       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
7470
7471       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7472
7473       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7474
7475       emitcode ("anl", "a,#!constbyte",
7476                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7477
7478       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7479
7480       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7481
7482       emitcode ("anl", "a,#!constbyte",
7483                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7484
7485       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7486
7487       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7488
7489       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
7490
7491       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7492       emitcode ("orl", "a,#!constbyte",
7493                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
7494
7495       emitcode ("", "!tlabeldef", tlbl->key + 100);
7496       break;                    // SSSSAAAA:BBBCCCCC
7497
7498     case 6:                     // AABBBBBB:CCDDDDDD
7499
7500       tlbl = newiTempLabel (NULL);
7501       emitcode ("mov", "c,acc.7");
7502       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7503
7504       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7505
7506       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7507
7508       emitcode ("anl", "a,#!constbyte",
7509                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7510
7511       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7512       emitcode ("orl", "a,#!constbyte",
7513                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
7514
7515       emitcode ("", "!tlabeldef", tlbl->key + 100);
7516       break;
7517     case 7:                     // ABBBBBBB:CDDDDDDD
7518
7519       tlbl = newiTempLabel (NULL);
7520       emitcode ("mov", "c,acc.7");      // c = A
7521
7522       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7523
7524       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7525
7526       emitcode ("anl", "a,#!constbyte",
7527                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7528
7529       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7530       emitcode ("orl", "a,#!constbyte",
7531                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
7532
7533       emitcode ("", "!tlabeldef", tlbl->key + 100);
7534       break;
7535     default:
7536       break;
7537     }
7538 }
7539 #endif
7540
7541 #ifdef BETTER_LITERAL_SHIFT
7542 static void
7543 _loadLeftIntoAx(char    **lsb, 
7544                 operand *left, 
7545                 operand *result,
7546                 int     offl,
7547                 int     offr)
7548 {
7549   // Get the initial value from left into a pair of registers.
7550   // MSB must be in A, LSB can be any register.
7551   //
7552   // If the result is held in registers, it is an optimization
7553   // if the LSB can be held in the register which will hold the,
7554   // result LSB since this saves us from having to copy it into
7555   // the result following AccAXLsh.
7556   //
7557   // If the result is addressed indirectly, this is not a gain.
7558   if (AOP_NEEDSACC(result))
7559   {
7560        char *leftByte;
7561        
7562        _startLazyDPSEvaluation();
7563       if (AOP_TYPE(left) == AOP_DPTR2)
7564        {
7565            // Get MSB in A.
7566            MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
7567            // get LSB in DP2_RESULT_REG.
7568            leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
7569            assert(!strcmp(leftByte, DP2_RESULT_REG));
7570        }
7571        else
7572        {
7573            // get LSB into DP2_RESULT_REG
7574            leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
7575            if (strcmp(leftByte, DP2_RESULT_REG))
7576            {
7577                TR_AP("#7");
7578                emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7579            }
7580            // And MSB in A.
7581            leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
7582            assert(strcmp(leftByte, DP2_RESULT_REG));
7583            MOVA(leftByte);
7584        }
7585        _endLazyDPSEvaluation();
7586        *lsb = DP2_RESULT_REG;
7587   }
7588   else
7589   {
7590       if (sameRegs (AOP (result), AOP (left)) &&
7591         ((offl + MSB16) == offr))
7592       {
7593           /* don't crash result[offr] */
7594           MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
7595           emitcode ("xch", "a,%s", 
7596                     aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
7597       }
7598       else
7599       {
7600           movLeft2Result (left, offl, result, offr, 0);
7601           MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
7602       }
7603       *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
7604       assert(strcmp(*lsb,"a"));      
7605   }
7606 }
7607
7608 static void
7609 _storeAxResults(char    *lsb,
7610                 operand *result,
7611                 int     offr)
7612 {
7613   _startLazyDPSEvaluation();
7614   if (AOP_NEEDSACC(result))
7615   {
7616       /* We have to explicitly update the result LSB.
7617        */
7618       emitcode("xch","a,%s", lsb);
7619       aopPut(AOP(result), "a", offr);
7620       emitcode("mov","a,%s", lsb);
7621   }
7622   if (getDataSize (result) > 1)
7623   {
7624       aopPut (AOP (result), "a", offr + MSB16);
7625   }
7626   _endLazyDPSEvaluation();
7627 }
7628
7629 /*-----------------------------------------------------------------*/
7630 /* shiftL2Left2Result - shift left two bytes from left to result   */
7631 /*-----------------------------------------------------------------*/
7632 static void
7633 shiftL2Left2Result (operand * left, int offl,
7634                     operand * result, int offr, int shCount)
7635 {
7636   char *lsb;
7637
7638   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7639   
7640   AccAXLsh (lsb, shCount);
7641   
7642   _storeAxResults(lsb, result, offr);
7643 }
7644 #endif
7645
7646 #ifdef BETTER_LITERAL_SHIFT
7647 /*-----------------------------------------------------------------*/
7648 /* shiftR2Left2Result - shift right two bytes from left to result  */
7649 /*-----------------------------------------------------------------*/
7650 static void
7651 shiftR2Left2Result (operand * left, int offl,
7652                     operand * result, int offr,
7653                     int shCount, int sign)
7654 {
7655   char *lsb;
7656   
7657   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7658   
7659   /* a:x >> shCount (x = lsb(result)) */
7660   if (sign)
7661   {
7662      AccAXRshS(lsb, shCount);
7663   }
7664   else
7665   {
7666     AccAXRsh(lsb, shCount);
7667   }
7668   
7669   _storeAxResults(lsb, result, offr);
7670 }
7671 #endif
7672
7673 #if 0
7674 //REMOVE ME!!!
7675 /*-----------------------------------------------------------------*/
7676 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7677 /*-----------------------------------------------------------------*/
7678 static void
7679 shiftLLeftOrResult (operand * left, int offl,
7680                     operand * result, int offr, int shCount)
7681 {
7682   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7683   /* shift left accumulator */
7684   AccLsh (shCount);
7685   /* or with result */
7686   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7687   /* back to result */
7688   aopPut (AOP (result), "a", offr);
7689 }
7690 #endif
7691
7692 #if 0
7693 //REMOVE ME!!!
7694 /*-----------------------------------------------------------------*/
7695 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7696 /*-----------------------------------------------------------------*/
7697 static void
7698 shiftRLeftOrResult (operand * left, int offl,
7699                     operand * result, int offr, int shCount)
7700 {
7701   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7702   /* shift right accumulator */
7703   AccRsh (shCount);
7704   /* or with result */
7705   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7706   /* back to result */
7707   aopPut (AOP (result), "a", offr);
7708 }
7709 #endif
7710
7711 #ifdef BETTER_LITERAL_SHIFT
7712 /*-----------------------------------------------------------------*/
7713 /* genlshOne - left shift a one byte quantity by known count       */
7714 /*-----------------------------------------------------------------*/
7715 static void
7716 genlshOne (operand * result, operand * left, int shCount)
7717 {
7718   D (emitcode (";", "genlshOne "););
7719   shiftL1Left2Result (left, LSB, result, LSB, shCount);
7720 }
7721 #endif
7722
7723 #ifdef BETTER_LITERAL_SHIFT
7724 /*-----------------------------------------------------------------*/
7725 /* genlshTwo - left shift two bytes by known amount != 0           */
7726 /*-----------------------------------------------------------------*/
7727 static void
7728 genlshTwo (operand * result, operand * left, int shCount)
7729 {
7730   int size;
7731
7732   D (emitcode (";", "genlshTwo "););
7733
7734   size = getDataSize (result);
7735
7736   /* if shCount >= 8 */
7737   if (shCount >= 8)
7738   {
7739       shCount -= 8;
7740
7741       _startLazyDPSEvaluation();
7742
7743       if (size > 1)
7744         {
7745           if (shCount)
7746           {
7747             _endLazyDPSEvaluation();
7748             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7749             aopPut (AOP (result), zero, LSB);       
7750           }
7751           else
7752           {
7753             movLeft2Result (left, LSB, result, MSB16, 0);
7754             aopPut (AOP (result), zero, LSB);
7755             _endLazyDPSEvaluation();
7756           }
7757         }
7758         else
7759         {
7760           aopPut (AOP (result), zero, LSB);
7761           _endLazyDPSEvaluation();
7762         }
7763   }
7764
7765   /*  1 <= shCount <= 7 */
7766   else
7767     {
7768       if (size == 1)
7769       {
7770         shiftL1Left2Result (left, LSB, result, LSB, shCount);
7771       }
7772       else
7773       {
7774         shiftL2Left2Result (left, LSB, result, LSB, shCount);
7775       }
7776     }
7777 }
7778 #endif
7779
7780 #if 0
7781 //REMOVE ME!!!
7782 /*-----------------------------------------------------------------*/
7783 /* shiftLLong - shift left one long from left to result            */
7784 /* offl = LSB or MSB16                                             */
7785 /*-----------------------------------------------------------------*/
7786 static void
7787 shiftLLong (operand * left, operand * result, int offr)
7788 {
7789   char *l;
7790   int size = AOP_SIZE (result);
7791
7792   if (size >= LSB + offr)
7793     {
7794       l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
7795       MOVA (l);
7796       emitcode ("add", "a,acc");
7797       if (sameRegs (AOP (left), AOP (result)) &&
7798           size >= MSB16 + offr && offr != LSB)
7799         emitcode ("xch", "a,%s",
7800                   aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
7801       else
7802         aopPut (AOP (result), "a", LSB + offr);
7803     }
7804
7805   if (size >= MSB16 + offr)
7806     {
7807       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7808         {
7809           l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
7810           MOVA (l);
7811         }
7812       emitcode ("rlc", "a");
7813       if (sameRegs (AOP (left), AOP (result)) &&
7814           size >= MSB24 + offr && offr != LSB)
7815         emitcode ("xch", "a,%s",
7816                   aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
7817       else
7818         aopPut (AOP (result), "a", MSB16 + offr);
7819     }
7820
7821   if (size >= MSB24 + offr)
7822     {
7823       if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7824         {
7825           l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
7826           MOVA (l);
7827         }
7828       emitcode ("rlc", "a");
7829       if (sameRegs (AOP (left), AOP (result)) &&
7830           size >= MSB32 + offr && offr != LSB)
7831         emitcode ("xch", "a,%s",
7832                   aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
7833       else
7834         aopPut (AOP (result), "a", MSB24 + offr);
7835     }
7836
7837   if (size > MSB32 + offr)
7838     {
7839       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7840         {
7841           l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
7842           MOVA (l);
7843         }
7844       emitcode ("rlc", "a");
7845       aopPut (AOP (result), "a", MSB32 + offr);
7846     }
7847   if (offr != LSB)
7848     aopPut (AOP (result), zero, LSB);
7849 }
7850 #endif
7851
7852 #if 0
7853 //REMOVE ME!!!
7854 /*-----------------------------------------------------------------*/
7855 /* genlshFour - shift four byte by a known amount != 0             */
7856 /*-----------------------------------------------------------------*/
7857 static void
7858 genlshFour (operand * result, operand * left, int shCount)
7859 {
7860   int size;
7861
7862   D (emitcode (";", "genlshFour ");
7863     );
7864
7865   size = AOP_SIZE (result);
7866
7867   /* if shifting more that 3 bytes */
7868   if (shCount >= 24)
7869     {
7870       shCount -= 24;
7871       if (shCount)
7872         /* lowest order of left goes to the highest
7873            order of the destination */
7874         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7875       else
7876         movLeft2Result (left, LSB, result, MSB32, 0);
7877       aopPut (AOP (result), zero, LSB);
7878       aopPut (AOP (result), zero, MSB16);
7879       aopPut (AOP (result), zero, MSB24);
7880       return;
7881     }
7882
7883   /* more than two bytes */
7884   else if (shCount >= 16)
7885     {
7886       /* lower order two bytes goes to higher order two bytes */
7887       shCount -= 16;
7888       /* if some more remaining */
7889       if (shCount)
7890         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7891       else
7892         {
7893           movLeft2Result (left, MSB16, result, MSB32, 0);
7894           movLeft2Result (left, LSB, result, MSB24, 0);
7895         }
7896       aopPut (AOP (result), zero, MSB16);
7897       aopPut (AOP (result), zero, LSB);
7898       return;
7899     }
7900
7901   /* if more than 1 byte */
7902   else if (shCount >= 8)
7903     {
7904       /* lower order three bytes goes to higher order  three bytes */
7905       shCount -= 8;
7906       if (size == 2)
7907         {
7908           if (shCount)
7909             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7910           else
7911             movLeft2Result (left, LSB, result, MSB16, 0);
7912         }
7913       else
7914         {                       /* size = 4 */
7915           if (shCount == 0)
7916             {
7917               movLeft2Result (left, MSB24, result, MSB32, 0);
7918               movLeft2Result (left, MSB16, result, MSB24, 0);
7919               movLeft2Result (left, LSB, result, MSB16, 0);
7920               aopPut (AOP (result), zero, LSB);
7921             }
7922           else if (shCount == 1)
7923             shiftLLong (left, result, MSB16);
7924           else
7925             {
7926               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7927               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7928               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7929               aopPut (AOP (result), zero, LSB);
7930             }
7931         }
7932     }
7933
7934   /* 1 <= shCount <= 7 */
7935   else if (shCount <= 2)
7936     {
7937       shiftLLong (left, result, LSB);
7938       if (shCount == 2)
7939         shiftLLong (result, result, LSB);
7940     }
7941   /* 3 <= shCount <= 7, optimize */
7942   else
7943     {
7944       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7945       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7946       shiftL2Left2Result (left, LSB, result, LSB, shCount);
7947     }
7948 }
7949 #endif
7950
7951 #ifdef BETTER_LITERAL_SHIFT
7952 /*-----------------------------------------------------------------*/
7953 /* genLeftShiftLiteral - left shifting by known count              */
7954 /*-----------------------------------------------------------------*/
7955 static bool
7956 genLeftShiftLiteral (operand * left,
7957                      operand * right,
7958                      operand * result,
7959                      iCode * ic)
7960 {
7961   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7962   int size;
7963
7964   size = getSize (operandType (result));
7965
7966   D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
7967
7968   /* We only handle certain easy cases so far. */
7969   if ((shCount != 0)
7970    && (shCount < (size * 8))
7971    && (size != 1)
7972    && (size != 2))
7973   {
7974       D(emitcode (";", "genLeftShiftLiteral wimping out"););    
7975       return FALSE;
7976   }
7977
7978   freeAsmop (right, NULL, ic, TRUE);
7979
7980   aopOp(left, ic, FALSE, FALSE);
7981   aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
7982
7983 #if 0 // debug spew
7984   if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
7985   {
7986         emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
7987         if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
7988         {
7989            emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
7990         }
7991   }
7992   if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
7993   {
7994         emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
7995         if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
7996         {
7997            emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
7998         }       
7999   }  
8000 #endif
8001   
8002 #if VIEW_SIZE
8003   emitcode ("; shift left ", "result %d, left %d", size,
8004             AOP_SIZE (left));
8005 #endif
8006
8007   /* I suppose that the left size >= result size */
8008   if (shCount == 0)
8009   {
8010         _startLazyDPSEvaluation();
8011         while (size--)
8012         {
8013           movLeft2Result (left, size, result, size, 0);
8014         }
8015         _endLazyDPSEvaluation();
8016   }
8017   else if (shCount >= (size * 8))
8018   {
8019     _startLazyDPSEvaluation();
8020     while (size--)
8021     {
8022       aopPut (AOP (result), zero, size);
8023     }
8024     _endLazyDPSEvaluation();
8025   }
8026   else
8027   {
8028       switch (size)
8029         {
8030         case 1:
8031           genlshOne (result, left, shCount);
8032           break;
8033
8034         case 2:
8035           genlshTwo (result, left, shCount);
8036           break;
8037 #if 0
8038         case 4:
8039           genlshFour (result, left, shCount);
8040           break;
8041 #endif
8042         default:
8043           fprintf(stderr, "*** ack! mystery literal shift!\n");   
8044           break;
8045         }
8046     }
8047   freeAsmop (left, NULL, ic, TRUE);
8048   freeAsmop (result, NULL, ic, TRUE);
8049   return TRUE;
8050 }
8051 #endif
8052
8053 /*-----------------------------------------------------------------*/
8054 /* genLeftShift - generates code for left shifting                 */
8055 /*-----------------------------------------------------------------*/
8056 static void
8057 genLeftShift (iCode * ic)
8058 {
8059   operand *left, *right, *result;
8060   int size, offset;
8061   char *l;
8062   symbol *tlbl, *tlbl1;
8063
8064   D (emitcode (";", "genLeftShift "););
8065
8066   right = IC_RIGHT (ic);
8067   left = IC_LEFT (ic);
8068   result = IC_RESULT (ic);
8069
8070   aopOp (right, ic, FALSE, FALSE);
8071
8072
8073 #ifdef BETTER_LITERAL_SHIFT
8074   /* if the shift count is known then do it
8075      as efficiently as possible */
8076   if (AOP_TYPE (right) == AOP_LIT)
8077     {
8078       if (genLeftShiftLiteral (left, right, result, ic))
8079       {
8080         return;
8081       }
8082     }
8083 #endif
8084
8085   /* shift count is unknown then we have to form
8086      a loop get the loop count in B : Note: we take
8087      only the lower order byte since shifting
8088      more that 32 bits make no sense anyway, ( the
8089      largest size of an object can be only 32 bits ) */
8090
8091   if (AOP_TYPE (right) == AOP_LIT)
8092   {
8093       /* Really should be handled by genLeftShiftLiteral,
8094        * but since I'm too lazy to fix that today, at least we can make
8095        * some small improvement.
8096        */
8097        emitcode("mov", "b,#!constbyte",
8098                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8099   }
8100   else
8101   {
8102         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8103         emitcode ("inc", "b");
8104   }
8105   freeAsmop (right, NULL, ic, TRUE);
8106   aopOp (left, ic, FALSE, FALSE);
8107   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8108
8109   /* now move the left to the result if they are not the
8110      same */
8111   if (!sameRegs (AOP (left), AOP (result)) &&
8112       AOP_SIZE (result) > 1)
8113     {
8114
8115       size = AOP_SIZE (result);
8116       offset = 0;
8117       _startLazyDPSEvaluation ();
8118       while (size--)
8119         {
8120           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8121           if (*l == '@' && (IS_AOP_PREG (result)))
8122             {
8123
8124               emitcode ("mov", "a,%s", l);
8125               aopPut (AOP (result), "a", offset);
8126             }
8127           else
8128             aopPut (AOP (result), l, offset);
8129           offset++;
8130         }
8131       _endLazyDPSEvaluation ();
8132     }
8133
8134   tlbl = newiTempLabel (NULL);
8135   size = AOP_SIZE (result);
8136   offset = 0;
8137   tlbl1 = newiTempLabel (NULL);
8138
8139   /* if it is only one byte then */
8140   if (size == 1)
8141     {
8142       symbol *tlbl1 = newiTempLabel (NULL);
8143
8144       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8145       MOVA (l);
8146       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8147       emitcode ("", "!tlabeldef", tlbl->key + 100);
8148       emitcode ("add", "a,acc");
8149       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8150       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8151       aopPut (AOP (result), "a", 0);
8152       goto release;
8153     }
8154
8155   reAdjustPreg (AOP (result));
8156
8157   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8158   emitcode ("", "!tlabeldef", tlbl->key + 100);
8159   l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8160   MOVA (l);
8161   emitcode ("add", "a,acc");
8162   aopPut (AOP (result), "a", offset++);
8163   _startLazyDPSEvaluation ();
8164   while (--size)
8165     {
8166       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8167       MOVA (l);
8168       emitcode ("rlc", "a");
8169       aopPut (AOP (result), "a", offset++);
8170     }
8171   _endLazyDPSEvaluation ();
8172   reAdjustPreg (AOP (result));
8173
8174   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8175   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8176 release:
8177   freeAsmop (left, NULL, ic, TRUE);
8178   freeAsmop (result, NULL, ic, TRUE);
8179 }
8180
8181 #ifdef BETTER_LITERAL_SHIFT
8182 /*-----------------------------------------------------------------*/
8183 /* genrshOne - right shift a one byte quantity by known count      */
8184 /*-----------------------------------------------------------------*/
8185 static void
8186 genrshOne (operand * result, operand * left,
8187            int shCount, int sign)
8188 {
8189   D (emitcode (";", "genrshOne"););
8190   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8191 }
8192 #endif
8193
8194 #ifdef BETTER_LITERAL_SHIFT
8195 /*-----------------------------------------------------------------*/
8196 /* genrshTwo - right shift two bytes by known amount != 0          */
8197 /*-----------------------------------------------------------------*/
8198 static void
8199 genrshTwo (operand * result, operand * left,
8200            int shCount, int sign)
8201 {
8202   D (emitcode (";", "genrshTwo"););
8203
8204   /* if shCount >= 8 */
8205   if (shCount >= 8)
8206     {
8207       shCount -= 8;
8208       _startLazyDPSEvaluation();
8209       if (shCount)
8210       {
8211         shiftR1Left2Result (left, MSB16, result, LSB,
8212                             shCount, sign);
8213       }                     
8214       else
8215       {
8216         movLeft2Result (left, MSB16, result, LSB, sign);
8217       }
8218       addSign (result, MSB16, sign);
8219       _endLazyDPSEvaluation();
8220     }
8221
8222   /*  1 <= shCount <= 7 */
8223   else
8224   {
8225     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8226   }
8227 }
8228 #endif
8229
8230 #if 0
8231 //REMOVE ME!!!
8232 /*-----------------------------------------------------------------*/
8233 /* shiftRLong - shift right one long from left to result           */
8234 /* offl = LSB or MSB16                                             */
8235 /*-----------------------------------------------------------------*/
8236 static void
8237 shiftRLong (operand * left, int offl,
8238             operand * result, int sign)
8239 {
8240   int isSameRegs=sameRegs(AOP(left),AOP(result));
8241
8242   if (isSameRegs && offl>1) {
8243     // we are in big trouble, but this shouldn't happen
8244     werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8245   }
8246
8247   MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
8248   
8249   if (offl==MSB16) {
8250     // shift is > 8
8251     if (sign) {
8252       emitcode ("rlc", "a");
8253       emitcode ("subb", "a,acc");
8254       emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
8255     } else {
8256       aopPut (AOP(result), zero, MSB32);
8257     }
8258   }
8259
8260   if (!sign) {
8261     emitcode ("clr", "c");
8262   } else {
8263     emitcode ("mov", "c,acc.7");
8264   }
8265
8266   emitcode ("rrc", "a");
8267
8268   if (isSameRegs && offl==MSB16) {
8269     emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
8270   } else {
8271     aopPut (AOP (result), "a", MSB32);
8272     MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
8273   }
8274
8275   emitcode ("rrc", "a");
8276   if (isSameRegs && offl==1) {
8277     emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
8278   } else {
8279     aopPut (AOP (result), "a", MSB24);
8280     MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
8281   }
8282   emitcode ("rrc", "a");
8283   aopPut (AOP (result), "a", MSB16 - offl);
8284
8285   if (offl == LSB)
8286     {
8287       MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
8288       emitcode ("rrc", "a");
8289       aopPut (AOP (result), "a", LSB);
8290     }
8291 }
8292 #endif
8293
8294 #if 0
8295 //REMOVE ME!!!
8296 /*-----------------------------------------------------------------*/
8297 /* genrshFour - shift four byte by a known amount != 0             */
8298 /*-----------------------------------------------------------------*/
8299 static void
8300 genrshFour (operand * result, operand * left,
8301             int shCount, int sign)
8302 {
8303   D (emitcode (";", "genrshFour");
8304     );
8305
8306   /* if shifting more that 3 bytes */
8307   if (shCount >= 24)
8308     {
8309       shCount -= 24;
8310       if (shCount)
8311         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8312       else
8313         movLeft2Result (left, MSB32, result, LSB, sign);
8314       addSign (result, MSB16, sign);
8315     }
8316   else if (shCount >= 16)
8317     {
8318       shCount -= 16;
8319       if (shCount)
8320         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8321       else
8322         {
8323           movLeft2Result (left, MSB24, result, LSB, 0);
8324           movLeft2Result (left, MSB32, result, MSB16, sign);
8325         }
8326       addSign (result, MSB24, sign);
8327     }
8328   else if (shCount >= 8)
8329     {
8330       shCount -= 8;
8331       if (shCount == 1)
8332         shiftRLong (left, MSB16, result, sign);
8333       else if (shCount == 0)
8334         {
8335           movLeft2Result (left, MSB16, result, LSB, 0);
8336           movLeft2Result (left, MSB24, result, MSB16, 0);
8337           movLeft2Result (left, MSB32, result, MSB24, sign);
8338           addSign (result, MSB32, sign);
8339         }
8340       else
8341         {
8342           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8343           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8344           /* the last shift is signed */
8345           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8346           addSign (result, MSB32, sign);
8347         }
8348     }
8349   else
8350     {                           /* 1 <= shCount <= 7 */
8351       if (shCount <= 2)
8352         {
8353           shiftRLong (left, LSB, result, sign);
8354           if (shCount == 2)
8355             shiftRLong (result, LSB, result, sign);
8356         }
8357       else
8358         {
8359           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8360           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8361           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8362         }
8363     }
8364 }
8365 #endif
8366
8367 #ifdef BETTER_LITERAL_SHIFT
8368 /*-----------------------------------------------------------------*/
8369 /* genRightShiftLiteral - right shifting by known count            */
8370 /*-----------------------------------------------------------------*/
8371 static bool
8372 genRightShiftLiteral (operand * left,
8373                       operand * right,
8374                       operand * result,
8375                       iCode * ic,
8376                       int sign)
8377 {
8378   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8379   int size;
8380
8381   size = getSize (operandType (result));
8382
8383   D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8384
8385   /* We only handle certain easy cases so far. */
8386   if ((shCount != 0)
8387    && (shCount < (size * 8))
8388    && (size != 1)
8389    && (size != 2))
8390   {
8391       D(emitcode (";", "genRightShiftLiteral wimping out"););   
8392       return FALSE;
8393   }
8394
8395   freeAsmop (right, NULL, ic, TRUE);
8396
8397   aopOp (left, ic, FALSE, FALSE);
8398   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8399
8400 #if VIEW_SIZE
8401   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8402             AOP_SIZE (left));
8403 #endif
8404
8405   /* test the LEFT size !!! */
8406
8407   /* I suppose that the left size >= result size */
8408   if (shCount == 0)
8409   {
8410       size = getDataSize (result);
8411       _startLazyDPSEvaluation();
8412       while (size--)
8413       {
8414         movLeft2Result (left, size, result, size, 0);
8415       }
8416       _endLazyDPSEvaluation();
8417   }
8418   else if (shCount >= (size * 8))
8419     {
8420       if (sign)
8421       {
8422         /* get sign in acc.7 */
8423         MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
8424       }
8425       addSign (result, LSB, sign);
8426     }
8427   else
8428     {
8429       switch (size)
8430         {
8431         case 1:
8432           genrshOne (result, left, shCount, sign);
8433           break;
8434
8435         case 2:
8436           genrshTwo (result, left, shCount, sign);
8437           break;
8438 #if 0
8439         case 4:
8440           genrshFour (result, left, shCount, sign);
8441           break;
8442 #endif    
8443         default:
8444           break;
8445         }
8446
8447       freeAsmop (left, NULL, ic, TRUE);
8448       freeAsmop (result, NULL, ic, TRUE);
8449     }
8450     return TRUE;
8451 }
8452 #endif
8453
8454 /*-----------------------------------------------------------------*/
8455 /* genSignedRightShift - right shift of signed number              */
8456 /*-----------------------------------------------------------------*/
8457 static void
8458 genSignedRightShift (iCode * ic)
8459 {
8460   operand *right, *left, *result;
8461   int size, offset;
8462   char *l;
8463   symbol *tlbl, *tlbl1;
8464
8465   D (emitcode (";", "genSignedRightShift "););
8466
8467   /* we do it the hard way put the shift count in b
8468      and loop thru preserving the sign */
8469
8470   right = IC_RIGHT (ic);
8471   left = IC_LEFT (ic);
8472   result = IC_RESULT (ic);
8473
8474   aopOp (right, ic, FALSE, FALSE);
8475
8476 #ifdef BETTER_LITERAL_SHIFT
8477   if (AOP_TYPE (right) == AOP_LIT)
8478     {
8479       if (genRightShiftLiteral (left, right, result, ic, 1))
8480       {
8481         return;
8482       }
8483     }
8484 #endif
8485   /* shift count is unknown then we have to form
8486      a loop get the loop count in B : Note: we take
8487      only the lower order byte since shifting
8488      more that 32 bits make no sense anyway, ( the
8489      largest size of an object can be only 32 bits ) */
8490
8491   if (AOP_TYPE (right) == AOP_LIT)
8492   {
8493       /* Really should be handled by genRightShiftLiteral,
8494        * but since I'm too lazy to fix that today, at least we can make
8495        * some small improvement.
8496        */
8497        emitcode("mov", "b,#!constbyte",
8498                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8499   }
8500   else
8501   {
8502         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8503         emitcode ("inc", "b");
8504   }
8505   freeAsmop (right, NULL, ic, TRUE);
8506   aopOp (left, ic, FALSE, FALSE);
8507   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8508
8509   /* now move the left to the result if they are not the
8510      same */
8511   if (!sameRegs (AOP (left), AOP (result)) &&
8512       AOP_SIZE (result) > 1)
8513     {
8514
8515       size = AOP_SIZE (result);
8516       offset = 0;
8517       _startLazyDPSEvaluation ();
8518       while (size--)
8519         {
8520           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8521           if (*l == '@' && IS_AOP_PREG (result))
8522             {
8523
8524               emitcode ("mov", "a,%s", l);
8525               aopPut (AOP (result), "a", offset);
8526             }
8527           else
8528             aopPut (AOP (result), l, offset);
8529           offset++;
8530         }
8531       _endLazyDPSEvaluation ();
8532     }
8533
8534   /* mov the highest order bit to OVR */
8535   tlbl = newiTempLabel (NULL);
8536   tlbl1 = newiTempLabel (NULL);
8537
8538   size = AOP_SIZE (result);
8539   offset = size - 1;
8540   emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
8541   emitcode ("rlc", "a");
8542   emitcode ("mov", "ov,c");
8543   /* if it is only one byte then */
8544   if (size == 1)
8545     {
8546       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8547       MOVA (l);
8548       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8549       emitcode ("", "!tlabeldef", tlbl->key + 100);
8550       emitcode ("mov", "c,ov");
8551       emitcode ("rrc", "a");
8552       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8553       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8554       aopPut (AOP (result), "a", 0);
8555       goto release;
8556     }
8557
8558   reAdjustPreg (AOP (result));
8559   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8560   emitcode ("", "!tlabeldef", tlbl->key + 100);
8561   emitcode ("mov", "c,ov");
8562   _startLazyDPSEvaluation ();
8563   while (size--)
8564     {
8565       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8566       MOVA (l);
8567       emitcode ("rrc", "a");
8568       aopPut (AOP (result), "a", offset--);
8569     }
8570   _endLazyDPSEvaluation ();
8571   reAdjustPreg (AOP (result));
8572   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8573   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8574
8575 release:
8576   freeAsmop (left, NULL, ic, TRUE);
8577   freeAsmop (result, NULL, ic, TRUE);
8578 }
8579
8580 /*-----------------------------------------------------------------*/
8581 /* genRightShift - generate code for right shifting                */
8582 /*-----------------------------------------------------------------*/
8583 static void
8584 genRightShift (iCode * ic)
8585 {
8586   operand *right, *left, *result;
8587   sym_link *retype;
8588   int size, offset;
8589   char *l;
8590   symbol *tlbl, *tlbl1;
8591
8592   D (emitcode (";", "genRightShift "););
8593
8594   /* if signed then we do it the hard way preserve the
8595      sign bit moving it inwards */
8596   retype = getSpec (operandType (IC_RESULT (ic)));
8597
8598   if (!SPEC_USIGN (retype))
8599     {
8600       genSignedRightShift (ic);
8601       return;
8602     }
8603
8604   /* signed & unsigned types are treated the same : i.e. the
8605      signed is NOT propagated inwards : quoting from the
8606      ANSI - standard : "for E1 >> E2, is equivalent to division
8607      by 2**E2 if unsigned or if it has a non-negative value,
8608      otherwise the result is implementation defined ", MY definition
8609      is that the sign does not get propagated */
8610
8611   right = IC_RIGHT (ic);
8612   left = IC_LEFT (ic);
8613   result = IC_RESULT (ic);
8614
8615   aopOp (right, ic, FALSE, FALSE);
8616
8617 #ifdef BETTER_LITERAL_SHIFT
8618   /* if the shift count is known then do it
8619      as efficiently as possible */
8620   if (AOP_TYPE (right) == AOP_LIT)
8621     {
8622       if (genRightShiftLiteral (left, right, result, ic, 0))
8623       {
8624         return;
8625       }
8626     }
8627 #endif
8628
8629   /* shift count is unknown then we have to form
8630      a loop get the loop count in B : Note: we take
8631      only the lower order byte since shifting
8632      more that 32 bits make no sense anyway, ( the
8633      largest size of an object can be only 32 bits ) */
8634   
8635   if (AOP_TYPE (right) == AOP_LIT)
8636   {
8637       /* Really should be handled by genRightShiftLiteral,
8638        * but since I'm too lazy to fix that today, at least we can make
8639        * some small improvement.
8640        */
8641        emitcode("mov", "b,#!constbyte",
8642                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8643   }
8644   else
8645   {
8646         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8647         emitcode ("inc", "b");
8648   }
8649   freeAsmop (right, NULL, ic, TRUE);
8650   aopOp (left, ic, FALSE, FALSE);
8651   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8652
8653   /* now move the left to the result if they are not the
8654      same */
8655   if (!sameRegs (AOP (left), AOP (result)) &&
8656       AOP_SIZE (result) > 1)
8657     {
8658
8659       size = AOP_SIZE (result);
8660       offset = 0;
8661       _startLazyDPSEvaluation ();
8662       while (size--)
8663         {
8664           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8665           if (*l == '@' && IS_AOP_PREG (result))
8666             {
8667
8668               emitcode ("mov", "a,%s", l);
8669               aopPut (AOP (result), "a", offset);
8670             }
8671           else
8672             aopPut (AOP (result), l, offset);
8673           offset++;
8674         }
8675       _endLazyDPSEvaluation ();
8676     }
8677
8678   tlbl = newiTempLabel (NULL);
8679   tlbl1 = newiTempLabel (NULL);
8680   size = AOP_SIZE (result);
8681   offset = size - 1;
8682
8683   /* if it is only one byte then */
8684   if (size == 1)
8685     {
8686       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8687       MOVA (l);
8688       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8689       emitcode ("", "!tlabeldef", tlbl->key + 100);
8690       CLRC;
8691       emitcode ("rrc", "a");
8692       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8693       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8694       aopPut (AOP (result), "a", 0);
8695       goto release;
8696     }
8697
8698   reAdjustPreg (AOP (result));
8699   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8700   emitcode ("", "!tlabeldef", tlbl->key + 100);
8701   CLRC;
8702   _startLazyDPSEvaluation ();
8703   while (size--)
8704     {
8705       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8706       MOVA (l);
8707       emitcode ("rrc", "a");
8708       aopPut (AOP (result), "a", offset--);
8709     }
8710   _endLazyDPSEvaluation ();
8711   reAdjustPreg (AOP (result));
8712
8713   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8714   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8715
8716 release:
8717   freeAsmop (left, NULL, ic, TRUE);
8718   freeAsmop (result, NULL, ic, TRUE);
8719 }
8720
8721 /*-----------------------------------------------------------------*/
8722 /* genUnpackBits - generates code for unpacking bits               */
8723 /*-----------------------------------------------------------------*/
8724 static void
8725 genUnpackBits (operand * result, char *rname, int ptype)
8726 {
8727   int shCnt;
8728   int rlen = 0;
8729   sym_link *etype;
8730   int offset = 0;
8731
8732   D (emitcode (";", "genUnpackBits ");
8733     );
8734
8735   etype = getSpec (operandType (result));
8736
8737   /* read the first byte  */
8738   switch (ptype)
8739     {
8740
8741     case POINTER:
8742     case IPOINTER:
8743       emitcode ("mov", "a,@%s", rname);
8744       break;
8745
8746     case PPOINTER:
8747       emitcode ("movx", "a,@%s", rname);
8748       break;
8749
8750     case FPOINTER:
8751       emitcode ("movx", "a,@dptr");
8752       break;
8753
8754     case CPOINTER:
8755       emitcode ("clr", "a");
8756       emitcode ("movc", "a,@a+dptr");
8757       break;
8758
8759     case GPOINTER:
8760       emitcode ("lcall", "__gptrget");
8761       break;
8762     }
8763
8764   /* if we have bitdisplacement then it fits   */
8765   /* into this byte completely or if length is */
8766   /* less than a byte                          */
8767   if ((shCnt = SPEC_BSTR (etype)) ||
8768       (SPEC_BLEN (etype) <= 8))
8769     {
8770
8771       /* shift right acc */
8772       AccRsh (shCnt);
8773
8774       emitcode ("anl", "a,#!constbyte",
8775                 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
8776       aopPut (AOP (result), "a", offset);
8777       return;
8778     }
8779
8780   /* bit field did not fit in a byte  */
8781   rlen = SPEC_BLEN (etype) - 8;
8782   aopPut (AOP (result), "a", offset++);
8783
8784   while (1)
8785     {
8786
8787       switch (ptype)
8788         {
8789         case POINTER:
8790         case IPOINTER:
8791           emitcode ("inc", "%s", rname);
8792           emitcode ("mov", "a,@%s", rname);
8793           break;
8794
8795         case PPOINTER:
8796           emitcode ("inc", "%s", rname);
8797           emitcode ("movx", "a,@%s", rname);
8798           break;
8799
8800         case FPOINTER:
8801           emitcode ("inc", "dptr");
8802           emitcode ("movx", "a,@dptr");
8803           break;
8804
8805         case CPOINTER:
8806           emitcode ("clr", "a");
8807           emitcode ("inc", "dptr");
8808           emitcode ("movc", "a,@a+dptr");
8809           break;
8810
8811         case GPOINTER:
8812           emitcode ("inc", "dptr");
8813           emitcode ("lcall", "__gptrget");
8814           break;
8815         }
8816
8817       rlen -= 8;
8818       /* if we are done */
8819       if (rlen < 8)
8820         break;
8821
8822       aopPut (AOP (result), "a", offset++);
8823
8824     }
8825
8826   if (rlen)
8827     {
8828       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (rlen));
8829       aopPut (AOP (result), "a", offset);
8830     }
8831
8832   return;
8833 }
8834
8835
8836 /*-----------------------------------------------------------------*/
8837 /* genDataPointerGet - generates code when ptr offset is known     */
8838 /*-----------------------------------------------------------------*/
8839 static void
8840 genDataPointerGet (operand * left,
8841                    operand * result,
8842                    iCode * ic)
8843 {
8844   char *l;
8845   char buffer[256];
8846   int size, offset = 0;
8847   aopOp (result, ic, TRUE, FALSE);
8848
8849   /* get the string representation of the name */
8850   l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
8851   size = AOP_SIZE (result);
8852   _startLazyDPSEvaluation ();
8853   while (size--)
8854     {
8855       if (offset)
8856         sprintf (buffer, "(%s + %d)", l + 1, offset);
8857       else
8858         sprintf (buffer, "%s", l + 1);
8859       aopPut (AOP (result), buffer, offset++);
8860     }
8861   _endLazyDPSEvaluation ();
8862
8863   freeAsmop (left, NULL, ic, TRUE);
8864   freeAsmop (result, NULL, ic, TRUE);
8865 }
8866
8867 /*-----------------------------------------------------------------*/
8868 /* genNearPointerGet - emitcode for near pointer fetch             */
8869 /*-----------------------------------------------------------------*/
8870 static void
8871 genNearPointerGet (operand * left,
8872                    operand * result,
8873                    iCode * ic,
8874                    iCode *pi)
8875 {
8876   asmop *aop = NULL;
8877   regs *preg = NULL;
8878   char *rname;
8879   sym_link *rtype, *retype, *letype;
8880   sym_link *ltype = operandType (left);
8881   char buffer[80];
8882
8883   rtype = operandType (result);
8884   retype = getSpec (rtype);
8885   letype = getSpec (ltype);
8886
8887   aopOp (left, ic, FALSE, FALSE);
8888
8889   /* if left is rematerialisable and
8890      result is not bit variable type and
8891      the left is pointer to data space i.e
8892      lower 128 bytes of space */
8893   if (AOP_TYPE (left) == AOP_IMMD &&
8894       !IS_BITVAR (retype) &&
8895       !IS_BITVAR (letype) &&
8896       DCL_TYPE (ltype) == POINTER)
8897     {
8898       genDataPointerGet (left, result, ic);
8899       return;
8900     }
8901
8902   /* if the value is already in a pointer register
8903      then don't need anything more */
8904   if (!AOP_INPREG (AOP (left)))
8905     {
8906       /* otherwise get a free pointer register */
8907       aop = newAsmop (0);
8908       preg = getFreePtr (ic, &aop, FALSE);
8909       emitcode ("mov", "%s,%s",
8910                 preg->name,
8911                 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8912       rname = preg->name;
8913     }
8914   else
8915     rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8916
8917   freeAsmop (left, NULL, ic, TRUE);
8918   aopOp (result, ic, FALSE, FALSE);
8919
8920   /* if bitfield then unpack the bits */
8921   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8922     genUnpackBits (result, rname, POINTER);
8923   else
8924     {
8925       /* we have can just get the values */
8926       int size = AOP_SIZE (result);
8927       int offset = 0;
8928
8929       while (size--)
8930         {
8931           if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8932             {
8933
8934               emitcode ("mov", "a,@%s", rname);
8935               aopPut (AOP (result), "a", offset);
8936             }
8937           else
8938             {
8939               sprintf (buffer, "@%s", rname);
8940               aopPut (AOP (result), buffer, offset);
8941             }
8942           offset++;
8943           if (size || pi)
8944             emitcode ("inc", "%s", rname);
8945         }
8946     }
8947
8948   /* now some housekeeping stuff */
8949   if (aop)
8950     {
8951       /* we had to allocate for this iCode */
8952       if (pi) { /* post increment present */
8953         aopPut(AOP ( left ),rname,0);
8954       }
8955       freeAsmop (NULL, aop, ic, TRUE);
8956     }
8957   else
8958     {
8959       /* we did not allocate which means left
8960          already in a pointer register, then
8961          if size > 0 && this could be used again
8962          we have to point it back to where it
8963          belongs */
8964       if (AOP_SIZE (result) > 1 &&
8965           !OP_SYMBOL (left)->remat &&
8966           (OP_SYMBOL (left)->liveTo > ic->seq ||
8967            ic->depth) &&
8968           !pi)
8969         {
8970           int size = AOP_SIZE (result) - 1;
8971           while (size--)
8972             emitcode ("dec", "%s", rname);
8973         }
8974     }
8975
8976   /* done */
8977   freeAsmop (result, NULL, ic, TRUE);
8978   if (pi) pi->generated = 1;
8979 }
8980
8981 /*-----------------------------------------------------------------*/
8982 /* genPagedPointerGet - emitcode for paged pointer fetch           */
8983 /*-----------------------------------------------------------------*/
8984 static void
8985 genPagedPointerGet (operand * left,
8986                     operand * result,
8987                     iCode * ic,
8988                     iCode * pi)
8989 {
8990   asmop *aop = NULL;
8991   regs *preg = NULL;
8992   char *rname;
8993   sym_link *rtype, *retype, *letype;
8994
8995   rtype = operandType (result);
8996   retype = getSpec (rtype);
8997   letype = getSpec (operandType (left));
8998   aopOp (left, ic, FALSE, FALSE);
8999
9000   /* if the value is already in a pointer register
9001      then don't need anything more */
9002   if (!AOP_INPREG (AOP (left)))
9003     {
9004       /* otherwise get a free pointer register */
9005       aop = newAsmop (0);
9006       preg = getFreePtr (ic, &aop, FALSE);
9007       emitcode ("mov", "%s,%s",
9008                 preg->name,
9009                 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
9010       rname = preg->name;
9011     }
9012   else
9013     rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
9014
9015   freeAsmop (left, NULL, ic, TRUE);
9016   aopOp (result, ic, FALSE, FALSE);
9017
9018   /* if bitfield then unpack the bits */
9019   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9020     genUnpackBits (result, rname, PPOINTER);
9021   else
9022     {
9023       /* we have can just get the values */
9024       int size = AOP_SIZE (result);
9025       int offset = 0;
9026
9027       while (size--)
9028         {
9029
9030           emitcode ("movx", "a,@%s", rname);
9031           aopPut (AOP (result), "a", offset);
9032
9033           offset++;
9034
9035           if (size || pi)
9036             emitcode ("inc", "%s", rname);
9037         }
9038     }
9039
9040   /* now some housekeeping stuff */
9041   if (aop)
9042     {
9043       /* we had to allocate for this iCode */
9044       if (pi) aopPut ( AOP (left), rname, 0);
9045       freeAsmop (NULL, aop, ic, TRUE);
9046     }
9047   else
9048     {
9049       /* we did not allocate which means left
9050          already in a pointer register, then
9051          if size > 0 && this could be used again
9052          we have to point it back to where it
9053          belongs */
9054       if (AOP_SIZE (result) > 1 &&
9055           !OP_SYMBOL (left)->remat &&
9056           (OP_SYMBOL (left)->liveTo > ic->seq ||
9057            ic->depth) &&
9058           !pi)
9059         {
9060           int size = AOP_SIZE (result) - 1;
9061           while (size--)
9062             emitcode ("dec", "%s", rname);
9063         }
9064     }
9065
9066   /* done */
9067   freeAsmop (result, NULL, ic, TRUE);
9068   if (pi) pi->generated = 1;
9069 }
9070
9071 /*-----------------------------------------------------------------*/
9072 /* genFarPointerGet - gget value from far space                    */
9073 /*-----------------------------------------------------------------*/
9074 static void
9075 genFarPointerGet (operand * left,
9076                   operand * result, iCode * ic, iCode *pi)
9077 {
9078     int size, offset, dopi=1;
9079   sym_link *retype = getSpec (operandType (result));
9080   sym_link *letype = getSpec (operandType (left));
9081   D (emitcode (";", "genFarPointerGet");
9082     );
9083
9084   aopOp (left, ic, FALSE, FALSE);
9085
9086   /* if the operand is already in dptr
9087      then we do nothing else we move the value to dptr */
9088   if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9089     {
9090       /* if this is remateriazable */
9091       if (AOP_TYPE (left) == AOP_IMMD)
9092         {
9093           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9094         }
9095       else
9096         {
9097           /* we need to get it byte by byte */
9098           _startLazyDPSEvaluation ();
9099           if (AOP_TYPE (left) != AOP_DPTR)
9100             {
9101               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9102               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9103               if (options.model == MODEL_FLAT24)
9104                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9105             }
9106           else
9107             {
9108               /* We need to generate a load to DPTR indirect through DPTR. */
9109               D (emitcode (";", "genFarPointerGet -- indirection special case.");
9110                 );
9111               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
9112               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
9113               if (options.model == MODEL_FLAT24)
9114                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9115               emitcode ("pop", "dph");
9116               emitcode ("pop", "dpl");
9117               dopi =0;
9118             }
9119           _endLazyDPSEvaluation ();
9120         }
9121     }
9122   /* so dptr know contains the address */
9123   aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9124
9125   /* if bit then unpack */
9126   if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
9127       if (AOP_INDPTRn(left)) {
9128           genSetDPTR(AOP(left)->aopu.dptr);
9129       }
9130       genUnpackBits (result, "dptr", FPOINTER);
9131       if (AOP_INDPTRn(left)) {
9132           genSetDPTR(0);
9133       }
9134   } else
9135     {
9136       size = AOP_SIZE (result);
9137       offset = 0;
9138
9139       if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9140           while (size--) {
9141               genSetDPTR(AOP(left)->aopu.dptr);
9142               emitcode ("movx", "a,@dptr");
9143               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9144                   emitcode ("inc", "dptr");
9145               genSetDPTR (0);
9146               aopPut (AOP (result), "a", offset++);
9147           }
9148       } else {
9149           _startLazyDPSEvaluation ();
9150           while (size--) {
9151               if (AOP_INDPTRn(left)) {
9152                   genSetDPTR(AOP(left)->aopu.dptr);
9153               } else {
9154                   genSetDPTR (0);
9155               }
9156               _flushLazyDPS ();
9157               
9158               emitcode ("movx", "a,@dptr");
9159               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9160                   emitcode ("inc", "dptr");
9161               
9162               aopPut (AOP (result), "a", offset++);
9163           }
9164           _endLazyDPSEvaluation ();
9165       }
9166     }
9167   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9168       if (!AOP_INDPTRn(left)) {
9169           aopPut ( AOP (left), "dpl", 0);
9170           aopPut ( AOP (left), "dph", 1);
9171           if (options.model == MODEL_FLAT24)
9172               aopPut ( AOP (left), "dpx", 2);
9173       }
9174     pi->generated = 1;
9175   } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) && 
9176              AOP_SIZE(result) > 1 &&
9177              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9178       
9179       size = AOP_SIZE (result) - 1;
9180       if (AOP_INDPTRn(left)) {
9181           genSetDPTR(AOP(left)->aopu.dptr);
9182       }
9183       while (size--) emitcode ("lcall","__decdptr");
9184       if (AOP_INDPTRn(left)) {
9185           genSetDPTR(0);
9186       }
9187   }
9188
9189   freeAsmop (left, NULL, ic, TRUE);
9190   freeAsmop (result, NULL, ic, TRUE);
9191 }
9192
9193 /*-----------------------------------------------------------------*/
9194 /* emitcodePointerGet - gget value from code space                  */
9195 /*-----------------------------------------------------------------*/
9196 static void
9197 emitcodePointerGet (operand * left,
9198                     operand * result, iCode * ic, iCode *pi)
9199 {
9200   int size, offset, dopi=1;
9201   sym_link *retype = getSpec (operandType (result));
9202
9203   aopOp (left, ic, FALSE, FALSE);
9204
9205   /* if the operand is already in dptr
9206      then we do nothing else we move the value to dptr */
9207   if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
9208     {
9209       /* if this is remateriazable */
9210       if (AOP_TYPE (left) == AOP_IMMD)
9211         {
9212           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9213         }
9214       else
9215         {                       /* we need to get it byte by byte */
9216           _startLazyDPSEvaluation ();
9217           if (AOP_TYPE (left) != AOP_DPTR)
9218             {
9219               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9220               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9221               if (options.model == MODEL_FLAT24)
9222                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9223             }
9224           else
9225             {
9226               /* We need to generate a load to DPTR indirect through DPTR. */
9227               D (emitcode (";", "gencodePointerGet -- indirection special case.");
9228                 );
9229               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
9230               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
9231               if (options.model == MODEL_FLAT24)
9232                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9233               emitcode ("pop", "dph");
9234               emitcode ("pop", "dpl");
9235               dopi=0;
9236             }
9237           _endLazyDPSEvaluation ();
9238         }
9239     }
9240   /* so dptr know contains the address */
9241   aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9242
9243   /* if bit then unpack */
9244   if (IS_BITVAR (retype)) {
9245       if (AOP_INDPTRn(left)) {
9246           genSetDPTR(AOP(left)->aopu.dptr);
9247       }
9248       genUnpackBits (result, "dptr", CPOINTER);
9249       if (AOP_INDPTRn(left)) {
9250           genSetDPTR(0);
9251       }
9252   } else
9253     {
9254       size = AOP_SIZE (result);
9255       offset = 0;
9256       if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9257           while (size--) {
9258               genSetDPTR(AOP(left)->aopu.dptr);
9259               emitcode ("clr", "a");
9260               emitcode ("movc", "a,@a+dptr");
9261               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9262                   emitcode ("inc", "dptr");
9263               genSetDPTR (0);
9264               aopPut (AOP (result), "a", offset++);
9265           }
9266       } else {
9267           _startLazyDPSEvaluation ();
9268           while (size--)
9269               {
9270                   if (AOP_INDPTRn(left)) {
9271                       genSetDPTR(AOP(left)->aopu.dptr);
9272                   } else {
9273                       genSetDPTR (0);
9274                   }
9275                   _flushLazyDPS ();
9276                   
9277                   emitcode ("clr", "a");
9278                   emitcode ("movc", "a,@a+dptr");
9279                   if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9280                       emitcode ("inc", "dptr");
9281                   aopPut (AOP (result), "a", offset++);
9282               }
9283           _endLazyDPSEvaluation ();
9284       }
9285     }
9286   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9287       if (!AOP_INDPTRn(left)) {
9288           aopPut ( AOP (left), "dpl", 0);
9289           aopPut ( AOP (left), "dph", 1);
9290           if (options.model == MODEL_FLAT24)
9291               aopPut ( AOP (left), "dpx", 2);
9292       }
9293       pi->generated = 1;
9294   } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) && 
9295              AOP_SIZE(result) > 1 &&
9296              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9297       
9298       size = AOP_SIZE (result) - 1;
9299       if (AOP_INDPTRn(left)) {
9300           genSetDPTR(AOP(left)->aopu.dptr);
9301       }
9302       while (size--) emitcode ("lcall","__decdptr");
9303       if (AOP_INDPTRn(left)) {
9304           genSetDPTR(0);
9305       }
9306   }
9307   
9308   freeAsmop (left, NULL, ic, TRUE);
9309   freeAsmop (result, NULL, ic, TRUE);
9310 }
9311
9312 /*-----------------------------------------------------------------*/
9313 /* genGenPointerGet - gget value from generic pointer space        */
9314 /*-----------------------------------------------------------------*/
9315 static void
9316 genGenPointerGet (operand * left,
9317                   operand * result, iCode * ic, iCode * pi)
9318 {
9319   int size, offset;
9320   sym_link *retype = getSpec (operandType (result));
9321   sym_link *letype = getSpec (operandType (left));
9322
9323   D (emitcode (";", "genGenPointerGet "); );
9324
9325   aopOp (left, ic, FALSE, (OP_SYMBOL(left)->ruonly ? FALSE : TRUE));
9326
9327   /* if the operand is already in dptr
9328      then we do nothing else we move the value to dptr */
9329   if (AOP_TYPE (left) != AOP_STR)
9330     {
9331       /* if this is remateriazable */
9332       if (AOP_TYPE (left) == AOP_IMMD)
9333         {
9334           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9335           if (AOP(left)->aopu.aop_immd.from_cast_remat) 
9336                   emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, FALSE));
9337           else
9338                   emitcode ("mov", "b,#%d", pointerCode (retype));
9339         }
9340       else
9341         {                       /* we need to get it byte by byte */
9342           _startLazyDPSEvaluation ();
9343           if (AOP(left)->type==AOP_DPTR2) {
9344             char *l;
9345             l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
9346             genSetDPTR(0);
9347             _flushLazyDPS();
9348             emitcode ("mov", "dpl,%s", l);
9349             l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
9350             genSetDPTR(0);
9351             _flushLazyDPS();
9352             emitcode ("mov", "dph,%s", l);
9353             if (options.model == MODEL_FLAT24) {
9354               l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
9355               genSetDPTR(0);
9356               _flushLazyDPS();
9357               emitcode ("mov", "dpx,%s", l);
9358               emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
9359             } else {
9360               emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9361             }
9362           } else {
9363             emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
9364             emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
9365             if (options.model == MODEL_FLAT24) {
9366               emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9367               emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
9368             } else {
9369               emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9370             }
9371           }
9372           _endLazyDPSEvaluation ();
9373         }
9374     }
9375   /* so dptr know contains the address */
9376   aopOp (result, ic, FALSE, TRUE);
9377
9378   /* if bit then unpack */
9379   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9380     genUnpackBits (result, "dptr", GPOINTER);
9381   else
9382     {
9383       size = AOP_SIZE (result);
9384       offset = 0;
9385
9386       while (size--)
9387         {
9388           emitcode ("lcall", "__gptrget");
9389           aopPut (AOP (result), "a", offset++);
9390           if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9391             emitcode ("inc", "dptr");
9392         }
9393     }
9394
9395   if (pi && AOP_TYPE (left) != AOP_IMMD) {
9396     aopPut ( AOP (left), "dpl", 0);
9397     aopPut ( AOP (left), "dph", 1);
9398     if (options.model == MODEL_FLAT24) {
9399         aopPut ( AOP (left), "dpx", 2);
9400         aopPut ( AOP (left), "b", 3);   
9401     } else  aopPut ( AOP (left), "b", 2);       
9402     pi->generated = 1;
9403   } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9404              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9405       
9406       size = AOP_SIZE (result) - 1;
9407       while (size--) emitcode ("lcall","__decdptr");
9408   }
9409
9410   freeAsmop (left, NULL, ic, TRUE);
9411   freeAsmop (result, NULL, ic, TRUE);
9412 }
9413
9414 /*-----------------------------------------------------------------*/
9415 /* genPointerGet - generate code for pointer get                   */
9416 /*-----------------------------------------------------------------*/
9417 static void
9418 genPointerGet (iCode * ic, iCode *pi)
9419 {
9420   operand *left, *result;
9421   sym_link *type, *etype;
9422   int p_type;
9423
9424   D (emitcode (";", "genPointerGet ");
9425     );
9426
9427   left = IC_LEFT (ic);
9428   result = IC_RESULT (ic);
9429
9430   /* depending on the type of pointer we need to
9431      move it to the correct pointer register */
9432   type = operandType (left);
9433   etype = getSpec (type);
9434   /* if left is of type of pointer then it is simple */
9435   if (IS_PTR (type) && !IS_FUNC (type->next))
9436     p_type = DCL_TYPE (type);
9437   else
9438     {
9439       /* we have to go by the storage class */
9440       p_type = PTR_TYPE (SPEC_OCLS (etype));
9441     }
9442   /* special case when cast remat */
9443   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9444       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9445           left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9446           type =   type = operandType (left);
9447           p_type = DCL_TYPE (type);
9448   }
9449   /* now that we have the pointer type we assign
9450      the pointer values */
9451   switch (p_type)
9452     {
9453
9454     case POINTER:
9455     case IPOINTER:
9456       genNearPointerGet (left, result, ic, pi);
9457       break;
9458
9459     case PPOINTER:
9460       genPagedPointerGet (left, result, ic, pi);
9461       break;
9462
9463     case FPOINTER:
9464       genFarPointerGet (left, result, ic, pi);
9465       break;
9466
9467     case CPOINTER:
9468       emitcodePointerGet (left, result, ic, pi);
9469       break;
9470
9471     case GPOINTER:
9472       genGenPointerGet (left, result, ic, pi);
9473       break;
9474     }
9475
9476 }
9477
9478 /*-----------------------------------------------------------------*/
9479 /* genPackBits - generates code for packed bit storage             */
9480 /*-----------------------------------------------------------------*/
9481 static void
9482 genPackBits (sym_link * etype,
9483              operand * right,
9484              char *rname, int p_type)
9485 {
9486   int shCount = 0;
9487   int offset = 0;
9488   int rLen = 0;
9489   int blen, bstr;
9490   char *l;
9491
9492   blen = SPEC_BLEN (etype);
9493   bstr = SPEC_BSTR (etype);
9494
9495   l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9496   MOVA (l);
9497
9498   /* if the bit lenth is less than or    */
9499   /* it exactly fits a byte then         */
9500   if (SPEC_BLEN (etype) <= 8)
9501     {
9502       shCount = SPEC_BSTR (etype);
9503
9504       /* shift left acc */
9505       AccLsh (shCount);
9506
9507       if (SPEC_BLEN (etype) < 8)
9508         {                       /* if smaller than a byte */
9509
9510
9511           switch (p_type)
9512             {
9513             case POINTER:
9514               emitcode ("mov", "b,a");
9515               emitcode ("mov", "a,@%s", rname);
9516               break;
9517
9518             case FPOINTER:
9519               emitcode ("mov", "b,a");
9520               emitcode ("movx", "a,@dptr");
9521               break;
9522
9523             case GPOINTER:
9524               emitcode ("push", "b");
9525               emitcode ("push", "acc");
9526               emitcode ("lcall", "__gptrget");
9527               emitcode ("pop", "b");
9528               break;
9529             }
9530
9531           emitcode ("anl", "a,#!constbyte", (unsigned char)
9532                     ((unsigned char) (0xFF << (blen + bstr)) |
9533                      (unsigned char) (0xFF >> (8 - bstr))));
9534           emitcode ("orl", "a,b");
9535           if (p_type == GPOINTER)
9536             emitcode ("pop", "b");
9537         }
9538     }
9539
9540   switch (p_type)
9541     {
9542     case POINTER:
9543       emitcode ("mov", "@%s,a", rname);
9544       break;
9545
9546     case FPOINTER:
9547       emitcode ("movx", "@dptr,a");
9548       break;
9549
9550     case GPOINTER:
9551       emitcode ("lcall", "__gptrput");
9552       break;
9553     }
9554
9555   /* if we r done */
9556   if (SPEC_BLEN (etype) <= 8)
9557     return;
9558
9559   emitcode ("inc", "%s", rname);
9560   rLen = SPEC_BLEN (etype);
9561
9562   /* now generate for lengths greater than one byte */
9563   while (1)
9564     {
9565
9566       l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
9567
9568       rLen -= 8;
9569       if (rLen < 8)
9570         break;
9571
9572       switch (p_type)
9573         {
9574         case POINTER:
9575           if (*l == '@')
9576             {
9577               MOVA (l);
9578               emitcode ("mov", "@%s,a", rname);
9579             }
9580           else
9581             emitcode ("mov", "@%s,%s", rname, l);
9582           break;
9583
9584         case FPOINTER:
9585           MOVA (l);
9586           emitcode ("movx", "@dptr,a");
9587           break;
9588
9589         case GPOINTER:
9590           MOVA (l);
9591           emitcode ("lcall", "__gptrput");
9592           break;
9593         }
9594       emitcode ("inc", "%s", rname);
9595     }
9596
9597   MOVA (l);
9598
9599   /* last last was not complete */
9600   if (rLen)
9601     {
9602       /* save the byte & read byte */
9603       switch (p_type)
9604         {
9605         case POINTER:
9606           emitcode ("mov", "b,a");
9607           emitcode ("mov", "a,@%s", rname);
9608           break;
9609
9610         case FPOINTER:
9611           emitcode ("mov", "b,a");
9612           emitcode ("movx", "a,@dptr");
9613           break;
9614
9615         case GPOINTER:
9616           emitcode ("push", "b");
9617           emitcode ("push", "acc");
9618           emitcode ("lcall", "__gptrget");
9619           emitcode ("pop", "b");
9620           break;
9621         }
9622
9623       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1 << rLen));
9624       emitcode ("orl", "a,b");
9625     }
9626
9627   if (p_type == GPOINTER)
9628     emitcode ("pop", "b");
9629
9630   switch (p_type)
9631     {
9632
9633     case POINTER:
9634       emitcode ("mov", "@%s,a", rname);
9635       break;
9636
9637     case FPOINTER:
9638       emitcode ("movx", "@dptr,a");
9639       break;
9640
9641     case GPOINTER:
9642       emitcode ("lcall", "__gptrput");
9643       break;
9644     }
9645 }
9646 /*-----------------------------------------------------------------*/
9647 /* genDataPointerSet - remat pointer to data space                 */
9648 /*-----------------------------------------------------------------*/
9649 static void
9650 genDataPointerSet (operand * right,
9651                    operand * result,
9652                    iCode * ic)
9653 {
9654   int size, offset = 0;
9655   char *l, buffer[256];
9656
9657   aopOp (right, ic, FALSE, FALSE);
9658
9659   l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
9660   size = AOP_SIZE (right);
9661   while (size--)
9662     {
9663       if (offset)
9664         sprintf (buffer, "(%s + %d)", l + 1, offset);
9665       else
9666         sprintf (buffer, "%s", l + 1);
9667       emitcode ("mov", "%s,%s", buffer,
9668                 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
9669     }
9670
9671   freeAsmop (right, NULL, ic, TRUE);
9672   freeAsmop (result, NULL, ic, TRUE);
9673 }
9674
9675 /*-----------------------------------------------------------------*/
9676 /* genNearPointerSet - emitcode for near pointer put                */
9677 /*-----------------------------------------------------------------*/
9678 static void
9679 genNearPointerSet (operand * right,
9680                    operand * result,
9681                    iCode * ic,
9682                    iCode * pi)
9683 {
9684   asmop *aop = NULL;
9685   regs *preg = NULL;
9686   char *rname, *l;
9687   sym_link *retype, *letype;
9688   sym_link *ptype = operandType (result);
9689
9690   retype = getSpec (operandType (right));
9691   letype = getSpec (ptype);
9692
9693   aopOp (result, ic, FALSE, FALSE);
9694
9695   /* if the result is rematerializable &
9696      in data space & not a bit variable */
9697   if (AOP_TYPE (result) == AOP_IMMD &&
9698       DCL_TYPE (ptype) == POINTER &&
9699       !IS_BITVAR (retype) &&
9700       !IS_BITVAR (letype))
9701     {
9702       genDataPointerSet (right, result, ic);
9703       return;
9704     }
9705
9706   /* if the value is already in a pointer register
9707      then don't need anything more */
9708   if (!AOP_INPREG (AOP (result)))
9709     {
9710       /* otherwise get a free pointer register */
9711       aop = newAsmop (0);
9712       preg = getFreePtr (ic, &aop, FALSE);
9713       emitcode ("mov", "%s,%s",
9714                 preg->name,
9715                 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9716       rname = preg->name;
9717     }
9718   else
9719     rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9720
9721   aopOp (right, ic, FALSE, FALSE);
9722
9723   /* if bitfield then unpack the bits */
9724   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9725     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
9726   else
9727     {
9728       /* we have can just get the values */
9729       int size = AOP_SIZE (right);
9730       int offset = 0;
9731
9732       while (size--)
9733         {
9734           l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
9735           if (*l == '@')
9736             {
9737               MOVA (l);
9738               emitcode ("mov", "@%s,a", rname);
9739             }
9740           else
9741             emitcode ("mov", "@%s,%s", rname, l);
9742           if (size || pi)
9743             emitcode ("inc", "%s", rname);
9744           offset++;
9745         }
9746     }
9747
9748   /* now some housekeeping stuff */
9749   if (aop)
9750     {
9751       /* we had to allocate for this iCode */
9752       if (pi) aopPut (AOP (result),rname,0);
9753       freeAsmop (NULL, aop, ic, TRUE);
9754     }
9755   else
9756     {
9757       /* we did not allocate which means left
9758          already in a pointer register, then
9759          if size > 0 && this could be used again
9760          we have to point it back to where it
9761          belongs */
9762       if (AOP_SIZE (right) > 1 &&
9763           !OP_SYMBOL (result)->remat &&
9764           (OP_SYMBOL (result)->liveTo > ic->seq ||
9765            ic->depth) &&
9766           !pi)
9767         {
9768           int size = AOP_SIZE (right) - 1;
9769           while (size--)
9770             emitcode ("dec", "%s", rname);
9771         }
9772     }
9773
9774   /* done */
9775   if (pi) pi->generated = 1;
9776   freeAsmop (result, NULL, ic, TRUE);
9777   freeAsmop (right, NULL, ic, TRUE);
9778
9779
9780 }
9781
9782 /*-----------------------------------------------------------------*/
9783 /* genPagedPointerSet - emitcode for Paged pointer put             */
9784 /*-----------------------------------------------------------------*/
9785 static void
9786 genPagedPointerSet (operand * right,
9787                     operand * result,
9788                     iCode * ic,
9789                     iCode *pi)
9790 {
9791   asmop *aop = NULL;
9792   regs *preg = NULL;
9793   char *rname, *l;
9794   sym_link *retype, *letype;
9795
9796   retype = getSpec (operandType (right));
9797   letype = getSpec (operandType (result));
9798
9799   aopOp (result, ic, FALSE, FALSE);
9800
9801   /* if the value is already in a pointer register
9802      then don't need anything more */
9803   if (!AOP_INPREG (AOP (result)))
9804     {
9805       /* otherwise get a free pointer register */
9806       aop = newAsmop (0);
9807       preg = getFreePtr (ic, &aop, FALSE);
9808       emitcode ("mov", "%s,%s",
9809                 preg->name,
9810                 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9811       rname = preg->name;
9812     }
9813   else
9814     rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9815
9816   aopOp (right, ic, FALSE, FALSE);
9817
9818   /* if bitfield then unpack the bits */
9819   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9820     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
9821   else
9822     {
9823       /* we have can just get the values */
9824       int size = AOP_SIZE (right);
9825       int offset = 0;
9826
9827       while (size--)
9828         {
9829           l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
9830
9831           MOVA (l);
9832           emitcode ("movx", "@%s,a", rname);
9833
9834           if (size || pi)
9835             emitcode ("inc", "%s", rname);
9836
9837           offset++;
9838         }
9839     }
9840
9841   /* now some housekeeping stuff */
9842   if (aop)
9843     {
9844       if (pi) aopPut (AOP (result),rname,0);
9845       /* we had to allocate for this iCode */
9846       freeAsmop (NULL, aop, ic, TRUE);
9847     }
9848   else
9849     {
9850       /* we did not allocate which means left
9851          already in a pointer register, then
9852          if size > 0 && this could be used again
9853          we have to point it back to where it
9854          belongs */
9855       if (AOP_SIZE (right) > 1 &&
9856           !OP_SYMBOL (result)->remat &&
9857           (OP_SYMBOL (result)->liveTo > ic->seq ||
9858            ic->depth) &&
9859           !pi)
9860         {
9861           int size = AOP_SIZE (right) - 1;
9862           while (size--)
9863             emitcode ("dec", "%s", rname);
9864         }
9865     }
9866
9867   /* done */
9868   if (pi) pi->generated = 1;
9869   freeAsmop (result, NULL, ic, TRUE);
9870   freeAsmop (right, NULL, ic, TRUE);
9871
9872
9873 }
9874
9875 /*-----------------------------------------------------------------*/
9876 /* genFarPointerSet - set value from far space                     */
9877 /*-----------------------------------------------------------------*/
9878 static void
9879 genFarPointerSet (operand * right,
9880                   operand * result, iCode * ic, iCode *pi)
9881 {
9882   int size, offset, dopi=1;
9883   sym_link *retype = getSpec (operandType (right));
9884   sym_link *letype = getSpec (operandType (result));
9885
9886   aopOp (result, ic, FALSE, FALSE);
9887
9888   /* if the operand is already in dptr
9889      then we do nothing else we move the value to dptr */
9890   if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
9891     {
9892       /* if this is remateriazable */
9893       if (AOP_TYPE (result) == AOP_IMMD)
9894         emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9895       else
9896         {
9897           /* we need to get it byte by byte */
9898           _startLazyDPSEvaluation ();
9899           if (AOP_TYPE (result) != AOP_DPTR)
9900             {
9901               emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9902               emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9903               if (options.model == MODEL_FLAT24)
9904                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9905             }
9906           else
9907             {
9908               /* We need to generate a load to DPTR indirect through DPTR. */
9909               D (emitcode (";", "genFarPointerSet -- indirection special case.");
9910                 );
9911               emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
9912               emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
9913               if (options.model == MODEL_FLAT24)
9914                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9915               emitcode ("pop", "dph");
9916               emitcode ("pop", "dpl");
9917               dopi=0;
9918             }
9919           _endLazyDPSEvaluation ();
9920         }
9921     }
9922   /* so dptr know contains the address */
9923   aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
9924
9925   /* if bit then unpack */
9926   if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
9927       if (AOP_INDPTRn(result)) {
9928           genSetDPTR(AOP(result)->aopu.dptr);
9929       }
9930       genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
9931       if (AOP_INDPTRn(result)) {
9932           genSetDPTR(0);
9933       }
9934   } else {
9935       size = AOP_SIZE (right);
9936       offset = 0;
9937       if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
9938           while (size--) {
9939               char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9940               MOVA (l);
9941               
9942               genSetDPTR(AOP(result)->aopu.dptr);
9943               emitcode ("movx", "@dptr,a");
9944               if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
9945                   emitcode ("inc", "dptr");
9946               genSetDPTR (0);
9947           }
9948       } else {
9949           _startLazyDPSEvaluation ();
9950           while (size--) {
9951               char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9952               MOVA (l);
9953               
9954               if (AOP_INDPTRn(result)) {
9955                   genSetDPTR(AOP(result)->aopu.dptr);
9956               } else {
9957                   genSetDPTR (0);
9958               }
9959               _flushLazyDPS ();
9960               
9961               emitcode ("movx", "@dptr,a");
9962               if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
9963                   emitcode ("inc", "dptr");
9964           }
9965           _endLazyDPSEvaluation ();
9966       }
9967   }
9968   
9969   if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
9970       if (!AOP_INDPTRn(result)) {
9971           aopPut (AOP(result),"dpl",0);
9972           aopPut (AOP(result),"dph",1);
9973           if (options.model == MODEL_FLAT24)
9974               aopPut (AOP(result),"dpx",2);
9975       }
9976       pi->generated=1;
9977   } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) && 
9978              AOP_SIZE(right) > 1 &&
9979              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
9980       
9981       size = AOP_SIZE (right) - 1;
9982       if (AOP_INDPTRn(result)) {
9983           genSetDPTR(AOP(result)->aopu.dptr);
9984       } 
9985       while (size--) emitcode ("lcall","__decdptr");
9986       if (AOP_INDPTRn(result)) {
9987           genSetDPTR(0);
9988       }
9989   }
9990   freeAsmop (result, NULL, ic, TRUE);
9991   freeAsmop (right, NULL, ic, TRUE);
9992 }
9993
9994 /*-----------------------------------------------------------------*/
9995 /* genGenPointerSet - set value from generic pointer space         */
9996 /*-----------------------------------------------------------------*/
9997 static void
9998 genGenPointerSet (operand * right,
9999                   operand * result, iCode * ic, iCode *pi)
10000 {
10001   int size, offset;
10002   sym_link *retype = getSpec (operandType (right));
10003   sym_link *letype = getSpec (operandType (result));
10004
10005   aopOp (result, ic, FALSE, OP_SYMBOL(result)->ruonly ? FALSE : TRUE);
10006
10007   /* if the operand is already in dptr
10008      then we do nothing else we move the value to dptr */
10009   if (AOP_TYPE (result) != AOP_STR)
10010     {
10011       _startLazyDPSEvaluation ();
10012       /* if this is remateriazable */
10013       if (AOP_TYPE (result) == AOP_IMMD)
10014         {
10015           emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
10016           if (AOP(result)->aopu.aop_immd.from_cast_remat) 
10017                   emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, FALSE));
10018           else
10019                   emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
10020         }
10021       else
10022         {                       /* we need to get it byte by byte */
10023           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
10024           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
10025           if (options.model == MODEL_FLAT24) {
10026             emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
10027             emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
10028           } else {
10029             emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
10030           }
10031         }
10032       _endLazyDPSEvaluation ();
10033     }
10034   /* so dptr know contains the address */
10035   aopOp (right, ic, FALSE, TRUE);
10036
10037   /* if bit then unpack */
10038   if (IS_BITVAR (retype) || IS_BITVAR (letype))
10039     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
10040   else
10041     {
10042       size = AOP_SIZE (right);
10043       offset = 0;
10044
10045       _startLazyDPSEvaluation ();
10046       while (size--)
10047         {
10048           char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
10049           MOVA (l);
10050
10051           genSetDPTR (0);
10052           _flushLazyDPS ();
10053
10054           emitcode ("lcall", "__gptrput");
10055           if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10056             emitcode ("inc", "dptr");
10057         }
10058       _endLazyDPSEvaluation ();
10059     }
10060
10061   if (pi && AOP_TYPE (result) != AOP_IMMD) {
10062       aopPut (AOP(result),"dpl",0);
10063       aopPut (AOP(result),"dph",1);
10064       if (options.model == MODEL_FLAT24) {
10065           aopPut (AOP(result),"dpx",2);
10066           aopPut (AOP(result),"b",3);
10067       } else {
10068           aopPut (AOP(result),"b",2);
10069       }
10070       pi->generated=1;
10071   } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10072              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10073       
10074       size = AOP_SIZE (right) - 1;
10075       while (size--) emitcode ("lcall","__decdptr");
10076   }
10077   freeAsmop (result, NULL, ic, TRUE);
10078   freeAsmop (right, NULL, ic, TRUE);
10079 }
10080
10081 /*-----------------------------------------------------------------*/
10082 /* genPointerSet - stores the value into a pointer location        */
10083 /*-----------------------------------------------------------------*/
10084 static void
10085 genPointerSet (iCode * ic, iCode *pi)
10086 {
10087   operand *right, *result;
10088   sym_link *type, *etype;
10089   int p_type;
10090
10091   D (emitcode (";", "genPointerSet ");
10092     );
10093
10094   right = IC_RIGHT (ic);
10095   result = IC_RESULT (ic);
10096
10097   /* depending on the type of pointer we need to
10098      move it to the correct pointer register */
10099   type = operandType (result);
10100   etype = getSpec (type);
10101   /* if left is of type of pointer then it is simple */
10102   if (IS_PTR (type) && !IS_FUNC (type->next))
10103     {
10104       p_type = DCL_TYPE (type);
10105     }
10106   else
10107     {
10108       /* we have to go by the storage class */
10109       p_type = PTR_TYPE (SPEC_OCLS (etype));
10110     }
10111   /* special case when cast remat */
10112   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10113       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10114           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10115           type =   type = operandType (result);
10116           p_type = DCL_TYPE (type);
10117   }
10118
10119   /* now that we have the pointer type we assign
10120      the pointer values */
10121   switch (p_type)
10122     {
10123
10124     case POINTER:
10125     case IPOINTER:
10126       genNearPointerSet (right, result, ic, pi);
10127       break;
10128
10129     case PPOINTER:
10130       genPagedPointerSet (right, result, ic, pi);
10131       break;
10132
10133     case FPOINTER:
10134       genFarPointerSet (right, result, ic, pi);
10135       break;
10136
10137     case GPOINTER:
10138       genGenPointerSet (right, result, ic, pi);
10139       break;
10140     }
10141
10142 }
10143
10144 /*-----------------------------------------------------------------*/
10145 /* genIfx - generate code for Ifx statement                        */
10146 /*-----------------------------------------------------------------*/
10147 static void
10148 genIfx (iCode * ic, iCode * popIc)
10149 {
10150   operand *cond = IC_COND (ic);
10151   int isbit = 0;
10152
10153   D (emitcode (";", "genIfx "););
10154
10155   aopOp (cond, ic, FALSE, FALSE);
10156
10157   /* get the value into acc */
10158   if (AOP_TYPE (cond) != AOP_CRY)
10159     toBoolean (cond);
10160   else
10161     isbit = 1;
10162   /* the result is now in the accumulator */
10163   freeAsmop (cond, NULL, ic, TRUE);
10164
10165   /* if there was something to be popped then do it */
10166   if (popIc)
10167     genIpop (popIc);
10168
10169   /* if the condition is  a bit variable */
10170   if (isbit && IS_ITEMP (cond) &&
10171       SPIL_LOC (cond))
10172     genIfxJump (ic, SPIL_LOC (cond)->rname);
10173   else if (isbit && !IS_ITEMP (cond))
10174     genIfxJump (ic, OP_SYMBOL (cond)->rname);
10175   else
10176     genIfxJump (ic, "a");
10177
10178   ic->generated = 1;
10179 }
10180
10181 /*-----------------------------------------------------------------*/
10182 /* genAddrOf - generates code for address of                       */
10183 /*-----------------------------------------------------------------*/
10184 static void
10185 genAddrOf (iCode * ic)
10186 {
10187   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10188   int size, offset;
10189
10190   D (emitcode (";", "genAddrOf ");
10191     );
10192
10193   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10194
10195   /* if the operand is on the stack then we
10196      need to get the stack offset of this
10197      variable */
10198   if (sym->onStack) {
10199       
10200       /* if 10 bit stack */
10201       if (options.stack10bit) {
10202           char buff[10];
10203           tsprintf(buff,"#!constbyte",(options.stack_loc >> 16) & 0xff);
10204           /* if it has an offset then we need to compute it */
10205           emitcode ("subb", "a,#!constbyte",
10206                     -((sym->stack < 0) ?
10207                       ((short) (sym->stack - _G.nRegsSaved)) :
10208                       ((short) sym->stack)) & 0xff);
10209           emitcode ("mov","b,a");
10210           emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ?
10211                                          ((short) (sym->stack - _G.nRegsSaved)) :
10212                                          ((short) sym->stack)) >> 8) & 0xff);
10213           if (sym->stack) {
10214               emitcode ("mov", "a,_bpx");
10215               emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ? 
10216                                              ((char) (sym->stack - _G.nRegsSaved)) :
10217                                              ((char) sym->stack )) & 0xff);
10218               emitcode ("mov", "b,a");
10219               emitcode ("mov", "a,_bpx+1");
10220               emitcode ("addc","a,#!constbyte", (((sym->stack < 0) ? 
10221                                               ((short) (sym->stack - _G.nRegsSaved)) :
10222                                               ((short) sym->stack )) >> 8) & 0xff);
10223               aopPut (AOP (IC_RESULT (ic)), "b", 0);
10224               aopPut (AOP (IC_RESULT (ic)), "a", 1);
10225               aopPut (AOP (IC_RESULT (ic)), buff, 2);
10226           } else {
10227               /* we can just move _bp */
10228               aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
10229               aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
10230               aopPut (AOP (IC_RESULT (ic)), buff, 2);
10231           }       
10232       } else {
10233           /* if it has an offset then we need to compute it */
10234           if (sym->stack) {
10235               emitcode ("mov", "a,_bp");
10236               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
10237               aopPut (AOP (IC_RESULT (ic)), "a", 0);
10238           } else {
10239               /* we can just move _bp */
10240               aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
10241           }
10242           /* fill the result with zero */
10243           size = AOP_SIZE (IC_RESULT (ic)) - 1;
10244           
10245           
10246           if (options.stack10bit && size < (FPTRSIZE - 1)) {
10247               fprintf (stderr,
10248                        "*** warning: pointer to stack var truncated.\n");
10249           }
10250
10251           offset = 1;
10252           while (size--) {
10253               aopPut (AOP (IC_RESULT (ic)), zero, offset++);
10254           }      
10255       }
10256       goto release;
10257   }
10258
10259   /* object not on stack then we need the name */
10260   size = AOP_SIZE (IC_RESULT (ic));
10261   offset = 0;
10262
10263   while (size--)
10264     {
10265       char s[SDCC_NAME_MAX];
10266       if (offset) {
10267           switch (offset) {
10268           case 1:
10269               tsprintf(s,"!his",sym->rname);
10270               break;
10271           case 2:
10272               tsprintf(s,"!hihis",sym->rname);
10273               break;
10274           case 3:
10275               tsprintf(s,"!hihihis",sym->rname);
10276               break;
10277           default: /* should not need this (just in case) */
10278               sprintf (s, "#(%s >> %d)",
10279                        sym->rname,
10280                        offset * 8);
10281           }
10282       } else
10283           sprintf (s, "#%s", sym->rname);
10284       aopPut (AOP (IC_RESULT (ic)), s, offset++);
10285     }
10286
10287 release:
10288   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10289
10290 }
10291
10292 /*-----------------------------------------------------------------*/
10293 /* genArrayInit - generates code for address of                       */
10294 /*-----------------------------------------------------------------*/
10295 static void
10296 genArrayInit (iCode * ic)
10297 {
10298     literalList *iLoop;
10299     int         ix, count;
10300     int         elementSize = 0, eIndex;
10301     unsigned    val, lastVal;
10302     sym_link    *type;
10303     operand     *left=IC_LEFT(ic);
10304     
10305     D (emitcode (";", "genArrayInit "););
10306
10307     aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10308     
10309     if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10310     {
10311         // Load immediate value into DPTR.
10312         emitcode("mov", "dptr, %s",
10313              aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, TRUE));
10314     }
10315     else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10316     {
10317 #if 0
10318       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10319               "Unexpected operand to genArrayInit.\n");
10320       exit(1);
10321 #else
10322       // a regression because of SDCCcse.c:1.52
10323       emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
10324       emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
10325       if (options.model == MODEL_FLAT24)
10326         emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
10327 #endif
10328     }
10329     
10330     type = operandType(IC_LEFT(ic));
10331     
10332     if (type && type->next)
10333     {
10334         elementSize = getSize(type->next);
10335     }
10336     else
10337     {
10338         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10339                                 "can't determine element size in genArrayInit.\n");
10340         exit(1);
10341     }
10342     
10343     iLoop = IC_ARRAYILIST(ic);
10344     lastVal = 0xffff;
10345     
10346     while (iLoop)
10347     {
10348         bool firstpass = TRUE;
10349         
10350         emitcode(";", "store %d x 0x%x to DPTR (element size %d)", 
10351                  iLoop->count, (int)iLoop->literalValue, elementSize);
10352         
10353         ix = iLoop->count;
10354         
10355         while (ix)
10356         {
10357             symbol *tlbl = NULL;
10358             
10359             count = ix > 256 ? 256 : ix;
10360             
10361             if (count > 1)
10362             {
10363                 tlbl = newiTempLabel (NULL);
10364                 if (firstpass || (count & 0xff))
10365                 {
10366                     emitcode("mov", "b, #!constbyte", count & 0xff);
10367                 }
10368                 
10369                 emitcode ("", "!tlabeldef", tlbl->key + 100);
10370             }
10371             
10372             firstpass = FALSE;
10373                 
10374             for (eIndex = 0; eIndex < elementSize; eIndex++)
10375             {
10376                 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10377                 if (val != lastVal)
10378                 {
10379                     emitcode("mov", "a, #!constbyte", val);
10380                     lastVal = val;
10381                 }
10382                 
10383                 emitcode("movx", "@dptr, a");
10384                 emitcode("inc", "dptr");
10385             }
10386             
10387             if (count > 1)
10388             {
10389                 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
10390             }
10391             
10392             ix -= count;
10393         }
10394         
10395         iLoop = iLoop->next;
10396     }
10397     
10398     freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10399 }
10400
10401 /*-----------------------------------------------------------------*/
10402 /* genFarFarAssign - assignment when both are in far space         */
10403 /*-----------------------------------------------------------------*/
10404 static void
10405 genFarFarAssign (operand * result, operand * right, iCode * ic)
10406 {
10407   int size = AOP_SIZE (right);
10408   int offset = 0;
10409   symbol *rSym = NULL;
10410
10411   if (size == 1)
10412   {
10413       /* quick & easy case. */
10414       D(emitcode(";","genFarFarAssign (1 byte case)"););      
10415       MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
10416       freeAsmop (right, NULL, ic, FALSE);
10417       /* now assign DPTR to result */
10418       _G.accInUse++;
10419       aopOp(result, ic, FALSE, FALSE);
10420       _G.accInUse--;
10421       aopPut(AOP(result), "a", 0);
10422       freeAsmop(result, NULL, ic, FALSE);
10423       return;
10424   }
10425   
10426   /* See if we've got an underlying symbol to abuse. */
10427   if (IS_SYMOP(result) && OP_SYMBOL(result))
10428   {
10429       if (IS_TRUE_SYMOP(result))
10430       {
10431           rSym = OP_SYMBOL(result);
10432       }
10433       else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10434       {
10435           rSym = OP_SYMBOL(result)->usl.spillLoc;
10436       }
10437   }
10438              
10439   if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10440   {
10441       /* We can use the '390 auto-toggle feature to good effect here. */
10442       
10443       D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10444       emitcode("mov", "dps,#!constbyte",0x21);  /* Select DPTR2 & auto-toggle. */
10445       emitcode ("mov", "dptr,#%s", rSym->rname); 
10446       /* DP2 = result, DP1 = right, DP1 is current. */
10447       while (size)
10448       {
10449           emitcode("movx", "a,@dptr");
10450           emitcode("movx", "@dptr,a");
10451           if (--size)
10452           {
10453                emitcode("inc", "dptr");
10454                emitcode("inc", "dptr");
10455           }
10456       }
10457       emitcode("mov", "dps,#0");
10458       freeAsmop (right, NULL, ic, FALSE);
10459 #if 0
10460 some alternative code for processors without auto-toggle
10461 no time to test now, so later well put in...kpb
10462         D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10463         emitcode("mov", "dps,#1");      /* Select DPTR2. */
10464         emitcode ("mov", "dptr,#%s", rSym->rname); 
10465         /* DP2 = result, DP1 = right, DP1 is current. */
10466         while (size)
10467         {
10468           --size;
10469           emitcode("movx", "a,@dptr");
10470           if (size)
10471             emitcode("inc", "dptr");
10472           emitcode("inc", "dps");
10473           emitcode("movx", "@dptr,a");
10474           if (size)
10475             emitcode("inc", "dptr");
10476           emitcode("inc", "dps");
10477         }
10478         emitcode("mov", "dps,#0");
10479         freeAsmop (right, NULL, ic, FALSE);
10480 #endif
10481   }
10482   else
10483   {
10484       D (emitcode (";", "genFarFarAssign"););
10485       aopOp (result, ic, TRUE, TRUE);
10486
10487       _startLazyDPSEvaluation ();
10488       
10489       while (size--)
10490         {
10491           aopPut (AOP (result),
10492                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
10493           offset++;
10494         }
10495       _endLazyDPSEvaluation ();
10496       freeAsmop (result, NULL, ic, FALSE);
10497       freeAsmop (right, NULL, ic, FALSE);
10498   }
10499 }
10500
10501 /*-----------------------------------------------------------------*/
10502 /* genAssign - generate code for assignment                        */
10503 /*-----------------------------------------------------------------*/
10504 static void
10505 genAssign (iCode * ic)
10506 {
10507   operand *result, *right;
10508   int size, offset;
10509   unsigned long lit = 0L;
10510
10511   D (emitcode (";", "genAssign ");
10512     );
10513
10514   result = IC_RESULT (ic);
10515   right = IC_RIGHT (ic);
10516
10517   /* if they are the same */
10518   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10519     return;
10520
10521   aopOp (right, ic, FALSE, FALSE);
10522
10523   emitcode (";", "genAssign: resultIsFar = %s",
10524             isOperandInFarSpace (result) ?
10525             "TRUE" : "FALSE");
10526
10527   /* special case both in far space */
10528   if ((AOP_TYPE (right) == AOP_DPTR ||
10529        AOP_TYPE (right) == AOP_DPTR2) &&
10530   /* IS_TRUE_SYMOP(result)       && */
10531       isOperandInFarSpace (result))
10532     {
10533       genFarFarAssign (result, right, ic);
10534       return;
10535     }
10536
10537   aopOp (result, ic, TRUE, FALSE);
10538
10539   /* if they are the same registers */
10540   if (sameRegs (AOP (right), AOP (result)))
10541     goto release;
10542
10543   /* if the result is a bit */
10544   if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10545     {
10546       /* if the right size is a literal then
10547          we know what the value is */
10548       if (AOP_TYPE (right) == AOP_LIT)
10549         {
10550           if (((int) operandLitValue (right)))
10551             aopPut (AOP (result), one, 0);
10552           else
10553             aopPut (AOP (result), zero, 0);
10554           goto release;
10555         }
10556
10557       /* the right is also a bit variable */
10558       if (AOP_TYPE (right) == AOP_CRY)
10559         {
10560           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10561           aopPut (AOP (result), "c", 0);
10562           goto release;
10563         }
10564
10565       /* we need to or */
10566       toBoolean (right);
10567       aopPut (AOP (result), "a", 0);
10568       goto release;
10569     }
10570
10571   /* bit variables done */
10572   /* general case */
10573   size = AOP_SIZE (result);
10574   offset = 0;
10575   if (AOP_TYPE (right) == AOP_LIT)
10576     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10577
10578   if ((size > 1) &&
10579       (AOP_TYPE (result) != AOP_REG) &&
10580       (AOP_TYPE (right) == AOP_LIT) &&
10581       !IS_FLOAT (operandType (right)))
10582     {
10583       _startLazyDPSEvaluation ();
10584       while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10585         {
10586           aopPut (AOP (result),
10587                   aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
10588                   offset);
10589           offset++;
10590           size--;
10591         }
10592       /* And now fill the rest with zeros. */
10593       if (size)
10594         {
10595           emitcode ("clr", "a");
10596         }
10597       while (size--)
10598         {
10599           aopPut (AOP (result), "a", offset++);
10600         }
10601       _endLazyDPSEvaluation ();
10602     }
10603   else
10604     {
10605       _startLazyDPSEvaluation ();
10606       while (size--)
10607         {
10608           aopPut (AOP (result),
10609                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10610                   offset);
10611           offset++;
10612         }
10613       _endLazyDPSEvaluation ();
10614     }
10615
10616 release:
10617   freeAsmop (right, NULL, ic, FALSE);
10618   freeAsmop (result, NULL, ic, TRUE);
10619 }
10620
10621 /*-----------------------------------------------------------------*/
10622 /* genJumpTab - generates code for jump table                      */
10623 /*-----------------------------------------------------------------*/
10624 static void
10625 genJumpTab (iCode * ic)
10626 {
10627   symbol *jtab;
10628   char *l;
10629
10630   D (emitcode (";", "genJumpTab ");
10631     );
10632
10633   aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10634   /* get the condition into accumulator */
10635   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
10636   MOVA (l);
10637   /* multiply by four! */
10638   emitcode ("add", "a,acc");
10639   emitcode ("add", "a,acc");
10640   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10641
10642   jtab = newiTempLabel (NULL);
10643   emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
10644   emitcode ("jmp", "@a+dptr");
10645   emitcode ("", "!tlabeldef", jtab->key + 100);
10646   /* now generate the jump labels */
10647   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10648        jtab = setNextItem (IC_JTLABELS (ic)))
10649     emitcode ("ljmp", "!tlabel", jtab->key + 100);
10650
10651 }
10652
10653 /*-----------------------------------------------------------------*/
10654 /* genCast - gen code for casting                                  */
10655 /*-----------------------------------------------------------------*/
10656 static void
10657 genCast (iCode * ic)
10658 {
10659   operand *result = IC_RESULT (ic);
10660   sym_link *ctype = operandType (IC_LEFT (ic));
10661   sym_link *rtype = operandType (IC_RIGHT (ic));
10662   operand *right = IC_RIGHT (ic);
10663   int size, offset;
10664
10665   D (emitcode (";", "genCast ");
10666     );
10667
10668   /* if they are equivalent then do nothing */
10669   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10670     return;
10671
10672   aopOp (right, ic, FALSE, FALSE);
10673   aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
10674
10675   /* if the result is a bit */
10676   // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10677   if (IS_BITVAR(OP_SYMBOL(result)->type))
10678     {
10679       /* if the right size is a literal then
10680          we know what the value is */
10681       if (AOP_TYPE (right) == AOP_LIT)
10682         {
10683           if (((int) operandLitValue (right)))
10684             aopPut (AOP (result), one, 0);
10685           else
10686             aopPut (AOP (result), zero, 0);
10687
10688           goto release;
10689         }
10690
10691       /* the right is also a bit variable */
10692       if (AOP_TYPE (right) == AOP_CRY)
10693         {
10694           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10695           aopPut (AOP (result), "c", 0);
10696           goto release;
10697         }
10698
10699       /* we need to or */
10700       toBoolean (right);
10701       aopPut (AOP (result), "a", 0);
10702       goto release;
10703     }
10704
10705   /* if they are the same size : or less */
10706   if (AOP_SIZE (result) <= AOP_SIZE (right))
10707     {
10708
10709       /* if they are in the same place */
10710       if (sameRegs (AOP (right), AOP (result)))
10711         goto release;
10712
10713       /* if they in different places then copy */
10714       size = AOP_SIZE (result);
10715       offset = 0;
10716       _startLazyDPSEvaluation ();
10717       while (size--)
10718         {
10719           aopPut (AOP (result),
10720                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10721                   offset);
10722           offset++;
10723         }
10724       _endLazyDPSEvaluation ();
10725       goto release;
10726     }
10727
10728
10729   /* if the result is of type pointer */
10730   if (IS_PTR (ctype))
10731     {
10732
10733       int p_type;
10734       sym_link *type = operandType (right);
10735
10736       /* pointer to generic pointer */
10737       if (IS_GENPTR (ctype))
10738         {
10739           char *l = zero;
10740
10741           if (IS_PTR (type))
10742             {
10743               p_type = DCL_TYPE (type);
10744             }
10745           else
10746             {
10747 #if OLD_CAST_BEHAVIOR
10748               /* KV: we are converting a non-pointer type to
10749                * a generic pointer. This (ifdef'd out) code
10750                * says that the resulting generic pointer
10751                * should have the same class as the storage
10752                * location of the non-pointer variable.
10753                *
10754                * For example, converting an int (which happens
10755                * to be stored in DATA space) to a pointer results
10756                * in a DATA generic pointer; if the original int
10757                * in XDATA space, so will be the resulting pointer.
10758                *
10759                * I don't like that behavior, and thus this change:
10760                * all such conversions will be forced to XDATA and
10761                * throw a warning. If you want some non-XDATA
10762                * type, or you want to suppress the warning, you
10763                * must go through an intermediate cast, like so:
10764                *
10765                * char _generic *gp = (char _xdata *)(intVar);
10766                */
10767               sym_link *etype = getSpec (type);
10768
10769               /* we have to go by the storage class */
10770               if (SPEC_OCLS (etype) != generic)
10771                 {
10772                   p_type = PTR_TYPE (SPEC_OCLS (etype));
10773                 }
10774               else
10775 #endif
10776                 {
10777                   /* Converting unknown class (i.e. register variable)
10778                    * to generic pointer. This is not good, but
10779                    * we'll make a guess (and throw a warning).
10780                    */
10781                   p_type = FPOINTER;
10782                   werror (W_INT_TO_GEN_PTR_CAST);
10783                 }
10784             }
10785
10786           /* the first two bytes are known */
10787           size = GPTRSIZE - 1;
10788           offset = 0;
10789           _startLazyDPSEvaluation ();
10790           while (size--)
10791             {
10792               aopPut (AOP (result),
10793                       aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10794                       offset);
10795               offset++;
10796             }
10797           _endLazyDPSEvaluation ();
10798
10799           /* the last byte depending on type */
10800           switch (p_type)
10801             {
10802             case IPOINTER:
10803             case POINTER:
10804               l = zero;
10805               break;
10806             case FPOINTER:
10807               l = one;
10808               break;
10809             case CPOINTER:
10810               l = "#0x02";
10811               break;
10812             case PPOINTER:
10813               l = "#0x03";
10814               break;
10815
10816             default:
10817               /* this should never happen */
10818               werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10819                       "got unknown pointer type");
10820               exit (1);
10821             }
10822           aopPut (AOP (result), l, GPTRSIZE - 1);
10823           goto release;
10824         }
10825
10826       /* just copy the pointers */
10827       size = AOP_SIZE (result);
10828       offset = 0;
10829       _startLazyDPSEvaluation ();
10830       while (size--)
10831         {
10832           aopPut (AOP (result),
10833                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10834                   offset);
10835           offset++;
10836         }
10837       _endLazyDPSEvaluation ();
10838       goto release;
10839     }
10840
10841   /* so we now know that the size of destination is greater
10842      than the size of the source */
10843   /* we move to result for the size of source */
10844   size = AOP_SIZE (right);
10845   offset = 0;
10846   _startLazyDPSEvaluation ();
10847   while (size--)
10848     {
10849       aopPut (AOP (result),
10850               aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10851               offset);
10852       offset++;
10853     }
10854   _endLazyDPSEvaluation ();
10855
10856   /* now depending on the sign of the source && destination */
10857   size = AOP_SIZE (result) - AOP_SIZE (right);
10858   /* if unsigned or not an integral type */
10859   /* also, if the source is a bit, we don't need to sign extend, because
10860    * it can't possibly have set the sign bit.
10861    */
10862   if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
10863     {
10864       while (size--)
10865         {
10866           aopPut (AOP (result), zero, offset++);
10867         }
10868     }
10869   else
10870     {
10871       /* we need to extend the sign :{ */
10872       char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
10873                         FALSE, FALSE, TRUE);
10874       MOVA (l);
10875       emitcode ("rlc", "a");
10876       emitcode ("subb", "a,acc");
10877       while (size--)
10878         aopPut (AOP (result), "a", offset++);
10879     }
10880
10881   /* we are done hurray !!!! */
10882
10883 release:
10884   freeAsmop (right, NULL, ic, TRUE);
10885   freeAsmop (result, NULL, ic, TRUE);
10886
10887 }
10888
10889 /*-----------------------------------------------------------------*/
10890 /* genDjnz - generate decrement & jump if not zero instrucion      */
10891 /*-----------------------------------------------------------------*/
10892 static int
10893 genDjnz (iCode * ic, iCode * ifx)
10894 {
10895   symbol *lbl, *lbl1;
10896   if (!ifx)
10897     return 0;
10898
10899   /* if the if condition has a false label
10900      then we cannot save */
10901   if (IC_FALSE (ifx))
10902     return 0;
10903
10904   /* if the minus is not of the form
10905      a = a - 1 */
10906   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
10907       !IS_OP_LITERAL (IC_RIGHT (ic)))
10908     return 0;
10909
10910   if (operandLitValue (IC_RIGHT (ic)) != 1)
10911     return 0;
10912
10913   /* if the size of this greater than one then no
10914      saving */
10915   if (getSize (operandType (IC_RESULT (ic))) > 1)
10916     return 0;
10917
10918   /* otherwise we can save BIG */
10919   D(emitcode(";", "genDjnz"););
10920
10921   lbl = newiTempLabel (NULL);
10922   lbl1 = newiTempLabel (NULL);
10923
10924   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10925
10926   if (AOP_NEEDSACC(IC_RESULT(ic)))
10927   {
10928       /* If the result is accessed indirectly via
10929        * the accumulator, we must explicitly write
10930        * it back after the decrement.
10931        */
10932       char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
10933       
10934       if (strcmp(rByte, "a"))
10935       {
10936            /* Something is hopelessly wrong */
10937            fprintf(stderr, "*** warning: internal error at %s:%d\n",
10938                    __FILE__, __LINE__);
10939            /* We can just give up; the generated code will be inefficient,
10940             * but what the hey.
10941             */
10942            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10943            return 0;
10944       }
10945       emitcode ("dec", "%s", rByte);
10946       aopPut(AOP(IC_RESULT(ic)), rByte, 0);
10947       emitcode ("jnz", "!tlabel", lbl->key + 100);
10948   }
10949   else if (IS_AOP_PREG (IC_RESULT (ic)))
10950     {
10951       emitcode ("dec", "%s",
10952                 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10953       emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10954       emitcode ("jnz", "!tlabel", lbl->key + 100);
10955     }
10956   else
10957     {
10958       emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
10959                 lbl->key + 100);
10960     }
10961   emitcode ("sjmp", "!tlabel", lbl1->key + 100);
10962   emitcode ("", "!tlabeldef", lbl->key + 100);
10963   emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
10964   emitcode ("", "!tlabeldef", lbl1->key + 100);
10965
10966   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10967   ifx->generated = 1;
10968   return 1;
10969 }
10970
10971 /*-----------------------------------------------------------------*/
10972 /* genReceive - generate code for a receive iCode                  */
10973 /*-----------------------------------------------------------------*/
10974 static void
10975 genReceive (iCode * ic)
10976 {
10977
10978     int size = getSize (operandType (IC_RESULT (ic)));
10979     int offset = 0;
10980     int rb1off ;
10981     
10982     D (emitcode (";", "genReceive ");
10983        );
10984
10985   if (ic->argreg == 1) { /* first parameter */
10986       if (isOperandInFarSpace (IC_RESULT (ic)) &&
10987           (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
10988            IS_TRUE_SYMOP (IC_RESULT (ic))))
10989           {
10990               offset = fReturnSizeDS390 - size;
10991               while (size--)
10992                   {
10993                       emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
10994                                                fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
10995                       offset++;
10996                   }
10997               aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10998               size = AOP_SIZE (IC_RESULT (ic));
10999               offset = 0;
11000               while (size--)
11001                   {
11002                       emitcode ("pop", "acc");
11003                       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
11004                   }
11005               
11006           } else {
11007               _G.accInUse++;
11008               aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11009               _G.accInUse--;
11010               assignResultValue (IC_RESULT (ic));
11011           }
11012   } else { /* second receive onwards */
11013       /* this gets a little tricky since unused recevies will be
11014          eliminated, we have saved the reg in the type field . and
11015          we use that to figure out which register to use */
11016       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11017       rb1off = ic->argreg;
11018       while (size--) {
11019           aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11020       }
11021       
11022   }
11023   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11024 }
11025
11026 /*-----------------------------------------------------------------*/
11027 /* genMemcpyX2X - gen code for memcpy xdata to xdata               */
11028 /*-----------------------------------------------------------------*/
11029 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11030 {
11031     operand *from , *to , *count;
11032     symbol *lbl;
11033     bitVect *rsave;
11034     int i;
11035
11036     /* we know it has to be 3 parameters */
11037     assert (nparms == 3);
11038     
11039     rsave = newBitVect(16);
11040     /* save DPTR if it needs to be saved */
11041     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11042             if (bitVectBitValue(ic->rMask,i))
11043                     rsave = bitVectSetBit(rsave,i);
11044     }
11045     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11046                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11047     savermask(rsave);
11048     
11049     to = parms[0];
11050     from = parms[1];
11051     count = parms[2];
11052
11053     aopOp (from, ic->next, FALSE, FALSE);
11054
11055     /* get from into DPTR1 */
11056     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, TRUE));
11057     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, TRUE));
11058     if (options.model == MODEL_FLAT24) {
11059         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, TRUE));
11060     }
11061
11062     freeAsmop (from, NULL, ic, FALSE);
11063     aopOp (to, ic, FALSE, FALSE);
11064     /* get "to" into DPTR */
11065     /* if the operand is already in dptr
11066        then we do nothing else we move the value to dptr */
11067     if (AOP_TYPE (to) != AOP_STR) {
11068         /* if already in DPTR then we need to push */
11069         if (AOP_TYPE(to) == AOP_DPTR) {
11070             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
11071             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
11072             if (options.model == MODEL_FLAT24)
11073                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11074             emitcode ("pop", "dph");
11075             emitcode ("pop", "dpl");        
11076         } else {
11077             _startLazyDPSEvaluation ();
11078             /* if this is remateriazable */
11079             if (AOP_TYPE (to) == AOP_IMMD) {
11080                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
11081             } else {                    /* we need to get it byte by byte */
11082                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
11083                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
11084                 if (options.model == MODEL_FLAT24) {
11085                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11086                 }
11087             }
11088             _endLazyDPSEvaluation ();
11089         }
11090     }
11091     freeAsmop (to, NULL, ic, FALSE);
11092
11093     aopOp (count, ic->next->next, FALSE,FALSE);
11094     lbl =newiTempLabel(NULL);
11095
11096     /* now for the actual copy */
11097     if (AOP_TYPE(count) == AOP_LIT && 
11098         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11099         emitcode (";","OH  JOY auto increment with djnz (very fast)");
11100         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
11101         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
11102         emitcode ("","!tlabeldef",lbl->key+100);
11103         if (fromc) {
11104             emitcode ("clr","a");
11105             emitcode ("movc", "a,@a+dptr");
11106         } else 
11107             emitcode ("movx", "a,@dptr");
11108         emitcode ("movx", "@dptr,a");
11109         emitcode ("inc", "dptr");
11110         emitcode ("inc", "dptr");
11111         emitcode ("djnz","b,!tlabel",lbl->key+100);
11112     } else {
11113         symbol *lbl1 = newiTempLabel(NULL);
11114         
11115         emitcode (";"," Auto increment but no djnz");
11116         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
11117         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
11118         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
11119         emitcode ("","!tlabeldef",lbl->key+100);
11120         if (fromc) {
11121             emitcode ("clr","a");
11122             emitcode ("movc", "a,@a+dptr");
11123         } else 
11124             emitcode ("movx", "a,@dptr");
11125         emitcode ("movx", "@dptr,a");
11126         emitcode ("inc", "dptr");
11127         emitcode ("inc", "dptr");
11128         emitcode ("mov","a,b");
11129         emitcode ("orl","a,_ap");
11130         emitcode ("jz","!tlabel",lbl1->key+100);
11131         emitcode ("mov","a,_ap");
11132         emitcode ("add","a,#!constbyte",0xFF);
11133         emitcode ("mov","_ap,a");
11134         emitcode ("mov","a,b");
11135         emitcode ("addc","a,#!constbyte",0xFF);
11136         emitcode ("mov","b,a");
11137         emitcode ("sjmp","!tlabel",lbl->key+100);
11138         emitcode ("","!tlabeldef",lbl1->key+100);
11139     }
11140     emitcode ("mov", "dps,#0"); 
11141     freeAsmop (count, NULL, ic, FALSE);
11142     unsavermask(rsave);
11143
11144 }
11145
11146 /*-----------------------------------------------------------------*/
11147 /* genMemcmpX2X - gen code for memcmp xdata to xdata               */
11148 /*-----------------------------------------------------------------*/
11149 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
11150 {
11151     operand *from , *to , *count;
11152     symbol *lbl,*lbl2;
11153     bitVect *rsave;
11154     int i;
11155
11156     /* we know it has to be 3 parameters */
11157     assert (nparms == 3);
11158     
11159     rsave = newBitVect(16);
11160     /* save DPTR if it needs to be saved */
11161     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11162             if (bitVectBitValue(ic->rMask,i))
11163                     rsave = bitVectSetBit(rsave,i);
11164     }
11165     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11166                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11167     savermask(rsave);
11168     
11169     to = parms[0];
11170     from = parms[1];
11171     count = parms[2];
11172
11173     aopOp (from, ic->next, FALSE, FALSE);
11174
11175     /* get from into DPTR1 */
11176     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, TRUE));
11177     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, TRUE));
11178     if (options.model == MODEL_FLAT24) {
11179         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, TRUE));
11180     }
11181
11182     freeAsmop (from, NULL, ic, FALSE);
11183     aopOp (to, ic, FALSE, FALSE);
11184     /* get "to" into DPTR */
11185     /* if the operand is already in dptr
11186        then we do nothing else we move the value to dptr */
11187     if (AOP_TYPE (to) != AOP_STR) {
11188         /* if already in DPTR then we need to push */
11189         if (AOP_TYPE(to) == AOP_DPTR) {
11190             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
11191             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
11192             if (options.model == MODEL_FLAT24)
11193                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11194             emitcode ("pop", "dph");
11195             emitcode ("pop", "dpl");        
11196         } else {
11197             _startLazyDPSEvaluation ();
11198             /* if this is remateriazable */
11199             if (AOP_TYPE (to) == AOP_IMMD) {
11200                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
11201             } else {                    /* we need to get it byte by byte */
11202                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
11203                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
11204                 if (options.model == MODEL_FLAT24) {
11205                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11206                 }
11207             }
11208             _endLazyDPSEvaluation ();
11209         }
11210     }
11211     freeAsmop (to, NULL, ic, FALSE);
11212
11213     aopOp (count, ic->next->next, FALSE,FALSE);
11214     lbl =newiTempLabel(NULL);
11215     lbl2 =newiTempLabel(NULL);
11216
11217     /* now for the actual compare */
11218     emitcode("push","ar0");
11219     if (AOP_TYPE(count) == AOP_LIT && 
11220         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11221         emitcode (";","OH  JOY auto increment with djnz (very fast)");
11222         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
11223         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
11224         emitcode ("","!tlabeldef",lbl->key+100);
11225         if (fromc) {
11226             emitcode ("clr","a");
11227             emitcode ("movc", "a,@a+dptr");
11228         } else 
11229             emitcode ("movx", "a,@dptr");
11230         emitcode ("mov","r0,a");
11231         emitcode ("movx", "a,@dptr");
11232         emitcode ("clr","c");
11233         emitcode ("subb","a,r0");
11234         emitcode ("jnz","!tlabel",lbl2->key+100);
11235         emitcode ("inc", "dptr");
11236         emitcode ("inc", "dptr");
11237         emitcode ("djnz","b,!tlabel",lbl->key+100);
11238         emitcode ("clr","a");   
11239     } else {
11240         symbol *lbl1 = newiTempLabel(NULL);
11241         
11242         emitcode (";"," Auto increment but no djnz");
11243         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
11244         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
11245         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
11246         emitcode ("","!tlabeldef",lbl->key+100);
11247         if (fromc) {
11248             emitcode ("clr","a");
11249             emitcode ("movc", "a,@a+dptr");
11250         } else 
11251             emitcode ("movx", "a,@dptr");
11252         emitcode ("mov","r0,a");
11253         emitcode ("movx", "a,@dptr");
11254         emitcode ("clr","c");
11255         emitcode ("subb","a,r0");
11256         emitcode ("jnz","!tlabel",lbl2->key+100);
11257         emitcode ("inc", "dptr");
11258         emitcode ("inc", "dptr");
11259         emitcode ("mov","a,b");
11260         emitcode ("orl","a,_ap");
11261         emitcode ("jz","!tlabel",lbl1->key+100);
11262         emitcode ("mov","a,_ap");
11263         emitcode ("add","a,#!constbyte",0xFF);
11264         emitcode ("mov","_ap,a");
11265         emitcode ("mov","a,b");
11266         emitcode ("addc","a,#!constbyte",0xFF);
11267         emitcode ("mov","b,a");
11268         emitcode ("sjmp","!tlabel",lbl->key+100);
11269         emitcode ("","!tlabeldef",lbl1->key+100);
11270         emitcode ("clr","a");
11271     }
11272     freeAsmop (count, NULL, ic, FALSE);
11273     emitcode ("","!tlabeldef",lbl2->key+100);
11274     aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11275     aopPut(AOP(IC_RESULT(ic)),"a",0);
11276     freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11277     emitcode("pop","ar0");
11278     emitcode ("mov", "dps,#0"); 
11279     
11280     unsavermask(rsave);
11281
11282 }
11283
11284 /*-----------------------------------------------------------------*/
11285 /* genInp - gen code for __builtin_inp read data from a mem mapped */
11286 /* port, first parameter output area second parameter pointer to   */
11287 /* port third parameter count                                      */
11288 /*-----------------------------------------------------------------*/
11289 static void genInp( iCode *ic, int nparms, operand **parms)
11290 {
11291     operand *from , *to , *count;
11292     symbol *lbl;
11293     bitVect *rsave;
11294     int i;
11295
11296     /* we know it has to be 3 parameters */
11297     assert (nparms == 3);
11298     
11299     rsave = newBitVect(16);
11300     /* save DPTR if it needs to be saved */
11301     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11302             if (bitVectBitValue(ic->rMask,i))
11303                     rsave = bitVectSetBit(rsave,i);
11304     }
11305     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11306                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11307     savermask(rsave);
11308     
11309     to = parms[0];
11310     from = parms[1];
11311     count = parms[2];
11312
11313     aopOp (from, ic->next, FALSE, FALSE);
11314
11315     /* get from into DPTR1 */
11316     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, TRUE));
11317     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, TRUE));
11318     if (options.model == MODEL_FLAT24) {
11319         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, TRUE));
11320     }
11321
11322     freeAsmop (from, NULL, ic, FALSE);
11323     aopOp (to, ic, FALSE, FALSE);
11324     /* get "to" into DPTR */
11325     /* if the operand is already in dptr
11326        then we do nothing else we move the value to dptr */
11327     if (AOP_TYPE (to) != AOP_STR) {
11328         /* if already in DPTR then we need to push */
11329         if (AOP_TYPE(to) == AOP_DPTR) {
11330             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
11331             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
11332             if (options.model == MODEL_FLAT24)
11333                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11334             emitcode ("pop", "dph");
11335             emitcode ("pop", "dpl");        
11336         } else {
11337             _startLazyDPSEvaluation ();
11338             /* if this is remateriazable */
11339             if (AOP_TYPE (to) == AOP_IMMD) {
11340                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
11341             } else {                    /* we need to get it byte by byte */
11342                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
11343                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
11344                 if (options.model == MODEL_FLAT24) {
11345                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11346                 }
11347             }
11348             _endLazyDPSEvaluation ();
11349         }
11350     }
11351     freeAsmop (to, NULL, ic, FALSE);
11352
11353     aopOp (count, ic->next->next, FALSE,FALSE);
11354     lbl =newiTempLabel(NULL);
11355
11356     /* now for the actual copy */
11357     if (AOP_TYPE(count) == AOP_LIT && 
11358         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11359         emitcode (";","OH  JOY auto increment with djnz (very fast)");
11360         emitcode ("mov", "dps,#!constbyte",0x1);        /* Select DPTR2 */
11361         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
11362         emitcode ("","!tlabeldef",lbl->key+100);
11363         emitcode ("movx", "a,@dptr");   /* read data from port */
11364         emitcode ("dec","dps");         /* switch to DPTR */
11365         emitcode ("movx", "@dptr,a");   /* save into location */
11366         emitcode ("inc", "dptr");       /* point to next area */
11367         emitcode ("inc","dps");         /* switch to DPTR2 */
11368         emitcode ("djnz","b,!tlabel",lbl->key+100);
11369     } else {
11370         symbol *lbl1 = newiTempLabel(NULL);
11371         
11372         emitcode (";"," Auto increment but no djnz");
11373         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
11374         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
11375         emitcode ("mov", "dps,#!constbyte",0x1);        /* Select DPTR2 */
11376         emitcode ("","!tlabeldef",lbl->key+100);
11377         emitcode ("movx", "a,@dptr");
11378         emitcode ("dec","dps");         /* switch to DPTR */
11379         emitcode ("movx", "@dptr,a");
11380         emitcode ("inc", "dptr");
11381         emitcode ("inc","dps");         /* switch to DPTR2 */
11382 /*      emitcode ("djnz","b,!tlabel",lbl->key+100); */
11383 /*      emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
11384         emitcode ("mov","a,b");
11385         emitcode ("orl","a,_ap");
11386         emitcode ("jz","!tlabel",lbl1->key+100);
11387         emitcode ("mov","a,_ap");
11388         emitcode ("add","a,#!constbyte",0xFF);
11389         emitcode ("mov","_ap,a");
11390         emitcode ("mov","a,b");
11391         emitcode ("addc","a,#!constbyte",0xFF);
11392         emitcode ("mov","b,a");
11393         emitcode ("sjmp","!tlabel",lbl->key+100);
11394         emitcode ("","!tlabeldef",lbl1->key+100);
11395     }
11396     emitcode ("mov", "dps,#0"); 
11397     freeAsmop (count, NULL, ic, FALSE);
11398     unsavermask(rsave);
11399
11400 }
11401
11402 /*-----------------------------------------------------------------*/
11403 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
11404 /* port, first parameter output area second parameter pointer to   */
11405 /* port third parameter count                                      */
11406 /*-----------------------------------------------------------------*/
11407 static void genOutp( iCode *ic, int nparms, operand **parms)
11408 {
11409     operand *from , *to , *count;
11410     symbol *lbl;
11411     bitVect *rsave;
11412     int i;
11413
11414     /* we know it has to be 3 parameters */
11415     assert (nparms == 3);
11416     
11417     rsave = newBitVect(16);
11418     /* save DPTR if it needs to be saved */
11419     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11420             if (bitVectBitValue(ic->rMask,i))
11421                     rsave = bitVectSetBit(rsave,i);
11422     }
11423     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11424                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11425     savermask(rsave);
11426     
11427     to = parms[0];
11428     from = parms[1];
11429     count = parms[2];
11430
11431     aopOp (from, ic->next, FALSE, FALSE);
11432
11433     /* get from into DPTR1 */
11434     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, TRUE));
11435     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, TRUE));
11436     if (options.model == MODEL_FLAT24) {
11437         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, TRUE));
11438     }
11439
11440     freeAsmop (from, NULL, ic, FALSE);
11441     aopOp (to, ic, FALSE, FALSE);
11442     /* get "to" into DPTR */
11443     /* if the operand is already in dptr
11444        then we do nothing else we move the value to dptr */
11445     if (AOP_TYPE (to) != AOP_STR) {
11446         /* if already in DPTR then we need to push */
11447         if (AOP_TYPE(to) == AOP_DPTR) {
11448             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
11449             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
11450             if (options.model == MODEL_FLAT24)
11451                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11452             emitcode ("pop", "dph");
11453             emitcode ("pop", "dpl");        
11454         } else {
11455             _startLazyDPSEvaluation ();
11456             /* if this is remateriazable */
11457             if (AOP_TYPE (to) == AOP_IMMD) {
11458                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
11459             } else {                    /* we need to get it byte by byte */
11460                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
11461                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
11462                 if (options.model == MODEL_FLAT24) {
11463                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11464                 }
11465             }
11466             _endLazyDPSEvaluation ();
11467         }
11468     }
11469     freeAsmop (to, NULL, ic, FALSE);
11470
11471     aopOp (count, ic->next->next, FALSE,FALSE);
11472     lbl =newiTempLabel(NULL);
11473
11474     /* now for the actual copy */
11475     if (AOP_TYPE(count) == AOP_LIT && 
11476         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11477         emitcode (";","OH  JOY auto increment with djnz (very fast)");
11478         emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
11479         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
11480         emitcode ("","!tlabeldef",lbl->key+100);
11481         emitcode ("movx", "a,@dptr");   /* read data from port */
11482         emitcode ("inc","dps");         /* switch to DPTR2 */
11483         emitcode ("movx", "@dptr,a");   /* save into location */
11484         emitcode ("inc", "dptr");       /* point to next area */
11485         emitcode ("dec","dps");         /* switch to DPTR */
11486         emitcode ("djnz","b,!tlabel",lbl->key+100);
11487     } else {
11488         symbol *lbl1 = newiTempLabel(NULL);
11489         
11490         emitcode (";"," Auto increment but no djnz");
11491         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
11492         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
11493         emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
11494         emitcode ("","!tlabeldef",lbl->key+100);
11495 /*      emitcode ("push","acc"); */
11496         emitcode ("movx", "a,@dptr");
11497         emitcode ("inc", "dptr");
11498         emitcode ("inc","dps");         /* switch to DPTR2 */
11499         emitcode ("movx", "@dptr,a");
11500         emitcode ("dec","dps");         /* switch to DPTR */
11501 /*      emitcode ("pop","acc"); */
11502 /*      emitcode ("djnz","acc,!tlabel",lbl->key+100); */
11503 /*      emitcode ("djnz","b,!tlabel",lbl->key+100); */
11504         emitcode ("mov","a,b");
11505         emitcode ("orl","a,_ap");
11506         emitcode ("jz","!tlabel",lbl1->key+100);
11507         emitcode ("mov","a,_ap");
11508         emitcode ("add","a,#!constbyte",0xFF);
11509         emitcode ("mov","_ap,a");
11510         emitcode ("mov","a,b");
11511         emitcode ("addc","a,#!constbyte",0xFF);
11512         emitcode ("mov","b,a");
11513         emitcode ("sjmp","!tlabel",lbl->key+100);
11514         emitcode ("","!tlabeldef",lbl1->key+100);
11515     }
11516     emitcode ("mov", "dps,#0"); 
11517     freeAsmop (count, NULL, ic, FALSE);
11518     unsavermask(rsave);
11519
11520 }
11521
11522 /*-----------------------------------------------------------------*/
11523 /* genSwapW - swap lower & high order bytes                        */
11524 /*-----------------------------------------------------------------*/
11525 static void genSwapW(iCode *ic, int nparms, operand **parms)
11526 {
11527     operand *dest;
11528     operand *src;
11529     assert (nparms==1);
11530
11531     src = parms[0];
11532     dest=IC_RESULT(ic);
11533
11534     assert(getSize(operandType(src))==2);
11535
11536     aopOp (src, ic, FALSE, FALSE);
11537     emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,TRUE));
11538     _G.accInUse++;
11539     emitcode ("mov","b,%s",aopGet(AOP(src),1,FALSE,FALSE,FALSE));
11540     _G.accInUse--;
11541     freeAsmop (src, NULL, ic, FALSE);
11542     
11543     aopOp (dest,ic, FALSE, FALSE);
11544     aopPut(AOP(dest),"b",0);
11545     aopPut(AOP(dest),"a",1);
11546     freeAsmop (dest, NULL, ic, FALSE);    
11547 }
11548
11549 /*-----------------------------------------------------------------*/
11550 /* genMemsetX - gencode for memSetX data                           */
11551 /*-----------------------------------------------------------------*/
11552 static void genMemsetX(iCode *ic, int nparms, operand **parms)
11553 {
11554     operand *to , *val , *count;
11555     symbol *lbl;
11556     char *l;
11557     int i;
11558     bitVect *rsave = NULL;
11559
11560     /* we know it has to be 3 parameters */
11561     assert (nparms == 3);
11562     
11563     to = parms[0];
11564     val = parms[1];
11565     count = parms[2];
11566         
11567     /* save DPTR if it needs to be saved */
11568     rsave = newBitVect(16);
11569     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11570             if (bitVectBitValue(ic->rMask,i))
11571                     rsave = bitVectSetBit(rsave,i);
11572     }
11573     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11574                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11575     savermask(rsave);
11576
11577     aopOp (to, ic, FALSE, FALSE);
11578     /* get "to" into DPTR */
11579     /* if the operand is already in dptr
11580        then we do nothing else we move the value to dptr */
11581     if (AOP_TYPE (to) != AOP_STR) {
11582         /* if already in DPTR then we need to push */
11583         if (AOP_TYPE(to) == AOP_DPTR) {
11584             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
11585             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
11586             if (options.model == MODEL_FLAT24)
11587                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11588             emitcode ("pop", "dph");
11589             emitcode ("pop", "dpl");        
11590         } else {
11591             _startLazyDPSEvaluation ();
11592             /* if this is remateriazable */
11593             if (AOP_TYPE (to) == AOP_IMMD) {
11594                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
11595             } else {                    /* we need to get it byte by byte */
11596                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
11597                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
11598                 if (options.model == MODEL_FLAT24) {
11599                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11600                 }
11601             }
11602             _endLazyDPSEvaluation ();
11603         }
11604     }
11605     freeAsmop (to, NULL, ic, FALSE);
11606
11607     aopOp (val, ic->next->next, FALSE,FALSE);
11608     aopOp (count, ic->next->next, FALSE,FALSE);    
11609     lbl =newiTempLabel(NULL);
11610     /* now for the actual copy */
11611     if (AOP_TYPE(count) == AOP_LIT && 
11612         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11613         l = aopGet(AOP (val), 0, FALSE, FALSE, TRUE);
11614         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
11615         MOVA(l);
11616         emitcode ("","!tlabeldef",lbl->key+100);
11617         emitcode ("movx", "@dptr,a");
11618         emitcode ("inc", "dptr");
11619         emitcode ("djnz","b,!tlabel",lbl->key+100);
11620     } else {
11621         symbol *lbl1 = newiTempLabel(NULL);
11622         
11623         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
11624         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
11625         emitcode ("","!tlabeldef",lbl->key+100);
11626         l = aopGet(AOP (val), 0, FALSE, FALSE, TRUE);
11627         MOVA(l);
11628         emitcode ("movx", "@dptr,a");
11629         emitcode ("inc", "dptr");
11630         emitcode ("mov","a,b");
11631         emitcode ("orl","a,_ap");
11632         emitcode ("jz","!tlabel",lbl1->key+100);
11633         emitcode ("mov","a,_ap");
11634         emitcode ("add","a,#!constbyte",0xFF);
11635         emitcode ("mov","_ap,a");
11636         emitcode ("mov","a,b");
11637         emitcode ("addc","a,#!constbyte",0xFF);
11638         emitcode ("mov","b,a");
11639         emitcode ("sjmp","!tlabel",lbl->key+100);
11640         emitcode ("","!tlabeldef",lbl1->key+100);
11641     }
11642     freeAsmop (count, NULL, ic, FALSE);
11643     unsavermask(rsave);
11644 }
11645
11646 /*-----------------------------------------------------------------*/
11647 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
11648 /*-----------------------------------------------------------------*/
11649 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
11650 {
11651         bitVect *rsave ;
11652         operand *pnum, *result;
11653         int i;
11654     
11655         assert (nparms==1);
11656         /* save registers that need to be saved */
11657         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11658                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11659     
11660         pnum = parms[0]; 
11661         aopOp (pnum, ic, FALSE, FALSE);
11662         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,FALSE));
11663         freeAsmop (pnum, NULL, ic, FALSE);
11664         emitcode ("lcall","NatLib_LoadPrimitive");
11665         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11666         if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) || 
11667             aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
11668                 for (i = (size-1) ; i >= 0 ; i-- ) {
11669                         emitcode ("push","a%s",javaRet[i]);
11670                 }
11671                 for (i=0; i < size ; i++ ) {
11672                         emitcode ("pop","a%s",aopGet(AOP(result),i,FALSE,FALSE,FALSE));
11673                 }
11674         } else {
11675                 for (i = 0 ; i < size ; i++ ) {
11676                         aopPut(AOP(result),javaRet[i],i);
11677                 }
11678         }    
11679         freeAsmop (result, NULL, ic, FALSE);
11680         unsavermask(rsave);
11681 }
11682
11683 /*-----------------------------------------------------------------*/
11684 /* genNatLibLoadPointer - calls TINI api function to load pointer  */
11685 /*-----------------------------------------------------------------*/
11686 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
11687 {
11688         bitVect *rsave ;
11689         operand *pnum, *result;
11690         int size = 3;
11691         int i;
11692     
11693         assert (nparms==1);
11694         /* save registers that need to be saved */
11695         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11696                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11697     
11698         pnum = parms[0]; 
11699         aopOp (pnum, ic, FALSE, FALSE);
11700         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,FALSE));
11701         freeAsmop (pnum, NULL, ic, FALSE);
11702         emitcode ("lcall","NatLib_LoadPointer");
11703         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11704         if (AOP_TYPE(result)!=AOP_STR) {
11705                 for (i = 0 ; i < size ; i++ ) {
11706                         aopPut(AOP(result),fReturn[i],i);
11707                 }
11708         }    
11709         freeAsmop (result, NULL, ic, FALSE);
11710         unsavermask(rsave);
11711 }
11712
11713 /*-----------------------------------------------------------------*/
11714 /* genNatLibInstallStateBlock -                                    */
11715 /*-----------------------------------------------------------------*/
11716 static void genNatLibInstallStateBlock(iCode *ic, int nparms, 
11717                                        operand **parms, const char *name)
11718 {
11719         bitVect *rsave ;
11720         operand *psb, *handle;
11721         assert (nparms==2);
11722
11723         /* save registers that need to be saved */
11724         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11725                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11726         psb = parms[0];
11727         handle = parms[1];
11728
11729         /* put pointer to state block into DPTR1 */
11730         aopOp (psb, ic, FALSE, FALSE);
11731         if (AOP_TYPE (psb) == AOP_IMMD) {
11732                 emitcode ("mov","dps,#1");
11733                 emitcode ("mov", "dptr,%s", aopGet (AOP (psb), 0, TRUE, FALSE, FALSE));
11734                 emitcode ("mov","dps,#0");
11735         } else {
11736                 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,FALSE));
11737                 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,FALSE));
11738                 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,FALSE));
11739         }
11740         freeAsmop (psb, NULL, ic, FALSE);
11741
11742         /* put libraryID into DPTR */
11743         emitcode ("mov","dptr,#LibraryID");
11744
11745         /* put handle into r3:r2 */
11746         aopOp (handle, ic, FALSE, FALSE);
11747         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11748                 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));  
11749                 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11750                 emitcode ("pop","ar3");
11751                 emitcode ("pop","ar2");
11752         } else {        
11753                 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));        
11754                 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11755         }
11756         freeAsmop (psb, NULL, ic, FALSE);
11757
11758         /* make the call */
11759         emitcode ("lcall","NatLib_Install%sStateBlock",name);
11760
11761         /* put return value into place*/
11762         _G.accInUse++;
11763         aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
11764         _G.accInUse--;
11765         aopPut(AOP(IC_RESULT(ic)),"a",0);
11766         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11767         unsavermask(rsave);
11768 }
11769
11770 /*-----------------------------------------------------------------*/
11771 /* genNatLibRemoveStateBlock -                                     */
11772 /*-----------------------------------------------------------------*/
11773 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
11774 {
11775         bitVect *rsave ;
11776
11777         assert(nparms==0);
11778
11779         /* save registers that need to be saved */
11780         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11781                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11782
11783         /* put libraryID into DPTR */
11784         emitcode ("mov","dptr,#LibraryID");
11785         /* make the call */
11786         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
11787         unsavermask(rsave);
11788 }
11789
11790 /*-----------------------------------------------------------------*/
11791 /* genNatLibGetStateBlock -                                        */
11792 /*-----------------------------------------------------------------*/
11793 static void genNatLibGetStateBlock(iCode *ic,int nparms,
11794                                    operand **parms,const char *name)
11795 {
11796         bitVect *rsave ;
11797         symbol *lbl = newiTempLabel(NULL);
11798         
11799         assert(nparms==0);
11800         /* save registers that need to be saved */
11801         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11802                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11803
11804         /* put libraryID into DPTR */
11805         emitcode ("mov","dptr,#LibraryID");
11806         /* make the call */
11807         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
11808         emitcode ("jnz","!tlabel",lbl->key+100);
11809
11810         /* put return value into place */
11811         aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
11812         if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
11813                 emitcode ("push","ar3");
11814                 emitcode ("push","ar2");
11815                 emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,FALSE));
11816                 emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,FALSE));
11817         } else {
11818                 aopPut(AOP(IC_RESULT(ic)),"r2",0);
11819                 aopPut(AOP(IC_RESULT(ic)),"r3",1);
11820         }
11821         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11822         emitcode ("","!tlabeldef",lbl->key+100);
11823         unsavermask(rsave);
11824 }
11825
11826 /*-----------------------------------------------------------------*/
11827 /* genMMMalloc -                                                   */
11828 /*-----------------------------------------------------------------*/
11829 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
11830                          int size, const char *name)
11831 {
11832         bitVect *rsave ;
11833         operand *bsize;
11834         symbol *rsym;
11835         symbol *lbl = newiTempLabel(NULL);
11836
11837         assert (nparms == 1);
11838         /* save registers that need to be saved */
11839         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11840                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
11841         
11842         bsize=parms[0];
11843         aopOp (bsize,ic,FALSE,FALSE);
11844
11845         /* put the size in R4-R2 */
11846         if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
11847                 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,FALSE));
11848                 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,FALSE));
11849                 if (size==3) {
11850                         emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,FALSE));
11851                         emitcode("pop","ar4");
11852                 }
11853                 emitcode("pop","ar3");
11854                 emitcode("pop","ar2");          
11855         } else {
11856                 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,FALSE));
11857                 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,FALSE));
11858                 if (size==3) {
11859                         emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,FALSE));
11860                 }
11861         }
11862         freeAsmop (bsize, NULL, ic, FALSE);
11863
11864         /* make the call */
11865         emitcode ("lcall","MM_%s",name);
11866         emitcode ("jz","!tlabel",lbl->key+100);
11867         emitcode ("mov","r2,#!constbyte",0xff);
11868         emitcode ("mov","r3,#!constbyte",0xff);
11869         emitcode ("","!tlabeldef",lbl->key+100);
11870         /* we don't care about the pointer : we just save the handle */
11871         rsym = OP_SYMBOL(IC_RESULT(ic));
11872         if (rsym->liveFrom != rsym->liveTo) {
11873                 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
11874                 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
11875                         emitcode ("push","ar3");
11876                         emitcode ("push","ar2");
11877                         emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,FALSE));
11878                         emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,FALSE));
11879                 } else {
11880                         aopPut(AOP(IC_RESULT(ic)),"r2",0);
11881                         aopPut(AOP(IC_RESULT(ic)),"r3",1);
11882                 }
11883                 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11884         }
11885         unsavermask(rsave);
11886 }
11887
11888 /*-----------------------------------------------------------------*/
11889 /* genMMDeref -                                                    */
11890 /*-----------------------------------------------------------------*/
11891 static void genMMDeref (iCode *ic,int nparms, operand **parms)
11892 {
11893         bitVect *rsave ;
11894         operand *handle;
11895
11896         assert (nparms == 1);
11897         /* save registers that need to be saved */
11898         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11899                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
11900         
11901         handle=parms[0];
11902         aopOp (handle,ic,FALSE,FALSE);
11903
11904         /* put the size in R4-R2 */
11905         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11906                 emitcode("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11907                 emitcode("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11908                 emitcode("pop","ar3");
11909                 emitcode("pop","ar2");          
11910         } else {
11911                 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11912                 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11913         }
11914         freeAsmop (handle, NULL, ic, FALSE);
11915
11916         /* make the call */
11917         emitcode ("lcall","MM_Deref");
11918         
11919         {
11920                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11921                 if (rsym->liveFrom != rsym->liveTo) {                   
11922                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11923                         if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
11924                                 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
11925                                 aopPut(AOP(IC_RESULT(ic)),"dph",1);
11926                                 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
11927                         }
11928                 }
11929         }
11930         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11931         unsavermask(rsave);
11932 }
11933
11934 /*-----------------------------------------------------------------*/
11935 /* genMMUnrestrictedPersist -                                      */
11936 /*-----------------------------------------------------------------*/
11937 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
11938 {
11939         bitVect *rsave ;
11940         operand *handle;
11941
11942         assert (nparms == 1);
11943         /* save registers that need to be saved */
11944         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11945                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
11946         
11947         handle=parms[0];
11948         aopOp (handle,ic,FALSE,FALSE);
11949
11950         /* put the size in R3-R2 */
11951         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11952                 emitcode("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11953                 emitcode("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11954                 emitcode("pop","ar3");
11955                 emitcode("pop","ar2");          
11956         } else {
11957                 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11958                 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11959         }
11960         freeAsmop (handle, NULL, ic, FALSE);
11961
11962         /* make the call */
11963         emitcode ("lcall","MM_UnrestrictedPersist");
11964
11965         {
11966                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11967                 if (rsym->liveFrom != rsym->liveTo) {   
11968                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11969                         aopPut(AOP(IC_RESULT(ic)),"a",0);
11970                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11971                 }
11972         }
11973         unsavermask(rsave);
11974 }
11975
11976 /*-----------------------------------------------------------------*/
11977 /* genSystemExecJavaProcess -                                      */
11978 /*-----------------------------------------------------------------*/
11979 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
11980 {
11981         bitVect *rsave ;
11982         operand *handle, *pp;
11983
11984         assert (nparms==2);
11985         /* save registers that need to be saved */
11986         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11987                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
11988         
11989         pp = parms[0];
11990         handle = parms[1];
11991         
11992         /* put the handle in R3-R2 */
11993         aopOp (handle,ic,FALSE,FALSE);
11994         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11995                 emitcode("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11996                 emitcode("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11997                 emitcode("pop","ar3");
11998                 emitcode("pop","ar2");          
11999         } else {
12000                 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
12001                 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
12002         }
12003         freeAsmop (handle, NULL, ic, FALSE);
12004         
12005         /* put pointer in DPTR */
12006         aopOp (pp,ic,FALSE,FALSE);
12007         if (AOP_TYPE(pp) == AOP_IMMD) {
12008                 emitcode ("mov", "dptr,%s", aopGet (AOP (pp), 0, TRUE, FALSE, FALSE));          
12009         } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12010                 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,FALSE));
12011                 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,FALSE));
12012                 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,FALSE));
12013         }
12014         freeAsmop (handle, NULL, ic, FALSE);
12015
12016         /* make the call */
12017         emitcode ("lcall","System_ExecJavaProcess");
12018         
12019         /* put result in place */
12020         {
12021                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12022                 if (rsym->liveFrom != rsym->liveTo) {   
12023                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12024                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12025                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12026                 }
12027         }
12028         
12029         unsavermask(rsave);
12030 }
12031
12032 /*-----------------------------------------------------------------*/
12033 /* genSystemRTCRegisters -                                         */
12034 /*-----------------------------------------------------------------*/
12035 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12036                                   char *name)
12037 {
12038         bitVect *rsave ;
12039         operand *pp;
12040
12041         assert (nparms==1);
12042         /* save registers that need to be saved */
12043         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12044                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12045         
12046         pp=parms[0];
12047         /* put pointer in DPTR */
12048         aopOp (pp,ic,FALSE,FALSE);
12049         if (AOP_TYPE (pp) == AOP_IMMD) {
12050                 emitcode ("mov","dps,#1");
12051                 emitcode ("mov", "dptr,%s", aopGet (AOP (pp), 0, TRUE, FALSE, FALSE));
12052                 emitcode ("mov","dps,#0");
12053         } else {
12054                 emitcode ("mov","dpl1,%s",aopGet(AOP(pp),0,FALSE,FALSE,FALSE));
12055                 emitcode ("mov","dph1,%s",aopGet(AOP(pp),1,FALSE,FALSE,FALSE));
12056                 emitcode ("mov","dpx1,%s",aopGet(AOP(pp),2,FALSE,FALSE,FALSE));
12057         }
12058         freeAsmop (pp, NULL, ic, FALSE);
12059
12060         /* make the call */
12061         emitcode ("lcall","System_%sRTCRegisters",name);
12062
12063         unsavermask(rsave);
12064 }
12065
12066 /*-----------------------------------------------------------------*/
12067 /* genSystemThreadSleep -                                          */
12068 /*-----------------------------------------------------------------*/
12069 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12070 {
12071         bitVect *rsave ;
12072         operand *to, *s;
12073
12074         assert (nparms==1);
12075         /* save registers that need to be saved */
12076         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12077                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12078
12079         to = parms[0];
12080         aopOp(to,ic,FALSE,FALSE);
12081         if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
12082             aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
12083                 emitcode ("push","%s",aopGet(AOP(to),0,FALSE,TRUE,FALSE));
12084                 emitcode ("push","%s",aopGet(AOP(to),1,FALSE,TRUE,FALSE));
12085                 emitcode ("push","%s",aopGet(AOP(to),2,FALSE,TRUE,FALSE));
12086                 emitcode ("push","%s",aopGet(AOP(to),3,FALSE,TRUE,FALSE));
12087                 emitcode ("pop","ar3");
12088                 emitcode ("pop","ar2");
12089                 emitcode ("pop","ar1");
12090                 emitcode ("pop","ar0");
12091         } else {
12092                 emitcode ("mov","r0,%s",aopGet(AOP(to),0,FALSE,TRUE,FALSE));
12093                 emitcode ("mov","r1,%s",aopGet(AOP(to),1,FALSE,TRUE,FALSE));
12094                 emitcode ("mov","r2,%s",aopGet(AOP(to),2,FALSE,TRUE,FALSE));
12095                 emitcode ("mov","r3,%s",aopGet(AOP(to),3,FALSE,TRUE,FALSE));
12096         }
12097         freeAsmop (to, NULL, ic, FALSE);
12098
12099         /* suspend in acc */
12100         s = parms[1];
12101         aopOp(s,ic,FALSE,FALSE);
12102         emitcode ("mov","a,%s",aopGet(AOP(s),0,FALSE,TRUE,FALSE));
12103         freeAsmop (s, NULL, ic, FALSE);
12104
12105         /* make the call */
12106         emitcode ("lcall","System_%s",name);
12107
12108         unsavermask(rsave);
12109 }
12110
12111 /*-----------------------------------------------------------------*/
12112 /* genSystemThreadResume -                                         */
12113 /*-----------------------------------------------------------------*/
12114 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
12115 {
12116         bitVect *rsave ;
12117         operand *tid,*pid;
12118
12119         assert (nparms==2);
12120         /* save registers that need to be saved */
12121         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12122                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12123         
12124         tid = parms[0];
12125         pid = parms[1];
12126         
12127         /* PID in R0 */
12128         aopOp(pid,ic,FALSE,FALSE);
12129         emitcode ("mov","r0,%s",aopGet(AOP(pid),0,FALSE,TRUE,FALSE));
12130         freeAsmop (pid, NULL, ic, FALSE);
12131         
12132         /* tid into ACC */
12133         aopOp(tid,ic,FALSE,FALSE);
12134         emitcode ("mov","a,%s",aopGet(AOP(tid),0,FALSE,TRUE,FALSE));
12135         freeAsmop (tid, NULL, ic, FALSE);
12136         
12137         emitcode ("lcall","System_ThreadResume");
12138
12139         /* put result into place */
12140         {
12141                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12142                 if (rsym->liveFrom != rsym->liveTo) {   
12143                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12144                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12145                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12146                 }
12147         }
12148         unsavermask(rsave);
12149 }
12150
12151 /*-----------------------------------------------------------------*/
12152 /* genSystemProcessResume -                                        */
12153 /*-----------------------------------------------------------------*/
12154 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
12155 {
12156         bitVect *rsave ;
12157         operand *pid;
12158
12159         assert (nparms==1);
12160         /* save registers that need to be saved */
12161         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12162                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12163         
12164         pid = parms[0];
12165         
12166         /* pid into ACC */
12167         aopOp(pid,ic,FALSE,FALSE);
12168         emitcode ("mov","a,%s",aopGet(AOP(pid),0,FALSE,TRUE,FALSE));
12169         freeAsmop (pid, NULL, ic, FALSE);
12170         
12171         emitcode ("lcall","System_ProcessResume");
12172
12173         unsavermask(rsave);
12174 }
12175
12176 /*-----------------------------------------------------------------*/
12177 /* genSystem -                                                     */
12178 /*-----------------------------------------------------------------*/
12179 static void genSystem (iCode *ic,int nparms,char *name)
12180 {
12181         assert(nparms == 0);
12182
12183         emitcode ("lcall","System_%s",name);
12184 }
12185
12186 /*-----------------------------------------------------------------*/
12187 /* genSystemPoll -                                                  */
12188 /*-----------------------------------------------------------------*/
12189 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
12190 {
12191         bitVect *rsave ;
12192         operand *fp;
12193
12194         assert (nparms==1);
12195         /* save registers that need to be saved */
12196         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12197                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12198
12199         fp = parms[0];
12200         aopOp (fp,ic,FALSE,FALSE);
12201         if (AOP_TYPE (fp) == AOP_IMMD) {
12202                 emitcode ("mov", "dptr,%s", aopGet (AOP (fp), 0, TRUE, FALSE, FALSE));
12203         } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
12204                 emitcode ("mov","dpl,%s",aopGet(AOP(fp),0,FALSE,FALSE,FALSE));
12205                 emitcode ("mov","dph,%s",aopGet(AOP(fp),1,FALSE,FALSE,FALSE));
12206                 emitcode ("mov","dpx,%s",aopGet(AOP(fp),2,FALSE,FALSE,FALSE));
12207         }
12208         freeAsmop (fp, NULL, ic, FALSE);
12209
12210         emitcode ("lcall","System_%sPoll",name);
12211
12212         /* put result into place */
12213         {
12214                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12215                 if (rsym->liveFrom != rsym->liveTo) {   
12216                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12217                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12218                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12219                 }
12220         }
12221         unsavermask(rsave);
12222 }
12223
12224 /*-----------------------------------------------------------------*/
12225 /* genSystemGetCurrentID -                                         */
12226 /*-----------------------------------------------------------------*/
12227 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
12228 {
12229         assert (nparms==0);
12230
12231         emitcode ("lcall","System_GetCurrent%sId",name);
12232         /* put result into place */
12233         {
12234                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12235                 if (rsym->liveFrom != rsym->liveTo) {   
12236                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12237                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12238                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12239                 }
12240         }
12241 }
12242
12243 /*-----------------------------------------------------------------*/
12244 /* genBuiltIn - calls the appropriate function to  generating code */
12245 /* for a built in function                                         */
12246 /*-----------------------------------------------------------------*/
12247 static void genBuiltIn (iCode *ic)
12248 {
12249         operand *bi_parms[MAX_BUILTIN_ARGS];
12250         int nbi_parms;
12251         iCode *bi_iCode;
12252         symbol *bif;
12253
12254         /* get all the arguments for a built in function */
12255         bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
12256
12257         /* which function is it */
12258         bif = OP_SYMBOL(IC_LEFT(bi_iCode));
12259         if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
12260                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
12261         } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
12262                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
12263         } else  if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
12264                 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
12265         } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
12266                 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
12267         } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
12268                 genMemsetX(bi_iCode,nbi_parms,bi_parms);
12269         } else if (strcmp(bif->name,"__builtin_inp")==0) {
12270                 genInp(bi_iCode,nbi_parms,bi_parms);
12271         } else if (strcmp(bif->name,"__builtin_outp")==0) {
12272                 genOutp(bi_iCode,nbi_parms,bi_parms);
12273         } else if (strcmp(bif->name,"__builtin_swapw")==0) {
12274                 genSwapW(bi_iCode,nbi_parms,bi_parms);
12275                 /* JavaNative builtIns */               
12276         } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
12277                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
12278         } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
12279                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
12280         } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
12281                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
12282         } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
12283                 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
12284         } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
12285                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12286         } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
12287                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12288         } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
12289                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
12290         } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
12291                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
12292         } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
12293                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12294         } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
12295                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12296         } else if (strcmp(bif->name,"MM_XMalloc")==0) {
12297                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
12298         } else if (strcmp(bif->name,"MM_Malloc")==0) {
12299                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
12300         } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
12301                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
12302         } else if (strcmp(bif->name,"MM_Free")==0) {
12303                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
12304         } else if (strcmp(bif->name,"MM_Deref")==0) {
12305                 genMMDeref(bi_iCode,nbi_parms,bi_parms);
12306         } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
12307                 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
12308         } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
12309                 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
12310         } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
12311                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
12312         } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
12313                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
12314         } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
12315                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
12316         } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
12317                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
12318         } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
12319                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
12320         } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
12321                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
12322         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12323                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12324         } else if (strcmp(bif->name,"System_SaveThread")==0) {
12325                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12326         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12327                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12328         } else if (strcmp(bif->name,"System_ProcessResume")==0) {
12329                 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
12330         } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
12331                 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
12332         } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
12333                 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
12334         } else if (strcmp(bif->name,"System_ProcessYield")==0) {
12335                 genSystem(bi_iCode,nbi_parms,"ProcessYield");
12336         } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
12337                 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
12338         } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
12339                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
12340         } else if (strcmp(bif->name,"System_RemovePoll")==0) {
12341                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
12342         } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
12343                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
12344         } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
12345                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
12346         } else {
12347                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
12348                 return ;
12349         }
12350         return ;    
12351 }
12352
12353 /*-----------------------------------------------------------------*/
12354 /* gen390Code - generate code for Dallas 390 based controllers     */
12355 /*-----------------------------------------------------------------*/
12356 void
12357 gen390Code (iCode * lic)
12358 {
12359   iCode *ic;
12360   int cln = 0;
12361
12362   lineHead = lineCurr = NULL;
12363   dptrn[1][0] = "dpl1";
12364   dptrn[1][1] = "dph1";
12365   dptrn[1][2] = "dpx1";
12366   
12367   if (options.model == MODEL_FLAT24) {
12368     fReturnSizeDS390 = 5;
12369     fReturn = fReturn24;
12370   } else {
12371     fReturnSizeDS390 = 4;
12372     fReturn = fReturn16;
12373     options.stack10bit=0;
12374   }
12375 #if 1
12376   /* print the allocation information */
12377   if (allocInfo)
12378     printAllocInfo (currFunc, codeOutFile);
12379 #endif
12380   /* if debug information required */
12381   if (options.debug && currFunc)
12382     {
12383       cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
12384       _G.debugLine = 1;
12385       if (IS_STATIC (currFunc->etype))
12386         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
12387       else
12388         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
12389       _G.debugLine = 0;
12390     }
12391   /* stack pointer name */
12392   if (options.useXstack)
12393     spname = "_spx";
12394   else
12395     spname = "sp";
12396
12397
12398   for (ic = lic; ic; ic = ic->next)
12399     {
12400
12401       if (ic->lineno && cln != ic->lineno)
12402         {
12403           if (options.debug)
12404             {
12405               _G.debugLine = 1;
12406               emitcode ("", "C$%s$%d$%d$%d ==.",
12407                         FileBaseName (ic->filename), ic->lineno,
12408                         ic->level, ic->block);
12409               _G.debugLine = 0;
12410             }
12411           emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno, 
12412                     printCLine(ic->filename, ic->lineno));
12413           cln = ic->lineno;
12414         }
12415       /* if the result is marked as
12416          spilt and rematerializable or code for
12417          this has already been generated then
12418          do nothing */
12419       if (resultRemat (ic) || ic->generated)
12420         continue;
12421
12422       /* depending on the operation */
12423       switch (ic->op)
12424         {
12425         case '!':
12426           genNot (ic);
12427           break;
12428
12429         case '~':
12430           genCpl (ic);
12431           break;
12432
12433         case UNARYMINUS:
12434           genUminus (ic);
12435           break;
12436
12437         case IPUSH:
12438           genIpush (ic);
12439           break;
12440
12441         case IPOP:
12442           /* IPOP happens only when trying to restore a
12443              spilt live range, if there is an ifx statement
12444              following this pop then the if statement might
12445              be using some of the registers being popped which
12446              would destory the contents of the register so
12447              we need to check for this condition and handle it */
12448           if (ic->next &&
12449               ic->next->op == IFX &&
12450               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
12451             genIfx (ic->next, ic);
12452           else
12453             genIpop (ic);
12454           break;
12455
12456         case CALL:
12457           genCall (ic);
12458           break;
12459
12460         case PCALL:
12461           genPcall (ic);
12462           break;
12463
12464         case FUNCTION:
12465           genFunction (ic);
12466           break;
12467
12468         case ENDFUNCTION:
12469           genEndFunction (ic);
12470           break;
12471
12472         case RETURN:
12473           genRet (ic);
12474           break;
12475
12476         case LABEL:
12477           genLabel (ic);
12478           break;
12479
12480         case GOTO:
12481           genGoto (ic);
12482           break;
12483
12484         case '+':
12485           genPlus (ic);
12486           break;
12487
12488         case '-':
12489           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
12490             genMinus (ic);
12491           break;
12492
12493         case '*':
12494           genMult (ic);
12495           break;
12496
12497         case '/':
12498           genDiv (ic);
12499           break;
12500
12501         case '%':
12502           genMod (ic);
12503           break;
12504
12505         case '>':
12506           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
12507           break;
12508
12509         case '<':
12510           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
12511           break;
12512
12513         case LE_OP:
12514         case GE_OP:
12515         case NE_OP:
12516
12517           /* note these two are xlated by algebraic equivalence
12518              during parsing SDCC.y */
12519           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12520                   "got '>=' or '<=' shouldn't have come here");
12521           break;
12522
12523         case EQ_OP:
12524           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
12525           break;
12526
12527         case AND_OP:
12528           genAndOp (ic);
12529           break;
12530
12531         case OR_OP:
12532           genOrOp (ic);
12533           break;
12534
12535         case '^':
12536           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
12537           break;
12538
12539         case '|':
12540           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
12541           break;
12542
12543         case BITWISEAND:
12544           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
12545           break;
12546
12547         case INLINEASM:
12548           genInline (ic);
12549           break;
12550
12551         case RRC:
12552           genRRC (ic);
12553           break;
12554
12555         case RLC:
12556           genRLC (ic);
12557           break;
12558
12559         case GETHBIT:
12560           genGetHbit (ic);
12561           break;
12562
12563         case LEFT_OP:
12564           genLeftShift (ic);
12565           break;
12566
12567         case RIGHT_OP:
12568           genRightShift (ic);
12569           break;
12570
12571         case GET_VALUE_AT_ADDRESS:
12572           genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
12573           break;
12574
12575         case '=':
12576           if (POINTER_SET (ic))
12577             genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
12578           else
12579             genAssign (ic);
12580           break;
12581
12582         case IFX:
12583           genIfx (ic, NULL);
12584           break;
12585
12586         case ADDRESS_OF:
12587           genAddrOf (ic);
12588           break;
12589
12590         case JUMPTABLE:
12591           genJumpTab (ic);
12592           break;
12593
12594         case CAST:
12595           genCast (ic);
12596           break;
12597
12598         case RECEIVE:
12599           genReceive (ic);
12600           break;
12601
12602         case SEND:
12603           if (ic->builtinSEND) genBuiltIn(ic);
12604           else addSet (&_G.sendSet, ic);
12605           break;
12606
12607         case ARRAYINIT:
12608             genArrayInit(ic);
12609             break;
12610             
12611         default:
12612           ic = ic;
12613         }
12614     }
12615
12616
12617   /* now we are ready to call the
12618      peep hole optimizer */
12619   if (!options.nopeep)
12620     peepHole (&lineHead);
12621
12622   /* now do the actual printing */
12623   printLine (lineHead, codeOutFile);
12624   return;
12625 }